local-commander-agent 0.3.50 → 0.3.52
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/CHANGELOG.md +11 -0
- package/bin/localcommander.mjs +3 -1
- package/package.json +4 -4
- package/runtime/JobHost.exe +0 -0
- package/runtime/LocalCommanderAgent.exe +0 -0
- package/runtime/OwnerBridge.exe +0 -0
- package/runtime/agent.mjs +906 -369
package/runtime/agent.mjs
CHANGED
|
@@ -3240,7 +3240,7 @@ var require_stream = __commonJS({
|
|
|
3240
3240
|
};
|
|
3241
3241
|
duplex._final = function(callback) {
|
|
3242
3242
|
if (ws.readyState === ws.CONNECTING) {
|
|
3243
|
-
ws.once("open", function
|
|
3243
|
+
ws.once("open", function open15() {
|
|
3244
3244
|
duplex._final(callback);
|
|
3245
3245
|
});
|
|
3246
3246
|
return;
|
|
@@ -3261,7 +3261,7 @@ var require_stream = __commonJS({
|
|
|
3261
3261
|
};
|
|
3262
3262
|
duplex._write = function(chunk, encoding, callback) {
|
|
3263
3263
|
if (ws.readyState === ws.CONNECTING) {
|
|
3264
|
-
ws.once("open", function
|
|
3264
|
+
ws.once("open", function open15() {
|
|
3265
3265
|
duplex._write(chunk, encoding, callback);
|
|
3266
3266
|
});
|
|
3267
3267
|
return;
|
|
@@ -4541,10 +4541,10 @@ function mergeDefs(...defs) {
|
|
|
4541
4541
|
function cloneDef(schema) {
|
|
4542
4542
|
return mergeDefs(schema._zod.def);
|
|
4543
4543
|
}
|
|
4544
|
-
function getElementAtPath(obj,
|
|
4545
|
-
if (!
|
|
4544
|
+
function getElementAtPath(obj, path32) {
|
|
4545
|
+
if (!path32)
|
|
4546
4546
|
return obj;
|
|
4547
|
-
return
|
|
4547
|
+
return path32.reduce((acc, key) => acc?.[key], obj);
|
|
4548
4548
|
}
|
|
4549
4549
|
function promiseAllObject(promisesObj) {
|
|
4550
4550
|
const keys = Object.keys(promisesObj);
|
|
@@ -4884,11 +4884,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
4884
4884
|
}
|
|
4885
4885
|
return false;
|
|
4886
4886
|
}
|
|
4887
|
-
function prefixIssues(
|
|
4887
|
+
function prefixIssues(path32, issues) {
|
|
4888
4888
|
return issues.map((iss) => {
|
|
4889
4889
|
var _a3;
|
|
4890
4890
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
4891
|
-
iss.path.unshift(
|
|
4891
|
+
iss.path.unshift(path32);
|
|
4892
4892
|
return iss;
|
|
4893
4893
|
});
|
|
4894
4894
|
}
|
|
@@ -4939,14 +4939,14 @@ function codePointLength(str) {
|
|
|
4939
4939
|
const units2 = str.length;
|
|
4940
4940
|
if (!highSurrogate.test(str))
|
|
4941
4941
|
return units2;
|
|
4942
|
-
let
|
|
4942
|
+
let count4 = units2;
|
|
4943
4943
|
for (let i = 0; i < units2 - 1; i++) {
|
|
4944
4944
|
if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
|
|
4945
|
-
|
|
4945
|
+
count4--;
|
|
4946
4946
|
i++;
|
|
4947
4947
|
}
|
|
4948
4948
|
}
|
|
4949
|
-
return
|
|
4949
|
+
return count4;
|
|
4950
4950
|
}
|
|
4951
4951
|
function getLengthableOrigin(input2) {
|
|
4952
4952
|
if (Array.isArray(input2))
|
|
@@ -5158,8 +5158,8 @@ var _E = "captureStackTrace" in Error ? Error : null;
|
|
|
5158
5158
|
function newError(Definition) {
|
|
5159
5159
|
const E = _E;
|
|
5160
5160
|
if (E) {
|
|
5161
|
-
const
|
|
5162
|
-
if (typeof
|
|
5161
|
+
const saved2 = E.stackTraceLimit;
|
|
5162
|
+
if (typeof saved2 === "number") {
|
|
5163
5163
|
try {
|
|
5164
5164
|
E.stackTraceLimit = 0;
|
|
5165
5165
|
} catch {
|
|
@@ -5169,7 +5169,7 @@ function newError(Definition) {
|
|
|
5169
5169
|
try {
|
|
5170
5170
|
return new Definition();
|
|
5171
5171
|
} finally {
|
|
5172
|
-
E.stackTraceLimit =
|
|
5172
|
+
E.stackTraceLimit = saved2;
|
|
5173
5173
|
}
|
|
5174
5174
|
}
|
|
5175
5175
|
}
|
|
@@ -5338,16 +5338,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
|
|
|
5338
5338
|
}
|
|
5339
5339
|
function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
5340
5340
|
const fieldErrors = { _errors: [] };
|
|
5341
|
-
const processError = (error63,
|
|
5341
|
+
const processError = (error63, path32 = []) => {
|
|
5342
5342
|
for (const issue2 of error63.issues) {
|
|
5343
5343
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
5344
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
5344
|
+
issue2.errors.map((issues) => processError({ issues }, [...path32, ...issue2.path]));
|
|
5345
5345
|
} else if (issue2.code === "invalid_key") {
|
|
5346
|
-
processError({ issues: issue2.issues }, [...
|
|
5346
|
+
processError({ issues: issue2.issues }, [...path32, ...issue2.path]);
|
|
5347
5347
|
} else if (issue2.code === "invalid_element") {
|
|
5348
|
-
processError({ issues: issue2.issues }, [...
|
|
5348
|
+
processError({ issues: issue2.issues }, [...path32, ...issue2.path]);
|
|
5349
5349
|
} else {
|
|
5350
|
-
const fullpath = [...
|
|
5350
|
+
const fullpath = [...path32, ...issue2.path];
|
|
5351
5351
|
if (fullpath.length === 0) {
|
|
5352
5352
|
fieldErrors._errors.push(mapper(issue2));
|
|
5353
5353
|
} else {
|
|
@@ -5386,17 +5386,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
|
5386
5386
|
}
|
|
5387
5387
|
function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
5388
5388
|
const result2 = { errors: [] };
|
|
5389
|
-
const processError = (error63,
|
|
5389
|
+
const processError = (error63, path32 = []) => {
|
|
5390
5390
|
var _a3;
|
|
5391
5391
|
for (const issue2 of error63.issues) {
|
|
5392
5392
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
5393
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
5393
|
+
issue2.errors.map((issues) => processError({ issues }, [...path32, ...issue2.path]));
|
|
5394
5394
|
} else if (issue2.code === "invalid_key") {
|
|
5395
|
-
processError({ issues: issue2.issues }, [...
|
|
5395
|
+
processError({ issues: issue2.issues }, [...path32, ...issue2.path]);
|
|
5396
5396
|
} else if (issue2.code === "invalid_element") {
|
|
5397
|
-
processError({ issues: issue2.issues }, [...
|
|
5397
|
+
processError({ issues: issue2.issues }, [...path32, ...issue2.path]);
|
|
5398
5398
|
} else {
|
|
5399
|
-
const fullpath = [...
|
|
5399
|
+
const fullpath = [...path32, ...issue2.path];
|
|
5400
5400
|
if (fullpath.length === 0) {
|
|
5401
5401
|
result2.errors.push(mapper(issue2));
|
|
5402
5402
|
continue;
|
|
@@ -5435,8 +5435,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
|
5435
5435
|
}
|
|
5436
5436
|
function toDotPath(_path) {
|
|
5437
5437
|
const segs = [];
|
|
5438
|
-
const
|
|
5439
|
-
for (const seg of
|
|
5438
|
+
const path32 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
5439
|
+
for (const seg of path32) {
|
|
5440
5440
|
if (typeof seg === "number")
|
|
5441
5441
|
segs.push(`[${seg}]`);
|
|
5442
5442
|
else if (typeof seg === "symbol")
|
|
@@ -8551,9 +8551,9 @@ function partPattern(schema) {
|
|
|
8551
8551
|
return own2;
|
|
8552
8552
|
}
|
|
8553
8553
|
if (def.options) {
|
|
8554
|
-
const
|
|
8555
|
-
if (
|
|
8556
|
-
return `^(${
|
|
8554
|
+
const sources2 = def.options.map(partPattern);
|
|
8555
|
+
if (sources2.every(Boolean))
|
|
8556
|
+
return `^(${sources2.map((s) => cleanRegex(s)).join("|")})$`;
|
|
8557
8557
|
}
|
|
8558
8558
|
return leafPattern(schema);
|
|
8559
8559
|
}
|
|
@@ -9301,8 +9301,8 @@ function az_default() {
|
|
|
9301
9301
|
}
|
|
9302
9302
|
|
|
9303
9303
|
// ../../node_modules/zod/v4/locales/be.js
|
|
9304
|
-
function getBelarusianPlural(
|
|
9305
|
-
const absCount = Math.abs(
|
|
9304
|
+
function getBelarusianPlural(count4, one, few, many) {
|
|
9305
|
+
const absCount = Math.abs(count4);
|
|
9306
9306
|
const lastDigit = absCount % 10;
|
|
9307
9307
|
const lastTwoDigits = absCount % 100;
|
|
9308
9308
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -11949,8 +11949,8 @@ function hu_default() {
|
|
|
11949
11949
|
}
|
|
11950
11950
|
|
|
11951
11951
|
// ../../node_modules/zod/v4/locales/hy.js
|
|
11952
|
-
function getArmenianPlural(
|
|
11953
|
-
return Math.abs(
|
|
11952
|
+
function getArmenianPlural(count4, one, many) {
|
|
11953
|
+
return Math.abs(count4) === 1 ? one : many;
|
|
11954
11954
|
}
|
|
11955
11955
|
function withDefiniteArticle(word) {
|
|
11956
11956
|
if (!word)
|
|
@@ -14688,8 +14688,8 @@ function ro_default() {
|
|
|
14688
14688
|
}
|
|
14689
14689
|
|
|
14690
14690
|
// ../../node_modules/zod/v4/locales/ru.js
|
|
14691
|
-
function getRussianPlural(
|
|
14692
|
-
const absCount = Math.abs(
|
|
14691
|
+
function getRussianPlural(count4, one, few, many) {
|
|
14692
|
+
const absCount = Math.abs(count4);
|
|
14693
14693
|
const lastDigit = absCount % 10;
|
|
14694
14694
|
const lastTwoDigits = absCount % 100;
|
|
14695
14695
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -19288,8 +19288,8 @@ function _stringFormat(Class2, format, fnOrRegex, _params = {}) {
|
|
|
19288
19288
|
}
|
|
19289
19289
|
|
|
19290
19290
|
// ../../node_modules/zod/v4/core/to-json-schema.js
|
|
19291
|
-
function assignProps(target, ...
|
|
19292
|
-
for (const source of
|
|
19291
|
+
function assignProps(target, ...sources2) {
|
|
19292
|
+
for (const source of sources2) {
|
|
19293
19293
|
for (const key of Reflect.ownKeys(source)) {
|
|
19294
19294
|
if (Object.prototype.propertyIsEnumerable.call(source, key)) {
|
|
19295
19295
|
assignProp(target, key, source[key]);
|
|
@@ -22538,13 +22538,13 @@ function resolveRef(ref, ctx) {
|
|
|
22538
22538
|
if (!ref.startsWith("#")) {
|
|
22539
22539
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
22540
22540
|
}
|
|
22541
|
-
const
|
|
22542
|
-
if (
|
|
22541
|
+
const path32 = ref.slice(1).split("/").filter(Boolean);
|
|
22542
|
+
if (path32.length === 0) {
|
|
22543
22543
|
return ctx.rootSchema;
|
|
22544
22544
|
}
|
|
22545
22545
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
22546
|
-
if (
|
|
22547
|
-
const key =
|
|
22546
|
+
if (path32[0] === defsKey) {
|
|
22547
|
+
const key = path32[1] === void 0 ? void 0 : decodeJSONPointerSegment(path32[1]);
|
|
22548
22548
|
if (!key || !ctx.defs[key]) {
|
|
22549
22549
|
throw new Error(`Reference not found: ${ref}`);
|
|
22550
22550
|
}
|
|
@@ -24580,7 +24580,7 @@ var RelayBridge = class _RelayBridge {
|
|
|
24580
24580
|
const upstream = netConnect({ host, port });
|
|
24581
24581
|
this.tunnels.add(socket);
|
|
24582
24582
|
this.tunnels.add(upstream);
|
|
24583
|
-
let
|
|
24583
|
+
let open15 = false;
|
|
24584
24584
|
const cleanup = () => {
|
|
24585
24585
|
this.tunnels.delete(socket);
|
|
24586
24586
|
this.tunnels.delete(upstream);
|
|
@@ -24588,13 +24588,13 @@ var RelayBridge = class _RelayBridge {
|
|
|
24588
24588
|
upstream.destroy();
|
|
24589
24589
|
};
|
|
24590
24590
|
const timer = setTimeout(() => {
|
|
24591
|
-
if (!
|
|
24591
|
+
if (!open15) {
|
|
24592
24592
|
refuse("504 Gateway Timeout");
|
|
24593
24593
|
cleanup();
|
|
24594
24594
|
}
|
|
24595
24595
|
}, CONNECT_TIMEOUT_MS);
|
|
24596
24596
|
upstream.once("connect", () => {
|
|
24597
|
-
|
|
24597
|
+
open15 = true;
|
|
24598
24598
|
clearTimeout(timer);
|
|
24599
24599
|
socket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
|
|
24600
24600
|
if (head.length) upstream.write(head);
|
|
@@ -24603,7 +24603,7 @@ var RelayBridge = class _RelayBridge {
|
|
|
24603
24603
|
});
|
|
24604
24604
|
upstream.on("error", () => {
|
|
24605
24605
|
clearTimeout(timer);
|
|
24606
|
-
if (!
|
|
24606
|
+
if (!open15) refuse("502 Bad Gateway");
|
|
24607
24607
|
cleanup();
|
|
24608
24608
|
});
|
|
24609
24609
|
socket.on("error", cleanup);
|
|
@@ -24624,7 +24624,7 @@ var RelayBridge = class _RelayBridge {
|
|
|
24624
24624
|
const remote = (0, import_stream.default)(ws, { allowHalfOpen: false });
|
|
24625
24625
|
this.tunnels.add(socket);
|
|
24626
24626
|
this.tunnels.add(remote);
|
|
24627
|
-
let reply = Buffer.alloc(0),
|
|
24627
|
+
let reply = Buffer.alloc(0), open15 = false;
|
|
24628
24628
|
const cleanup = () => {
|
|
24629
24629
|
this.tunnels.delete(socket);
|
|
24630
24630
|
this.tunnels.delete(remote);
|
|
@@ -24632,7 +24632,7 @@ var RelayBridge = class _RelayBridge {
|
|
|
24632
24632
|
remote.destroy();
|
|
24633
24633
|
};
|
|
24634
24634
|
const timer = setTimeout(() => {
|
|
24635
|
-
if (!
|
|
24635
|
+
if (!open15) {
|
|
24636
24636
|
refuse("504 Gateway Timeout");
|
|
24637
24637
|
cleanup();
|
|
24638
24638
|
}
|
|
@@ -24654,7 +24654,7 @@ var RelayBridge = class _RelayBridge {
|
|
|
24654
24654
|
cleanup();
|
|
24655
24655
|
return;
|
|
24656
24656
|
}
|
|
24657
|
-
|
|
24657
|
+
open15 = true;
|
|
24658
24658
|
socket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
|
|
24659
24659
|
const rest = reply.subarray(end + 4);
|
|
24660
24660
|
if (rest.length) socket.write(rest);
|
|
@@ -24671,7 +24671,7 @@ Proxy-Authorization: Basic ${Buffer.from("lc:" + route.token).toString("base64")
|
|
|
24671
24671
|
remote.on("data", onReply);
|
|
24672
24672
|
});
|
|
24673
24673
|
remote.on("error", () => {
|
|
24674
|
-
if (!
|
|
24674
|
+
if (!open15) refuse("502 Bad Gateway");
|
|
24675
24675
|
cleanup();
|
|
24676
24676
|
});
|
|
24677
24677
|
socket.on("error", cleanup);
|
|
@@ -24917,14 +24917,14 @@ async function loadProxyModeFlag(dir) {
|
|
|
24917
24917
|
}
|
|
24918
24918
|
}
|
|
24919
24919
|
async function writeProxyState(dir, state) {
|
|
24920
|
-
const
|
|
24920
|
+
const file3 = path.join(dir, "proxy.json");
|
|
24921
24921
|
try {
|
|
24922
24922
|
if (!state) {
|
|
24923
|
-
await rm(
|
|
24923
|
+
await rm(file3, { force: true });
|
|
24924
24924
|
return;
|
|
24925
24925
|
}
|
|
24926
24926
|
await mkdir(dir, { recursive: true });
|
|
24927
|
-
await writeFile(
|
|
24927
|
+
await writeFile(file3, JSON.stringify({ ...state, updatedAt: Date.now() }), { mode: 384 });
|
|
24928
24928
|
} catch {
|
|
24929
24929
|
}
|
|
24930
24930
|
}
|
|
@@ -25037,21 +25037,21 @@ import path2 from "node:path";
|
|
|
25037
25037
|
import { spawn, spawnSync } from "node:child_process";
|
|
25038
25038
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
25039
25039
|
var Receipt = external_exports.object({ version: external_exports.literal(1), deviceId: external_exports.string().uuid(), tenantId: external_exports.string().uuid(), accountId: external_exports.string().uuid(), bundleId: external_exports.string().regex(/^[a-f0-9]{64}$/) }).strict();
|
|
25040
|
-
function networkPath(
|
|
25041
|
-
return path2.join(path2.dirname(
|
|
25040
|
+
function networkPath(stateDirectory2, name2) {
|
|
25041
|
+
return path2.join(path2.dirname(stateDirectory2), "Network", name2);
|
|
25042
25042
|
}
|
|
25043
|
-
async function networkDirectory(
|
|
25044
|
-
const directory = path2.dirname(networkPath(
|
|
25043
|
+
async function networkDirectory(stateDirectory2) {
|
|
25044
|
+
const directory = path2.dirname(networkPath(stateDirectory2, "x"));
|
|
25045
25045
|
await fs.mkdir(directory, { recursive: true, mode: 448 });
|
|
25046
25046
|
const stat2 = await fs.lstat(directory);
|
|
25047
25047
|
if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw Error("NETWORK_DIRECTORY_INVALID");
|
|
25048
25048
|
return directory;
|
|
25049
25049
|
}
|
|
25050
|
-
async function networkPrepared(
|
|
25050
|
+
async function networkPrepared(stateDirectory2, identity) {
|
|
25051
25051
|
try {
|
|
25052
|
-
const
|
|
25052
|
+
const file3 = networkPath(stateDirectory2, "network-prepared.json"), stat2 = await fs.lstat(file3);
|
|
25053
25053
|
if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > 1024) return false;
|
|
25054
|
-
const receipt = Receipt.parse(JSON.parse(await fs.readFile(
|
|
25054
|
+
const receipt = Receipt.parse(JSON.parse(await fs.readFile(file3, "utf8"))), e = identity.enrollment;
|
|
25055
25055
|
return !!e && receipt.deviceId === e.deviceId && receipt.tenantId === e.tenantId && receipt.accountId === e.accountId;
|
|
25056
25056
|
} catch {
|
|
25057
25057
|
return false;
|
|
@@ -25087,9 +25087,9 @@ async function payload(binaryDirectory) {
|
|
|
25087
25087
|
throw error62;
|
|
25088
25088
|
}
|
|
25089
25089
|
}
|
|
25090
|
-
async function installedNetworkHelper(
|
|
25090
|
+
async function installedNetworkHelper(stateDirectory2) {
|
|
25091
25091
|
try {
|
|
25092
|
-
const receipt = Receipt.parse(JSON.parse(await fs.readFile(networkPath(
|
|
25092
|
+
const receipt = Receipt.parse(JSON.parse(await fs.readFile(networkPath(stateDirectory2, "network-prepared.json"), "utf8")));
|
|
25093
25093
|
const programFiles = process.env.ProgramW6432 ?? process.env.ProgramFiles ?? "C:\\Program Files";
|
|
25094
25094
|
const helper = path2.join(programFiles, "LocalCommander", "Network", receipt.bundleId, "NetworkService.exe"), stat2 = await fs.lstat(helper);
|
|
25095
25095
|
if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > 4 * 1024 * 1024 || (await fs.realpath(helper)).toLowerCase() !== path2.resolve(helper).toLowerCase()) return null;
|
|
@@ -25118,23 +25118,23 @@ async function elevated(helper, command, requestPath, directory) {
|
|
|
25118
25118
|
await fs.rm(scriptPath, { force: true });
|
|
25119
25119
|
}
|
|
25120
25120
|
}
|
|
25121
|
-
async function setupNetwork(binaryDirectory,
|
|
25121
|
+
async function setupNetwork(binaryDirectory, stateDirectory2, identity) {
|
|
25122
25122
|
const bundle = await payload(binaryDirectory);
|
|
25123
25123
|
if (!bundle) return "not_packaged";
|
|
25124
25124
|
const e = identity.enrollment;
|
|
25125
25125
|
if (!e?.accountId) throw Error("NETWORK_ACCOUNT_BINDING_REQUIRED");
|
|
25126
25126
|
const request = { ownerSid: windowsSid(), tenantId: e.tenantId, accountId: e.accountId, deviceId: e.deviceId, keyFingerprint: identity.fingerprint };
|
|
25127
|
-
const directory = await networkDirectory(
|
|
25127
|
+
const directory = await networkDirectory(stateDirectory2);
|
|
25128
25128
|
const requestPath = path2.join(directory, "network-setup-" + randomUUID2() + ".json");
|
|
25129
25129
|
await fs.writeFile(requestPath, JSON.stringify(request), { flag: "wx", mode: 384 });
|
|
25130
25130
|
try {
|
|
25131
25131
|
await elevated(bundle.helper, "setup", requestPath, directory);
|
|
25132
25132
|
await localNetworkControl(e.deviceId);
|
|
25133
25133
|
const receipt = Receipt.parse({ version: 1, deviceId: e.deviceId, tenantId: e.tenantId, accountId: e.accountId, bundleId: bundle.bundleId });
|
|
25134
|
-
const
|
|
25134
|
+
const file3 = path2.join(directory, "network-prepared.json"), temp = file3 + "." + randomUUID2();
|
|
25135
25135
|
await fs.writeFile(temp, JSON.stringify(receipt), { flag: "wx", mode: 384 });
|
|
25136
25136
|
try {
|
|
25137
|
-
await fs.rename(temp,
|
|
25137
|
+
await fs.rename(temp, file3);
|
|
25138
25138
|
} finally {
|
|
25139
25139
|
await fs.rm(temp, { force: true });
|
|
25140
25140
|
}
|
|
@@ -25143,14 +25143,14 @@ async function setupNetwork(binaryDirectory, stateDirectory, identity) {
|
|
|
25143
25143
|
await fs.rm(requestPath, { force: true });
|
|
25144
25144
|
}
|
|
25145
25145
|
}
|
|
25146
|
-
async function removeNetwork(binaryDirectory,
|
|
25146
|
+
async function removeNetwork(binaryDirectory, stateDirectory2, identity) {
|
|
25147
25147
|
const e = identity.enrollment;
|
|
25148
|
-
if (!e || !await networkPrepared(
|
|
25148
|
+
if (!e || !await networkPrepared(stateDirectory2, identity)) return;
|
|
25149
25149
|
await localNetworkControl(e.deviceId, "off");
|
|
25150
|
-
const helper = (await payload(binaryDirectory))?.helper ?? await installedNetworkHelper(
|
|
25150
|
+
const helper = (await payload(binaryDirectory))?.helper ?? await installedNetworkHelper(stateDirectory2);
|
|
25151
25151
|
if (!helper) throw Error("NETWORK_REMOVAL_PACKAGE_REQUIRED");
|
|
25152
|
-
await elevated(helper, "uninstall", void 0, await networkDirectory(
|
|
25153
|
-
await fs.rm(networkPath(
|
|
25152
|
+
await elevated(helper, "uninstall", void 0, await networkDirectory(stateDirectory2));
|
|
25153
|
+
await fs.rm(networkPath(stateDirectory2, "network-prepared.json"), { force: true });
|
|
25154
25154
|
}
|
|
25155
25155
|
async function openNetworkPanel(binaryDirectory, identity) {
|
|
25156
25156
|
const bundle = await payload(binaryDirectory), e = identity.enrollment;
|
|
@@ -25164,8 +25164,8 @@ async function openNetworkPanel(binaryDirectory, identity) {
|
|
|
25164
25164
|
}
|
|
25165
25165
|
|
|
25166
25166
|
// agent/src/main.ts
|
|
25167
|
-
import
|
|
25168
|
-
import
|
|
25167
|
+
import path31 from "node:path";
|
|
25168
|
+
import os9 from "node:os";
|
|
25169
25169
|
|
|
25170
25170
|
// agent/src/posix-store.ts
|
|
25171
25171
|
import { constants } from "node:fs";
|
|
@@ -25584,7 +25584,7 @@ async function acquirePosixJournalGuard(directory, helper) {
|
|
|
25584
25584
|
}
|
|
25585
25585
|
|
|
25586
25586
|
// agent/src/main.ts
|
|
25587
|
-
import { mkdir as
|
|
25587
|
+
import { mkdir as mkdir16, open as open14, readFile as readFile14, realpath as realpath10, rm as rm12 } from "node:fs/promises";
|
|
25588
25588
|
import { fileURLToPath } from "node:url";
|
|
25589
25589
|
|
|
25590
25590
|
// packages/operations/src/crypto.ts
|
|
@@ -25721,8 +25721,8 @@ var exec2 = promisify2(execFile2);
|
|
|
25721
25721
|
async function darwinSupervisorLiveness(helper, pids, records = []) {
|
|
25722
25722
|
if (process.platform !== "darwin" || !process.getuid?.() || process.getuid() !== process.geteuid?.()) return null;
|
|
25723
25723
|
const remaining = new Set(pids), uid = process.getuid(), deadline = Date.now() + 1e4, env = buildChildEnvironment(process.env);
|
|
25724
|
-
const run2 = (
|
|
25725
|
-
|
|
25724
|
+
const run2 = (file3, args) => exec2(
|
|
25725
|
+
file3,
|
|
25726
25726
|
args,
|
|
25727
25727
|
{ env, timeout: Math.max(1, Math.min(7e3, deadline - Date.now())), maxBuffer: 8192, encoding: "utf8", windowsHide: true }
|
|
25728
25728
|
);
|
|
@@ -26490,6 +26490,7 @@ var NATIVE_STATUS_CAPABILITY = "nativeStatusV1";
|
|
|
26490
26490
|
var NativeStatusSchema = NativeCapacitySchema.extend({ type: external_exports.literal("nativeStatus"), active: external_exports.number().int().min(0).max(32), queued: external_exports.number().int().min(0).max(256), paused: external_exports.boolean() }).strict().refine((v) => v.active <= v.safeSlots);
|
|
26491
26491
|
var TerminalEventSchema = external_exports.object({ type: external_exports.literal("executionResult"), protocolVersion: external_exports.literal(1), requestId: uuid11, tenantId: uuid11, deviceId: uuid11, connectionEpoch: epoch2, binding: ExecutionBindingSchema, state: external_exports.enum(["finished", "failed", "cancelled", "unknown", "rejected"]), resultCode: external_exports.string().regex(/^[A-Z0-9_]{1,40}$/), metrics: TerminalMetricsSchema.optional() }).strict();
|
|
26492
26492
|
var HeldLeasesFrameSchema = external_exports.object({ type: external_exports.literal("heldLeases"), protocolVersion: external_exports.literal(1), connectionEpoch: epoch2, bindings: external_exports.array(ExecutionBindingSchema).min(1).max(64) }).strict();
|
|
26493
|
+
var FullLogStateSchema = external_exports.object({ type: external_exports.literal("fullLogState"), protocolVersion: external_exports.literal(1), connectionEpoch: epoch2, enabled: external_exports.boolean().nullable() }).strict();
|
|
26493
26494
|
var TerminalEventAckSchema = external_exports.object({ type: external_exports.literal("executionResultAck"), protocolVersion: external_exports.literal(1), requestId: uuid11, ok: external_exports.boolean() }).strict();
|
|
26494
26495
|
function canonicalJson(value) {
|
|
26495
26496
|
function canonical2(v) {
|
|
@@ -26785,23 +26786,23 @@ var NativeJournal = class _NativeJournal {
|
|
|
26785
26786
|
}
|
|
26786
26787
|
const dir = await safeDirectory(directory), lockPath = path6.join(dir, "journal.lock"), nonce2 = randomBytes4(16).toString("hex");
|
|
26787
26788
|
const guard = options.lockHelper ? await acquirePosixJournalGuard(dir, options.lockHelper) : void 0;
|
|
26788
|
-
let
|
|
26789
|
+
let file3;
|
|
26789
26790
|
try {
|
|
26790
|
-
|
|
26791
|
+
file3 = await open3(lockPath, constants2.O_CREAT | constants2.O_EXCL | constants2.O_WRONLY, 384);
|
|
26791
26792
|
} catch (e) {
|
|
26792
26793
|
await guard?.close();
|
|
26793
26794
|
if (e.code === "EEXIST") throw failure2("JOURNAL_LOCKED");
|
|
26794
26795
|
throw e;
|
|
26795
26796
|
}
|
|
26796
|
-
const journal = new _NativeJournal(dir, box, { path: lockPath, nonce: nonce2, file:
|
|
26797
|
+
const journal = new _NativeJournal(dir, box, { path: lockPath, nonce: nonce2, file: file3, guard }, { maxEntries, maxBytes, retentionMs, now: options.now ?? (() => /* @__PURE__ */ new Date()) });
|
|
26797
26798
|
try {
|
|
26798
|
-
await
|
|
26799
|
-
await
|
|
26799
|
+
await file3.writeFile(JSON.stringify({ pid: process.pid, nonce: nonce2, createdAt: journal.now().toISOString() }));
|
|
26800
|
+
await file3.sync();
|
|
26800
26801
|
await journal.load();
|
|
26801
26802
|
await journal.loadStart(existed);
|
|
26802
26803
|
return journal;
|
|
26803
26804
|
} catch (e) {
|
|
26804
|
-
await
|
|
26805
|
+
await file3.close().catch(() => {
|
|
26805
26806
|
});
|
|
26806
26807
|
try {
|
|
26807
26808
|
const value = JSON.parse(await readFile3(lockPath, "utf8"));
|
|
@@ -27139,7 +27140,7 @@ var NativeJournal = class _NativeJournal {
|
|
|
27139
27140
|
* still alive; otherwise, including every entry from an older agent, it stays EXECUTION_UNKNOWN (#194). */
|
|
27140
27141
|
recoverAfterRestart(liveness) {
|
|
27141
27142
|
return this.enqueue(async () => {
|
|
27142
|
-
let
|
|
27143
|
+
let count4 = 0;
|
|
27143
27144
|
const interrupted = [...this.entries.values()].filter((e) => ["accepted", "running"].includes(e.state));
|
|
27144
27145
|
const pids = [...new Set(interrupted.flatMap((e) => e.supervisors ?? []))];
|
|
27145
27146
|
const linuxSupervisors = interrupted.flatMap((e) => e.linuxSupervisors ?? []), darwinSupervisors = interrupted.flatMap((e) => e.darwinSupervisors ?? []);
|
|
@@ -27172,9 +27173,9 @@ var NativeJournal = class _NativeJournal {
|
|
|
27172
27173
|
} });
|
|
27173
27174
|
}
|
|
27174
27175
|
await this.persist(e);
|
|
27175
|
-
|
|
27176
|
+
count4++;
|
|
27176
27177
|
}
|
|
27177
|
-
return
|
|
27178
|
+
return count4;
|
|
27178
27179
|
});
|
|
27179
27180
|
}
|
|
27180
27181
|
eligibleForPruning(entry, cutoff) {
|
|
@@ -27182,20 +27183,20 @@ var NativeJournal = class _NativeJournal {
|
|
|
27182
27183
|
}
|
|
27183
27184
|
admissionAvailable() {
|
|
27184
27185
|
if (this.closed || this.lock.guard && !this.lock.guard.active) return false;
|
|
27185
|
-
let
|
|
27186
|
-
if (
|
|
27186
|
+
let count4 = this.entries.size, bytes3 = this.totalBytes;
|
|
27187
|
+
if (count4 < this.options.maxEntries && bytes3 + MAX_ENVELOPE <= this.options.maxBytes) return true;
|
|
27187
27188
|
const cutoff = this.now().getTime() - this.options.retentionMs;
|
|
27188
27189
|
for (const entry of this.entries.values()) {
|
|
27189
27190
|
if (!this.eligibleForPruning(entry, cutoff)) continue;
|
|
27190
|
-
|
|
27191
|
+
count4--;
|
|
27191
27192
|
bytes3 -= this.sizes.get(entry.executionId);
|
|
27192
|
-
if (
|
|
27193
|
+
if (count4 < this.options.maxEntries && bytes3 + MAX_ENVELOPE <= this.options.maxBytes) return true;
|
|
27193
27194
|
}
|
|
27194
27195
|
return false;
|
|
27195
27196
|
}
|
|
27196
27197
|
// Called only inside the serialized queue; enqueueing prune here would deadlock.
|
|
27197
27198
|
async pruneEligible() {
|
|
27198
|
-
let
|
|
27199
|
+
let count4 = 0;
|
|
27199
27200
|
const cutoff = this.now().getTime() - this.options.retentionMs;
|
|
27200
27201
|
for (const e of [...this.entries.values()]) {
|
|
27201
27202
|
if (!this.eligibleForPruning(e, cutoff)) continue;
|
|
@@ -27205,9 +27206,9 @@ var NativeJournal = class _NativeJournal {
|
|
|
27205
27206
|
this.entries.delete(e.executionId);
|
|
27206
27207
|
this.sizes.delete(e.executionId);
|
|
27207
27208
|
this.digests.delete(e.executionId);
|
|
27208
|
-
|
|
27209
|
+
count4++;
|
|
27209
27210
|
}
|
|
27210
|
-
return
|
|
27211
|
+
return count4;
|
|
27211
27212
|
}
|
|
27212
27213
|
prune() {
|
|
27213
27214
|
return this.enqueue(() => this.pruneEligible());
|
|
@@ -28768,9 +28769,9 @@ function resolveWindowsLauncher(commandName, env = process.env) {
|
|
|
28768
28769
|
const dir = entry.trim().replace(/^"(.*)"$/, "$1");
|
|
28769
28770
|
if (!path11.win32.isAbsolute(dir)) continue;
|
|
28770
28771
|
for (const ext of extensions) {
|
|
28771
|
-
const
|
|
28772
|
+
const file3 = path11.win32.join(dir, commandName + ext);
|
|
28772
28773
|
try {
|
|
28773
|
-
if (statSync(
|
|
28774
|
+
if (statSync(file3).isFile()) return { file: file3, shell: ext === ".bat" || ext === ".cmd" };
|
|
28774
28775
|
} catch {
|
|
28775
28776
|
}
|
|
28776
28777
|
}
|
|
@@ -28791,8 +28792,8 @@ var Entry = external_exports.strictObject({
|
|
|
28791
28792
|
});
|
|
28792
28793
|
var State = external_exports.strictObject({ version: external_exports.literal(1), platform: external_exports.string().max(16), entries: external_exports.array(Entry).max(32) });
|
|
28793
28794
|
var HostMemory = class {
|
|
28794
|
-
constructor(
|
|
28795
|
-
this.file =
|
|
28795
|
+
constructor(file3, allowed, programs) {
|
|
28796
|
+
this.file = file3;
|
|
28796
28797
|
this.allowed = allowed;
|
|
28797
28798
|
this.programs = programs;
|
|
28798
28799
|
}
|
|
@@ -28832,9 +28833,9 @@ var HostMemory = class {
|
|
|
28832
28833
|
else if (!this.programs && !available) available = (process.env.PATH ?? "").split(path12.delimiter).some((dir) => {
|
|
28833
28834
|
if (!path12.isAbsolute(dir)) return false;
|
|
28834
28835
|
try {
|
|
28835
|
-
const
|
|
28836
|
-
accessSync(
|
|
28837
|
-
return statSync2(
|
|
28836
|
+
const file3 = path12.join(dir, command);
|
|
28837
|
+
accessSync(file3, constants5.X_OK);
|
|
28838
|
+
return statSync2(file3).isFile();
|
|
28838
28839
|
} catch {
|
|
28839
28840
|
return false;
|
|
28840
28841
|
}
|
|
@@ -28894,13 +28895,13 @@ var HostMemory = class {
|
|
|
28894
28895
|
await mkdir5(directory2, { recursive: true, mode: 448 });
|
|
28895
28896
|
const stat2 = await lstat5(directory2);
|
|
28896
28897
|
if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw Error("HOST_MEMORY_DIRECTORY_INVALID");
|
|
28897
|
-
const
|
|
28898
|
+
const file3 = await open5(temp, "wx", 384);
|
|
28898
28899
|
try {
|
|
28899
|
-
await
|
|
28900
|
-
await
|
|
28900
|
+
await file3.writeFile(encoded);
|
|
28901
|
+
await file3.close();
|
|
28901
28902
|
await rename3(temp, this.file);
|
|
28902
28903
|
} finally {
|
|
28903
|
-
await
|
|
28904
|
+
await file3.close().catch(() => {
|
|
28904
28905
|
});
|
|
28905
28906
|
await rm4(temp, { force: true }).catch(() => {
|
|
28906
28907
|
});
|
|
@@ -29127,11 +29128,11 @@ var PathGuard = class _PathGuard {
|
|
|
29127
29128
|
// src/windows-file-read.ts
|
|
29128
29129
|
import { execFile as execFile3 } from "node:child_process";
|
|
29129
29130
|
import path14 from "node:path";
|
|
29130
|
-
function readWindowsFile(bridge,
|
|
29131
|
-
return invokeRead(bridge,
|
|
29131
|
+
function readWindowsFile(bridge, file3, maxBytes, signal) {
|
|
29132
|
+
return invokeRead(bridge, file3, maxBytes, false, signal);
|
|
29132
29133
|
}
|
|
29133
|
-
async function readWindowsFilePrefix(bridge,
|
|
29134
|
-
const output2 = await invokeRead(bridge,
|
|
29134
|
+
async function readWindowsFilePrefix(bridge, file3, maxBytes, signal) {
|
|
29135
|
+
const output2 = await invokeRead(bridge, file3, maxBytes, true, signal);
|
|
29135
29136
|
try {
|
|
29136
29137
|
const value = JSON.parse(output2.toString("utf8"));
|
|
29137
29138
|
if (!value || Object.keys(value).length !== 4 || typeof value.data !== "string" || !Number.isSafeInteger(value.size) || value.size < 0 || typeof value.modifiedAt !== "string" || new Date(value.modifiedAt).toISOString() !== value.modifiedAt || value.truncated !== value.size > maxBytes) throw Error();
|
|
@@ -29144,7 +29145,7 @@ async function readWindowsFilePrefix(bridge, file2, maxBytes, signal) {
|
|
|
29144
29145
|
}
|
|
29145
29146
|
function readWindowsFiles(bridge, files, maxBytes, maxTotalBytes, signal) {
|
|
29146
29147
|
const input2 = JSON.stringify({ paths: files });
|
|
29147
|
-
if (process.platform !== "win32" || !path14.isAbsolute(bridge) || files.length < 1 || files.length > 64 || files.some((
|
|
29148
|
+
if (process.platform !== "win32" || !path14.isAbsolute(bridge) || files.length < 1 || files.length > 64 || files.some((file3) => !path14.isAbsolute(file3)) || Buffer.byteLength(input2) > 3e5 || !Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > 1048576 || !Number.isSafeInteger(maxTotalBytes) || maxTotalBytes < 1 || maxTotalBytes > 16777216) {
|
|
29148
29149
|
return Promise.reject(new Error("FILE_READ_ARGUMENT_INVALID"));
|
|
29149
29150
|
}
|
|
29150
29151
|
if (signal?.aborted) return Promise.reject(new Error("CANCELLED"));
|
|
@@ -29181,8 +29182,8 @@ function readWindowsFiles(bridge, files, maxBytes, maxTotalBytes, signal) {
|
|
|
29181
29182
|
child.stdin.end(input2);
|
|
29182
29183
|
});
|
|
29183
29184
|
}
|
|
29184
|
-
function invokeRead(bridge,
|
|
29185
|
-
if (process.platform !== "win32" || !path14.isAbsolute(bridge) || !path14.isAbsolute(
|
|
29185
|
+
function invokeRead(bridge, file3, maxBytes, prefix, signal) {
|
|
29186
|
+
if (process.platform !== "win32" || !path14.isAbsolute(bridge) || !path14.isAbsolute(file3) || !Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > (prefix ? 16777216 : 1048576)) {
|
|
29186
29187
|
return Promise.reject(new Error("FILE_READ_ARGUMENT_INVALID"));
|
|
29187
29188
|
}
|
|
29188
29189
|
if (signal?.aborted) return Promise.reject(new Error("CANCELLED"));
|
|
@@ -29205,7 +29206,7 @@ function invokeRead(bridge, file2, maxBytes, prefix, signal) {
|
|
|
29205
29206
|
});
|
|
29206
29207
|
child.stdin.on("error", () => {
|
|
29207
29208
|
});
|
|
29208
|
-
child.stdin.end(JSON.stringify({ path:
|
|
29209
|
+
child.stdin.end(JSON.stringify({ path: file3 }));
|
|
29209
29210
|
});
|
|
29210
29211
|
}
|
|
29211
29212
|
|
|
@@ -29545,11 +29546,11 @@ async function portalScreenshot(socket, uid, token, signal) {
|
|
|
29545
29546
|
signal.addEventListener("abort", abort, { once: true });
|
|
29546
29547
|
connection.on("error", fail7);
|
|
29547
29548
|
connection.on("close", () => fail7(Error("CLOSED")));
|
|
29548
|
-
const call = (destination,
|
|
29549
|
+
const call = (destination, path32, iface, member, signature = "", body = () => {
|
|
29549
29550
|
}) => new Promise((done, failed) => {
|
|
29550
29551
|
const payload2 = new Writer();
|
|
29551
29552
|
body(payload2);
|
|
29552
|
-
const header = new Writer(), fields = [[1, "o",
|
|
29553
|
+
const header = new Writer(), fields = [[1, "o", path32], [2, "s", iface], [3, "s", member], [6, "s", destination]];
|
|
29553
29554
|
if (signature) fields.push([8, "g", signature]);
|
|
29554
29555
|
header.byte(108);
|
|
29555
29556
|
header.byte(1);
|
|
@@ -29732,8 +29733,8 @@ function downscale(image, edge) {
|
|
|
29732
29733
|
sums[x * 3 + 2] = sums[x * 3 + 2] + image.rgb[i + 2];
|
|
29733
29734
|
}
|
|
29734
29735
|
for (let x = 0; x < width; x++) {
|
|
29735
|
-
const
|
|
29736
|
-
for (let c = 0; c < 3; c++) rgb[(y * width + x) * 3 + c] = Math.round(sums[x * 3 + c] /
|
|
29736
|
+
const count4 = (ys[y + 1] - ys[y]) * (xs[x + 1] - xs[x]);
|
|
29737
|
+
for (let c = 0; c < 3; c++) rgb[(y * width + x) * 3 + c] = Math.round(sums[x * 3 + c] / count4);
|
|
29737
29738
|
}
|
|
29738
29739
|
}
|
|
29739
29740
|
return { width, height, rgb };
|
|
@@ -30209,8 +30210,8 @@ var HUFFMAN = [
|
|
|
30209
30210
|
var CODES = HUFFMAN.map(([, counts, values]) => {
|
|
30210
30211
|
const table2 = [];
|
|
30211
30212
|
let code = 0, at = 0;
|
|
30212
|
-
counts.forEach((
|
|
30213
|
-
for (let i = 0; i <
|
|
30213
|
+
counts.forEach((count4, index) => {
|
|
30214
|
+
for (let i = 0; i < count4; i++) table2[values[at++]] = [code++, index + 1];
|
|
30214
30215
|
code <<= 1;
|
|
30215
30216
|
});
|
|
30216
30217
|
return table2;
|
|
@@ -30394,10 +30395,10 @@ function jpegSize(data) {
|
|
|
30394
30395
|
}
|
|
30395
30396
|
return null;
|
|
30396
30397
|
}
|
|
30397
|
-
function run(
|
|
30398
|
+
function run(file3, args, signal, maxBuffer = 65536, env = buildChildEnvironment(process.env, process.platform)) {
|
|
30398
30399
|
return new Promise((resolve, reject) => {
|
|
30399
30400
|
execFile4(
|
|
30400
|
-
|
|
30401
|
+
file3,
|
|
30401
30402
|
args,
|
|
30402
30403
|
{ encoding: "buffer", timeout: 15e3, maxBuffer, windowsHide: true, shell: false, env, signal },
|
|
30403
30404
|
(error62, stdout, stderr) => error62 ? reject(Object.assign(error62, { stdout, stderr })) : resolve({ stdout, stderr })
|
|
@@ -30469,10 +30470,10 @@ var SESSION_VALUE = /^[A-Za-z0-9_.:,;=@+/-]{1,256}$/;
|
|
|
30469
30470
|
var LINUX_SOURCE_BYTES = 150994944;
|
|
30470
30471
|
async function linuxTool(name2) {
|
|
30471
30472
|
for (const directory of ["/usr/bin", "/bin", "/usr/local/bin"]) {
|
|
30472
|
-
const
|
|
30473
|
+
const file3 = path17.posix.join(directory, name2);
|
|
30473
30474
|
try {
|
|
30474
|
-
await access3(
|
|
30475
|
-
return
|
|
30475
|
+
await access3(file3, constants7.X_OK);
|
|
30476
|
+
return file3;
|
|
30476
30477
|
} catch {
|
|
30477
30478
|
}
|
|
30478
30479
|
}
|
|
@@ -30517,8 +30518,8 @@ async function linuxSession(signal) {
|
|
|
30517
30518
|
}
|
|
30518
30519
|
}
|
|
30519
30520
|
if (session.DISPLAY && !session.XAUTHORITY) {
|
|
30520
|
-
const
|
|
30521
|
-
if ((await lstat7(
|
|
30521
|
+
const file3 = path17.posix.join(os4.homedir(), ".Xauthority");
|
|
30522
|
+
if ((await lstat7(file3).catch(() => null))?.isFile()) take("XAUTHORITY", file3);
|
|
30522
30523
|
}
|
|
30523
30524
|
if (session.XDG_RUNTIME_DIR) take("DBUS_SESSION_BUS_ADDRESS", "unix:path=" + session.XDG_RUNTIME_DIR + "/bus");
|
|
30524
30525
|
const wayland = !!session.WAYLAND_DISPLAY || session.XDG_SESSION_TYPE === "wayland";
|
|
@@ -30541,13 +30542,13 @@ async function portalCapture(socket, signal) {
|
|
|
30541
30542
|
const { code, uri } = answer;
|
|
30542
30543
|
if (code === 1) throw new ScreenCaptureError("SCREEN_RECORDING_PERMISSION_REQUIRED");
|
|
30543
30544
|
if (code !== 0 || !uri?.startsWith("file://")) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
|
|
30544
|
-
const
|
|
30545
|
+
const file3 = decodeURIComponent(new URL(uri).pathname), info = await lstat7(file3);
|
|
30545
30546
|
const fresh = info.isFile() && info.uid === uid && info.mtimeMs >= started - 5e3;
|
|
30546
30547
|
try {
|
|
30547
30548
|
if (!fresh || info.size > LINUX_SOURCE_BYTES) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
|
|
30548
|
-
return await readFile6(
|
|
30549
|
+
return await readFile6(file3);
|
|
30549
30550
|
} finally {
|
|
30550
|
-
if (fresh) await unlink2(
|
|
30551
|
+
if (fresh) await unlink2(file3).catch(() => {
|
|
30551
30552
|
});
|
|
30552
30553
|
}
|
|
30553
30554
|
}
|
|
@@ -30630,16 +30631,16 @@ function result(body) {
|
|
|
30630
30631
|
function stopped(signal) {
|
|
30631
30632
|
if (signal.aborted) fail3("CANCELLED");
|
|
30632
30633
|
}
|
|
30633
|
-
async function readBoundedFile(
|
|
30634
|
-
const stat2 = await lstat8(
|
|
30634
|
+
async function readBoundedFile(file3, maxBytes, bridge, signal) {
|
|
30635
|
+
const stat2 = await lstat8(file3);
|
|
30635
30636
|
if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > maxBytes) fail3("FILE_UNSUPPORTED_OR_TOO_LARGE");
|
|
30636
30637
|
if (process.platform === "win32") {
|
|
30637
|
-
if (maxBytes <= 1048576 || stat2.size <= 1048576) return readWindowsFile(bridge,
|
|
30638
|
-
const read = await readWindowsFilePrefix(bridge,
|
|
30638
|
+
if (maxBytes <= 1048576 || stat2.size <= 1048576) return readWindowsFile(bridge, file3, Math.min(maxBytes, 1048576), signal);
|
|
30639
|
+
const read = await readWindowsFilePrefix(bridge, file3, maxBytes, signal);
|
|
30639
30640
|
if (read.truncated) fail3("FILE_UNSUPPORTED_OR_TOO_LARGE");
|
|
30640
30641
|
return read.data;
|
|
30641
30642
|
}
|
|
30642
|
-
const handle = await open6(
|
|
30643
|
+
const handle = await open6(file3, constants8.O_RDONLY | (constants8.O_NOFOLLOW ?? 0));
|
|
30643
30644
|
try {
|
|
30644
30645
|
const current2 = await handle.stat();
|
|
30645
30646
|
if (!current2.isFile() || current2.size > maxBytes) fail3("FILE_UNSUPPORTED_OR_TOO_LARGE");
|
|
@@ -30695,9 +30696,9 @@ var NativeTools = class {
|
|
|
30695
30696
|
}
|
|
30696
30697
|
options;
|
|
30697
30698
|
memory;
|
|
30698
|
-
async readFile(
|
|
30699
|
+
async readFile(file3, maxBytes, signal) {
|
|
30699
30700
|
try {
|
|
30700
|
-
return await readBoundedFile(
|
|
30701
|
+
return await readBoundedFile(file3, maxBytes, this.options.ownerBridgePath ?? path18.join(path18.dirname(this.options.helperPath), "OwnerBridge.exe"), signal);
|
|
30701
30702
|
} catch (error62) {
|
|
30702
30703
|
if (error62.code === "ENOENT") throw error62;
|
|
30703
30704
|
if (error62 instanceof Error && /^[A-Z_]{1,40}$/.test(error62.message)) fail3(error62.message);
|
|
@@ -31080,16 +31081,16 @@ var NativeTools = class {
|
|
|
31080
31081
|
if (value) selectedHeaders[name2] = value.slice(0, 2048);
|
|
31081
31082
|
}
|
|
31082
31083
|
const reader = response.body?.getReader(), chunks = [];
|
|
31083
|
-
let
|
|
31084
|
+
let count4 = 0, truncated = false;
|
|
31084
31085
|
try {
|
|
31085
31086
|
if (reader) for (; ; ) {
|
|
31086
31087
|
const part = await reader.read();
|
|
31087
31088
|
if (part.done) break;
|
|
31088
31089
|
const b = Buffer.from(part.value);
|
|
31089
|
-
const take = Math.min(b.length, 1e5 -
|
|
31090
|
+
const take = Math.min(b.length, 1e5 - count4);
|
|
31090
31091
|
chunks.push(b.subarray(0, take));
|
|
31091
|
-
|
|
31092
|
-
if (take !== b.length ||
|
|
31092
|
+
count4 += take;
|
|
31093
|
+
if (take !== b.length || count4 >= 1e5) {
|
|
31093
31094
|
truncated = true;
|
|
31094
31095
|
break;
|
|
31095
31096
|
}
|
|
@@ -31131,8 +31132,8 @@ var NativeTools = class {
|
|
|
31131
31132
|
else if (call.name === "git_diff") {
|
|
31132
31133
|
argv = ["diff", "--no-ext-diff", "--no-textconv", ...call.args.staged ? ["--cached"] : []];
|
|
31133
31134
|
if (call.args.file) {
|
|
31134
|
-
const
|
|
31135
|
-
const relative = path18.relative(cwd,
|
|
31135
|
+
const file3 = await resolve(path18.resolve(cwd, call.args.file));
|
|
31136
|
+
const relative = path18.relative(cwd, file3);
|
|
31136
31137
|
if (relative.startsWith(".." + path18.sep) || relative === ".." || path18.isAbsolute(relative)) fail3("PATH_NOT_ALLOWED");
|
|
31137
31138
|
argv.push("--", relative);
|
|
31138
31139
|
} else argv.push("--stat");
|
|
@@ -31164,9 +31165,9 @@ var NativeTools = class {
|
|
|
31164
31165
|
}
|
|
31165
31166
|
const contextFile = async (relative, limit, optional2 = false) => {
|
|
31166
31167
|
try {
|
|
31167
|
-
const
|
|
31168
|
-
guard.assertSafeFile(
|
|
31169
|
-
return utf8(await this.readFile(
|
|
31168
|
+
const file3 = await guard.resolveExisting(path18.join(primary, relative));
|
|
31169
|
+
guard.assertSafeFile(file3);
|
|
31170
|
+
return utf8(await this.readFile(file3, limit, signal));
|
|
31170
31171
|
} catch (error62) {
|
|
31171
31172
|
if (optional2 && error62.code === "ENOENT") return null;
|
|
31172
31173
|
throw error62;
|
|
@@ -31643,11 +31644,11 @@ function parseNodeTapShadow(input2) {
|
|
|
31643
31644
|
return passThrough(input2, "unrecognized_record", true, notices);
|
|
31644
31645
|
}
|
|
31645
31646
|
if (line === "") continue;
|
|
31646
|
-
const
|
|
31647
|
-
if (
|
|
31648
|
-
const key =
|
|
31647
|
+
const count4 = SUMMARY_COUNT.exec(line);
|
|
31648
|
+
if (count4) {
|
|
31649
|
+
const key = count4[1];
|
|
31649
31650
|
if (counts.has(key)) return passThrough(input2, "summary_inconsistent", true, notices);
|
|
31650
|
-
counts.set(key, Number(
|
|
31651
|
+
counts.set(key, Number(count4[2]));
|
|
31651
31652
|
continue;
|
|
31652
31653
|
}
|
|
31653
31654
|
const summaryDuration = SUMMARY_DURATION.exec(line);
|
|
@@ -31761,11 +31762,11 @@ function parseNodeTapFailureShadow(input2) {
|
|
|
31761
31762
|
let durationMs = null;
|
|
31762
31763
|
for (const line of lines.slice(index + 1)) {
|
|
31763
31764
|
if (!line) continue;
|
|
31764
|
-
const
|
|
31765
|
-
if (
|
|
31766
|
-
const key =
|
|
31765
|
+
const count4 = SUMMARY_COUNT.exec(line);
|
|
31766
|
+
if (count4) {
|
|
31767
|
+
const key = count4[1];
|
|
31767
31768
|
if (counts.has(key)) return fallback("summary_inconsistent");
|
|
31768
|
-
counts.set(key, Number(
|
|
31769
|
+
counts.set(key, Number(count4[2]));
|
|
31769
31770
|
} else {
|
|
31770
31771
|
const duration3 = SUMMARY_DURATION.exec(line);
|
|
31771
31772
|
if (duration3) {
|
|
@@ -31859,7 +31860,7 @@ function shapeCommandResultForAgentDetailed(input2, result2) {
|
|
|
31859
31860
|
if (parsed.state !== "candidate" && result2.exitCode === 0 && !result2.stdoutTruncated && !result2.stderrTruncated && result2.stderr === "") {
|
|
31860
31861
|
const compact = compactJsonOutput(result2.stdout);
|
|
31861
31862
|
if (compact !== null) {
|
|
31862
|
-
const sent = bytes(compact),
|
|
31863
|
+
const sent = bytes(compact), saved2 = originalBytes - sent;
|
|
31863
31864
|
return Object.freeze({ result: Object.freeze({ ...result2, stdout: compact }), telemetry: Object.freeze({
|
|
31864
31865
|
parserId: "json-whitespace",
|
|
31865
31866
|
parserVersion: "1",
|
|
@@ -31868,8 +31869,8 @@ function shapeCommandResultForAgentDetailed(input2, result2) {
|
|
|
31868
31869
|
reason: "validated_compact",
|
|
31869
31870
|
originalStdoutBytes: originalBytes,
|
|
31870
31871
|
sentStdoutBytes: sent,
|
|
31871
|
-
savedStdoutBytes:
|
|
31872
|
-
reductionPercent: originalBytes === 0 ? 0 :
|
|
31872
|
+
savedStdoutBytes: saved2,
|
|
31873
|
+
reductionPercent: originalBytes === 0 ? 0 : saved2 / originalBytes * 100
|
|
31873
31874
|
}) });
|
|
31874
31875
|
}
|
|
31875
31876
|
}
|
|
@@ -36574,9 +36575,9 @@ var rev2026Codec = {
|
|
|
36574
36575
|
});
|
|
36575
36576
|
const parsed = buildSchemas2026().RequestMetaEnvelopeSchema.safeParse(meta3);
|
|
36576
36577
|
if (!parsed.success) for (const issue2 of parsed.error.issues) {
|
|
36577
|
-
const
|
|
36578
|
-
const key =
|
|
36579
|
-
if (
|
|
36578
|
+
const path32 = issue2.path.map(String);
|
|
36579
|
+
const key = path32.length > 0 ? path32.join(".") : "_meta";
|
|
36580
|
+
if (path32.length === 1 && issues.some((existing) => existing.key === key && existing.problem === "missing")) continue;
|
|
36580
36581
|
issues.push({
|
|
36581
36582
|
key,
|
|
36582
36583
|
problem: issue2.message
|
|
@@ -36878,29 +36879,29 @@ var PERMITTED_X_MCP_HEADER_TYPES = /* @__PURE__ */ new Set([
|
|
|
36878
36879
|
function scanXMcpHeaderDeclarations(inputSchema) {
|
|
36879
36880
|
const declarations = [];
|
|
36880
36881
|
const seenLower = /* @__PURE__ */ new Map();
|
|
36881
|
-
const visit2 = (node2,
|
|
36882
|
+
const visit2 = (node2, path32, reachable) => {
|
|
36882
36883
|
if (node2 === null || typeof node2 !== "object") return void 0;
|
|
36883
36884
|
const schema = node2;
|
|
36884
36885
|
if (X_MCP_HEADER_KEY in schema) {
|
|
36885
|
-
if (!reachable ||
|
|
36886
|
+
if (!reachable || path32.length === 0) return `${pathName(path32)}: 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)`;
|
|
36886
36887
|
const raw = schema[X_MCP_HEADER_KEY];
|
|
36887
|
-
if (typeof raw !== "string" || raw.length === 0) return `${pathName(
|
|
36888
|
-
if (!RFC9110_TOKEN.test(raw)) return `${pathName(
|
|
36888
|
+
if (typeof raw !== "string" || raw.length === 0) return `${pathName(path32)}: x-mcp-header MUST be a non-empty string`;
|
|
36889
|
+
if (!RFC9110_TOKEN.test(raw)) return `${pathName(path32)}: x-mcp-header '${raw}' is not a valid RFC 9110 token (no spaces, control characters or HTTP delimiters)`;
|
|
36889
36890
|
const type = typeof schema.type === "string" ? schema.type : void 0;
|
|
36890
|
-
if (type === void 0 || !PERMITTED_X_MCP_HEADER_TYPES.has(type)) return `${pathName(
|
|
36891
|
+
if (type === void 0 || !PERMITTED_X_MCP_HEADER_TYPES.has(type)) return `${pathName(path32)}: x-mcp-header is only permitted on primitive-typed properties (string, integer, boolean); got ${type ?? "<none>"}`;
|
|
36891
36892
|
const lower = raw.toLowerCase();
|
|
36892
36893
|
const prior = seenLower.get(lower);
|
|
36893
36894
|
if (prior !== void 0) return `x-mcp-header '${raw}' is not case-insensitively unique (also declared as '${prior}')`;
|
|
36894
36895
|
seenLower.set(lower, raw);
|
|
36895
36896
|
declarations.push({
|
|
36896
|
-
path:
|
|
36897
|
+
path: path32,
|
|
36897
36898
|
headerName: raw,
|
|
36898
36899
|
type
|
|
36899
36900
|
});
|
|
36900
36901
|
}
|
|
36901
36902
|
const properties = schema.properties;
|
|
36902
36903
|
if (properties !== null && typeof properties === "object") for (const [key, child] of Object.entries(properties)) {
|
|
36903
|
-
const fault$1 = visit2(child, [...
|
|
36904
|
+
const fault$1 = visit2(child, [...path32, key], reachable);
|
|
36904
36905
|
if (fault$1 !== void 0) return fault$1;
|
|
36905
36906
|
}
|
|
36906
36907
|
for (const k of NON_REACHABLE_SUBSCHEMA_KEYWORDS) {
|
|
@@ -36908,7 +36909,7 @@ function scanXMcpHeaderDeclarations(inputSchema) {
|
|
|
36908
36909
|
if (sub === void 0) continue;
|
|
36909
36910
|
const branches = Array.isArray(sub) ? sub : sub !== null && typeof sub === "object" && OBJECT_VALUED_SUBSCHEMA_KEYWORDS.has(k) ? Object.values(sub) : [sub];
|
|
36910
36911
|
for (const branch of branches) {
|
|
36911
|
-
const fault$1 = visit2(branch, [...
|
|
36912
|
+
const fault$1 = visit2(branch, [...path32, `<${k}>`], false);
|
|
36912
36913
|
if (fault$1 !== void 0) return fault$1;
|
|
36913
36914
|
}
|
|
36914
36915
|
}
|
|
@@ -36948,8 +36949,8 @@ var OBJECT_VALUED_SUBSCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
36948
36949
|
"$defs",
|
|
36949
36950
|
"definitions"
|
|
36950
36951
|
]);
|
|
36951
|
-
function pathName(
|
|
36952
|
-
return
|
|
36952
|
+
function pathName(path32) {
|
|
36953
|
+
return path32.length === 0 ? "<root>" : path32.join(".");
|
|
36953
36954
|
}
|
|
36954
36955
|
var HEADER_MISMATCH_ERROR_CODE = -32020;
|
|
36955
36956
|
var INBOUND_VALIDATION_LADDER = [
|
|
@@ -37199,7 +37200,7 @@ var PROPERTY_KEYS_BY_TYPE = {
|
|
|
37199
37200
|
array: shapeKeys([UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema])
|
|
37200
37201
|
};
|
|
37201
37202
|
var SUPPORTED_STRING_FORMATS = new Set(StringSchemaSchema.shape.format.unwrap().options);
|
|
37202
|
-
function walkProperty(node2,
|
|
37203
|
+
function walkProperty(node2, path32, vendor, unsupported) {
|
|
37203
37204
|
if (!isJsonObject(node2)) return node2;
|
|
37204
37205
|
const allowedKeys = typeof node2.type === "string" && Object.hasOwn(PROPERTY_KEYS_BY_TYPE, node2.type) ? PROPERTY_KEYS_BY_TYPE[node2.type] : void 0;
|
|
37205
37206
|
if (allowedKeys === void 0) return node2;
|
|
@@ -37207,8 +37208,8 @@ function walkProperty(node2, path30, vendor, unsupported) {
|
|
|
37207
37208
|
for (const [key, value] of Object.entries(node2)) if (allowedKeys.has(key) || isAnnotationOnlyJsonSchemaKeyword(key)) pruned[key] = value;
|
|
37208
37209
|
else if (key === "pattern" && node2.type === "string" && typeof node2.format === "string") {
|
|
37209
37210
|
if (!SUPPORTED_STRING_FORMATS.has(node2.format)) pruned[key] = value;
|
|
37210
|
-
else if (typeof value !== "string" || !isLibraryFormatPattern(node2.format, value, vendor)) unsupported.push(`${
|
|
37211
|
-
} else unsupported.push(`${
|
|
37211
|
+
else if (typeof value !== "string" || !isLibraryFormatPattern(node2.format, value, vendor)) unsupported.push(`${path32}.${key}`);
|
|
37212
|
+
} else unsupported.push(`${path32}.${key}`);
|
|
37212
37213
|
return pruned;
|
|
37213
37214
|
}
|
|
37214
37215
|
function walkRequestedSchema(converted, vendor) {
|
|
@@ -37225,11 +37226,11 @@ function describeUnsupportedProperties(pruned, fallback) {
|
|
|
37225
37226
|
const offenders = Object.entries(pruned.properties).filter(([, node2]) => !parseSchema(PrimitiveSchemaDefinitionSchema, node2).success).map(([name2]) => `properties.${name2}`);
|
|
37226
37227
|
return offenders.length > 0 ? offenders.join(", ") : fallback;
|
|
37227
37228
|
}
|
|
37228
|
-
function findDroppedConstraintPaths(original, parsed,
|
|
37229
|
-
if (Array.isArray(original) && Array.isArray(parsed)) return original.flatMap((item, index) => findDroppedConstraintPaths(item, parsed[index], `${
|
|
37229
|
+
function findDroppedConstraintPaths(original, parsed, path32 = "") {
|
|
37230
|
+
if (Array.isArray(original) && Array.isArray(parsed)) return original.flatMap((item, index) => findDroppedConstraintPaths(item, parsed[index], `${path32}[${index}]`));
|
|
37230
37231
|
if (!isJsonObject(original) || !isJsonObject(parsed)) return [];
|
|
37231
37232
|
return Object.entries(original).flatMap(([key, value]) => {
|
|
37232
|
-
const childPath =
|
|
37233
|
+
const childPath = path32 ? `${path32}.${key}` : key;
|
|
37233
37234
|
if (!Object.prototype.hasOwnProperty.call(parsed, key)) return isAnnotationOnlyJsonSchemaKeyword(key) ? [] : [childPath];
|
|
37234
37235
|
return findDroppedConstraintPaths(value, parsed[key], childPath);
|
|
37235
37236
|
});
|
|
@@ -40459,15 +40460,15 @@ var require_resolve = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
40459
40460
|
return false;
|
|
40460
40461
|
}
|
|
40461
40462
|
function countKeys(schema) {
|
|
40462
|
-
let
|
|
40463
|
+
let count4 = 0;
|
|
40463
40464
|
for (const key in schema) {
|
|
40464
40465
|
if (key === "$ref") return Infinity;
|
|
40465
|
-
|
|
40466
|
+
count4++;
|
|
40466
40467
|
if (SIMPLE_INLINED.has(key)) continue;
|
|
40467
|
-
if (typeof schema[key] == "object") (0, util_1.eachItem)(schema[key], (sch) =>
|
|
40468
|
-
if (
|
|
40468
|
+
if (typeof schema[key] == "object") (0, util_1.eachItem)(schema[key], (sch) => count4 += countKeys(sch));
|
|
40469
|
+
if (count4 === Infinity) return Infinity;
|
|
40469
40470
|
}
|
|
40470
|
-
return
|
|
40471
|
+
return count4;
|
|
40471
40472
|
}
|
|
40472
40473
|
function getFullPath(resolver, id2 = "", normalize) {
|
|
40473
40474
|
if (normalize !== false) id2 = normalizeId(id2);
|
|
@@ -41305,8 +41306,8 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
41305
41306
|
for (let i = 0; i < str.length; i++) if (str[i] === token) ind++;
|
|
41306
41307
|
return ind;
|
|
41307
41308
|
}
|
|
41308
|
-
function removeDotSegments(
|
|
41309
|
-
let input2 =
|
|
41309
|
+
function removeDotSegments(path32) {
|
|
41310
|
+
let input2 = path32;
|
|
41310
41311
|
const output2 = [];
|
|
41311
41312
|
let nextSlash = -1;
|
|
41312
41313
|
let len = 0;
|
|
@@ -41459,8 +41460,8 @@ var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
41459
41460
|
wsComponent.secure = void 0;
|
|
41460
41461
|
}
|
|
41461
41462
|
if (wsComponent.resourceName) {
|
|
41462
|
-
const [
|
|
41463
|
-
wsComponent.path =
|
|
41463
|
+
const [path32, query] = wsComponent.resourceName.split("?");
|
|
41464
|
+
wsComponent.path = path32 && path32 !== "/" ? path32 : void 0;
|
|
41464
41465
|
wsComponent.query = query;
|
|
41465
41466
|
wsComponent.resourceName = void 0;
|
|
41466
41467
|
}
|
|
@@ -43067,8 +43068,8 @@ var require_contains = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
43067
43068
|
cxt.result(valid, () => cxt.reset());
|
|
43068
43069
|
function validateItemsWithCount() {
|
|
43069
43070
|
const schValid = gen.name("_valid");
|
|
43070
|
-
const
|
|
43071
|
-
validateItems(schValid, () => gen.if(schValid, () => checkLimits(
|
|
43071
|
+
const count4 = gen.let("count", 0);
|
|
43072
|
+
validateItems(schValid, () => gen.if(schValid, () => checkLimits(count4)));
|
|
43072
43073
|
}
|
|
43073
43074
|
function validateItems(_valid, block) {
|
|
43074
43075
|
gen.forRange("i", 0, len, (i) => {
|
|
@@ -43081,13 +43082,13 @@ var require_contains = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
43081
43082
|
block();
|
|
43082
43083
|
});
|
|
43083
43084
|
}
|
|
43084
|
-
function checkLimits(
|
|
43085
|
-
gen.code((0, codegen_1._)`${
|
|
43086
|
-
if (max === void 0) gen.if((0, codegen_1._)`${
|
|
43085
|
+
function checkLimits(count4) {
|
|
43086
|
+
gen.code((0, codegen_1._)`${count4}++`);
|
|
43087
|
+
if (max === void 0) gen.if((0, codegen_1._)`${count4} >= ${min}`, () => gen.assign(valid, true).break());
|
|
43087
43088
|
else {
|
|
43088
|
-
gen.if((0, codegen_1._)`${
|
|
43089
|
+
gen.if((0, codegen_1._)`${count4} > ${max}`, () => gen.assign(valid, false).break());
|
|
43089
43090
|
if (min === 1) gen.assign(valid, true);
|
|
43090
|
-
else gen.if((0, codegen_1._)`${
|
|
43091
|
+
else gen.if((0, codegen_1._)`${count4} >= ${min}`, () => gen.assign(valid, true));
|
|
43091
43092
|
}
|
|
43092
43093
|
}
|
|
43093
43094
|
}
|
|
@@ -47262,6 +47263,42 @@ var NativeIncidentProducer = class {
|
|
|
47262
47263
|
}
|
|
47263
47264
|
};
|
|
47264
47265
|
|
|
47266
|
+
// packages/contracts/src/token-usage-protocol.ts
|
|
47267
|
+
var TOKEN_USAGE_CAPABILITY = "tokenUsageV1";
|
|
47268
|
+
var uuid20 = external_exports.string().uuid().toLowerCase();
|
|
47269
|
+
var epoch3 = external_exports.string().refine((v) => /^[1-9]\d{0,18}$/.test(v) && BigInt(v) <= 9223372036854775807n);
|
|
47270
|
+
var tokens = external_exports.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
|
|
47271
|
+
var TokenUsageClientSchema = external_exports.enum(["claude-code", "codex"]);
|
|
47272
|
+
var TOKEN_USAGE_MODEL = /^[A-Za-z0-9][A-Za-z0-9._:/@+-]{0,79}$/;
|
|
47273
|
+
var TokenUsageRowSchema = external_exports.object({
|
|
47274
|
+
day: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine((v) => Number.isFinite(Date.parse(v + "T00:00:00Z"))),
|
|
47275
|
+
client: TokenUsageClientSchema,
|
|
47276
|
+
model: external_exports.string().regex(TOKEN_USAGE_MODEL),
|
|
47277
|
+
requests: tokens,
|
|
47278
|
+
inputTokens: tokens,
|
|
47279
|
+
cachedInputTokens: tokens,
|
|
47280
|
+
cacheWriteTokens: tokens,
|
|
47281
|
+
outputTokens: tokens,
|
|
47282
|
+
reasoningTokens: tokens.nullable()
|
|
47283
|
+
}).strict().refine((row) => row.cachedInputTokens + row.cacheWriteTokens <= row.inputTokens && (row.reasoningTokens === null || row.reasoningTokens <= row.outputTokens), "Subset exceeds total");
|
|
47284
|
+
var TokenUsageBatchSchema = external_exports.object({
|
|
47285
|
+
type: external_exports.literal("tokenUsageBatch"),
|
|
47286
|
+
protocolVersion: external_exports.literal(1),
|
|
47287
|
+
batchId: uuid20,
|
|
47288
|
+
connectionEpoch: epoch3,
|
|
47289
|
+
/** Random per agent state; a new state counts only usage after it started, so states never overlap. */
|
|
47290
|
+
stateId: uuid20,
|
|
47291
|
+
rows: external_exports.array(TokenUsageRowSchema).min(1).max(64)
|
|
47292
|
+
}).strict().refine((batch) => new Set(batch.rows.map((r) => `${r.day}|${r.client}|${r.model}`)).size === batch.rows.length, "Duplicate rows");
|
|
47293
|
+
var TokenUsageBatchResultSchema = external_exports.enum(["accepted", "invalid", "stale", "disabled", "retry", "busy"]);
|
|
47294
|
+
var TokenUsageBatchAckSchema = external_exports.object({
|
|
47295
|
+
type: external_exports.literal("tokenUsageBatchAck"),
|
|
47296
|
+
protocolVersion: external_exports.literal(1),
|
|
47297
|
+
batchId: uuid20.optional(),
|
|
47298
|
+
result: TokenUsageBatchResultSchema
|
|
47299
|
+
}).strict();
|
|
47300
|
+
var TokenUsageStateSchema = external_exports.object({ type: external_exports.literal("tokenUsageState"), protocolVersion: external_exports.literal(1), connectionEpoch: epoch3, enabled: external_exports.boolean() }).strict();
|
|
47301
|
+
|
|
47265
47302
|
// agent/src/relay-client.ts
|
|
47266
47303
|
var RelayClientError = class extends Error {
|
|
47267
47304
|
constructor(code) {
|
|
@@ -47297,7 +47334,7 @@ function relayUrlFromEnrollment(enrollment) {
|
|
|
47297
47334
|
url2.pathname = "/api/agent/relay";
|
|
47298
47335
|
return url2.toString();
|
|
47299
47336
|
}
|
|
47300
|
-
function
|
|
47337
|
+
function uuid21(value, code) {
|
|
47301
47338
|
if (typeof value !== "string" || !UUID2.test(value)) fail5(code);
|
|
47302
47339
|
return value.toLowerCase();
|
|
47303
47340
|
}
|
|
@@ -47305,7 +47342,7 @@ function protocol(value, expected) {
|
|
|
47305
47342
|
if (value !== expected) fail5("RELAY_PROTOCOL_INVALID");
|
|
47306
47343
|
return expected;
|
|
47307
47344
|
}
|
|
47308
|
-
function
|
|
47345
|
+
function epoch4(value) {
|
|
47309
47346
|
if (typeof value !== "string" || !EPOCH.test(value) || BigInt(value) > 9223372036854775807n) fail5("RELAY_EPOCH_INVALID");
|
|
47310
47347
|
return value;
|
|
47311
47348
|
}
|
|
@@ -47427,11 +47464,11 @@ function sendJson(socket, value, maxBytes) {
|
|
|
47427
47464
|
function validateChallenge(frame, expectedProtocol) {
|
|
47428
47465
|
if (frame.type !== "challenge") fail5("RELAY_HANDSHAKE_INVALID");
|
|
47429
47466
|
protocol(frame.protocolVersion, expectedProtocol);
|
|
47430
|
-
|
|
47467
|
+
uuid21(frame.gatewayId, "RELAY_HANDSHAKE_INVALID");
|
|
47431
47468
|
if (typeof frame.nonce !== "string" || frame.nonce.length < 32 || frame.nonce.length > 512 || /[\u0000-\u001f\u007f]/u.test(frame.nonce)) fail5("RELAY_HANDSHAKE_INVALID");
|
|
47432
47469
|
if (typeof frame.expiresAt !== "string" || !Number.isFinite(Date.parse(frame.expiresAt)) || Date.parse(frame.expiresAt) <= Date.now()) fail5("RELAY_HANDSHAKE_INVALID");
|
|
47433
47470
|
return {
|
|
47434
|
-
challengeId:
|
|
47471
|
+
challengeId: uuid21(frame.challengeId, "RELAY_HANDSHAKE_INVALID"),
|
|
47435
47472
|
nonce: frame.nonce,
|
|
47436
47473
|
// Older servers offer no capabilities and verify only the v1 proof.
|
|
47437
47474
|
machineIdentity: Array.isArray(frame.capabilities) && frame.capabilities.includes(MACHINE_IDENTITY_CAPABILITY)
|
|
@@ -47440,27 +47477,27 @@ function validateChallenge(frame, expectedProtocol) {
|
|
|
47440
47477
|
function validateReady(frame, enrollment, expectedProtocol) {
|
|
47441
47478
|
if (frame.type !== "connected") fail5("RELAY_HANDSHAKE_INVALID");
|
|
47442
47479
|
protocol(frame.protocolVersion, expectedProtocol);
|
|
47443
|
-
if (
|
|
47444
|
-
if (
|
|
47480
|
+
if (uuid21(frame.tenantId, "RELAY_HANDSHAKE_INVALID") !== enrollment.tenantId.toLowerCase()) fail5("RELAY_ID_MISMATCH");
|
|
47481
|
+
if (uuid21(frame.deviceId, "RELAY_HANDSHAKE_INVALID") !== enrollment.deviceId.toLowerCase()) fail5("RELAY_ID_MISMATCH");
|
|
47445
47482
|
const terminalMetrics2 = Array.isArray(frame.capabilities) && frame.capabilities.includes(TERMINAL_METRICS_CAPABILITY);
|
|
47446
|
-
return { connectionEpoch:
|
|
47483
|
+
return { connectionEpoch: epoch4(frame.connectionEpoch), terminalMetrics: terminalMetrics2 };
|
|
47447
47484
|
}
|
|
47448
47485
|
function validateRequest(frame, enrollment, expectedProtocol, connectionEpoch) {
|
|
47449
47486
|
if (frame.type !== "relayFrame") fail5("RELAY_REQUEST_INVALID");
|
|
47450
47487
|
protocol(frame.protocolVersion, expectedProtocol);
|
|
47451
|
-
const tenantId =
|
|
47452
|
-
const deviceId =
|
|
47488
|
+
const tenantId = uuid21(frame.tenantId, "RELAY_REQUEST_INVALID");
|
|
47489
|
+
const deviceId = uuid21(frame.deviceId, "RELAY_REQUEST_INVALID");
|
|
47453
47490
|
if (tenantId !== enrollment.tenantId.toLowerCase() || deviceId !== enrollment.deviceId.toLowerCase()) fail5("RELAY_ID_MISMATCH");
|
|
47454
|
-
if (
|
|
47491
|
+
if (epoch4(frame.connectionEpoch) !== connectionEpoch) fail5("RELAY_EPOCH_MISMATCH");
|
|
47455
47492
|
const kind = frame.kind;
|
|
47456
47493
|
if (typeof kind !== "string" || !REQUEST_KINDS.has(kind)) fail5("RELAY_REQUEST_INVALID");
|
|
47457
47494
|
return {
|
|
47458
|
-
requestId:
|
|
47495
|
+
requestId: uuid21(frame.requestId, "RELAY_REQUEST_INVALID"),
|
|
47459
47496
|
tenantId,
|
|
47460
47497
|
deviceId,
|
|
47461
47498
|
connectionEpoch,
|
|
47462
|
-
operationId:
|
|
47463
|
-
executionId:
|
|
47499
|
+
operationId: uuid21(frame.operationId, "RELAY_REQUEST_INVALID"),
|
|
47500
|
+
executionId: uuid21(frame.executionId, "RELAY_REQUEST_INVALID"),
|
|
47464
47501
|
kind,
|
|
47465
47502
|
payload: frame.payload,
|
|
47466
47503
|
deadlineAt: isoDate(frame.deadlineAt),
|
|
@@ -47502,8 +47539,8 @@ async function connectOnce(options) {
|
|
|
47502
47539
|
const identity = await options.store.load();
|
|
47503
47540
|
if (!identity || !identity.enrollment) fail5("ENROLLMENT_MISSING");
|
|
47504
47541
|
const enrollment = identity.enrollment;
|
|
47505
|
-
const tenantId =
|
|
47506
|
-
const deviceId =
|
|
47542
|
+
const tenantId = uuid21(enrollment.tenantId, "ENROLLMENT_INVALID");
|
|
47543
|
+
const deviceId = uuid21(enrollment.deviceId, "ENROLLMENT_INVALID");
|
|
47507
47544
|
const url2 = relayUrlFromEnrollment(enrollment);
|
|
47508
47545
|
const socket = new wrapper_default(url2, [], {
|
|
47509
47546
|
followRedirects: false,
|
|
@@ -47521,7 +47558,9 @@ async function connectOnce(options) {
|
|
|
47521
47558
|
deviceId,
|
|
47522
47559
|
guardIdentity: true,
|
|
47523
47560
|
...options.aiConnectivity ? { aiConnectivity: true } : {},
|
|
47524
|
-
...options.onHeldLeases ? { heldLeases: true } : {}
|
|
47561
|
+
...options.onHeldLeases ? { heldLeases: true } : {},
|
|
47562
|
+
...options.onFullLogChoice ? { fullLogNotice: true } : {},
|
|
47563
|
+
...options.onTokenUsageState ? { tokenUsage: true } : {}
|
|
47525
47564
|
}, maxFrameBytes);
|
|
47526
47565
|
const challenge = validateChallenge(await waitForMessage(socket, maxFrameBytes, connectTimeoutMs, "RELAY_HANDSHAKE_TIMEOUT"), protocolVersion2);
|
|
47527
47566
|
const machine = challenge.machineIdentity ? options.machineIdentity?.(deviceId) ?? null : null;
|
|
@@ -47548,6 +47587,7 @@ async function connectOnce(options) {
|
|
|
47548
47587
|
const { connectionEpoch, terminalMetrics: terminalMetrics2 } = validateReady(readyFrame, enrollment, protocolVersion2);
|
|
47549
47588
|
const rejectionResults = Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes(REJECTION_RESULT_CAPABILITY);
|
|
47550
47589
|
const incidents = Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes("incidentBatchV1");
|
|
47590
|
+
const tokenUsage = !!options.onTokenUsageState && Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes(TOKEN_USAGE_CAPABILITY);
|
|
47551
47591
|
const monitorHeartbeat = Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes("monitorHeartbeatV1") && typeof readyFrame.heartbeatMs === "number" && Number.isInteger(readyFrame.heartbeatMs) && readyFrame.heartbeatMs >= 1e3 && readyFrame.heartbeatMs <= 6e4 ? readyFrame.heartbeatMs : void 0;
|
|
47552
47592
|
const nativeStatus = Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes(NATIVE_STATUS_CAPABILITY) && options.status;
|
|
47553
47593
|
const accessModes = Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes(WORKSPACE_ACCESS_MODE_CAPABILITY);
|
|
@@ -47624,6 +47664,37 @@ async function connectOnce(options) {
|
|
|
47624
47664
|
void (async () => {
|
|
47625
47665
|
try {
|
|
47626
47666
|
const frame = parseFrame(data, maxFrameBytes);
|
|
47667
|
+
if (frame.type === "fullLogState") {
|
|
47668
|
+
const state = FullLogStateSchema.safeParse(frame);
|
|
47669
|
+
if (state.success && state.data.connectionEpoch === connectionEpoch) {
|
|
47670
|
+
try {
|
|
47671
|
+
void Promise.resolve(options.onFullLogChoice?.(state.data.enabled)).catch(() => {
|
|
47672
|
+
});
|
|
47673
|
+
} catch {
|
|
47674
|
+
}
|
|
47675
|
+
}
|
|
47676
|
+
return;
|
|
47677
|
+
}
|
|
47678
|
+
if (frame.type === "tokenUsageState") {
|
|
47679
|
+
const state = TokenUsageStateSchema.safeParse(frame);
|
|
47680
|
+
if (tokenUsage && state.success && state.data.connectionEpoch === connectionEpoch) {
|
|
47681
|
+
try {
|
|
47682
|
+
options.onTokenUsageState?.(state.data.enabled);
|
|
47683
|
+
} catch {
|
|
47684
|
+
}
|
|
47685
|
+
}
|
|
47686
|
+
return;
|
|
47687
|
+
}
|
|
47688
|
+
if (frame.type === "tokenUsageBatchAck") {
|
|
47689
|
+
const ack = TokenUsageBatchAckSchema.safeParse(frame);
|
|
47690
|
+
if (tokenUsage && ack.success) {
|
|
47691
|
+
try {
|
|
47692
|
+
options.onTokenUsageAck?.(ack.data.batchId, ack.data.result);
|
|
47693
|
+
} catch {
|
|
47694
|
+
}
|
|
47695
|
+
}
|
|
47696
|
+
return;
|
|
47697
|
+
}
|
|
47627
47698
|
if (frame.type === "aiConnectivityRevoked") {
|
|
47628
47699
|
if (connectivity && frame.protocolVersion === 1 && frame.connectionEpoch === connectionEpoch) notifyConnectivityRevoked();
|
|
47629
47700
|
return;
|
|
@@ -47754,6 +47825,15 @@ async function connectOnce(options) {
|
|
|
47754
47825
|
return false;
|
|
47755
47826
|
}
|
|
47756
47827
|
} } : {},
|
|
47828
|
+
...tokenUsage ? { sendTokenUsageBatch: (batch) => {
|
|
47829
|
+
try {
|
|
47830
|
+
if (socket.readyState !== wrapper_default.OPEN) return false;
|
|
47831
|
+
sendJson(socket, TokenUsageBatchSchema.parse({ type: "tokenUsageBatch", protocolVersion: 1, batchId: batch.batchId, connectionEpoch, stateId: batch.stateId, rows: batch.rows }), Math.min(maxFrameBytes, 32768));
|
|
47832
|
+
return true;
|
|
47833
|
+
} catch {
|
|
47834
|
+
return false;
|
|
47835
|
+
}
|
|
47836
|
+
} } : {},
|
|
47757
47837
|
sendTerminal: (binding2, state, resultCode, metrics) => {
|
|
47758
47838
|
if (state === "rejected" && !rejectionResults) return Promise.reject(new RelayClientError("RELAY_RESULT_UNSUPPORTED"));
|
|
47759
47839
|
if (pendingTerminal.size >= 64) return Promise.reject(new RelayClientError("RELAY_PENDING_LIMIT"));
|
|
@@ -47972,10 +48052,10 @@ function canonicalOrigin2(value) {
|
|
|
47972
48052
|
fail6("ORIGIN_INVALID");
|
|
47973
48053
|
}
|
|
47974
48054
|
}
|
|
47975
|
-
function endpoint(origin,
|
|
47976
|
-
return origin +
|
|
48055
|
+
function endpoint(origin, path32) {
|
|
48056
|
+
return origin + path32;
|
|
47977
48057
|
}
|
|
47978
|
-
function
|
|
48058
|
+
function uuid22(value, code) {
|
|
47979
48059
|
if (typeof value !== "string" || !UUID3.test(value)) fail6(code);
|
|
47980
48060
|
return value.toLowerCase();
|
|
47981
48061
|
}
|
|
@@ -48095,7 +48175,7 @@ var PairingClient = class {
|
|
|
48095
48175
|
publicKey: identity.publicKeyPem,
|
|
48096
48176
|
agentVersion: this.version
|
|
48097
48177
|
}));
|
|
48098
|
-
const pairingId =
|
|
48178
|
+
const pairingId = uuid22(response.pairingId, "PAIRING_RESPONSE_INVALID");
|
|
48099
48179
|
const expiresAt = parseDate(response.expiresAt, "PAIRING_RESPONSE_INVALID");
|
|
48100
48180
|
const now = this.nowMs();
|
|
48101
48181
|
if (expiresAt.getTime() <= now || expiresAt.getTime() - now > 30 * 6e4) fail6("PAIRING_RESPONSE_INVALID");
|
|
@@ -48129,7 +48209,7 @@ var PairingClient = class {
|
|
|
48129
48209
|
}
|
|
48130
48210
|
async completeOnce(beginResult, approved, displayNameValue) {
|
|
48131
48211
|
const pairing = this.validateBeginResult(beginResult);
|
|
48132
|
-
const tenantId =
|
|
48212
|
+
const tenantId = uuid22(approved.tenantId, "PAIRING_RESPONSE_INVALID");
|
|
48133
48213
|
const email3 = accountEmail(approved.accountEmail);
|
|
48134
48214
|
const name2 = displayName(displayNameValue);
|
|
48135
48215
|
const identity = await this.currentIdentity();
|
|
@@ -48143,15 +48223,15 @@ var PairingClient = class {
|
|
|
48143
48223
|
displayName: name2,
|
|
48144
48224
|
agentVersion: this.version
|
|
48145
48225
|
}));
|
|
48146
|
-
const completedTenant =
|
|
48226
|
+
const completedTenant = uuid22(response.tenantId, "PAIRING_RESPONSE_INVALID");
|
|
48147
48227
|
if (completedTenant !== tenantId) fail6("PAIRING_RESPONSE_INVALID");
|
|
48148
|
-
const deviceId =
|
|
48228
|
+
const deviceId = uuid22(response.deviceId, "PAIRING_RESPONSE_INVALID");
|
|
48149
48229
|
const enrollment = {
|
|
48150
48230
|
tenantId,
|
|
48151
48231
|
deviceId,
|
|
48152
48232
|
serverOrigin: this.origin,
|
|
48153
48233
|
accountEmail: email3,
|
|
48154
|
-
...response.accountId !== void 0 ? { accountId:
|
|
48234
|
+
...response.accountId !== void 0 ? { accountId: uuid22(response.accountId, "PAIRING_RESPONSE_INVALID") } : {}
|
|
48155
48235
|
};
|
|
48156
48236
|
await this.store.saveEnrollment(enrollment);
|
|
48157
48237
|
return { ...enrollment };
|
|
@@ -48165,7 +48245,7 @@ var PairingClient = class {
|
|
|
48165
48245
|
state: response.state,
|
|
48166
48246
|
expiresAt: parseDate(response.expiresAt, "PAIRING_RESPONSE_INVALID")
|
|
48167
48247
|
};
|
|
48168
|
-
if (response.tenantId !== void 0) result2.tenantId =
|
|
48248
|
+
if (response.tenantId !== void 0) result2.tenantId = uuid22(response.tenantId, "PAIRING_RESPONSE_INVALID");
|
|
48169
48249
|
if (response.accountEmail !== void 0) result2.accountEmail = accountEmail(response.accountEmail);
|
|
48170
48250
|
return result2;
|
|
48171
48251
|
}
|
|
@@ -48177,10 +48257,10 @@ var PairingClient = class {
|
|
|
48177
48257
|
}
|
|
48178
48258
|
validateBeginResult(value) {
|
|
48179
48259
|
return {
|
|
48180
|
-
pairingId:
|
|
48260
|
+
pairingId: uuid22(value.pairingId, "PAIRING_INVALID"),
|
|
48181
48261
|
pairingSecret: pairingSecret(value.pairingSecret),
|
|
48182
48262
|
confirmationCode: confirmationCode(value.confirmationCode),
|
|
48183
|
-
approvalUrl: approvalUrl(value.approvalUrl, this.origin,
|
|
48263
|
+
approvalUrl: approvalUrl(value.approvalUrl, this.origin, uuid22(value.pairingId, "PAIRING_INVALID")),
|
|
48184
48264
|
expiresAt: value.expiresAt instanceof Date ? new Date(value.expiresAt.getTime()) : parseDate(value.expiresAt, "PAIRING_INVALID"),
|
|
48185
48265
|
keyFingerprint: fingerprint2(value.keyFingerprint)
|
|
48186
48266
|
};
|
|
@@ -48711,9 +48791,9 @@ function commandSummary2(tool) {
|
|
|
48711
48791
|
return { name: name2, command };
|
|
48712
48792
|
}
|
|
48713
48793
|
var ProductionMonitor = class {
|
|
48714
|
-
constructor(directory,
|
|
48794
|
+
constructor(directory, stateDirectory2, agentVersion3) {
|
|
48715
48795
|
this.agentVersion = agentVersion3;
|
|
48716
|
-
const key = createHash17("sha256").update(path23.resolve(
|
|
48796
|
+
const key = createHash17("sha256").update(path23.resolve(stateDirectory2).toLowerCase()).digest("hex");
|
|
48717
48797
|
this.file = path23.join(directory, key + ".json");
|
|
48718
48798
|
this.transportFile = path23.join(directory, key + ".transport");
|
|
48719
48799
|
}
|
|
@@ -48940,12 +49020,12 @@ var ProductionMonitor = class {
|
|
|
48940
49020
|
});
|
|
48941
49021
|
return this.writing;
|
|
48942
49022
|
}
|
|
48943
|
-
async write(
|
|
48944
|
-
const directory = path23.dirname(
|
|
49023
|
+
async write(file3, contents) {
|
|
49024
|
+
const directory = path23.dirname(file3);
|
|
48945
49025
|
await mkdir9(directory, { recursive: true, mode: 448 });
|
|
48946
49026
|
const stat2 = await lstat10(directory);
|
|
48947
49027
|
if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw Error("MONITOR_DIRECTORY_INVALID");
|
|
48948
|
-
const temporary =
|
|
49028
|
+
const temporary = file3 + "." + this.instanceId + ".tmp";
|
|
48949
49029
|
const handle = await open9(temporary, "wx", 384);
|
|
48950
49030
|
try {
|
|
48951
49031
|
try {
|
|
@@ -48953,7 +49033,7 @@ var ProductionMonitor = class {
|
|
|
48953
49033
|
} finally {
|
|
48954
49034
|
await handle.close();
|
|
48955
49035
|
}
|
|
48956
|
-
await rename6(temporary,
|
|
49036
|
+
await rename6(temporary, file3);
|
|
48957
49037
|
} finally {
|
|
48958
49038
|
await rm8(temporary, { force: true });
|
|
48959
49039
|
}
|
|
@@ -48965,6 +49045,444 @@ var ProductionMonitor = class {
|
|
|
48965
49045
|
}
|
|
48966
49046
|
};
|
|
48967
49047
|
|
|
49048
|
+
// agent/src/full-log-notice.ts
|
|
49049
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
49050
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
49051
|
+
import { lstat as lstat11, mkdir as mkdir10, readFile as readFile10, rename as rename7, rm as rm9, writeFile as writeFile4 } from "node:fs/promises";
|
|
49052
|
+
import path24 from "node:path";
|
|
49053
|
+
import { promisify as promisify3 } from "node:util";
|
|
49054
|
+
var exec3 = promisify3(execFile5);
|
|
49055
|
+
var manageUrl = "https://localcmd.app";
|
|
49056
|
+
var noticeDirectory = (directory) => path24.join(directory, "optimization");
|
|
49057
|
+
var file2 = (directory) => path24.join(noticeDirectory(directory), "full-log-notice.json");
|
|
49058
|
+
async function saved(directory, enrollment) {
|
|
49059
|
+
if (!enrollment) return null;
|
|
49060
|
+
try {
|
|
49061
|
+
const parent = await lstat11(noticeDirectory(directory));
|
|
49062
|
+
if (!parent.isDirectory() || parent.isSymbolicLink()) return null;
|
|
49063
|
+
const info = await lstat11(file2(directory));
|
|
49064
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > 4096) return null;
|
|
49065
|
+
const value = JSON.parse(await readFile10(file2(directory), "utf8"));
|
|
49066
|
+
if (value.tenantId !== enrollment.tenantId || value.deviceId !== enrollment.deviceId || !(value.enabled === null || typeof value.enabled === "boolean") || !(value.lastNotified === null || typeof value.lastNotified === "boolean") || !Number.isInteger(value.pid) || value.pid <= 0 || !Number.isFinite(Date.parse(value.confirmedAt))) return null;
|
|
49067
|
+
return value;
|
|
49068
|
+
} catch {
|
|
49069
|
+
return null;
|
|
49070
|
+
}
|
|
49071
|
+
}
|
|
49072
|
+
async function readFullLogNotice(directory, enrollment) {
|
|
49073
|
+
const value = await saved(directory, enrollment);
|
|
49074
|
+
let live = false;
|
|
49075
|
+
if (value) {
|
|
49076
|
+
try {
|
|
49077
|
+
const processRecord = JSON.parse(await readFile10(path24.join(directory, "agent-process.json"), "utf8"));
|
|
49078
|
+
if (processRecord.pid === value.pid && Date.parse(processRecord.startedAt) <= Date.parse(value.confirmedAt)) {
|
|
49079
|
+
process.kill(value.pid, 0);
|
|
49080
|
+
live = true;
|
|
49081
|
+
}
|
|
49082
|
+
} catch {
|
|
49083
|
+
}
|
|
49084
|
+
}
|
|
49085
|
+
return { enabled: live ? value.enabled : null, confirmedAt: value?.confirmedAt ?? null, manageUrl };
|
|
49086
|
+
}
|
|
49087
|
+
async function showFullLogNotice(enabled) {
|
|
49088
|
+
const title = "Local Commander: full logs " + (enabled ? "enabled" : "disabled");
|
|
49089
|
+
const body = enabled ? "Your account owner enabled full logs for this computer. Tool requests and responses may be stored for up to 7 days. Review the choice at localcmd.app." : "Your account owner disabled full logs for this computer. Review the choice and deletion status at localcmd.app.";
|
|
49090
|
+
const options = { windowsHide: true, timeout: 12e3, maxBuffer: 4096 };
|
|
49091
|
+
if (process.platform === "win32") {
|
|
49092
|
+
const script = `Add-Type -AssemblyName System.Windows.Forms; Add-Type -AssemblyName System.Drawing; $notice=New-Object System.Windows.Forms.NotifyIcon; try { $notice.Icon=[System.Drawing.SystemIcons]::Information; $notice.Visible=$true; $notice.ShowBalloonTip(8000,'${title}','${body}',[System.Windows.Forms.ToolTipIcon]::Info); Start-Sleep -Seconds 8 } finally { $notice.Dispose() }`;
|
|
49093
|
+
await exec3("powershell.exe", ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script], options);
|
|
49094
|
+
} else if (process.platform === "darwin") {
|
|
49095
|
+
await exec3("/usr/bin/osascript", ["-e", `display notification "${body}" with title "${title}"`], options);
|
|
49096
|
+
} else if (process.platform === "linux") {
|
|
49097
|
+
await exec3("notify-send", ["--app-name=Local Commander", title, body], options);
|
|
49098
|
+
}
|
|
49099
|
+
}
|
|
49100
|
+
var FullLogNotice = class {
|
|
49101
|
+
constructor(directory, enrollment, notify = showFullLogNotice) {
|
|
49102
|
+
this.directory = directory;
|
|
49103
|
+
this.enrollment = enrollment;
|
|
49104
|
+
this.notify = notify;
|
|
49105
|
+
}
|
|
49106
|
+
directory;
|
|
49107
|
+
enrollment;
|
|
49108
|
+
notify;
|
|
49109
|
+
pending;
|
|
49110
|
+
writing;
|
|
49111
|
+
update(enabled) {
|
|
49112
|
+
this.pending = enabled;
|
|
49113
|
+
return this.writing ??= this.drain().finally(() => {
|
|
49114
|
+
this.writing = void 0;
|
|
49115
|
+
});
|
|
49116
|
+
}
|
|
49117
|
+
async drain() {
|
|
49118
|
+
await mkdir10(noticeDirectory(this.directory), { mode: 448 }).catch((error62) => {
|
|
49119
|
+
if (error62.code !== "EEXIST") throw error62;
|
|
49120
|
+
});
|
|
49121
|
+
const parent = await lstat11(noticeDirectory(this.directory));
|
|
49122
|
+
if (!parent.isDirectory() || parent.isSymbolicLink()) throw Error("FULL_LOG_NOTICE_DIRECTORY_INVALID");
|
|
49123
|
+
let previous = await saved(this.directory, this.enrollment);
|
|
49124
|
+
while (this.pending !== void 0) {
|
|
49125
|
+
const enabled = this.pending;
|
|
49126
|
+
this.pending = void 0;
|
|
49127
|
+
const changed = enabled !== null && enabled !== previous?.lastNotified && (enabled || previous?.lastNotified === true);
|
|
49128
|
+
const next = {
|
|
49129
|
+
...this.enrollment,
|
|
49130
|
+
enabled,
|
|
49131
|
+
lastNotified: changed ? enabled : previous?.lastNotified ?? null,
|
|
49132
|
+
confirmedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
49133
|
+
pid: process.pid
|
|
49134
|
+
};
|
|
49135
|
+
const temporary = file2(this.directory) + "." + randomUUID13() + ".tmp";
|
|
49136
|
+
try {
|
|
49137
|
+
await writeFile4(temporary, JSON.stringify(next) + "\n", { flag: "wx", mode: 384 });
|
|
49138
|
+
await rename7(temporary, file2(this.directory));
|
|
49139
|
+
} finally {
|
|
49140
|
+
await rm9(temporary, { force: true }).catch(() => {
|
|
49141
|
+
});
|
|
49142
|
+
}
|
|
49143
|
+
previous = next;
|
|
49144
|
+
if (changed) void this.notify(enabled).catch(() => {
|
|
49145
|
+
});
|
|
49146
|
+
}
|
|
49147
|
+
}
|
|
49148
|
+
};
|
|
49149
|
+
|
|
49150
|
+
// agent/src/token-usage.ts
|
|
49151
|
+
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
49152
|
+
import { lstat as lstat12, mkdir as mkdir11, open as open10, readdir as readdir6, readFile as readFile11, rename as rename8, rm as rm10, writeFile as writeFile5 } from "node:fs/promises";
|
|
49153
|
+
import os8 from "node:os";
|
|
49154
|
+
import path25 from "node:path";
|
|
49155
|
+
var KEEP_DAYS = 35;
|
|
49156
|
+
var MAX_FILES = 1e4;
|
|
49157
|
+
var MAX_SCAN_BYTES = 256 * 1024 * 1024;
|
|
49158
|
+
var CHUNK_BYTES = 4 * 1024 * 1024;
|
|
49159
|
+
var MAX_ROWS = 64;
|
|
49160
|
+
var DAY_MS = 864e5;
|
|
49161
|
+
function tokenUsageRoots(env = process.env) {
|
|
49162
|
+
const home = os8.homedir();
|
|
49163
|
+
const absolute2 = (value, fallback) => value && path25.isAbsolute(value) ? value : fallback;
|
|
49164
|
+
return { claude: absolute2(env.CLAUDE_CONFIG_DIR, path25.join(home, ".claude")), codex: absolute2(env.CODEX_HOME, path25.join(home, ".codex")) };
|
|
49165
|
+
}
|
|
49166
|
+
var stateDirectory = (directory) => path25.join(directory, "optimization");
|
|
49167
|
+
var stateFile = (directory) => path25.join(stateDirectory(directory), "token-usage.json");
|
|
49168
|
+
var utcDay = (ms) => new Date(ms).toISOString().slice(0, 10);
|
|
49169
|
+
var count2 = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
49170
|
+
var modelName = (value) => typeof value === "string" && TOKEN_USAGE_MODEL.test(value) ? value : "unknown";
|
|
49171
|
+
async function sources(roots, since) {
|
|
49172
|
+
const found = [];
|
|
49173
|
+
const entries = async (dir) => {
|
|
49174
|
+
try {
|
|
49175
|
+
return await readdir6(dir, { withFileTypes: true });
|
|
49176
|
+
} catch {
|
|
49177
|
+
return [];
|
|
49178
|
+
}
|
|
49179
|
+
};
|
|
49180
|
+
const add = async (client, file3) => {
|
|
49181
|
+
if (found.length >= MAX_FILES) return;
|
|
49182
|
+
try {
|
|
49183
|
+
const info = await lstat12(file3);
|
|
49184
|
+
if (info.isFile() && info.mtimeMs >= since) found.push({ client, file: file3 });
|
|
49185
|
+
} catch {
|
|
49186
|
+
}
|
|
49187
|
+
};
|
|
49188
|
+
const projects = path25.join(roots.claude, "projects");
|
|
49189
|
+
for (const project of await entries(projects)) {
|
|
49190
|
+
if (!project.isDirectory()) continue;
|
|
49191
|
+
for (const entry of await entries(path25.join(projects, project.name))) {
|
|
49192
|
+
if (entry.isFile() && entry.name.endsWith(".jsonl")) await add("claude-code", path25.join(projects, project.name, entry.name));
|
|
49193
|
+
else if (entry.isDirectory()) {
|
|
49194
|
+
const subagents = path25.join(projects, project.name, entry.name, "subagents");
|
|
49195
|
+
for (const agent of await entries(subagents)) if (agent.isFile() && agent.name.endsWith(".jsonl")) await add("claude-code", path25.join(subagents, agent.name));
|
|
49196
|
+
}
|
|
49197
|
+
}
|
|
49198
|
+
}
|
|
49199
|
+
const sessions = path25.join(roots.codex, "sessions"), first = utcDay(since - DAY_MS);
|
|
49200
|
+
for (const year of await entries(sessions)) {
|
|
49201
|
+
if (!year.isDirectory() || !/^\d{4}$/.test(year.name) || year.name < first.slice(0, 4)) continue;
|
|
49202
|
+
for (const month of await entries(path25.join(sessions, year.name))) {
|
|
49203
|
+
if (!month.isDirectory() || !/^\d{2}$/.test(month.name) || `${year.name}-${month.name}` < first.slice(0, 7)) continue;
|
|
49204
|
+
for (const day of await entries(path25.join(sessions, year.name, month.name))) {
|
|
49205
|
+
if (!day.isDirectory() || !/^\d{2}$/.test(day.name) || `${year.name}-${month.name}-${day.name}` < first) continue;
|
|
49206
|
+
const folder = path25.join(sessions, year.name, month.name, day.name);
|
|
49207
|
+
for (const file3 of await entries(folder)) if (file3.isFile() && file3.name.endsWith(".jsonl")) await add("codex", path25.join(folder, file3.name));
|
|
49208
|
+
}
|
|
49209
|
+
}
|
|
49210
|
+
}
|
|
49211
|
+
return found;
|
|
49212
|
+
}
|
|
49213
|
+
function usageFromLine(client, line, file3) {
|
|
49214
|
+
if (client === "claude-code" ? !line.includes('"usage"') : !line.includes('"token_count"') && !line.includes('"turn_context"')) return null;
|
|
49215
|
+
let value;
|
|
49216
|
+
try {
|
|
49217
|
+
value = JSON.parse(line);
|
|
49218
|
+
} catch {
|
|
49219
|
+
return null;
|
|
49220
|
+
}
|
|
49221
|
+
const at = typeof value?.timestamp === "string" ? Date.parse(value.timestamp) : NaN;
|
|
49222
|
+
if (client === "claude-code") {
|
|
49223
|
+
const message2 = value?.type === "assistant" ? value.message : void 0, usage = message2?.usage;
|
|
49224
|
+
if (!usage || typeof message2.id !== "string" || message2.model === "<synthetic>") return null;
|
|
49225
|
+
if (message2.id === file3.lastMessageId) return null;
|
|
49226
|
+
file3.lastMessageId = message2.id.slice(0, 128);
|
|
49227
|
+
const input3 = count2(usage.input_tokens), cacheWrite2 = count2(usage.cache_creation_input_tokens ?? 0), cached3 = count2(usage.cache_read_input_tokens ?? 0), output3 = count2(usage.output_tokens);
|
|
49228
|
+
if (input3 === null || cacheWrite2 === null || cached3 === null || output3 === null || !Number.isFinite(at)) return null;
|
|
49229
|
+
return { at, model: modelName(message2.model), input: input3 + cacheWrite2 + cached3, cached: cached3, cacheWrite: cacheWrite2, output: output3, reasoning: null };
|
|
49230
|
+
}
|
|
49231
|
+
if (value?.type === "turn_context") {
|
|
49232
|
+
file3.model = modelName(value.payload?.model);
|
|
49233
|
+
return null;
|
|
49234
|
+
}
|
|
49235
|
+
const info = value?.type === "event_msg" && value.payload?.type === "token_count" ? value.payload.info : void 0;
|
|
49236
|
+
const total = count2(info?.total_token_usage?.total_tokens), last = info?.last_token_usage;
|
|
49237
|
+
if (total === null || !last || total === file3.lastTotal) return null;
|
|
49238
|
+
file3.lastTotal = total;
|
|
49239
|
+
const input2 = count2(last.input_tokens), cached2 = count2(last.cached_input_tokens ?? 0), cacheWrite = count2(last.cache_write_input_tokens ?? 0), output2 = count2(last.output_tokens), reasoning = count2(last.reasoning_output_tokens ?? 0);
|
|
49240
|
+
if (input2 === null || cached2 === null || cacheWrite === null || output2 === null || reasoning === null || !Number.isFinite(at)) return null;
|
|
49241
|
+
if (cached2 + cacheWrite > input2 || reasoning > output2) return null;
|
|
49242
|
+
return { at, model: file3.model ?? "unknown", input: input2, cached: cached2, cacheWrite, output: output2, reasoning };
|
|
49243
|
+
}
|
|
49244
|
+
async function readNew(source, file3, size, budget, countFrom, add) {
|
|
49245
|
+
if (size < file3.offset) Object.assign(file3, { offset: 0, lastMessageId: void 0, lastTotal: void 0, skipping: false });
|
|
49246
|
+
let read = 0;
|
|
49247
|
+
const handle = await open10(source.file, "r");
|
|
49248
|
+
try {
|
|
49249
|
+
while (file3.offset < size && read < budget) {
|
|
49250
|
+
const length = Math.min(CHUNK_BYTES, size - file3.offset);
|
|
49251
|
+
const buffer = Buffer.alloc(length);
|
|
49252
|
+
const { bytesRead } = await handle.read(buffer, 0, length, file3.offset);
|
|
49253
|
+
if (bytesRead <= 0) break;
|
|
49254
|
+
read += bytesRead;
|
|
49255
|
+
const end = buffer.lastIndexOf(10, bytesRead - 1);
|
|
49256
|
+
if (end < 0) {
|
|
49257
|
+
if (bytesRead < CHUNK_BYTES) break;
|
|
49258
|
+
file3.offset += bytesRead;
|
|
49259
|
+
file3.skipping = true;
|
|
49260
|
+
continue;
|
|
49261
|
+
}
|
|
49262
|
+
let start = 0;
|
|
49263
|
+
if (file3.skipping) {
|
|
49264
|
+
start = buffer.indexOf(10) + 1;
|
|
49265
|
+
file3.skipping = false;
|
|
49266
|
+
}
|
|
49267
|
+
for (const line of buffer.toString("utf8", start, end).split("\n")) {
|
|
49268
|
+
const usage = usageFromLine(source.client, line, file3);
|
|
49269
|
+
if (usage && usage.at >= countFrom) add(source.client, usage);
|
|
49270
|
+
}
|
|
49271
|
+
file3.offset += end + 1;
|
|
49272
|
+
}
|
|
49273
|
+
} finally {
|
|
49274
|
+
await handle.close();
|
|
49275
|
+
}
|
|
49276
|
+
return read;
|
|
49277
|
+
}
|
|
49278
|
+
var TokenUsageReporter = class {
|
|
49279
|
+
constructor(directory, enrollment, options = {}) {
|
|
49280
|
+
this.directory = directory;
|
|
49281
|
+
this.enrollment = enrollment;
|
|
49282
|
+
this.options = options;
|
|
49283
|
+
}
|
|
49284
|
+
directory;
|
|
49285
|
+
enrollment;
|
|
49286
|
+
options;
|
|
49287
|
+
saved;
|
|
49288
|
+
send;
|
|
49289
|
+
enabled = false;
|
|
49290
|
+
wanted = false;
|
|
49291
|
+
timer;
|
|
49292
|
+
running;
|
|
49293
|
+
inFlight;
|
|
49294
|
+
closed = false;
|
|
49295
|
+
failed = false;
|
|
49296
|
+
/** The state frame can arrive before the connection is handed over, so both feed one decision. */
|
|
49297
|
+
connected(send) {
|
|
49298
|
+
this.send = send;
|
|
49299
|
+
this.apply();
|
|
49300
|
+
}
|
|
49301
|
+
disconnected() {
|
|
49302
|
+
this.send = void 0;
|
|
49303
|
+
this.wanted = false;
|
|
49304
|
+
this.apply();
|
|
49305
|
+
if (this.inFlight) {
|
|
49306
|
+
clearTimeout(this.inFlight.timer);
|
|
49307
|
+
this.inFlight = void 0;
|
|
49308
|
+
}
|
|
49309
|
+
}
|
|
49310
|
+
close() {
|
|
49311
|
+
this.closed = true;
|
|
49312
|
+
this.disconnected();
|
|
49313
|
+
}
|
|
49314
|
+
/** The server's choice for this computer, sent after connect and on every change. */
|
|
49315
|
+
state(enabled) {
|
|
49316
|
+
this.wanted = enabled;
|
|
49317
|
+
this.apply();
|
|
49318
|
+
if (!enabled) void this.exclusive(async () => {
|
|
49319
|
+
const saved2 = await this.load();
|
|
49320
|
+
if (!saved2.paused) {
|
|
49321
|
+
saved2.paused = true;
|
|
49322
|
+
await this.persist();
|
|
49323
|
+
}
|
|
49324
|
+
}).catch(() => {
|
|
49325
|
+
});
|
|
49326
|
+
}
|
|
49327
|
+
apply() {
|
|
49328
|
+
const on = this.wanted && !!this.send && !this.closed;
|
|
49329
|
+
if (on && !this.enabled) {
|
|
49330
|
+
this.enabled = true;
|
|
49331
|
+
this.schedule(this.options.firstDelayMs ?? 6e4);
|
|
49332
|
+
} else if (!on && this.enabled) {
|
|
49333
|
+
this.enabled = false;
|
|
49334
|
+
clearTimeout(this.timer);
|
|
49335
|
+
this.timer = void 0;
|
|
49336
|
+
}
|
|
49337
|
+
}
|
|
49338
|
+
ack(batchId, result2) {
|
|
49339
|
+
const flight = this.inFlight;
|
|
49340
|
+
if (!flight || batchId !== flight.batchId) return;
|
|
49341
|
+
clearTimeout(flight.timer);
|
|
49342
|
+
this.inFlight = void 0;
|
|
49343
|
+
if (result2 === "disabled") {
|
|
49344
|
+
this.state(false);
|
|
49345
|
+
return;
|
|
49346
|
+
}
|
|
49347
|
+
if (result2 !== "accepted" && result2 !== "invalid") return;
|
|
49348
|
+
void this.exclusive(async () => {
|
|
49349
|
+
const saved2 = await this.load();
|
|
49350
|
+
for (const [key, version2] of Object.entries(flight.versions)) if (saved2.dirty[key] === version2) delete saved2.dirty[key];
|
|
49351
|
+
await this.persist();
|
|
49352
|
+
if (result2 === "accepted") this.flush();
|
|
49353
|
+
});
|
|
49354
|
+
}
|
|
49355
|
+
/** One scan and report now; used by the timer and by manual checks. */
|
|
49356
|
+
async scanOnce() {
|
|
49357
|
+
await this.exclusive(async () => {
|
|
49358
|
+
const saved2 = await this.load(), now = this.now();
|
|
49359
|
+
if (saved2.paused) {
|
|
49360
|
+
saved2.countFrom = new Date(now).toISOString();
|
|
49361
|
+
saved2.files = {};
|
|
49362
|
+
saved2.baseline = true;
|
|
49363
|
+
delete saved2.paused;
|
|
49364
|
+
}
|
|
49365
|
+
const countFrom = Date.parse(saved2.countFrom);
|
|
49366
|
+
const since = Math.max(countFrom, now - KEEP_DAYS * DAY_MS);
|
|
49367
|
+
let budget = MAX_SCAN_BYTES;
|
|
49368
|
+
const seen = /* @__PURE__ */ new Set();
|
|
49369
|
+
const baseline = saved2.baseline === true;
|
|
49370
|
+
for (const source of await sources(this.roots(), since - DAY_MS)) {
|
|
49371
|
+
if (budget <= 0) break;
|
|
49372
|
+
seen.add(source.file);
|
|
49373
|
+
let info;
|
|
49374
|
+
try {
|
|
49375
|
+
info = await lstat12(source.file);
|
|
49376
|
+
} catch {
|
|
49377
|
+
continue;
|
|
49378
|
+
}
|
|
49379
|
+
const file3 = saved2.files[source.file] ??= { offset: baseline ? info.size : 0, mtimeMs: 0 };
|
|
49380
|
+
file3.mtimeMs = info.mtimeMs;
|
|
49381
|
+
if (info.size === file3.offset) continue;
|
|
49382
|
+
try {
|
|
49383
|
+
budget -= await readNew(source, file3, info.size, budget, countFrom, (client, usage) => this.add(saved2, client, usage));
|
|
49384
|
+
} catch {
|
|
49385
|
+
}
|
|
49386
|
+
}
|
|
49387
|
+
if (baseline) delete saved2.baseline;
|
|
49388
|
+
for (const [name2, file3] of Object.entries(saved2.files)) if (!seen.has(name2) && file3.mtimeMs < now - KEEP_DAYS * DAY_MS) delete saved2.files[name2];
|
|
49389
|
+
const oldest = utcDay(now - KEEP_DAYS * DAY_MS);
|
|
49390
|
+
for (const key of Object.keys(saved2.totals)) if (key.slice(0, 10) < oldest) {
|
|
49391
|
+
delete saved2.totals[key];
|
|
49392
|
+
delete saved2.dirty[key];
|
|
49393
|
+
}
|
|
49394
|
+
await this.persist();
|
|
49395
|
+
});
|
|
49396
|
+
this.flush();
|
|
49397
|
+
}
|
|
49398
|
+
add(saved2, client, usage) {
|
|
49399
|
+
const key = `${utcDay(usage.at)}|${client}|${usage.model}`;
|
|
49400
|
+
const row = saved2.totals[key] ??= { requests: 0, inputTokens: 0, cachedInputTokens: 0, cacheWriteTokens: 0, outputTokens: 0, reasoningTokens: client === "codex" ? 0 : null };
|
|
49401
|
+
row.requests++;
|
|
49402
|
+
row.inputTokens += usage.input;
|
|
49403
|
+
row.cachedInputTokens += usage.cached;
|
|
49404
|
+
row.cacheWriteTokens += usage.cacheWrite;
|
|
49405
|
+
row.outputTokens += usage.output;
|
|
49406
|
+
if (row.reasoningTokens !== null && usage.reasoning !== null) row.reasoningTokens += usage.reasoning;
|
|
49407
|
+
saved2.dirty[key] = (saved2.dirty[key] ?? 0) + 1;
|
|
49408
|
+
}
|
|
49409
|
+
flush() {
|
|
49410
|
+
const saved2 = this.saved, send = this.send;
|
|
49411
|
+
if (!saved2 || !send || !this.enabled || this.inFlight) return;
|
|
49412
|
+
const keys = Object.keys(saved2.dirty).filter((key) => saved2.totals[key]).sort().slice(0, MAX_ROWS);
|
|
49413
|
+
if (!keys.length) return;
|
|
49414
|
+
const rows = keys.map((key) => {
|
|
49415
|
+
const [day, client, model] = key.split("|");
|
|
49416
|
+
return { day, client, model, ...saved2.totals[key] };
|
|
49417
|
+
});
|
|
49418
|
+
const batchId = randomUUID14(), versions = Object.fromEntries(keys.map((key) => [key, saved2.dirty[key]]));
|
|
49419
|
+
let sent = false;
|
|
49420
|
+
try {
|
|
49421
|
+
sent = send({ batchId, stateId: saved2.stateId, rows });
|
|
49422
|
+
} catch {
|
|
49423
|
+
}
|
|
49424
|
+
if (sent) this.inFlight = { batchId, versions, timer: setTimeout(() => {
|
|
49425
|
+
if (this.inFlight?.batchId === batchId) this.inFlight = void 0;
|
|
49426
|
+
}, 3e4).unref() };
|
|
49427
|
+
}
|
|
49428
|
+
schedule(delay4) {
|
|
49429
|
+
clearTimeout(this.timer);
|
|
49430
|
+
this.timer = setTimeout(() => {
|
|
49431
|
+
if (!this.enabled) return;
|
|
49432
|
+
void this.scanOnce().catch(() => {
|
|
49433
|
+
if (!this.failed) {
|
|
49434
|
+
this.failed = true;
|
|
49435
|
+
process.stderr.write("TOKEN_USAGE_SCAN_FAILED\n");
|
|
49436
|
+
}
|
|
49437
|
+
}).finally(() => {
|
|
49438
|
+
if (this.enabled) this.schedule(this.options.intervalMs ?? 36e5);
|
|
49439
|
+
});
|
|
49440
|
+
}, delay4);
|
|
49441
|
+
this.timer.unref();
|
|
49442
|
+
}
|
|
49443
|
+
exclusive(task) {
|
|
49444
|
+
const next = (this.running ?? Promise.resolve()).then(task, task);
|
|
49445
|
+
this.running = next.catch(() => {
|
|
49446
|
+
});
|
|
49447
|
+
return next;
|
|
49448
|
+
}
|
|
49449
|
+
now() {
|
|
49450
|
+
return (this.options.now ?? Date.now)();
|
|
49451
|
+
}
|
|
49452
|
+
roots() {
|
|
49453
|
+
return this.options.roots ?? tokenUsageRoots();
|
|
49454
|
+
}
|
|
49455
|
+
async load() {
|
|
49456
|
+
if (this.saved) return this.saved;
|
|
49457
|
+
let value;
|
|
49458
|
+
try {
|
|
49459
|
+
const info = await lstat12(stateFile(this.directory));
|
|
49460
|
+
if (info.isFile() && !info.isSymbolicLink() && info.size <= 16 * 1024 * 1024) {
|
|
49461
|
+
const parsed = JSON.parse(await readFile11(stateFile(this.directory), "utf8"));
|
|
49462
|
+
if (parsed.version === 1 && parsed.tenantId === this.enrollment.tenantId && parsed.deviceId === this.enrollment.deviceId && typeof parsed.stateId === "string" && Number.isFinite(Date.parse(parsed.countFrom)) && parsed.files && parsed.totals && parsed.dirty) value = parsed;
|
|
49463
|
+
}
|
|
49464
|
+
} catch {
|
|
49465
|
+
}
|
|
49466
|
+
return this.saved = value ?? { version: 1, ...this.enrollment, stateId: randomUUID14(), countFrom: new Date(this.now()).toISOString(), files: {}, totals: {}, dirty: {}, baseline: true };
|
|
49467
|
+
}
|
|
49468
|
+
async persist() {
|
|
49469
|
+
if (!this.saved) return;
|
|
49470
|
+
await mkdir11(stateDirectory(this.directory), { mode: 448 }).catch((error62) => {
|
|
49471
|
+
if (error62.code !== "EEXIST") throw error62;
|
|
49472
|
+
});
|
|
49473
|
+
const parent = await lstat12(stateDirectory(this.directory));
|
|
49474
|
+
if (!parent.isDirectory() || parent.isSymbolicLink()) throw Error("TOKEN_USAGE_DIRECTORY_INVALID");
|
|
49475
|
+
const temporary = stateFile(this.directory) + "." + randomUUID14() + ".tmp";
|
|
49476
|
+
try {
|
|
49477
|
+
await writeFile5(temporary, JSON.stringify(this.saved), { flag: "wx", mode: 384 });
|
|
49478
|
+
await rename8(temporary, stateFile(this.directory));
|
|
49479
|
+
} finally {
|
|
49480
|
+
await rm10(temporary, { force: true }).catch(() => {
|
|
49481
|
+
});
|
|
49482
|
+
}
|
|
49483
|
+
}
|
|
49484
|
+
};
|
|
49485
|
+
|
|
48968
49486
|
// agent/src/native-event-buffer.ts
|
|
48969
49487
|
import { createHash as createHash18 } from "node:crypto";
|
|
48970
49488
|
function nativeFingerprint(code, executionId = "") {
|
|
@@ -49247,7 +49765,7 @@ var NativeEventSupervisor = class {
|
|
|
49247
49765
|
};
|
|
49248
49766
|
|
|
49249
49767
|
// agent/src/native-fabric-observer.ts
|
|
49250
|
-
var
|
|
49768
|
+
var uuid23 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
49251
49769
|
var NativeFabricObserver = class {
|
|
49252
49770
|
constructor(supervisor, source) {
|
|
49253
49771
|
this.supervisor = supervisor;
|
|
@@ -49269,7 +49787,7 @@ var NativeFabricObserver = class {
|
|
|
49269
49787
|
unsubscribe;
|
|
49270
49788
|
connected(authenticatedDeviceId) {
|
|
49271
49789
|
this.disconnected();
|
|
49272
|
-
if (
|
|
49790
|
+
if (uuid23.test(authenticatedDeviceId)) this.deviceId = authenticatedDeviceId.toLowerCase();
|
|
49273
49791
|
this.activity();
|
|
49274
49792
|
}
|
|
49275
49793
|
disconnected() {
|
|
@@ -49304,17 +49822,17 @@ var NativeFabricObserver = class {
|
|
|
49304
49822
|
void Promise.resolve().then(() => this.source.mailbox.snapshot()).then((state) => {
|
|
49305
49823
|
if (this.closed || expired || generation !== this.generation) return;
|
|
49306
49824
|
if (state.workers.length > 64 || state.assignments.length > 256 || state.messages.length > 1024) throw Error("FABRIC_BOUND_INVALID");
|
|
49307
|
-
const workers = new Set(state.workers.filter((w) => w.device?.deviceId.toLowerCase() === deviceId &&
|
|
49825
|
+
const workers = new Set(state.workers.filter((w) => w.device?.deviceId.toLowerCase() === deviceId && uuid23.test(w.workerId)).map((w) => w.workerId));
|
|
49308
49826
|
const assignments = new Map(state.assignments.filter((a) => workers.has(a.workerId)).map((a) => [a.assignmentId, a]));
|
|
49309
49827
|
const refs = /* @__PURE__ */ new Map();
|
|
49310
49828
|
for (const a of assignments.values()) {
|
|
49311
49829
|
const id2 = a.execution?.executionId;
|
|
49312
|
-
if (!id2 || !
|
|
49830
|
+
if (!id2 || !uuid23.test(id2)) continue;
|
|
49313
49831
|
if (refs.has(id2.toLowerCase())) throw Error("FABRIC_EXECUTION_CONFLICT");
|
|
49314
49832
|
refs.set(id2.toLowerCase(), {
|
|
49315
49833
|
executionId: id2.toLowerCase(),
|
|
49316
49834
|
workerId: a.workerId.toLowerCase(),
|
|
49317
|
-
...
|
|
49835
|
+
...uuid23.test(a.taskId) ? { taskId: a.taskId.toLowerCase() } : {}
|
|
49318
49836
|
});
|
|
49319
49837
|
}
|
|
49320
49838
|
this.referencesByExecution.clear();
|
|
@@ -49366,27 +49884,27 @@ var NativeFabricObserver = class {
|
|
|
49366
49884
|
};
|
|
49367
49885
|
|
|
49368
49886
|
// agent/src/native-fabric-startup.ts
|
|
49369
|
-
import { lstat as
|
|
49370
|
-
import
|
|
49887
|
+
import { lstat as lstat14, mkdir as mkdir14, open as open12, readFile as readFile12 } from "node:fs/promises";
|
|
49888
|
+
import path28 from "node:path";
|
|
49371
49889
|
|
|
49372
49890
|
// src/agent-fabric-service.ts
|
|
49373
|
-
import { lstat as
|
|
49891
|
+
import { lstat as lstat13, mkdir as mkdir13, realpath as realpath9 } from "node:fs/promises";
|
|
49374
49892
|
import { watch } from "node:fs";
|
|
49375
|
-
import
|
|
49893
|
+
import path27 from "node:path";
|
|
49376
49894
|
|
|
49377
49895
|
// src/agent-runtime-identity.ts
|
|
49378
|
-
import { createHash as createHash19, randomBytes as randomBytes8, randomUUID as
|
|
49896
|
+
import { createHash as createHash19, randomBytes as randomBytes8, randomUUID as randomUUID16, timingSafeEqual as timingSafeEqual4 } from "node:crypto";
|
|
49379
49897
|
|
|
49380
49898
|
// src/agent-fabric-state.ts
|
|
49381
|
-
import { randomUUID as
|
|
49382
|
-
import { mkdir as
|
|
49383
|
-
import
|
|
49899
|
+
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
49900
|
+
import { mkdir as mkdir12, open as open11, rename as rename9, unlink as unlink3 } from "node:fs/promises";
|
|
49901
|
+
import path26 from "node:path";
|
|
49384
49902
|
var queues = /* @__PURE__ */ new Map();
|
|
49385
49903
|
var FabricStateFile = class {
|
|
49386
|
-
constructor(
|
|
49904
|
+
constructor(file3, maxBytes, parse4) {
|
|
49387
49905
|
this.maxBytes = maxBytes;
|
|
49388
49906
|
this.parse = parse4;
|
|
49389
|
-
this.file =
|
|
49907
|
+
this.file = path26.resolve(file3);
|
|
49390
49908
|
}
|
|
49391
49909
|
maxBytes;
|
|
49392
49910
|
parse;
|
|
@@ -49404,7 +49922,7 @@ var FabricStateFile = class {
|
|
|
49404
49922
|
return result2;
|
|
49405
49923
|
}
|
|
49406
49924
|
async load() {
|
|
49407
|
-
const handle = await
|
|
49925
|
+
const handle = await open11(this.file, "r");
|
|
49408
49926
|
try {
|
|
49409
49927
|
const info = await handle.stat();
|
|
49410
49928
|
if (!info.isFile() || info.size > this.maxBytes) throw Error("FABRIC_STATE_LIMIT");
|
|
@@ -49430,10 +49948,10 @@ var FabricStateFile = class {
|
|
|
49430
49948
|
}
|
|
49431
49949
|
update(fn, create) {
|
|
49432
49950
|
return this.serial(async () => {
|
|
49433
|
-
if (create) await
|
|
49951
|
+
if (create) await mkdir12(path26.dirname(this.file), { recursive: true });
|
|
49434
49952
|
const lockPath = this.file + ".lock";
|
|
49435
|
-
const token =
|
|
49436
|
-
const lock = await
|
|
49953
|
+
const token = randomUUID15();
|
|
49954
|
+
const lock = await open11(lockPath, "wx", 384).catch((error62) => {
|
|
49437
49955
|
if (error62.code === "EEXIST") throw Error("FABRIC_STATE_BUSY");
|
|
49438
49956
|
throw error62;
|
|
49439
49957
|
});
|
|
@@ -49451,7 +49969,7 @@ var FabricStateFile = class {
|
|
|
49451
49969
|
const encoded = JSON.stringify(this.parse(state));
|
|
49452
49970
|
if (Buffer.byteLength(encoded) > this.maxBytes) throw Error("FABRIC_STATE_LIMIT");
|
|
49453
49971
|
const temporary = this.file + "." + token + ".tmp";
|
|
49454
|
-
const handle = await
|
|
49972
|
+
const handle = await open11(temporary, "wx", 384);
|
|
49455
49973
|
try {
|
|
49456
49974
|
try {
|
|
49457
49975
|
await handle.writeFile(encoded, "utf8");
|
|
@@ -49459,7 +49977,7 @@ var FabricStateFile = class {
|
|
|
49459
49977
|
} finally {
|
|
49460
49978
|
await handle.close();
|
|
49461
49979
|
}
|
|
49462
|
-
await
|
|
49980
|
+
await rename9(temporary, this.file);
|
|
49463
49981
|
} finally {
|
|
49464
49982
|
await unlink3(temporary).catch((error62) => {
|
|
49465
49983
|
if (error62.code !== "ENOENT") throw error62;
|
|
@@ -49468,7 +49986,7 @@ var FabricStateFile = class {
|
|
|
49468
49986
|
return result2;
|
|
49469
49987
|
} finally {
|
|
49470
49988
|
await lock.close();
|
|
49471
|
-
const current2 = await
|
|
49989
|
+
const current2 = await open11(lockPath, "r");
|
|
49472
49990
|
try {
|
|
49473
49991
|
if ((await current2.stat()).size > 1024 || JSON.parse(await current2.readFile("utf8")).token !== token)
|
|
49474
49992
|
throw Error("FABRIC_STATE_LOCK_CHANGED");
|
|
@@ -49507,9 +50025,9 @@ function validKey(value) {
|
|
|
49507
50025
|
return typeof value === "string" && /^[A-Za-z0-9_-]{43}$/.test(value);
|
|
49508
50026
|
}
|
|
49509
50027
|
var AgentRuntimeIdentityStore = class {
|
|
49510
|
-
constructor(
|
|
50028
|
+
constructor(file3, now = Date.now) {
|
|
49511
50029
|
this.now = now;
|
|
49512
|
-
this.state = new FabricStateFile(
|
|
50030
|
+
this.state = new FabricStateFile(file3, MAX_BYTES, (value) => {
|
|
49513
50031
|
const state = StateSchema.parse(value);
|
|
49514
50032
|
if (new Set(state.bindings.map((item) => item.runtimeId)).size !== state.bindings.length)
|
|
49515
50033
|
throw Error("RUNTIME_IDENTITY_STATE_CORRUPT");
|
|
@@ -49528,7 +50046,7 @@ var AgentRuntimeIdentityStore = class {
|
|
|
49528
50046
|
issue() {
|
|
49529
50047
|
return this.serial((state) => {
|
|
49530
50048
|
if (state.bindings.length >= MAX_BINDINGS) throw Error("RUNTIME_IDENTITY_LIMIT");
|
|
49531
|
-
const runtimeId = "rt-" +
|
|
50049
|
+
const runtimeId = "rt-" + randomUUID16();
|
|
49532
50050
|
const runtimeKey = randomBytes8(32).toString("base64url");
|
|
49533
50051
|
const now = this.now();
|
|
49534
50052
|
state.bindings.push({ runtimeId, keyHash: encodedDigest(runtimeKey), createdAt: now, lastUsedAt: now, revoked: false });
|
|
@@ -49561,10 +50079,10 @@ var AgentRuntimeIdentityStore = class {
|
|
|
49561
50079
|
};
|
|
49562
50080
|
|
|
49563
50081
|
// src/agent-fabric-mailbox.ts
|
|
49564
|
-
import { randomUUID as
|
|
50082
|
+
import { randomUUID as randomUUID18 } from "node:crypto";
|
|
49565
50083
|
|
|
49566
50084
|
// src/agent-fabric-timeline.ts
|
|
49567
|
-
import { randomUUID as
|
|
50085
|
+
import { randomUUID as randomUUID17 } from "node:crypto";
|
|
49568
50086
|
import { performance as performance2 } from "node:perf_hooks";
|
|
49569
50087
|
var FabricId = external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9_.:-]{0,95}$/);
|
|
49570
50088
|
var FabricUtc = external_exports.string().datetime({ precision: 3 }).refine((value) => new Date(value).toISOString() === value);
|
|
@@ -49573,7 +50091,7 @@ var FabricStampSchema = external_exports.strictObject({
|
|
|
49573
50091
|
clockId: FabricId,
|
|
49574
50092
|
monotonicMs: external_exports.number().finite().nonnegative().max(Number.MAX_SAFE_INTEGER)
|
|
49575
50093
|
});
|
|
49576
|
-
var processClockId = "clock-" +
|
|
50094
|
+
var processClockId = "clock-" + randomUUID17();
|
|
49577
50095
|
function createFabricClock() {
|
|
49578
50096
|
return () => ({ atUtc: (/* @__PURE__ */ new Date()).toISOString(), clockId: processClockId, monotonicMs: performance2.now() });
|
|
49579
50097
|
}
|
|
@@ -49759,12 +50277,12 @@ function parseState(value) {
|
|
|
49759
50277
|
return state;
|
|
49760
50278
|
}
|
|
49761
50279
|
var AgentWorkerMailbox = class {
|
|
49762
|
-
constructor(
|
|
50280
|
+
constructor(file3, controllerId, identities, clock = createFabricClock(), notify) {
|
|
49763
50281
|
this.identities = identities;
|
|
49764
50282
|
this.clock = clock;
|
|
49765
50283
|
this.notify = notify;
|
|
49766
50284
|
this.controllerId = FabricId.parse(controllerId);
|
|
49767
|
-
this.state = new FabricStateFile(
|
|
50285
|
+
this.state = new FabricStateFile(file3, 2 * 1024 * 1024, (value) => {
|
|
49768
50286
|
const state = parseState(value);
|
|
49769
50287
|
if (state.controllerId !== this.controllerId) throw Error("FABRIC_CONTROLLER_MISMATCH");
|
|
49770
50288
|
return state;
|
|
@@ -49830,7 +50348,7 @@ var AgentWorkerMailbox = class {
|
|
|
49830
50348
|
const now = this.clock().atUtc;
|
|
49831
50349
|
const worker = {
|
|
49832
50350
|
...registration,
|
|
49833
|
-
workerId:
|
|
50351
|
+
workerId: randomUUID18(),
|
|
49834
50352
|
controllerId: this.controllerId,
|
|
49835
50353
|
runtimeId: null,
|
|
49836
50354
|
attribution: WorkerAttributionSchema.parse({}),
|
|
@@ -49864,7 +50382,7 @@ var AgentWorkerMailbox = class {
|
|
|
49864
50382
|
if (state.messages.length >= MAX_MESSAGES) throw Error("FABRIC_MESSAGE_LIMIT");
|
|
49865
50383
|
const now = this.clock();
|
|
49866
50384
|
const message2 = {
|
|
49867
|
-
messageId:
|
|
50385
|
+
messageId: randomUUID18(),
|
|
49868
50386
|
key: request.key,
|
|
49869
50387
|
assignmentId: assignment.assignmentId,
|
|
49870
50388
|
direction,
|
|
@@ -49881,7 +50399,7 @@ var AgentWorkerMailbox = class {
|
|
|
49881
50399
|
}
|
|
49882
50400
|
async assign(input2) {
|
|
49883
50401
|
const request = AssignmentInput.parse(input2);
|
|
49884
|
-
const
|
|
50402
|
+
const saved2 = await this.state.update((state) => {
|
|
49885
50403
|
this.worker(state, request.workerId);
|
|
49886
50404
|
const existing = state.assignments.find((a) => a.runId === request.runId && a.selectedRuntime === request.selectedRuntime);
|
|
49887
50405
|
if (existing) {
|
|
@@ -49894,7 +50412,7 @@ var AgentWorkerMailbox = class {
|
|
|
49894
50412
|
const now = this.clock().atUtc;
|
|
49895
50413
|
const assignment = {
|
|
49896
50414
|
...request,
|
|
49897
|
-
assignmentId:
|
|
50415
|
+
assignmentId: randomUUID18(),
|
|
49898
50416
|
phase: "assigned",
|
|
49899
50417
|
createdAt: now,
|
|
49900
50418
|
updatedAt: now,
|
|
@@ -49909,30 +50427,30 @@ var AgentWorkerMailbox = class {
|
|
|
49909
50427
|
const { message: message2 } = this.append(state, assignment, "ASSIGN", "controller", { key: "assign", payloadRef: request.payloadRef });
|
|
49910
50428
|
return { state, assignment, notice: message2 };
|
|
49911
50429
|
});
|
|
49912
|
-
if (
|
|
49913
|
-
return
|
|
50430
|
+
if (saved2.notice) this.emit(saved2.state, saved2.notice);
|
|
50431
|
+
return saved2.assignment;
|
|
49914
50432
|
}
|
|
49915
50433
|
async control(assignmentId, kind, input2) {
|
|
49916
50434
|
Control.parse(kind);
|
|
49917
|
-
const
|
|
50435
|
+
const saved2 = await this.state.update((state) => {
|
|
49918
50436
|
const assignment = this.assignment(state, assignmentId);
|
|
49919
50437
|
if (!assignmentActive(assignment)) throw Error("FABRIC_ASSIGNMENT_INACTIVE");
|
|
49920
50438
|
return { state, ...this.append(state, assignment, kind, "controller", input2) };
|
|
49921
50439
|
});
|
|
49922
|
-
if (
|
|
49923
|
-
return
|
|
50440
|
+
if (saved2.added) this.emit(saved2.state, saved2.message);
|
|
50441
|
+
return saved2.message;
|
|
49924
50442
|
}
|
|
49925
50443
|
async report(workerId, credential, assignmentId, kind, input2) {
|
|
49926
50444
|
Report.parse(kind);
|
|
49927
50445
|
await this.identities.authenticate(credential.runtimeId, credential.runtimeKey);
|
|
49928
|
-
const
|
|
50446
|
+
const saved2 = await this.state.update((state) => {
|
|
49929
50447
|
this.bound(state, workerId, credential);
|
|
49930
50448
|
const assignment = this.assignment(state, assignmentId);
|
|
49931
50449
|
if (assignment.workerId !== workerId || assignment.phase === "not_started") throw Error("FABRIC_ASSIGNMENT_DENIED");
|
|
49932
50450
|
return { state, ...this.append(state, assignment, kind, "worker", input2) };
|
|
49933
50451
|
});
|
|
49934
|
-
if (
|
|
49935
|
-
return
|
|
50452
|
+
if (saved2.added) this.emit(saved2.state, saved2.message);
|
|
50453
|
+
return saved2.message;
|
|
49936
50454
|
}
|
|
49937
50455
|
pending(state, direction, workerId) {
|
|
49938
50456
|
const now = this.clock().atUtc;
|
|
@@ -49972,12 +50490,12 @@ var AgentWorkerMailbox = class {
|
|
|
49972
50490
|
return this.state.update((state) => this.acknowledge(state, messageId, "to_controller"));
|
|
49973
50491
|
}
|
|
49974
50492
|
async adapterResult(assignmentId, payloadRef) {
|
|
49975
|
-
const
|
|
50493
|
+
const saved2 = await this.state.update((state) => {
|
|
49976
50494
|
const assignment = this.assignment(state, assignmentId);
|
|
49977
50495
|
if (assignment.phase !== "exited") throw Error("FABRIC_RESULT_UNCONFIRMED");
|
|
49978
50496
|
return { state, ...this.append(state, assignment, "RESULT", "adapter", { key: "result", payloadRef }) };
|
|
49979
50497
|
});
|
|
49980
|
-
if (
|
|
50498
|
+
if (saved2.added) this.emit(saved2.state, saved2.message);
|
|
49981
50499
|
}
|
|
49982
50500
|
claimLaunch(assignmentId) {
|
|
49983
50501
|
return this.state.update((state) => {
|
|
@@ -50074,9 +50592,9 @@ var WorkerRequest = external_exports.discriminatedUnion("operation", [
|
|
|
50074
50592
|
var AgentFabricService = class _AgentFabricService {
|
|
50075
50593
|
constructor(directory, controllerId) {
|
|
50076
50594
|
this.directory = directory;
|
|
50077
|
-
this.identities = new AgentRuntimeIdentityStore(
|
|
50595
|
+
this.identities = new AgentRuntimeIdentityStore(path27.join(directory, "identities.json"));
|
|
50078
50596
|
this.mailbox = new AgentWorkerMailbox(
|
|
50079
|
-
|
|
50597
|
+
path27.join(directory, "mailbox.json"),
|
|
50080
50598
|
controllerId,
|
|
50081
50599
|
this.identities,
|
|
50082
50600
|
void 0,
|
|
@@ -50091,29 +50609,29 @@ var AgentFabricService = class _AgentFabricService {
|
|
|
50091
50609
|
closed = false;
|
|
50092
50610
|
static async open(directory, controllerId, device = null, initialize = true) {
|
|
50093
50611
|
const expected = Binding.parse({ version: 1, controllerId, device, initialized: false });
|
|
50094
|
-
const absolute2 =
|
|
50095
|
-
for (let current2 = absolute2; ; current2 =
|
|
50612
|
+
const absolute2 = path27.resolve(directory);
|
|
50613
|
+
for (let current2 = absolute2; ; current2 = path27.dirname(current2)) {
|
|
50096
50614
|
try {
|
|
50097
|
-
if ((await
|
|
50615
|
+
if ((await lstat13(current2)).isSymbolicLink()) throw Error("FABRIC_DIRECTORY_INVALID");
|
|
50098
50616
|
} catch (error62) {
|
|
50099
50617
|
if (error62.code !== "ENOENT") throw error62;
|
|
50100
50618
|
}
|
|
50101
|
-
if (
|
|
50619
|
+
if (path27.dirname(current2) === current2) break;
|
|
50102
50620
|
}
|
|
50103
|
-
if (initialize) await
|
|
50104
|
-
if (!(await
|
|
50621
|
+
if (initialize) await mkdir13(absolute2, { recursive: true, mode: 448 });
|
|
50622
|
+
if (!(await lstat13(absolute2)).isDirectory() || (await realpath9(absolute2)).toLowerCase() !== absolute2.toLowerCase())
|
|
50105
50623
|
throw Error("FABRIC_DIRECTORY_INVALID");
|
|
50106
50624
|
const present = /* @__PURE__ */ new Set();
|
|
50107
50625
|
for (const name2 of ["binding.json", "mailbox.json", "identities.json"]) {
|
|
50108
|
-
const
|
|
50626
|
+
const file3 = await lstat13(path27.join(absolute2, name2)).catch((error62) => {
|
|
50109
50627
|
if (error62.code === "ENOENT") return null;
|
|
50110
50628
|
throw error62;
|
|
50111
50629
|
});
|
|
50112
|
-
if (
|
|
50113
|
-
if (
|
|
50630
|
+
if (file3 && (!file3.isFile() || file3.isSymbolicLink())) throw Error("FABRIC_FILE_INVALID");
|
|
50631
|
+
if (file3) present.add(name2);
|
|
50114
50632
|
}
|
|
50115
50633
|
if (!present.has("binding.json") && present.size) throw Error("FABRIC_BINDING_MISSING");
|
|
50116
|
-
const binding2 = new FabricStateFile(
|
|
50634
|
+
const binding2 = new FabricStateFile(path27.join(absolute2, "binding.json"), 2048, (value) => Binding.parse(value));
|
|
50117
50635
|
const service2 = new _AgentFabricService(absolute2, controllerId);
|
|
50118
50636
|
await binding2.update(async (state) => {
|
|
50119
50637
|
if (state.controllerId !== expected.controllerId || JSON.stringify(state.device) !== JSON.stringify(expected.device))
|
|
@@ -50128,7 +50646,7 @@ var AgentFabricService = class _AgentFabricService {
|
|
|
50128
50646
|
state.initialized = true;
|
|
50129
50647
|
}
|
|
50130
50648
|
const snapshot2 = await service2.mailbox.snapshot();
|
|
50131
|
-
if (snapshot2.workers.some((worker) => worker.runtimeId !== null)) await
|
|
50649
|
+
if (snapshot2.workers.some((worker) => worker.runtimeId !== null)) await lstat13(path27.join(absolute2, "identities.json"));
|
|
50132
50650
|
}, initialize ? () => expected : void 0);
|
|
50133
50651
|
return service2;
|
|
50134
50652
|
}
|
|
@@ -50145,8 +50663,8 @@ var AgentFabricService = class _AgentFabricService {
|
|
|
50145
50663
|
this.listeners.add(callback);
|
|
50146
50664
|
try {
|
|
50147
50665
|
if (!this.watcher) {
|
|
50148
|
-
this.watcher = watch(this.directory, { persistent: false }, (_event,
|
|
50149
|
-
if (
|
|
50666
|
+
this.watcher = watch(this.directory, { persistent: false }, (_event, file3) => {
|
|
50667
|
+
if (file3?.toString().toLowerCase() === "mailbox.json") this.changed();
|
|
50150
50668
|
});
|
|
50151
50669
|
this.watcher.on("error", () => {
|
|
50152
50670
|
this.watcher?.close();
|
|
@@ -50212,51 +50730,51 @@ var OwnerRequest = external_exports.discriminatedUnion("operation", [
|
|
|
50212
50730
|
})
|
|
50213
50731
|
]);
|
|
50214
50732
|
var Delivery = external_exports.strictObject({ capability: external_exports.string().regex(/^[A-Za-z0-9+/]+={0,2}$/).max(4096), request: external_exports.unknown() });
|
|
50215
|
-
async function openNativeFabric(
|
|
50733
|
+
async function openNativeFabric(stateDirectory2, enrollment, box, initialize = true) {
|
|
50216
50734
|
const controllerId = "device-" + external_exports.string().uuid().parse(enrollment.deviceId).toLowerCase();
|
|
50217
50735
|
const tenantId = external_exports.string().uuid().parse(enrollment.tenantId).toLowerCase();
|
|
50218
|
-
const parent =
|
|
50736
|
+
const parent = path28.join(stateDirectory2, ".local-commander"), marker = path28.join(parent, "fabric-established.json");
|
|
50219
50737
|
try {
|
|
50220
|
-
await
|
|
50738
|
+
await mkdir14(parent, { mode: 448 });
|
|
50221
50739
|
} catch (error62) {
|
|
50222
50740
|
if (error62.code !== "EEXIST") throw error62;
|
|
50223
50741
|
}
|
|
50224
|
-
const parentInfo = await
|
|
50742
|
+
const parentInfo = await lstat14(parent);
|
|
50225
50743
|
if (!parentInfo.isDirectory() || parentInfo.isSymbolicLink()) throw Error("FABRIC_DIRECTORY_INVALID");
|
|
50226
50744
|
const expected = JSON.stringify({ version: 1, controllerId, tenantId });
|
|
50227
50745
|
let fresh = false;
|
|
50228
50746
|
try {
|
|
50229
|
-
const info = await
|
|
50230
|
-
if (!info.isFile() || info.isSymbolicLink() || info.size > 2048 || await
|
|
50747
|
+
const info = await lstat14(marker);
|
|
50748
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > 2048 || await readFile12(marker, "utf8") !== expected)
|
|
50231
50749
|
throw Error("FABRIC_BINDING_CHANGED");
|
|
50232
50750
|
} catch (error62) {
|
|
50233
50751
|
if (error62.code !== "ENOENT" || !initialize) throw error62;
|
|
50234
|
-
const
|
|
50752
|
+
const file3 = await open12(marker, "wx", 384);
|
|
50235
50753
|
try {
|
|
50236
|
-
await
|
|
50237
|
-
await
|
|
50754
|
+
await file3.writeFile(expected);
|
|
50755
|
+
await file3.datasync();
|
|
50238
50756
|
} finally {
|
|
50239
|
-
await
|
|
50757
|
+
await file3.close();
|
|
50240
50758
|
}
|
|
50241
50759
|
fresh = true;
|
|
50242
50760
|
}
|
|
50243
50761
|
const service2 = await AgentFabricService.open(
|
|
50244
|
-
|
|
50762
|
+
path28.join(stateDirectory2, ".local-commander", "fabric"),
|
|
50245
50763
|
controllerId,
|
|
50246
50764
|
{ deviceId: enrollment.deviceId.toLowerCase(), enrollmentEvidenceRef: "enrollment-" + tenantId },
|
|
50247
50765
|
fresh
|
|
50248
50766
|
);
|
|
50249
50767
|
const purpose = "native-fabric:" + tenantId + ":" + controllerId;
|
|
50250
|
-
const credentialFile = (workerId) =>
|
|
50768
|
+
const credentialFile = (workerId) => path28.join(service2.directory, external_exports.string().uuid().parse(workerId) + ".capability");
|
|
50251
50769
|
const decode4 = (value) => {
|
|
50252
50770
|
const credential = Credential.parse(JSON.parse(box.open(Buffer.from(value, "base64"), purpose).toString("utf8")));
|
|
50253
50771
|
if (credential.controllerId !== controllerId) throw Error("FABRIC_WORKER_DENIED");
|
|
50254
50772
|
return credential;
|
|
50255
50773
|
};
|
|
50256
50774
|
async function capability(workerId) {
|
|
50257
|
-
const
|
|
50775
|
+
const file3 = credentialFile(workerId), info = await lstat14(file3);
|
|
50258
50776
|
if (!info.isFile() || info.isSymbolicLink() || info.size > 4096) throw Error("FABRIC_CREDENTIAL_UNKNOWN");
|
|
50259
|
-
const encoded = await
|
|
50777
|
+
const encoded = await readFile12(file3, "utf8");
|
|
50260
50778
|
if (decode4(encoded).workerId !== workerId) throw Error("FABRIC_WORKER_DENIED");
|
|
50261
50779
|
return encoded;
|
|
50262
50780
|
}
|
|
@@ -50289,12 +50807,12 @@ async function openNativeFabric(stateDirectory, enrollment, box, initialize = tr
|
|
|
50289
50807
|
} else {
|
|
50290
50808
|
const credential = await service2.identities.issue();
|
|
50291
50809
|
const encoded = box.seal(Buffer.from(JSON.stringify({ ...credential, workerId: worker.workerId, controllerId })), purpose).toString("base64");
|
|
50292
|
-
const
|
|
50810
|
+
const file3 = await open12(credentialFile(worker.workerId), "wx", 384);
|
|
50293
50811
|
try {
|
|
50294
|
-
await
|
|
50295
|
-
await
|
|
50812
|
+
await file3.writeFile(encoded);
|
|
50813
|
+
await file3.datasync();
|
|
50296
50814
|
} finally {
|
|
50297
|
-
await
|
|
50815
|
+
await file3.close();
|
|
50298
50816
|
}
|
|
50299
50817
|
await service2.mailbox.bindRuntime(worker.workerId, credential);
|
|
50300
50818
|
}
|
|
@@ -50348,7 +50866,7 @@ async function readFabricRequest(input2 = process.stdin) {
|
|
|
50348
50866
|
|
|
50349
50867
|
// agent/src/supervisor-liveness.ts
|
|
50350
50868
|
import { spawn as spawn6 } from "node:child_process";
|
|
50351
|
-
import
|
|
50869
|
+
import path29 from "node:path";
|
|
50352
50870
|
import { setTimeout as delay3 } from "node:timers/promises";
|
|
50353
50871
|
var ROW = /^"([^"]+)","(\d{1,10})"/;
|
|
50354
50872
|
function parseTasklist(output2, image) {
|
|
@@ -50363,7 +50881,7 @@ function parseTasklist(output2, image) {
|
|
|
50363
50881
|
}
|
|
50364
50882
|
function listProcesses(image, timeoutMs2 = 5e3) {
|
|
50365
50883
|
if (process.platform !== "win32" || !/^[A-Za-z0-9._-]{1,64}\.exe$/i.test(image)) return Promise.resolve(null);
|
|
50366
|
-
const tasklist =
|
|
50884
|
+
const tasklist = path29.join(process.env.SystemRoot || "C:\\Windows", "System32", "tasklist.exe");
|
|
50367
50885
|
return new Promise((resolve) => {
|
|
50368
50886
|
let output2 = "", settled = false;
|
|
50369
50887
|
const finish = (value) => {
|
|
@@ -50392,8 +50910,8 @@ function listProcesses(image, timeoutMs2 = 5e3) {
|
|
|
50392
50910
|
}
|
|
50393
50911
|
function supervisorLiveness(helperPath, options = {}) {
|
|
50394
50912
|
if (process.platform === "linux" && !options.list) return linuxSupervisorLiveness;
|
|
50395
|
-
if (process.platform === "darwin" && !options.list) return (pids, _linux, darwin) => darwinSupervisorLiveness(
|
|
50396
|
-
const image =
|
|
50913
|
+
if (process.platform === "darwin" && !options.list) return (pids, _linux, darwin) => darwinSupervisorLiveness(path29.join(path29.dirname(helperPath), "posix-host"), pids, darwin);
|
|
50914
|
+
const image = path29.basename(helperPath), waitMs = options.waitMs ?? 1e4, pollMs = options.pollMs ?? 500, list = options.list ?? listProcesses;
|
|
50397
50915
|
return async (pids) => {
|
|
50398
50916
|
const deadline = Date.now() + waitMs;
|
|
50399
50917
|
for (; ; ) {
|
|
@@ -50408,17 +50926,17 @@ function supervisorLiveness(helperPath, options = {}) {
|
|
|
50408
50926
|
|
|
50409
50927
|
// agent/src/content-audit.ts
|
|
50410
50928
|
import { createReadStream } from "node:fs";
|
|
50411
|
-
import { appendFile, lstat as
|
|
50412
|
-
import
|
|
50929
|
+
import { appendFile, lstat as lstat15, mkdir as mkdir15, open as open13, readdir as readdir7, readFile as readFile13, rename as rename10, rm as rm11, writeFile as writeFile6 } from "node:fs/promises";
|
|
50930
|
+
import path30 from "node:path";
|
|
50413
50931
|
import { performance as performance3 } from "node:perf_hooks";
|
|
50414
50932
|
import { createInterface as createInterface2 } from "node:readline";
|
|
50415
50933
|
import { randomBytes as randomBytes10 } from "node:crypto";
|
|
50416
50934
|
|
|
50417
50935
|
// src/audit-crypto.ts
|
|
50418
50936
|
import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, createHash as createHash20, randomBytes as randomBytes9 } from "node:crypto";
|
|
50419
|
-
import { promisify as
|
|
50937
|
+
import { promisify as promisify4 } from "node:util";
|
|
50420
50938
|
import { gunzipSync, gzip, gzipSync } from "node:zlib";
|
|
50421
|
-
var gzipAsync =
|
|
50939
|
+
var gzipAsync = promisify4(gzip);
|
|
50422
50940
|
var AUDIT_ENCRYPTION_ALGORITHM = "A256GCM";
|
|
50423
50941
|
var AUDIT_COMPRESSION = "gzip";
|
|
50424
50942
|
var AUDIT_RECOVERY_KEY_PREFIX = "lca1_";
|
|
@@ -50576,19 +51094,19 @@ var AUDIT_MAX_BYTES = 512 * 1024 * 1024;
|
|
|
50576
51094
|
var MAX_PENDING = 64;
|
|
50577
51095
|
var FILE = /^(full|metrics)-(\d{4}-\d{2}-\d{2})\.jsonl$/;
|
|
50578
51096
|
var PAUSED_FILE = "paused.json";
|
|
50579
|
-
var
|
|
51097
|
+
var DAY_MS2 = 864e5;
|
|
50580
51098
|
function contentAuditDirectory(stateDir) {
|
|
50581
|
-
return
|
|
51099
|
+
return path30.join(path30.dirname(path30.resolve(stateDir)), "Audit");
|
|
50582
51100
|
}
|
|
50583
51101
|
async function plainDirectory(dir) {
|
|
50584
|
-
await
|
|
50585
|
-
const info = await
|
|
51102
|
+
await mkdir15(dir, { recursive: true, mode: 448 });
|
|
51103
|
+
const info = await lstat15(dir);
|
|
50586
51104
|
if (info.isSymbolicLink() || !info.isDirectory()) throw Error("AUDIT_DIRECTORY_INVALID");
|
|
50587
51105
|
}
|
|
50588
51106
|
async function auditFiles(dir) {
|
|
50589
51107
|
let names;
|
|
50590
51108
|
try {
|
|
50591
|
-
names = await
|
|
51109
|
+
names = await readdir7(dir);
|
|
50592
51110
|
} catch (error62) {
|
|
50593
51111
|
if (error62.code === "ENOENT") return [];
|
|
50594
51112
|
throw error62;
|
|
@@ -50597,18 +51115,18 @@ async function auditFiles(dir) {
|
|
|
50597
51115
|
for (const name2 of names) {
|
|
50598
51116
|
const match = FILE.exec(name2);
|
|
50599
51117
|
if (!match) continue;
|
|
50600
|
-
const info = await
|
|
51118
|
+
const info = await lstat15(path30.join(dir, name2));
|
|
50601
51119
|
if (info.isFile()) files.push({ name: name2, kind: match[1], day: match[2], bytes: info.size });
|
|
50602
51120
|
}
|
|
50603
51121
|
return files.sort((a, b) => a.name.localeCompare(b.name));
|
|
50604
51122
|
}
|
|
50605
|
-
async function writeJsonAtomic(
|
|
50606
|
-
const temp = `${
|
|
51123
|
+
async function writeJsonAtomic(file3, value) {
|
|
51124
|
+
const temp = `${file3}.${randomBytes10(6).toString("hex")}.tmp`;
|
|
50607
51125
|
try {
|
|
50608
|
-
await
|
|
50609
|
-
await
|
|
51126
|
+
await writeFile6(temp, JSON.stringify(value) + "\n", { flag: "wx", mode: 384 });
|
|
51127
|
+
await rename10(temp, file3);
|
|
50610
51128
|
} finally {
|
|
50611
|
-
await
|
|
51129
|
+
await rm11(temp, { force: true }).catch(() => {
|
|
50612
51130
|
});
|
|
50613
51131
|
}
|
|
50614
51132
|
}
|
|
@@ -50635,7 +51153,7 @@ var ContentAudit = class _ContentAudit {
|
|
|
50635
51153
|
skipped = 0;
|
|
50636
51154
|
closed = false;
|
|
50637
51155
|
static async open(options) {
|
|
50638
|
-
const dir =
|
|
51156
|
+
const dir = path30.resolve(options.directory);
|
|
50639
51157
|
await plainDirectory(dir);
|
|
50640
51158
|
const audit = new _ContentAudit(
|
|
50641
51159
|
dir,
|
|
@@ -50644,7 +51162,7 @@ var ContentAudit = class _ContentAudit {
|
|
|
50644
51162
|
{ retentionDays: options.retentionDays ?? AUDIT_RETENTION_DAYS, maxBytes: options.maxBytes ?? AUDIT_MAX_BYTES },
|
|
50645
51163
|
options.now ?? (() => /* @__PURE__ */ new Date())
|
|
50646
51164
|
);
|
|
50647
|
-
await
|
|
51165
|
+
await rm11(path30.join(dir, PAUSED_FILE), { force: true });
|
|
50648
51166
|
await audit.rollover(audit.now());
|
|
50649
51167
|
if (audit.usedBytes >= audit.limits.maxBytes) await audit.pause("QUOTA_EXCEEDED");
|
|
50650
51168
|
return audit;
|
|
@@ -50714,25 +51232,25 @@ var ContentAudit = class _ContentAudit {
|
|
|
50714
51232
|
await this.pause("QUOTA_EXCEEDED");
|
|
50715
51233
|
return;
|
|
50716
51234
|
}
|
|
50717
|
-
await appendFile(
|
|
50718
|
-
await appendFile(
|
|
51235
|
+
await appendFile(path30.join(this.dir, `full-${day}.jsonl`), line, { mode: 384 });
|
|
51236
|
+
await appendFile(path30.join(this.dir, `metrics-${day}.jsonl`), metrics, { mode: 384 });
|
|
50719
51237
|
this.usedBytes += bytes3;
|
|
50720
51238
|
}
|
|
50721
51239
|
/** Daily retention runs on the first write of a new day; no timer or background scan. */
|
|
50722
51240
|
async rollover(at) {
|
|
50723
51241
|
this.day = at.toISOString().slice(0, 10);
|
|
50724
|
-
const cutoff = new Date(at.getTime() - this.limits.retentionDays *
|
|
51242
|
+
const cutoff = new Date(at.getTime() - this.limits.retentionDays * DAY_MS2).toISOString().slice(0, 10);
|
|
50725
51243
|
let used = 0;
|
|
50726
|
-
for (const
|
|
50727
|
-
if (
|
|
50728
|
-
else used +=
|
|
51244
|
+
for (const file3 of await auditFiles(this.dir)) {
|
|
51245
|
+
if (file3.day <= cutoff) await rm11(path30.join(this.dir, file3.name), { force: true });
|
|
51246
|
+
else used += file3.bytes;
|
|
50729
51247
|
}
|
|
50730
51248
|
this.usedBytes = used;
|
|
50731
51249
|
}
|
|
50732
51250
|
async pause(reason) {
|
|
50733
51251
|
if (this.paused) return;
|
|
50734
51252
|
this.paused = reason;
|
|
50735
|
-
await writeJsonAtomic(
|
|
51253
|
+
await writeJsonAtomic(path30.join(this.dir, PAUSED_FILE), { reason, at: this.now().toISOString() });
|
|
50736
51254
|
}
|
|
50737
51255
|
};
|
|
50738
51256
|
function percentiles(values) {
|
|
@@ -50741,8 +51259,8 @@ function percentiles(values) {
|
|
|
50741
51259
|
const at = (fraction) => sorted[Math.min(sorted.length - 1, Math.ceil(fraction * sorted.length) - 1)];
|
|
50742
51260
|
return { p50: at(0.5), p95: at(0.95), max: sorted[sorted.length - 1] };
|
|
50743
51261
|
}
|
|
50744
|
-
async function* jsonLines(
|
|
50745
|
-
const lines = createInterface2({ input: createReadStream(
|
|
51262
|
+
async function* jsonLines(file3) {
|
|
51263
|
+
const lines = createInterface2({ input: createReadStream(file3, { encoding: "utf8" }), crlfDelay: Infinity });
|
|
50746
51264
|
for await (const line of lines) {
|
|
50747
51265
|
if (!line.trim()) continue;
|
|
50748
51266
|
try {
|
|
@@ -50752,35 +51270,35 @@ async function* jsonLines(file2) {
|
|
|
50752
51270
|
}
|
|
50753
51271
|
}
|
|
50754
51272
|
}
|
|
50755
|
-
var
|
|
51273
|
+
var count3 = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
|
|
50756
51274
|
async function summarizeContentAudit(directory, key) {
|
|
50757
|
-
const dir =
|
|
51275
|
+
const dir = path30.resolve(directory);
|
|
50758
51276
|
const files = await auditFiles(dir);
|
|
50759
51277
|
const days = /* @__PURE__ */ new Map();
|
|
50760
51278
|
const sizes = [];
|
|
50761
51279
|
const timings = [];
|
|
50762
|
-
for (const
|
|
50763
|
-
for await (const line of jsonLines(
|
|
50764
|
-
let day = days.get(
|
|
51280
|
+
for (const file3 of files.filter((f) => f.kind === "metrics")) {
|
|
51281
|
+
for await (const line of jsonLines(path30.join(dir, file3.name))) {
|
|
51282
|
+
let day = days.get(file3.day);
|
|
50765
51283
|
if (!day) {
|
|
50766
|
-
day = { day:
|
|
50767
|
-
days.set(
|
|
51284
|
+
day = { day: file3.day, records: 0, failed: 0, rawBytes: 0, sanitizedBytes: 0, compressedBytes: 0, envelopeBytes: 0 };
|
|
51285
|
+
days.set(file3.day, day);
|
|
50768
51286
|
}
|
|
50769
51287
|
day.records += 1;
|
|
50770
51288
|
if (line.resultCode !== "SUCCESS") day.failed += 1;
|
|
50771
|
-
day.rawBytes +=
|
|
50772
|
-
day.sanitizedBytes +=
|
|
50773
|
-
day.compressedBytes +=
|
|
50774
|
-
day.envelopeBytes +=
|
|
51289
|
+
day.rawBytes += count3(line.rawBytes);
|
|
51290
|
+
day.sanitizedBytes += count3(line.sanitizedBytes);
|
|
51291
|
+
day.compressedBytes += count3(line.compressedBytes);
|
|
51292
|
+
day.envelopeBytes += count3(line.envelopeBytes);
|
|
50775
51293
|
if (sizes.length < 1e5) {
|
|
50776
|
-
sizes.push(
|
|
50777
|
-
timings.push(
|
|
51294
|
+
sizes.push(count3(line.envelopeBytes));
|
|
51295
|
+
timings.push(count3(line.encryptMs));
|
|
50778
51296
|
}
|
|
50779
51297
|
}
|
|
50780
51298
|
}
|
|
50781
51299
|
let paused = null;
|
|
50782
51300
|
try {
|
|
50783
|
-
const value = JSON.parse(await
|
|
51301
|
+
const value = JSON.parse(await readFile13(path30.join(dir, PAUSED_FILE), "utf8"));
|
|
50784
51302
|
if (typeof value.reason === "string" && typeof value.at === "string") paused = { reason: value.reason.slice(0, 40), at: value.at.slice(0, 40) };
|
|
50785
51303
|
} catch {
|
|
50786
51304
|
}
|
|
@@ -50788,7 +51306,7 @@ async function summarizeContentAudit(directory, key) {
|
|
|
50788
51306
|
const newest = files.filter((f) => f.kind === "full").at(-1);
|
|
50789
51307
|
if (key && newest) {
|
|
50790
51308
|
const tail = [];
|
|
50791
|
-
for await (const line of jsonLines(
|
|
51309
|
+
for await (const line of jsonLines(path30.join(dir, newest.name))) {
|
|
50792
51310
|
tail.push(line);
|
|
50793
51311
|
if (tail.length > 5) tail.shift();
|
|
50794
51312
|
}
|
|
@@ -50806,7 +51324,7 @@ async function summarizeContentAudit(directory, key) {
|
|
|
50806
51324
|
const rawBytes = total("rawBytes"), envelopeBytes = total("envelopeBytes");
|
|
50807
51325
|
return {
|
|
50808
51326
|
directory: dir,
|
|
50809
|
-
fileBytes: files.reduce((sum,
|
|
51327
|
+
fileBytes: files.reduce((sum, file3) => sum + file3.bytes, 0),
|
|
50810
51328
|
paused,
|
|
50811
51329
|
records: total("records"),
|
|
50812
51330
|
rawBytes,
|
|
@@ -50822,10 +51340,10 @@ async function summarizeContentAudit(directory, key) {
|
|
|
50822
51340
|
};
|
|
50823
51341
|
}
|
|
50824
51342
|
async function restoreContentAudit(input2, output2, key) {
|
|
50825
|
-
const handle = await
|
|
51343
|
+
const handle = await open13(path30.resolve(output2), "wx", 384);
|
|
50826
51344
|
let records = 0, failed = 0;
|
|
50827
51345
|
try {
|
|
50828
|
-
for await (const line of jsonLines(
|
|
51346
|
+
for await (const line of jsonLines(path30.resolve(input2))) {
|
|
50829
51347
|
try {
|
|
50830
51348
|
await handle.appendFile(JSON.stringify(decryptAuditRecord(line, key)) + "\n");
|
|
50831
51349
|
records += 1;
|
|
@@ -50840,7 +51358,7 @@ async function restoreContentAudit(input2, output2, key) {
|
|
|
50840
51358
|
}
|
|
50841
51359
|
|
|
50842
51360
|
// agent/src/main.ts
|
|
50843
|
-
var AGENT_VERSION2 = true ? "0.3.
|
|
51361
|
+
var AGENT_VERSION2 = true ? "0.3.52" : "0.3.2";
|
|
50844
51362
|
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" : "";
|
|
50845
51363
|
var AI_CONNECTION_SHIPPED = false;
|
|
50846
51364
|
var QUARANTINE_RETRY_MS = 6e4;
|
|
@@ -50854,11 +51372,11 @@ function processAlive(pid) {
|
|
|
50854
51372
|
}
|
|
50855
51373
|
}
|
|
50856
51374
|
async function claimAgentProcess(stateDir, runtimeDir, version2) {
|
|
50857
|
-
await
|
|
50858
|
-
const
|
|
51375
|
+
await mkdir16(stateDir, { recursive: true });
|
|
51376
|
+
const file3 = path31.join(stateDir, "agent-process.json");
|
|
50859
51377
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
50860
51378
|
try {
|
|
50861
|
-
const handle = await
|
|
51379
|
+
const handle = await open14(file3, "wx", 384);
|
|
50862
51380
|
try {
|
|
50863
51381
|
await handle.writeFile(JSON.stringify({ pid: process.pid, runtimeDir, version: version2, startedAt: (/* @__PURE__ */ new Date()).toISOString() }) + "\n", "utf8");
|
|
50864
51382
|
} finally {
|
|
@@ -50866,8 +51384,8 @@ async function claimAgentProcess(stateDir, runtimeDir, version2) {
|
|
|
50866
51384
|
}
|
|
50867
51385
|
return async () => {
|
|
50868
51386
|
try {
|
|
50869
|
-
const current2 = JSON.parse(await
|
|
50870
|
-
if (current2.pid === process.pid) await
|
|
51387
|
+
const current2 = JSON.parse(await readFile14(file3, "utf8"));
|
|
51388
|
+
if (current2.pid === process.pid) await rm12(file3, { force: true });
|
|
50871
51389
|
} catch {
|
|
50872
51390
|
}
|
|
50873
51391
|
};
|
|
@@ -50875,12 +51393,12 @@ async function claimAgentProcess(stateDir, runtimeDir, version2) {
|
|
|
50875
51393
|
if (!error62 || typeof error62 !== "object" || !("code" in error62) || error62.code !== "EEXIST") throw error62;
|
|
50876
51394
|
let stale = true;
|
|
50877
51395
|
try {
|
|
50878
|
-
const current2 = JSON.parse(await
|
|
51396
|
+
const current2 = JSON.parse(await readFile14(file3, "utf8"));
|
|
50879
51397
|
stale = typeof current2.pid !== "number" || !processAlive(current2.pid);
|
|
50880
51398
|
} catch {
|
|
50881
51399
|
}
|
|
50882
51400
|
if (!stale) throw Error("AGENT_ALREADY_RUNNING");
|
|
50883
|
-
await
|
|
51401
|
+
await rm12(file3, { force: true });
|
|
50884
51402
|
}
|
|
50885
51403
|
}
|
|
50886
51404
|
throw Error("AGENT_ALREADY_RUNNING");
|
|
@@ -51003,6 +51521,8 @@ async function runAgent(options) {
|
|
|
51003
51521
|
safeSlots: runtime.status().safeSlots,
|
|
51004
51522
|
status: () => runtime.status(),
|
|
51005
51523
|
onIncidentAck: (ack) => incidentProducer.ack(ack),
|
|
51524
|
+
onFullLogChoice: options.onFullLogChoice,
|
|
51525
|
+
...options.tokenUsage ? { onTokenUsageState: (enabled) => options.tokenUsage.state(enabled), onTokenUsageAck: (batchId, result2) => options.tokenUsage.ack(batchId, result2) } : {},
|
|
51006
51526
|
// After bridge.connected, like requests: the journal has recorded this connection first.
|
|
51007
51527
|
onHeldLeases: (bindings) => {
|
|
51008
51528
|
void readyPromise.then(() => bridge.heldLeases(bindings)).catch(() => {
|
|
@@ -51036,6 +51556,7 @@ async function runAgent(options) {
|
|
|
51036
51556
|
await options.journal.prune();
|
|
51037
51557
|
connection.reportStatus?.();
|
|
51038
51558
|
incidentProducer.connected(connection.sendIncidentBatch);
|
|
51559
|
+
options.tokenUsage?.connected(connection.sendTokenUsageBatch);
|
|
51039
51560
|
supervisor.observe({ kind: "connected" });
|
|
51040
51561
|
monitor(() => options.monitor?.setConnection("connected", connection));
|
|
51041
51562
|
if (options.monitor && !connection.monitorFreshnessMs) {
|
|
@@ -51091,8 +51612,13 @@ async function runAgent(options) {
|
|
|
51091
51612
|
clearInterval(legacyMonitorTimer);
|
|
51092
51613
|
legacyMonitorTimer = void 0;
|
|
51093
51614
|
incidentProducer.disconnected();
|
|
51615
|
+
options.tokenUsage?.disconnected();
|
|
51094
51616
|
if (!options.signal.aborted) supervisor.observe({ kind: "disconnected" });
|
|
51095
51617
|
monitor(() => options.monitor?.setConnection("disconnected"));
|
|
51618
|
+
try {
|
|
51619
|
+
options.onFullLogChoice?.(null);
|
|
51620
|
+
} catch {
|
|
51621
|
+
}
|
|
51096
51622
|
connection?.close("agent_disconnect");
|
|
51097
51623
|
await bridge.disconnected();
|
|
51098
51624
|
connection = null;
|
|
@@ -51107,6 +51633,7 @@ async function runAgent(options) {
|
|
|
51107
51633
|
} finally {
|
|
51108
51634
|
fabric?.close();
|
|
51109
51635
|
incidentProducer.close();
|
|
51636
|
+
options.tokenUsage?.close();
|
|
51110
51637
|
supervisor.close();
|
|
51111
51638
|
await options.journal.close();
|
|
51112
51639
|
}
|
|
@@ -51133,10 +51660,10 @@ async function openContentAudit(store, stateDir) {
|
|
|
51133
51660
|
async function main() {
|
|
51134
51661
|
if (!["win32", "linux", "darwin"].includes(process.platform)) throw Error("PLATFORM_UNSUPPORTED");
|
|
51135
51662
|
const appData = process.env.LC_AGENT_DATA_DIR ?? (process.platform === "win32" ? process.env.LOCALAPPDATA : posixDataHome());
|
|
51136
|
-
if (!appData || !
|
|
51137
|
-
const stateDir = process.env.LC_AGENT_STATE_DIR ??
|
|
51138
|
-
const binaryDir =
|
|
51139
|
-
const ownerBridgePath = process.env.LC_OWNER_BRIDGE ??
|
|
51663
|
+
if (!appData || !path31.isAbsolute(appData)) throw Error("APP_DATA_MISSING");
|
|
51664
|
+
const stateDir = process.env.LC_AGENT_STATE_DIR ?? path31.join(appData, "LocalCommander", "Agent");
|
|
51665
|
+
const binaryDir = path31.dirname(process.platform === "win32" ? process.execPath : await realpath10(process.execPath));
|
|
51666
|
+
const ownerBridgePath = process.env.LC_OWNER_BRIDGE ?? path31.join(binaryDir, process.platform === "win32" ? "OwnerBridge.exe" : "owner-store");
|
|
51140
51667
|
const store = await WindowsPrivateStore.open(stateDir, ownerBridgePath);
|
|
51141
51668
|
const command = process.argv[2] ?? "run";
|
|
51142
51669
|
if (process.platform !== "win32" && (command.startsWith("guard-") || command.startsWith("network-"))) throw Error("FEATURE_PLATFORM_UNSUPPORTED");
|
|
@@ -51146,7 +51673,7 @@ async function main() {
|
|
|
51146
51673
|
const pairing = new PairingClient(store, { controlPlaneOrigin: origin, agentVersion: AGENT_VERSION2 });
|
|
51147
51674
|
const begun = await pairing.begin();
|
|
51148
51675
|
process.stdout.write(JSON.stringify({ approvalUrl: begun.approvalUrl, confirmationCode: begun.confirmationCode, expiresAt: begun.expiresAt.toISOString() }) + "\n");
|
|
51149
|
-
await pairing.waitAndComplete(begun,
|
|
51676
|
+
await pairing.waitAndComplete(begun, os9.hostname().slice(0, 120));
|
|
51150
51677
|
process.stdout.write("DEVICE_PAIRED\n");
|
|
51151
51678
|
return;
|
|
51152
51679
|
}
|
|
@@ -51155,7 +51682,8 @@ async function main() {
|
|
|
51155
51682
|
process.stdout.write(JSON.stringify({
|
|
51156
51683
|
paired: !!identity?.enrollment,
|
|
51157
51684
|
accountEmail: identity?.enrollment?.accountEmail ?? null,
|
|
51158
|
-
deviceId: identity?.enrollment?.deviceId ?? null
|
|
51685
|
+
deviceId: identity?.enrollment?.deviceId ?? null,
|
|
51686
|
+
fullLogs: await readFullLogNotice(stateDir, identity?.enrollment)
|
|
51159
51687
|
}) + "\n");
|
|
51160
51688
|
return;
|
|
51161
51689
|
}
|
|
@@ -51231,7 +51759,7 @@ async function main() {
|
|
|
51231
51759
|
}
|
|
51232
51760
|
if (command === "efficiency-report") {
|
|
51233
51761
|
if (args.length) throw Error("AGENT_COMMAND_INVALID");
|
|
51234
|
-
const ledger = await OptimizationLedger.open(
|
|
51762
|
+
const ledger = await OptimizationLedger.open(path31.join(stateDir, "optimization"));
|
|
51235
51763
|
try {
|
|
51236
51764
|
process.stdout.write(JSON.stringify(await ledger.report(), null, 2) + "\n");
|
|
51237
51765
|
} finally {
|
|
@@ -51241,7 +51769,7 @@ async function main() {
|
|
|
51241
51769
|
}
|
|
51242
51770
|
if (command === "guard-configure") {
|
|
51243
51771
|
if (args.length !== 1) throw Error("AGENT_COMMAND_INVALID");
|
|
51244
|
-
const filename = await (await import("node:fs/promises")).realpath(
|
|
51772
|
+
const filename = await (await import("node:fs/promises")).realpath(path31.resolve(args[0]));
|
|
51245
51773
|
const input2 = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readWindowsFile(ownerBridgePath, filename, 2e5)));
|
|
51246
51774
|
if (!input2 || typeof input2 !== "object" || Object.keys(input2).sort().join(",") !== "compact,settings") throw Error("GUARD_CONFIGURATION_INVALID");
|
|
51247
51775
|
await store.configureGuard(input2.settings, input2.compact);
|
|
@@ -51260,7 +51788,7 @@ async function main() {
|
|
|
51260
51788
|
}
|
|
51261
51789
|
if (command === "guard-evidence") {
|
|
51262
51790
|
if (args.length) throw Error("AGENT_COMMAND_INVALID");
|
|
51263
|
-
const journal = await NativeJournal.open(
|
|
51791
|
+
const journal = await NativeJournal.open(path31.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
|
|
51264
51792
|
try {
|
|
51265
51793
|
process.stdout.write(JSON.stringify(await journal.guardEvidence()) + "\n");
|
|
51266
51794
|
} finally {
|
|
@@ -51272,7 +51800,7 @@ async function main() {
|
|
|
51272
51800
|
if (args.length !== (command === "guard-export" ? 0 : 1)) throw Error("AGENT_COMMAND_INVALID");
|
|
51273
51801
|
const identity = await store.load();
|
|
51274
51802
|
if (!identity?.enrollment) throw Error("ENROLLMENT_MISSING");
|
|
51275
|
-
const journal = await NativeJournal.open(
|
|
51803
|
+
const journal = await NativeJournal.open(path31.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
|
|
51276
51804
|
try {
|
|
51277
51805
|
const { tenantId, deviceId } = identity.enrollment;
|
|
51278
51806
|
const records = (await journal.guardEvidence()).filter((record2) => record2.tenantId === tenantId && record2.deviceId === deviceId);
|
|
@@ -51350,33 +51878,40 @@ async function main() {
|
|
|
51350
51878
|
if (args.length) throw Error("AGENT_COMMAND_INVALID");
|
|
51351
51879
|
if (!(await store.load())?.enrollment) throw Error("ENROLLMENT_MISSING");
|
|
51352
51880
|
const releaseProcess = await claimAgentProcess(stateDir, binaryDir, AGENT_VERSION2);
|
|
51353
|
-
const monitor = new ProductionMonitor(
|
|
51881
|
+
const monitor = new ProductionMonitor(path31.join(appData, "LocalCommander", "Monitor"), stateDir, AGENT_VERSION2);
|
|
51354
51882
|
const publishMonitor = () => monitor.flush().catch(() => {
|
|
51355
51883
|
process.stderr.write("MONITOR_WRITE_FAILED\n");
|
|
51356
51884
|
});
|
|
51357
51885
|
await publishMonitor();
|
|
51358
51886
|
try {
|
|
51359
51887
|
const journal = await NativeJournal.open(
|
|
51360
|
-
|
|
51888
|
+
path31.join(stateDir, "journal"),
|
|
51361
51889
|
new SecretBox({ "1": await store.loadDataKey() }),
|
|
51362
|
-
process.platform === "win32" ? {} : { lockHelper:
|
|
51890
|
+
process.platform === "win32" ? {} : { lockHelper: path31.join(binaryDir, "posix-host") }
|
|
51363
51891
|
);
|
|
51364
51892
|
const ledgerLoss = () => {
|
|
51365
51893
|
process.stderr.write("OPTIMIZATION_TELEMETRY_INCOMPLETE\n");
|
|
51366
51894
|
};
|
|
51367
51895
|
const efficiencyLedger = await new OptionalWork(ledgerLoss, 1e3, 1).run(
|
|
51368
|
-
() => OptimizationLedger.open(
|
|
51896
|
+
() => OptimizationLedger.open(path31.join(stateDir, "optimization")),
|
|
51369
51897
|
void 0,
|
|
51370
51898
|
(ledger) => ledger.close()
|
|
51371
51899
|
);
|
|
51372
51900
|
try {
|
|
51373
|
-
const helperPath = process.env.LC_JOB_HOST ??
|
|
51901
|
+
const helperPath = process.env.LC_JOB_HOST ?? path31.join(binaryDir, process.platform === "win32" ? "JobHost.exe" : "job-host.mjs");
|
|
51374
51902
|
const tools = new NativeTools({ stateDirectory: stateDir, helperPath, ownerBridgePath, programs: await store.loadPrograms() });
|
|
51375
51903
|
const stop = new AbortController();
|
|
51376
51904
|
process.once("SIGINT", () => stop.abort());
|
|
51377
51905
|
process.once("SIGTERM", () => stop.abort());
|
|
51378
51906
|
const guard = await NativeGuard.open(store, journal);
|
|
51379
51907
|
const enrollment = (await store.load()).enrollment;
|
|
51908
|
+
const fullLogNotice = new FullLogNotice(stateDir, enrollment);
|
|
51909
|
+
const onFullLogChoice = (enabled) => {
|
|
51910
|
+
void fullLogNotice.update(enabled).catch(() => {
|
|
51911
|
+
});
|
|
51912
|
+
};
|
|
51913
|
+
onFullLogChoice(null);
|
|
51914
|
+
const tokenUsage = process.env.LC_TOKEN_USAGE === "off" ? void 0 : new TokenUsageReporter(stateDir, enrollment);
|
|
51380
51915
|
const fabric = await openNativeFabric(stateDir, enrollment, new SecretBox({ "1": await store.loadDataKey() })).catch(() => {
|
|
51381
51916
|
process.stderr.write("FABRIC_STARTUP_FAILED\n");
|
|
51382
51917
|
return void 0;
|
|
@@ -51405,6 +51940,8 @@ async function main() {
|
|
|
51405
51940
|
guard,
|
|
51406
51941
|
efficiencyLedger,
|
|
51407
51942
|
monitor,
|
|
51943
|
+
onFullLogChoice,
|
|
51944
|
+
...tokenUsage ? { tokenUsage } : {},
|
|
51408
51945
|
localDirect: { key: localDirectKey(await store.loadDataKey()), directory: localDirectDirectory(appData) },
|
|
51409
51946
|
supervisorLiveness: supervisorLiveness(helperPath),
|
|
51410
51947
|
...proxyMode ? { proxyMode: { providers: proxyMode.providers, publicKeyPem: NETWORK_PUBLIC_KEY, endpoint: proxyEndpoint, onState: onProxyState } } : {},
|
|
@@ -51441,7 +51978,7 @@ async function main() {
|
|
|
51441
51978
|
await releaseProcess();
|
|
51442
51979
|
}
|
|
51443
51980
|
}
|
|
51444
|
-
var entrypoint = process.argv[1] && (process.platform === "win32" ?
|
|
51981
|
+
var entrypoint = process.argv[1] && (process.platform === "win32" ? path31.resolve(process.argv[1]) : await realpath10(process.argv[1]).catch(() => null));
|
|
51445
51982
|
if (entrypoint === fileURLToPath(import.meta.url)) {
|
|
51446
51983
|
void main().catch((error62) => {
|
|
51447
51984
|
const code = error62 instanceof Error && /^[A-Z0-9_]{1,64}$/.test(error62.message) ? error62.message : "AGENT_START_FAILED";
|