local-commander-agent 0.3.6 → 0.3.9-issue11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -4
- package/bin/command-path.mjs +102 -0
- package/bin/localcommander.mjs +42 -3
- package/bin/monitor.mjs +310 -0
- package/package.json +1 -1
- package/runtime/JobHost.exe +0 -0
- package/runtime/LocalCommanderAgent.exe +0 -0
- package/runtime/OwnerBridge.exe +0 -0
- package/runtime/agent.mjs +2364 -285
package/runtime/agent.mjs
CHANGED
|
@@ -2278,7 +2278,7 @@ var require_websocket = __commonJS({
|
|
|
2278
2278
|
var http = __require("http");
|
|
2279
2279
|
var net = __require("net");
|
|
2280
2280
|
var tls = __require("tls");
|
|
2281
|
-
var { randomBytes:
|
|
2281
|
+
var { randomBytes: randomBytes5, createHash: createHash13 } = __require("crypto");
|
|
2282
2282
|
var { Duplex, Readable } = __require("stream");
|
|
2283
2283
|
var { URL: URL2 } = __require("url");
|
|
2284
2284
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -2829,7 +2829,7 @@ var require_websocket = __commonJS({
|
|
|
2829
2829
|
}
|
|
2830
2830
|
}
|
|
2831
2831
|
const defaultPort = isSecure ? 443 : 80;
|
|
2832
|
-
const key =
|
|
2832
|
+
const key = randomBytes5(16).toString("base64");
|
|
2833
2833
|
const request = isSecure ? https.request : http.request;
|
|
2834
2834
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
2835
2835
|
let perMessageDeflate;
|
|
@@ -2959,8 +2959,8 @@ var require_websocket = __commonJS({
|
|
|
2959
2959
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
2960
2960
|
return;
|
|
2961
2961
|
}
|
|
2962
|
-
const
|
|
2963
|
-
if (res.headers["sec-websocket-accept"] !==
|
|
2962
|
+
const digest5 = createHash13("sha1").update(key + GUID).digest("base64");
|
|
2963
|
+
if (res.headers["sec-websocket-accept"] !== digest5) {
|
|
2964
2964
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
2965
2965
|
return;
|
|
2966
2966
|
}
|
|
@@ -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 open10() {
|
|
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 open10() {
|
|
3265
3265
|
duplex._write(chunk, encoding, callback);
|
|
3266
3266
|
});
|
|
3267
3267
|
return;
|
|
@@ -3328,7 +3328,7 @@ var require_websocket_server = __commonJS({
|
|
|
3328
3328
|
var EventEmitter = __require("events");
|
|
3329
3329
|
var http = __require("http");
|
|
3330
3330
|
var { Duplex } = __require("stream");
|
|
3331
|
-
var { createHash:
|
|
3331
|
+
var { createHash: createHash13 } = __require("crypto");
|
|
3332
3332
|
var extension2 = require_extension();
|
|
3333
3333
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
3334
3334
|
var subprotocol2 = require_subprotocol();
|
|
@@ -3635,12 +3635,12 @@ var require_websocket_server = __commonJS({
|
|
|
3635
3635
|
);
|
|
3636
3636
|
}
|
|
3637
3637
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
3638
|
-
const
|
|
3638
|
+
const digest5 = createHash13("sha1").update(key + GUID).digest("base64");
|
|
3639
3639
|
const headers = [
|
|
3640
3640
|
"HTTP/1.1 101 Switching Protocols",
|
|
3641
3641
|
"Upgrade: websocket",
|
|
3642
3642
|
"Connection: Upgrade",
|
|
3643
|
-
`Sec-WebSocket-Accept: ${
|
|
3643
|
+
`Sec-WebSocket-Accept: ${digest5}`
|
|
3644
3644
|
];
|
|
3645
3645
|
const ws = new this.options.WebSocket(null, void 0, this.options);
|
|
3646
3646
|
if (protocols.size) {
|
|
@@ -3723,9 +3723,9 @@ var require_websocket_server = __commonJS({
|
|
|
3723
3723
|
});
|
|
3724
3724
|
|
|
3725
3725
|
// agent/src/main.ts
|
|
3726
|
-
import
|
|
3727
|
-
import
|
|
3728
|
-
import { mkdir as
|
|
3726
|
+
import path17 from "node:path";
|
|
3727
|
+
import os4 from "node:os";
|
|
3728
|
+
import { mkdir as mkdir9, open as open9, readFile as readFile6, rm as rm5 } from "node:fs/promises";
|
|
3729
3729
|
import { fileURLToPath } from "node:url";
|
|
3730
3730
|
|
|
3731
3731
|
// packages/operations/src/crypto.ts
|
|
@@ -3733,9 +3733,9 @@ import { createCipheriv, createDecipheriv, createHmac, randomBytes, timingSafeEq
|
|
|
3733
3733
|
var SecretBox = class {
|
|
3734
3734
|
constructor(keys, activeId = 1) {
|
|
3735
3735
|
this.activeId = activeId;
|
|
3736
|
-
for (const [
|
|
3737
|
-
const n = Number(
|
|
3738
|
-
if (!Number.isInteger(n) || n < 1 || n > 255 || String(n) !==
|
|
3736
|
+
for (const [id2, value] of Object.entries(keys)) {
|
|
3737
|
+
const n = Number(id2);
|
|
3738
|
+
if (!Number.isInteger(n) || n < 1 || n > 255 || String(n) !== id2 || !Buffer.isBuffer(value) || value.length !== 32) throw Error("INVALID_DATA_KEY");
|
|
3739
3739
|
this.keys.set(n, Buffer.from(value));
|
|
3740
3740
|
}
|
|
3741
3741
|
if (!this.keys.has(activeId)) throw Error("ACTIVE_DATA_KEY_MISSING");
|
|
@@ -4674,18 +4674,18 @@ function mergeDefs(...defs) {
|
|
|
4674
4674
|
function cloneDef(schema) {
|
|
4675
4675
|
return mergeDefs(schema._zod.def);
|
|
4676
4676
|
}
|
|
4677
|
-
function getElementAtPath(obj,
|
|
4678
|
-
if (!
|
|
4677
|
+
function getElementAtPath(obj, path18) {
|
|
4678
|
+
if (!path18)
|
|
4679
4679
|
return obj;
|
|
4680
|
-
return
|
|
4680
|
+
return path18.reduce((acc, key) => acc?.[key], obj);
|
|
4681
4681
|
}
|
|
4682
4682
|
function promiseAllObject(promisesObj) {
|
|
4683
4683
|
const keys = Object.keys(promisesObj);
|
|
4684
4684
|
const promises = keys.map((key) => promisesObj[key]);
|
|
4685
|
-
return Promise.all(promises).then((
|
|
4685
|
+
return Promise.all(promises).then((results2) => {
|
|
4686
4686
|
const resolvedObj = {};
|
|
4687
4687
|
for (let i = 0; i < keys.length; i++) {
|
|
4688
|
-
resolvedObj[keys[i]] =
|
|
4688
|
+
resolvedObj[keys[i]] = results2[i];
|
|
4689
4689
|
}
|
|
4690
4690
|
return resolvedObj;
|
|
4691
4691
|
});
|
|
@@ -5017,11 +5017,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
5017
5017
|
}
|
|
5018
5018
|
return false;
|
|
5019
5019
|
}
|
|
5020
|
-
function prefixIssues(
|
|
5020
|
+
function prefixIssues(path18, issues) {
|
|
5021
5021
|
return issues.map((iss) => {
|
|
5022
5022
|
var _a3;
|
|
5023
5023
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
5024
|
-
iss.path.unshift(
|
|
5024
|
+
iss.path.unshift(path18);
|
|
5025
5025
|
return iss;
|
|
5026
5026
|
});
|
|
5027
5027
|
}
|
|
@@ -5471,16 +5471,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
|
|
|
5471
5471
|
}
|
|
5472
5472
|
function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
5473
5473
|
const fieldErrors = { _errors: [] };
|
|
5474
|
-
const processError = (error63,
|
|
5474
|
+
const processError = (error63, path18 = []) => {
|
|
5475
5475
|
for (const issue2 of error63.issues) {
|
|
5476
5476
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
5477
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
5477
|
+
issue2.errors.map((issues) => processError({ issues }, [...path18, ...issue2.path]));
|
|
5478
5478
|
} else if (issue2.code === "invalid_key") {
|
|
5479
|
-
processError({ issues: issue2.issues }, [...
|
|
5479
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
5480
5480
|
} else if (issue2.code === "invalid_element") {
|
|
5481
|
-
processError({ issues: issue2.issues }, [...
|
|
5481
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
5482
5482
|
} else {
|
|
5483
|
-
const fullpath = [...
|
|
5483
|
+
const fullpath = [...path18, ...issue2.path];
|
|
5484
5484
|
if (fullpath.length === 0) {
|
|
5485
5485
|
fieldErrors._errors.push(mapper(issue2));
|
|
5486
5486
|
} else {
|
|
@@ -5519,17 +5519,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
|
5519
5519
|
}
|
|
5520
5520
|
function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
5521
5521
|
const result2 = { errors: [] };
|
|
5522
|
-
const processError = (error63,
|
|
5522
|
+
const processError = (error63, path18 = []) => {
|
|
5523
5523
|
var _a3;
|
|
5524
5524
|
for (const issue2 of error63.issues) {
|
|
5525
5525
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
5526
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
5526
|
+
issue2.errors.map((issues) => processError({ issues }, [...path18, ...issue2.path]));
|
|
5527
5527
|
} else if (issue2.code === "invalid_key") {
|
|
5528
|
-
processError({ issues: issue2.issues }, [...
|
|
5528
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
5529
5529
|
} else if (issue2.code === "invalid_element") {
|
|
5530
|
-
processError({ issues: issue2.issues }, [...
|
|
5530
|
+
processError({ issues: issue2.issues }, [...path18, ...issue2.path]);
|
|
5531
5531
|
} else {
|
|
5532
|
-
const fullpath = [...
|
|
5532
|
+
const fullpath = [...path18, ...issue2.path];
|
|
5533
5533
|
if (fullpath.length === 0) {
|
|
5534
5534
|
result2.errors.push(mapper(issue2));
|
|
5535
5535
|
continue;
|
|
@@ -5568,8 +5568,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
|
5568
5568
|
}
|
|
5569
5569
|
function toDotPath(_path) {
|
|
5570
5570
|
const segs = [];
|
|
5571
|
-
const
|
|
5572
|
-
for (const seg of
|
|
5571
|
+
const path18 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
5572
|
+
for (const seg of path18) {
|
|
5573
5573
|
if (typeof seg === "number")
|
|
5574
5574
|
segs.push(`[${seg}]`);
|
|
5575
5575
|
else if (typeof seg === "symbol")
|
|
@@ -7437,15 +7437,15 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
7437
7437
|
const syms = normalized.symbolKeys;
|
|
7438
7438
|
const doc = new Doc(["payload", "ctx"], { shape, inst, memo: memo2, syms });
|
|
7439
7439
|
const parseStr = (k) => `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
|
|
7440
|
-
const prefixStr = (
|
|
7441
|
-
let ${
|
|
7442
|
-
for (let i = 0; i < ${
|
|
7443
|
-
const iss = ${
|
|
7440
|
+
const prefixStr = (id2, k) => `
|
|
7441
|
+
let ${id2}_ab = false;
|
|
7442
|
+
for (let i = 0; i < ${id2}.issues.length; i++) {
|
|
7443
|
+
const iss = ${id2}.issues[i];
|
|
7444
7444
|
iss.path = iss.path ? [${k}, ...iss.path] : [${k}];
|
|
7445
7445
|
payload.issues.push(iss);
|
|
7446
|
-
if (iss.continue !== true) ${
|
|
7446
|
+
if (iss.continue !== true) ${id2}_ab = true;
|
|
7447
7447
|
}
|
|
7448
|
-
if (${
|
|
7448
|
+
if (${id2}_ab && ctx && ctx.abortEarly) {
|
|
7449
7449
|
payload.value = newResult;
|
|
7450
7450
|
return payload;
|
|
7451
7451
|
}`;
|
|
@@ -7459,34 +7459,34 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
7459
7459
|
for (const key of normalized.allKeys) {
|
|
7460
7460
|
if (key === "__proto__")
|
|
7461
7461
|
continue;
|
|
7462
|
-
const
|
|
7462
|
+
const id2 = ids[key];
|
|
7463
7463
|
const k = typeof key === "symbol" ? `syms[${syms.indexOf(key)}]` : esc(key);
|
|
7464
7464
|
const isPresent = `${k} in input`;
|
|
7465
7465
|
const schema = shape[key];
|
|
7466
7466
|
const optin = schema?._zod?.optin;
|
|
7467
7467
|
const isOptionalIn = optin !== void 0;
|
|
7468
7468
|
const isOptionalOut = schema?._zod?.optout === "optional";
|
|
7469
|
-
doc.write(`const ${
|
|
7469
|
+
doc.write(`const ${id2} = ${parseStr(k)};`);
|
|
7470
7470
|
if (isOptionalIn && isOptionalOut) {
|
|
7471
|
-
const assign = optin === "optional" ? `${
|
|
7471
|
+
const assign = optin === "optional" ? `${id2}_present` : `${id2}.value !== undefined || ${id2}_present`;
|
|
7472
7472
|
doc.write(`
|
|
7473
|
-
const ${
|
|
7474
|
-
if (!${
|
|
7475
|
-
if (${
|
|
7473
|
+
const ${id2}_present = ${isPresent};
|
|
7474
|
+
if (!${id2}.issues.length || ${id2}_present) {
|
|
7475
|
+
if (${id2}.issues.length) {${prefixStr(id2, k)}
|
|
7476
7476
|
}
|
|
7477
7477
|
|
|
7478
7478
|
if (${assign}) {
|
|
7479
|
-
newResult[${k}] = ${
|
|
7479
|
+
newResult[${k}] = ${id2}.value;
|
|
7480
7480
|
}
|
|
7481
7481
|
}
|
|
7482
7482
|
|
|
7483
7483
|
`);
|
|
7484
7484
|
} else if (!isOptionalIn) {
|
|
7485
7485
|
doc.write(`
|
|
7486
|
-
const ${
|
|
7487
|
-
if (${
|
|
7486
|
+
const ${id2}_present = ${isPresent};
|
|
7487
|
+
if (${id2}.issues.length) {${prefixStr(id2, k)}
|
|
7488
7488
|
}
|
|
7489
|
-
if (!${
|
|
7489
|
+
if (!${id2}_present && !${id2}.issues.length) {
|
|
7490
7490
|
payload.issues.push({
|
|
7491
7491
|
code: "invalid_type",
|
|
7492
7492
|
expected: "nonoptional",
|
|
@@ -7499,22 +7499,22 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
7499
7499
|
}
|
|
7500
7500
|
}
|
|
7501
7501
|
|
|
7502
|
-
if (${
|
|
7503
|
-
newResult[${k}] = ${
|
|
7502
|
+
if (${id2}_present) {
|
|
7503
|
+
newResult[${k}] = ${id2}.value;
|
|
7504
7504
|
}
|
|
7505
7505
|
|
|
7506
7506
|
`);
|
|
7507
7507
|
} else {
|
|
7508
7508
|
doc.write(`
|
|
7509
|
-
if (${
|
|
7509
|
+
if (${id2}.issues.length) {${prefixStr(id2, k)}
|
|
7510
7510
|
}
|
|
7511
7511
|
`);
|
|
7512
7512
|
if (optin === "defaulted") {
|
|
7513
|
-
doc.write(`newResult[${k}] = ${
|
|
7513
|
+
doc.write(`newResult[${k}] = ${id2}.value;`);
|
|
7514
7514
|
} else {
|
|
7515
7515
|
doc.write(`
|
|
7516
|
-
if (${
|
|
7517
|
-
newResult[${k}] = ${
|
|
7516
|
+
if (${id2}.value !== undefined || ${isPresent}) {
|
|
7517
|
+
newResult[${k}] = ${id2}.value;
|
|
7518
7518
|
}
|
|
7519
7519
|
`);
|
|
7520
7520
|
}
|
|
@@ -7554,14 +7554,14 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
7554
7554
|
return superParse(payload, ctx);
|
|
7555
7555
|
};
|
|
7556
7556
|
});
|
|
7557
|
-
function handleUnionResults(
|
|
7558
|
-
for (const result2 of
|
|
7557
|
+
function handleUnionResults(results2, final, inst, ctx) {
|
|
7558
|
+
for (const result2 of results2) {
|
|
7559
7559
|
if (result2.issues.length === 0) {
|
|
7560
7560
|
final.value = result2.value;
|
|
7561
7561
|
return final;
|
|
7562
7562
|
}
|
|
7563
7563
|
}
|
|
7564
|
-
const nonaborted =
|
|
7564
|
+
const nonaborted = results2.filter((r) => !aborted(r));
|
|
7565
7565
|
if (nonaborted.length === 1) {
|
|
7566
7566
|
final.value = nonaborted[0].value;
|
|
7567
7567
|
return nonaborted[0];
|
|
@@ -7570,7 +7570,7 @@ function handleUnionResults(results, final, inst, ctx) {
|
|
|
7570
7570
|
code: "invalid_union",
|
|
7571
7571
|
input: final.value,
|
|
7572
7572
|
inst,
|
|
7573
|
-
errors:
|
|
7573
|
+
errors: results2.map((result2) => result2.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
7574
7574
|
});
|
|
7575
7575
|
return final;
|
|
7576
7576
|
}
|
|
@@ -7597,36 +7597,36 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
|
|
|
7597
7597
|
return first(payload, ctx);
|
|
7598
7598
|
}
|
|
7599
7599
|
let async = false;
|
|
7600
|
-
const
|
|
7600
|
+
const results2 = [];
|
|
7601
7601
|
for (const option of def.options) {
|
|
7602
7602
|
const result2 = option._zod.run({
|
|
7603
7603
|
value: payload.value,
|
|
7604
7604
|
issues: []
|
|
7605
7605
|
}, ctx);
|
|
7606
7606
|
if (result2 instanceof Promise) {
|
|
7607
|
-
|
|
7607
|
+
results2.push(result2);
|
|
7608
7608
|
async = true;
|
|
7609
7609
|
} else {
|
|
7610
7610
|
if (result2.issues.length === 0)
|
|
7611
7611
|
return result2;
|
|
7612
|
-
|
|
7612
|
+
results2.push(result2);
|
|
7613
7613
|
}
|
|
7614
7614
|
}
|
|
7615
7615
|
if (!async)
|
|
7616
|
-
return handleUnionResults(results, payload, inst, ctx);
|
|
7617
|
-
return Promise.all(results).then((results2) => {
|
|
7618
7616
|
return handleUnionResults(results2, payload, inst, ctx);
|
|
7617
|
+
return Promise.all(results2).then((results3) => {
|
|
7618
|
+
return handleUnionResults(results3, payload, inst, ctx);
|
|
7619
7619
|
});
|
|
7620
7620
|
};
|
|
7621
7621
|
});
|
|
7622
|
-
function handleExclusiveUnionResults(
|
|
7622
|
+
function handleExclusiveUnionResults(results2, final, inst, ctx) {
|
|
7623
7623
|
const matches2 = [];
|
|
7624
|
-
for (let i = 0; i <
|
|
7625
|
-
if (
|
|
7624
|
+
for (let i = 0; i < results2.length; i++) {
|
|
7625
|
+
if (results2[i].issues.length === 0)
|
|
7626
7626
|
matches2.push(i);
|
|
7627
7627
|
}
|
|
7628
7628
|
if (matches2.length === 1) {
|
|
7629
|
-
final.value =
|
|
7629
|
+
final.value = results2[matches2[0]].value;
|
|
7630
7630
|
return final;
|
|
7631
7631
|
}
|
|
7632
7632
|
if (matches2.length === 0) {
|
|
@@ -7634,7 +7634,7 @@ function handleExclusiveUnionResults(results, final, inst, ctx) {
|
|
|
7634
7634
|
code: "invalid_union",
|
|
7635
7635
|
input: final.value,
|
|
7636
7636
|
inst,
|
|
7637
|
-
errors:
|
|
7637
|
+
errors: results2.map((result2) => result2.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
7638
7638
|
});
|
|
7639
7639
|
} else {
|
|
7640
7640
|
final.issues.push({
|
|
@@ -7657,23 +7657,23 @@ var $ZodXor = /* @__PURE__ */ $constructor("$ZodXor", (inst, def) => {
|
|
|
7657
7657
|
return first(payload, ctx);
|
|
7658
7658
|
}
|
|
7659
7659
|
let async = false;
|
|
7660
|
-
const
|
|
7660
|
+
const results2 = [];
|
|
7661
7661
|
for (const option of def.options) {
|
|
7662
7662
|
const result2 = option._zod.run({
|
|
7663
7663
|
value: payload.value,
|
|
7664
7664
|
issues: []
|
|
7665
7665
|
}, ctx);
|
|
7666
7666
|
if (result2 instanceof Promise) {
|
|
7667
|
-
|
|
7667
|
+
results2.push(result2);
|
|
7668
7668
|
async = true;
|
|
7669
7669
|
} else {
|
|
7670
|
-
|
|
7670
|
+
results2.push(result2);
|
|
7671
7671
|
}
|
|
7672
7672
|
}
|
|
7673
7673
|
if (!async)
|
|
7674
|
-
return handleExclusiveUnionResults(results, payload, inst, ctx);
|
|
7675
|
-
return Promise.all(results).then((results2) => {
|
|
7676
7674
|
return handleExclusiveUnionResults(results2, payload, inst, ctx);
|
|
7675
|
+
return Promise.all(results2).then((results3) => {
|
|
7676
|
+
return handleExclusiveUnionResults(results3, payload, inst, ctx);
|
|
7677
7677
|
});
|
|
7678
7678
|
};
|
|
7679
7679
|
});
|
|
@@ -19532,26 +19532,26 @@ function extractDefs(ctx, schema) {
|
|
|
19532
19532
|
return;
|
|
19533
19533
|
const idToSchema = /* @__PURE__ */ new Map();
|
|
19534
19534
|
for (const entry of ctx.seen.entries()) {
|
|
19535
|
-
const
|
|
19536
|
-
if (
|
|
19537
|
-
const existing = idToSchema.get(
|
|
19535
|
+
const id2 = ctx.metadataRegistry.get(entry[0])?.id;
|
|
19536
|
+
if (id2) {
|
|
19537
|
+
const existing = idToSchema.get(id2);
|
|
19538
19538
|
if (existing && existing !== entry[0]) {
|
|
19539
|
-
throw new Error(`Duplicate schema id "${
|
|
19539
|
+
throw new Error(`Duplicate schema id "${id2}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
|
|
19540
19540
|
}
|
|
19541
|
-
idToSchema.set(
|
|
19541
|
+
idToSchema.set(id2, entry[0]);
|
|
19542
19542
|
}
|
|
19543
19543
|
}
|
|
19544
19544
|
const makeURI = (entry) => {
|
|
19545
19545
|
const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
|
|
19546
19546
|
if (ctx.external) {
|
|
19547
19547
|
const externalId = ctx.external.registry.get(entry[0])?.id;
|
|
19548
|
-
const uriGenerator = ctx.external.uri ?? ((
|
|
19548
|
+
const uriGenerator = ctx.external.uri ?? ((id3) => id3);
|
|
19549
19549
|
if (externalId) {
|
|
19550
19550
|
return { ref: uriGenerator(externalId) };
|
|
19551
19551
|
}
|
|
19552
|
-
const
|
|
19553
|
-
entry[1].defId =
|
|
19554
|
-
return { defId:
|
|
19552
|
+
const id2 = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
|
|
19553
|
+
entry[1].defId = id2;
|
|
19554
|
+
return { defId: id2, ref: `${uriGenerator("__shared")}#/${defsSegment}/${encodeJSONPointerSegment(id2)}` };
|
|
19555
19555
|
}
|
|
19556
19556
|
const uriPrefix = `#`;
|
|
19557
19557
|
const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
|
|
@@ -19599,8 +19599,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19599
19599
|
continue;
|
|
19600
19600
|
}
|
|
19601
19601
|
}
|
|
19602
|
-
const
|
|
19603
|
-
if (
|
|
19602
|
+
const id2 = ctx.metadataRegistry.get(entry[0])?.id;
|
|
19603
|
+
if (id2) {
|
|
19604
19604
|
extractToDef(entry);
|
|
19605
19605
|
continue;
|
|
19606
19606
|
}
|
|
@@ -19833,10 +19833,10 @@ function finalize(ctx, schema) {
|
|
|
19833
19833
|
} else {
|
|
19834
19834
|
}
|
|
19835
19835
|
if (ctx.external?.uri) {
|
|
19836
|
-
const
|
|
19837
|
-
if (!
|
|
19836
|
+
const id2 = ctx.external.registry.get(schema)?.id;
|
|
19837
|
+
if (!id2)
|
|
19838
19838
|
throw new Error("Schema is missing an `id` property");
|
|
19839
|
-
result2.$id = ctx.external.uri(
|
|
19839
|
+
result2.$id = ctx.external.uri(id2);
|
|
19840
19840
|
}
|
|
19841
19841
|
assignProps(result2, root.defId ? root.schema : root.def ?? root.schema);
|
|
19842
19842
|
const rootMetaId = ctx.metadataRegistry.get(schema)?.id;
|
|
@@ -20442,7 +20442,7 @@ function stringifyKeyNames(bySchema, json2, visited) {
|
|
|
20442
20442
|
const values = json2.enum ?? (json2.const !== void 0 ? [json2.const] : void 0);
|
|
20443
20443
|
if (!numericType && !values?.some((v) => typeof v === "number"))
|
|
20444
20444
|
return json2;
|
|
20445
|
-
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } = json2;
|
|
20445
|
+
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id: id2, ...rest } = json2;
|
|
20446
20446
|
if (rest.enum)
|
|
20447
20447
|
rest.enum = rest.enum.map((v) => typeof v === "number" ? String(v) : v);
|
|
20448
20448
|
else if (typeof rest.const === "number")
|
|
@@ -22671,13 +22671,13 @@ function resolveRef(ref, ctx) {
|
|
|
22671
22671
|
if (!ref.startsWith("#")) {
|
|
22672
22672
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
22673
22673
|
}
|
|
22674
|
-
const
|
|
22675
|
-
if (
|
|
22674
|
+
const path18 = ref.slice(1).split("/").filter(Boolean);
|
|
22675
|
+
if (path18.length === 0) {
|
|
22676
22676
|
return ctx.rootSchema;
|
|
22677
22677
|
}
|
|
22678
22678
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
22679
|
-
if (
|
|
22680
|
-
const key =
|
|
22679
|
+
if (path18[0] === defsKey) {
|
|
22680
|
+
const key = path18[1] === void 0 ? void 0 : decodeJSONPointerSegment(path18[1]);
|
|
22681
22681
|
if (!key || !ctx.defs[key]) {
|
|
22682
22682
|
throw new Error(`Reference not found: ${ref}`);
|
|
22683
22683
|
}
|
|
@@ -24438,6 +24438,9 @@ var hash2 = external_exports.string().regex(/^[a-f0-9]{64}$/);
|
|
|
24438
24438
|
var epoch = external_exports.string().regex(/^[1-9]\d{0,18}$/).refine((v) => BigInt(v) <= 9223372036854775807n);
|
|
24439
24439
|
var text = external_exports.string().max(32767).refine((v) => !v.includes("\0"));
|
|
24440
24440
|
var timestamp = external_exports.iso.datetime({ offset: false });
|
|
24441
|
+
var EfficiencyProfileSchema = external_exports.object({
|
|
24442
|
+
model: external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:/+-]{0,79}$/)
|
|
24443
|
+
}).strict();
|
|
24441
24444
|
var path = text.min(1);
|
|
24442
24445
|
var ToolCallSchema = external_exports.discriminatedUnion("name", [
|
|
24443
24446
|
external_exports.object({ name: external_exports.literal("fs_list"), args: external_exports.object({ path: path.optional(), recursive: external_exports.boolean().default(false), maxDepth: external_exports.number().int().min(0).max(8).default(3), maxEntries: external_exports.number().int().min(1).max(1e3).default(200) }).strict() }).strict(),
|
|
@@ -24448,7 +24451,7 @@ var ToolCallSchema = external_exports.discriminatedUnion("name", [
|
|
|
24448
24451
|
external_exports.object({ name: external_exports.literal("git_status"), args: external_exports.object({ path: path.optional() }).strict() }).strict(),
|
|
24449
24452
|
external_exports.object({ name: external_exports.literal("git_diff"), args: external_exports.object({ path: path.optional(), file: path.optional(), staged: external_exports.boolean().default(false) }).strict() }).strict(),
|
|
24450
24453
|
external_exports.object({ name: external_exports.literal("git_log"), args: external_exports.object({ path: path.optional(), limit: external_exports.number().int().min(1).max(50).default(15) }).strict() }).strict(),
|
|
24451
|
-
external_exports.object({ name: external_exports.literal("project_snapshot"), args: external_exports.object({ path: path.optional() }).strict() }).strict(),
|
|
24454
|
+
external_exports.object({ name: external_exports.literal("project_snapshot"), args: external_exports.object({ path: path.optional(), startup: external_exports.boolean().optional(), taskId: external_exports.string().regex(/^[A-Za-z0-9_-]{1,100}$/).optional() }).strict() }).strict(),
|
|
24452
24455
|
external_exports.object({ name: external_exports.literal("command_run"), args: external_exports.object({ command: external_exports.string().min(1).max(260).refine((v) => !/[\r\n\0]/.test(v)), args: external_exports.array(external_exports.string().max(8192).refine((v) => !v.includes("\0"))).max(128).default([]), cwd: path.optional(), timeoutMs: external_exports.number().int().min(100).max(864e5).default(6e4) }).strict() }).strict(),
|
|
24453
24456
|
external_exports.object({ name: external_exports.literal("localhost_request"), args: external_exports.object({ url: external_exports.string().url().max(2048), method: external_exports.enum(["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"]).default("GET"), headers: external_exports.record(external_exports.string().max(128), external_exports.string().max(2048)).optional(), body: external_exports.string().max(6e4).optional() }).strict() }).strict()
|
|
24454
24457
|
]);
|
|
@@ -24483,6 +24486,8 @@ var ClientFrameSchema = external_exports.discriminatedUnion("type", [
|
|
|
24483
24486
|
]);
|
|
24484
24487
|
var TerminalMetricsSchema = external_exports.object({ stdoutBytes: external_exports.number().int().min(0).max(4194304), stderrBytes: external_exports.number().int().min(0).max(4194304), outputTruncated: external_exports.boolean() }).strict();
|
|
24485
24488
|
var TERMINAL_METRICS_CAPABILITY = "terminalMetrics";
|
|
24489
|
+
var NATIVE_CAPACITY_CAPABILITY = "nativeCapacity";
|
|
24490
|
+
var NativeCapacitySchema = external_exports.object({ type: external_exports.literal("nativeCapacity"), protocolVersion: external_exports.literal(1), connectionEpoch: epoch, safeSlots: external_exports.number().int().min(1).max(32), agentVersion: external_exports.string().regex(/^[A-Za-z0-9._+-]{1,64}$/) }).strict();
|
|
24486
24491
|
var TerminalEventSchema = external_exports.object({ type: external_exports.literal("executionResult"), protocolVersion: external_exports.literal(1), requestId: uuid8, tenantId: uuid8, deviceId: uuid8, connectionEpoch: epoch, binding: ExecutionBindingSchema, state: external_exports.enum(["finished", "failed", "cancelled", "unknown"]), resultCode: external_exports.string().regex(/^[A-Z0-9_]{1,40}$/), metrics: TerminalMetricsSchema.optional() }).strict();
|
|
24487
24492
|
var TerminalEventAckSchema = external_exports.object({ type: external_exports.literal("executionResultAck"), protocolVersion: external_exports.literal(1), requestId: uuid8, ok: external_exports.boolean() }).strict();
|
|
24488
24493
|
function canonicalJson(value) {
|
|
@@ -24621,9 +24626,9 @@ var GuardEvidenceRecordSchema = external_exports.object({
|
|
|
24621
24626
|
function verifyGuardEvidence(input2) {
|
|
24622
24627
|
const events = external_exports.array(GuardEventSchema).min(1).max(12).parse(input2);
|
|
24623
24628
|
let previous = "0".repeat(64);
|
|
24624
|
-
for (const { hash:
|
|
24625
|
-
if (record2.previousHash !== previous || guardHash(record2) !==
|
|
24626
|
-
previous =
|
|
24629
|
+
for (const { hash: digest5, ...record2 } of events) {
|
|
24630
|
+
if (record2.previousHash !== previous || guardHash(record2) !== digest5 || record2.event.content.mode !== "none") throw Error("GUARD_EVIDENCE_INVALID");
|
|
24631
|
+
previous = digest5;
|
|
24627
24632
|
}
|
|
24628
24633
|
return events;
|
|
24629
24634
|
}
|
|
@@ -24795,17 +24800,17 @@ var NativeJournal = class _NativeJournal {
|
|
|
24795
24800
|
});
|
|
24796
24801
|
return next;
|
|
24797
24802
|
}
|
|
24798
|
-
file(
|
|
24799
|
-
return path2.join(this.dir,
|
|
24803
|
+
file(id2) {
|
|
24804
|
+
return path2.join(this.dir, id2 + ".entry");
|
|
24800
24805
|
}
|
|
24801
|
-
need(
|
|
24802
|
-
if (!uuid11.test(
|
|
24803
|
-
const e = this.entries.get(
|
|
24806
|
+
need(id2) {
|
|
24807
|
+
if (!uuid11.test(id2)) throw failure2("JOURNAL_INPUT_INVALID");
|
|
24808
|
+
const e = this.entries.get(id2);
|
|
24804
24809
|
if (!e) throw failure2("EXECUTION_UNKNOWN");
|
|
24805
24810
|
return clone2(e);
|
|
24806
24811
|
}
|
|
24807
|
-
async readOwned(
|
|
24808
|
-
const filename = this.file(
|
|
24812
|
+
async readOwned(id2) {
|
|
24813
|
+
const filename = this.file(id2), stat = await lstat(filename);
|
|
24809
24814
|
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_ENVELOPE) throw failure2("JOURNAL_CORRUPT");
|
|
24810
24815
|
const handle = await open2(filename, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
24811
24816
|
try {
|
|
@@ -24821,30 +24826,30 @@ var NativeJournal = class _NativeJournal {
|
|
|
24821
24826
|
if (names.length > this.options.maxEntries + 256) throw failure2("JOURNAL_CAPACITY_EXCEEDED");
|
|
24822
24827
|
for (const name2 of names) {
|
|
24823
24828
|
if (!name2.endsWith(".entry")) continue;
|
|
24824
|
-
const
|
|
24825
|
-
if (!uuid11.test(
|
|
24826
|
-
const envelope = await this.readOwned(
|
|
24829
|
+
const id2 = name2.slice(0, -6);
|
|
24830
|
+
if (!uuid11.test(id2)) throw failure2("JOURNAL_CORRUPT");
|
|
24831
|
+
const envelope = await this.readOwned(id2);
|
|
24827
24832
|
this.totalBytes += envelope.length;
|
|
24828
24833
|
if (this.totalBytes > this.options.maxBytes || this.entries.size >= this.options.maxEntries) throw failure2("JOURNAL_CAPACITY_EXCEEDED");
|
|
24829
24834
|
let entry;
|
|
24830
24835
|
try {
|
|
24831
|
-
entry = JSON.parse(this.box.open(envelope, "execution:" +
|
|
24836
|
+
entry = JSON.parse(this.box.open(envelope, "execution:" + id2).toString("utf8"));
|
|
24832
24837
|
const binding2 = Object.fromEntries(bindingKeys.map((k) => [k, entry[k]]));
|
|
24833
24838
|
validateInput(binding2);
|
|
24834
|
-
if (entry.executionId !==
|
|
24839
|
+
if (entry.executionId !== id2 || !states.has(entry.state) || !canonicalTime(entry.createdAt) || !canonicalTime(entry.updatedAt) || Date.parse(entry.updatedAt) < Date.parse(entry.createdAt)) throw Error();
|
|
24835
24840
|
if (entry.result) boundedResult(entry.result);
|
|
24836
24841
|
if (entry.resultCode !== void 0 && (typeof entry.resultCode !== "string" || !/^[A-Z0-9_]{1,40}$/.test(entry.resultCode))) throw Error();
|
|
24837
24842
|
if (entry.reportedAt !== void 0 && (!entry.resultCode || !canonicalTime(entry.reportedAt))) throw Error();
|
|
24838
24843
|
if (entry.guardEvents) {
|
|
24839
24844
|
verifyGuardEvidence(entry.guardEvents);
|
|
24840
|
-
if (entry.guardEvents.some((record2) => record2.event.requestId !==
|
|
24845
|
+
if (entry.guardEvents.some((record2) => record2.event.requestId !== id2)) throw Error();
|
|
24841
24846
|
}
|
|
24842
24847
|
} catch {
|
|
24843
24848
|
throw failure2("JOURNAL_CORRUPT");
|
|
24844
24849
|
}
|
|
24845
|
-
this.entries.set(
|
|
24846
|
-
this.sizes.set(
|
|
24847
|
-
this.digests.set(
|
|
24850
|
+
this.entries.set(id2, entry);
|
|
24851
|
+
this.sizes.set(id2, envelope.length);
|
|
24852
|
+
this.digests.set(id2, digest2(envelope));
|
|
24848
24853
|
}
|
|
24849
24854
|
}
|
|
24850
24855
|
async persist(entry) {
|
|
@@ -24909,9 +24914,9 @@ var NativeJournal = class _NativeJournal {
|
|
|
24909
24914
|
return { entry: clone2(entry), created: true };
|
|
24910
24915
|
});
|
|
24911
24916
|
}
|
|
24912
|
-
accept(
|
|
24917
|
+
accept(id2, payloadHash) {
|
|
24913
24918
|
return this.enqueue(async () => {
|
|
24914
|
-
const e = this.need(
|
|
24919
|
+
const e = this.need(id2);
|
|
24915
24920
|
if (e.payloadHash !== payloadHash) throw failure2("IDEMPOTENCY_CONFLICT");
|
|
24916
24921
|
if (e.state !== "prepared") throw failure2("EXECUTION_ALREADY_ACCEPTED");
|
|
24917
24922
|
if (Date.parse(e.deadlineAt) <= this.now().getTime()) throw failure2("JOURNAL_DEADLINE_EXPIRED");
|
|
@@ -24921,9 +24926,9 @@ var NativeJournal = class _NativeJournal {
|
|
|
24921
24926
|
return clone2(e);
|
|
24922
24927
|
});
|
|
24923
24928
|
}
|
|
24924
|
-
running(
|
|
24929
|
+
running(id2) {
|
|
24925
24930
|
return this.enqueue(async () => {
|
|
24926
|
-
const e = this.need(
|
|
24931
|
+
const e = this.need(id2);
|
|
24927
24932
|
if (e.state !== "accepted") throw failure2("JOURNAL_STATE_INVALID");
|
|
24928
24933
|
e.state = "running";
|
|
24929
24934
|
e.updatedAt = this.now().toISOString();
|
|
@@ -24931,11 +24936,11 @@ var NativeJournal = class _NativeJournal {
|
|
|
24931
24936
|
return clone2(e);
|
|
24932
24937
|
});
|
|
24933
24938
|
}
|
|
24934
|
-
finish(
|
|
24939
|
+
finish(id2, value, resultCode) {
|
|
24935
24940
|
const result2 = boundedResult(value);
|
|
24936
24941
|
if (resultCode !== void 0 && !/^[A-Z0-9_]{1,40}$/.test(resultCode)) throw failure2("JOURNAL_RESULT_INVALID");
|
|
24937
24942
|
return this.enqueue(async () => {
|
|
24938
|
-
const e = this.need(
|
|
24943
|
+
const e = this.need(id2);
|
|
24939
24944
|
if (terminal.has(e.state)) {
|
|
24940
24945
|
if (JSON.stringify(e.result) !== JSON.stringify(result2) || resultCode !== void 0 && e.resultCode !== resultCode) throw failure2("IDEMPOTENCY_CONFLICT");
|
|
24941
24946
|
return e;
|
|
@@ -24950,15 +24955,15 @@ var NativeJournal = class _NativeJournal {
|
|
|
24950
24955
|
return clone2(e);
|
|
24951
24956
|
});
|
|
24952
24957
|
}
|
|
24953
|
-
reject(
|
|
24954
|
-
return this.finishPrepared(
|
|
24958
|
+
reject(id2) {
|
|
24959
|
+
return this.finishPrepared(id2, "rejected");
|
|
24955
24960
|
}
|
|
24956
|
-
cancelPrepared(
|
|
24957
|
-
return this.finishPrepared(
|
|
24961
|
+
cancelPrepared(id2) {
|
|
24962
|
+
return this.finishPrepared(id2, "cancelled");
|
|
24958
24963
|
}
|
|
24959
|
-
finishPrepared(
|
|
24964
|
+
finishPrepared(id2, state) {
|
|
24960
24965
|
return this.enqueue(async () => {
|
|
24961
|
-
const e = this.need(
|
|
24966
|
+
const e = this.need(id2);
|
|
24962
24967
|
if (e.state === state) return e;
|
|
24963
24968
|
if (e.state !== "prepared") throw failure2("JOURNAL_STATE_INVALID");
|
|
24964
24969
|
e.state = state;
|
|
@@ -24967,18 +24972,18 @@ var NativeJournal = class _NativeJournal {
|
|
|
24967
24972
|
return clone2(e);
|
|
24968
24973
|
});
|
|
24969
24974
|
}
|
|
24970
|
-
get(
|
|
24975
|
+
get(id2) {
|
|
24971
24976
|
return this.enqueue(async () => {
|
|
24972
|
-
if (!uuid11.test(
|
|
24973
|
-
const e = this.entries.get(
|
|
24977
|
+
if (!uuid11.test(id2)) throw failure2("JOURNAL_INPUT_INVALID");
|
|
24978
|
+
const e = this.entries.get(id2);
|
|
24974
24979
|
return e ? clone2(e) : null;
|
|
24975
24980
|
});
|
|
24976
24981
|
}
|
|
24977
|
-
appendGuardEvidence(
|
|
24982
|
+
appendGuardEvidence(id2, input2) {
|
|
24978
24983
|
const snapshot2 = clone2(input2);
|
|
24979
24984
|
return this.enqueue(async () => {
|
|
24980
|
-
const entry = this.need(
|
|
24981
|
-
if (snapshot2.event.requestId !==
|
|
24985
|
+
const entry = this.need(id2);
|
|
24986
|
+
if (snapshot2.event.requestId !== id2) throw failure2("GUARD_EVIDENCE_INVALID");
|
|
24982
24987
|
entry.guardEvents = appendGuardEvent(entry.guardEvents ?? [], snapshot2);
|
|
24983
24988
|
entry.updatedAt = this.now().toISOString();
|
|
24984
24989
|
await this.persist(entry);
|
|
@@ -25009,9 +25014,9 @@ var NativeJournal = class _NativeJournal {
|
|
|
25009
25014
|
listUnreportedResults() {
|
|
25010
25015
|
return this.enqueue(async () => [...this.entries.values()].filter((e) => !e.reportedAt && e.resultCode && e.workspaceGrantId && e.policyVersion && ["finished", "failed", "cancelled", "unknown"].includes(e.state)).map(clone2));
|
|
25011
25016
|
}
|
|
25012
|
-
markReported(
|
|
25017
|
+
markReported(id2, resultCode) {
|
|
25013
25018
|
return this.enqueue(async () => {
|
|
25014
|
-
const e = this.need(
|
|
25019
|
+
const e = this.need(id2);
|
|
25015
25020
|
if (!e.resultCode || e.resultCode !== resultCode || !e.workspaceGrantId || !e.policyVersion || !["finished", "failed", "cancelled", "unknown"].includes(e.state)) throw failure2("JOURNAL_STATE_INVALID");
|
|
25016
25021
|
if (e.reportedAt) return;
|
|
25017
25022
|
e.reportedAt = this.now().toISOString();
|
|
@@ -25288,12 +25293,21 @@ async function planPermissionChange(current2, programs, input2) {
|
|
|
25288
25293
|
workspace.permissions.writeFiles = change.enabled;
|
|
25289
25294
|
detail = "File writes: " + (change.enabled ? "ALLOW" : "DENY");
|
|
25290
25295
|
} else if (change.kind === "localhost") {
|
|
25296
|
+
if (workspace.fullAccess) {
|
|
25297
|
+
workspace.deniedLocalhostPorts = change.enabled ? (workspace.deniedLocalhostPorts ?? []).filter((port) => port !== change.port) : [.../* @__PURE__ */ new Set([...workspace.deniedLocalhostPorts ?? [], change.port])];
|
|
25298
|
+
if (workspace.deniedLocalhostPorts.length > 32) invalid2("PERMISSION_LIMIT");
|
|
25299
|
+
}
|
|
25291
25300
|
workspace.localhostPorts = change.enabled ? [.../* @__PURE__ */ new Set([...workspace.localhostPorts, change.port])].sort((a, b) => a - b) : workspace.localhostPorts.filter((port) => port !== change.port);
|
|
25292
25301
|
if (workspace.localhostPorts.length > 32) invalid2("PERMISSION_LIMIT");
|
|
25293
|
-
workspace.permissions.localhost = workspace.localhostPorts.length > 0;
|
|
25302
|
+
workspace.permissions.localhost = workspace.fullAccess === true || workspace.localhostPorts.length > 0;
|
|
25294
25303
|
resource = { rootHash: workspace.rootHash, kind: change.kind, port: change.port };
|
|
25295
25304
|
detail = "Localhost port " + change.port + ": " + (change.enabled ? "ALLOW" : "DENY");
|
|
25296
25305
|
} else {
|
|
25306
|
+
if (workspace.fullAccess) {
|
|
25307
|
+
const key = change.name.replace(/\.(exe|com|cmd|bat)$/i, "");
|
|
25308
|
+
workspace.deniedCommands = change.enabled ? (workspace.deniedCommands ?? []).filter((name2) => name2.replace(/\.(exe|com|cmd|bat)$/i, "") !== key) : [.../* @__PURE__ */ new Set([...workspace.deniedCommands ?? [], change.name])];
|
|
25309
|
+
if (workspace.deniedCommands.length > 32) invalid2("PERMISSION_LIMIT");
|
|
25310
|
+
}
|
|
25297
25311
|
let executableIdentity = null;
|
|
25298
25312
|
if (change.enabled) {
|
|
25299
25313
|
const executable = change.executable;
|
|
@@ -25307,7 +25321,7 @@ async function planPermissionChange(current2, programs, input2) {
|
|
|
25307
25321
|
if (workspace.allowedCommands.length > 32 || Object.keys(nextPrograms).length > 32) invalid2("PERMISSION_LIMIT");
|
|
25308
25322
|
executableIdentity = { executable: canonical2, dev: stat.dev, ino: stat.ino, size: stat.size, mtimeMs: stat.mtimeMs, ctimeMs: stat.ctimeMs };
|
|
25309
25323
|
} else workspace.allowedCommands = workspace.allowedCommands.filter((value) => value !== change.name);
|
|
25310
|
-
workspace.permissions.executeCommands = workspace.allowedCommands.length > 0;
|
|
25324
|
+
workspace.permissions.executeCommands = workspace.fullAccess === true || workspace.allowedCommands.length > 0;
|
|
25311
25325
|
resource = { rootHash: workspace.rootHash, kind: change.kind, name: change.name, executable: nextPrograms[change.name] ?? null, executableIdentity };
|
|
25312
25326
|
detail = "Command " + permissionLabel(change.name) + ": " + (change.enabled ? "ALLOW" : "DENY") + "\nExact executable: " + permissionLabel(nextPrograms[change.name] ?? "not registered") + nonAsciiNotice(nextPrograms[change.name]) + "\nA permitted program can access resources available to your Windows account, including outside this folder. This is not an OS sandbox.";
|
|
25313
25327
|
}
|
|
@@ -25570,19 +25584,19 @@ function issueApproval(ledgerInput, context, authorityInput, now, expiresAt) {
|
|
|
25570
25584
|
}
|
|
25571
25585
|
function consumeApproval(ledgerInput, context, approvalId, now) {
|
|
25572
25586
|
try {
|
|
25573
|
-
const ledger = current(ledgerInput, now), bound = binding(ledger, context, now),
|
|
25574
|
-
const grant = ledger.grants.find((candidate) => candidate.approvalId ===
|
|
25587
|
+
const ledger = current(ledgerInput, now), bound = binding(ledger, context, now), id2 = uuid14.parse(approvalId);
|
|
25588
|
+
const grant = ledger.grants.find((candidate) => candidate.approvalId === id2);
|
|
25575
25589
|
if (!grant || grant.state !== "active" || grant.bindingHash !== bound.bindingHash || grant.uses === Number.MAX_SAFE_INTEGER || Date.parse(now) < Date.parse(grant.issuedAt) || grant.scope === "once" && (grant.requestId !== bound.request.requestId || grant.decisionId !== bound.decision.decisionId)) throw Error();
|
|
25576
25590
|
const consumed = { ...grant, uses: grant.uses + 1, state: grant.scope === "once" ? "consumed" : "active" };
|
|
25577
|
-
return { ledger: { ...ledger, grants: ledger.grants.map((candidate) => candidate.approvalId ===
|
|
25591
|
+
return { ledger: { ...ledger, grants: ledger.grants.map((candidate) => candidate.approvalId === id2 ? consumed : candidate) }, grant: consumed };
|
|
25578
25592
|
} catch {
|
|
25579
25593
|
throw Error("APPROVAL_INVALID");
|
|
25580
25594
|
}
|
|
25581
25595
|
}
|
|
25582
25596
|
function revokeApproval(ledgerInput, approvalId, now) {
|
|
25583
25597
|
try {
|
|
25584
|
-
const ledger = current(ledgerInput, now),
|
|
25585
|
-
return { ...ledger, grants: ledger.grants.map((grant) => grant.approvalId ===
|
|
25598
|
+
const ledger = current(ledgerInput, now), id2 = uuid14.parse(approvalId);
|
|
25599
|
+
return { ...ledger, grants: ledger.grants.map((grant) => grant.approvalId === id2 && grant.state === "active" ? { ...grant, state: "revoked" } : grant) };
|
|
25586
25600
|
} catch {
|
|
25587
25601
|
throw Error("APPROVAL_INVALID");
|
|
25588
25602
|
}
|
|
@@ -25677,11 +25691,14 @@ function validateState(value) {
|
|
|
25677
25691
|
const workspaces = value.workspaces ?? [];
|
|
25678
25692
|
const programs = value.programs ?? {};
|
|
25679
25693
|
const pendingWorkspaceRevokes = value.pendingWorkspaceRevokes ?? [];
|
|
25680
|
-
if (!Array.isArray(pendingWorkspaceRevokes) || pendingWorkspaceRevokes.length > 32 || pendingWorkspaceRevokes.some((
|
|
25694
|
+
if (!Array.isArray(pendingWorkspaceRevokes) || pendingWorkspaceRevokes.length > 32 || pendingWorkspaceRevokes.some((id2) => typeof id2 !== "string" || !UUID.test(id2) || id2 !== id2.toLowerCase()) || new Set(pendingWorkspaceRevokes).size !== pendingWorkspaceRevokes.length) throw fail("STATE_CORRUPT");
|
|
25681
25695
|
if (!programs || typeof programs !== "object" || Array.isArray(programs) || Object.keys(programs).length > 32 || Object.entries(programs).some(([name2, executable]) => !/^[a-z0-9_.-]{1,64}$/.test(name2) || typeof executable !== "string" || !path5.isAbsolute(executable) || executable.length > 4096 || /[\u0000-\u001f]/.test(executable))) throw fail("STATE_CORRUPT");
|
|
25682
|
-
if (!Array.isArray(workspaces) || workspaces.length > 32 || workspaces.some((w) => !w || !UUID.test(w.workspaceGrantId) || typeof w.root !== "string" || !path5.isAbsolute(w.root) || w.root.length > 4096 || /[\u0000-\u001f]/.test(w.root) || !/^[a-f0-9]{64}$/.test(w.rootHash) || typeof w.displayName !== "string" || !w.displayName || w.displayName.length > 120 || w.policyVersion !== 1 || !w.permissions || w.permissions.readFiles !== true || typeof w.permissions.writeFiles !== "boolean" || typeof w.permissions.executeCommands !== "boolean" || typeof w.permissions.localhost !== "boolean" || !Array.isArray(w.allowedCommands) || w.allowedCommands.length > 32 || w.allowedCommands.some((name2) => typeof name2 !== "string" || !Object.hasOwn(programs, name2)) || new Set(w.allowedCommands).size !== w.allowedCommands.length || w.permissions.executeCommands !== w.allowedCommands.length > 0 || !Array.isArray(w.localhostPorts) || w.localhostPorts.length > 32 || w.localhostPorts.some((port) => !Number.isInteger(port) || port < 1 || port > 65535) || new Set(w.localhostPorts).size !== w.localhostPorts.length || w.permissions.localhost !== w.localhostPorts.length > 0)) throw fail("STATE_CORRUPT");
|
|
25696
|
+
if (!Array.isArray(workspaces) || workspaces.length > 32 || workspaces.some((w) => !w || !UUID.test(w.workspaceGrantId) || typeof w.root !== "string" || !path5.isAbsolute(w.root) || w.root.length > 4096 || /[\u0000-\u001f]/.test(w.root) || !/^[a-f0-9]{64}$/.test(w.rootHash) || typeof w.displayName !== "string" || !w.displayName || w.displayName.length > 120 || w.policyVersion !== 1 || !w.permissions || w.permissions.readFiles !== true || typeof w.permissions.writeFiles !== "boolean" || typeof w.permissions.executeCommands !== "boolean" || typeof w.permissions.localhost !== "boolean" || !Array.isArray(w.allowedCommands) || w.allowedCommands.length > 32 || w.allowedCommands.some((name2) => typeof name2 !== "string" || !Object.hasOwn(programs, name2)) || new Set(w.allowedCommands).size !== w.allowedCommands.length || w.permissions.executeCommands !== (w.fullAccess === true || w.allowedCommands.length > 0) || !Array.isArray(w.localhostPorts) || w.localhostPorts.length > 32 || w.localhostPorts.some((port) => !Number.isInteger(port) || port < 1 || port > 65535) || new Set(w.localhostPorts).size !== w.localhostPorts.length || w.permissions.localhost !== (w.fullAccess === true || w.localhostPorts.length > 0))) throw fail("STATE_CORRUPT");
|
|
25683
25697
|
if (new Set(workspaces.map((w) => w.workspaceGrantId)).size !== workspaces.length || new Set(workspaces.map((w) => w.rootHash)).size !== workspaces.length) throw fail("STATE_CORRUPT");
|
|
25684
25698
|
if (workspaces.some((w) => pendingWorkspaceRevokes.includes(w.workspaceGrantId))) throw fail("STATE_CORRUPT");
|
|
25699
|
+
for (const w of workspaces) {
|
|
25700
|
+
if (w.fullAccess !== void 0 && w.fullAccess !== true || w.deniedCommands !== void 0 && (!w.fullAccess || !Array.isArray(w.deniedCommands) || w.deniedCommands.length > 32 || w.deniedCommands.some((name2) => typeof name2 !== "string" || !/^[a-z0-9_.-]{1,64}$/.test(name2))) || w.deniedLocalhostPorts !== void 0 && (!w.fullAccess || !Array.isArray(w.deniedLocalhostPorts) || w.deniedLocalhostPorts.length > 32 || w.deniedLocalhostPorts.some((port) => !Number.isInteger(port) || port < 1 || port > 65535))) throw fail("STATE_CORRUPT");
|
|
25701
|
+
}
|
|
25685
25702
|
return { version: 1, publicKeyPem: value.publicKeyPem, privateKeyPem: value.privateKeyPem, fingerprint: value.fingerprint, dataKey: value.dataKey, ...enrollment ? { enrollment } : {}, workspaces, programs, pendingWorkspaceRevokes, ...value.permissionHistory ? { permissionHistory: permissionHistory.data } : {}, ...policyBundle ? { policyBundle } : {}, ...approvals?.success ? { approvals: approvals.data } : {}, ...value.guardRequired ? { guardRequired: true } : {}, ...guard ? { guard } : {} };
|
|
25686
25703
|
}
|
|
25687
25704
|
async function noSymlinkChain(target) {
|
|
@@ -25752,13 +25769,13 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
|
|
|
25752
25769
|
} catch (error62) {
|
|
25753
25770
|
if (error62.code !== "ENOENT") throw error62;
|
|
25754
25771
|
}
|
|
25755
|
-
const approved = /* @__PURE__ */ new Set([MARKER, "owner-state.dat", "owner-state.lock", "journal", "agent-process.json", "optimization"]);
|
|
25772
|
+
const approved = /* @__PURE__ */ new Set([MARKER, "owner-state.dat", "owner-state.lock", "journal", "agent-process.json", "optimization", ".local-commander"]);
|
|
25756
25773
|
if (names.length && !names.includes(MARKER)) throw fail("STORE_DIRECTORY_UNKNOWN");
|
|
25757
25774
|
if (names.some((name2) => !approved.has(name2))) throw fail("STORE_DIRECTORY_UNKNOWN");
|
|
25758
|
-
for (const name2 of ["agent-process.json", "optimization"]) {
|
|
25775
|
+
for (const name2 of ["agent-process.json", "optimization", ".local-commander"]) {
|
|
25759
25776
|
if (!names.includes(name2)) continue;
|
|
25760
25777
|
const filename = path5.join(absolute2, name2), stat = await lstat3(filename);
|
|
25761
|
-
if (stat.isSymbolicLink() || (name2
|
|
25778
|
+
if (stat.isSymbolicLink() || (name2 !== "agent-process.json" ? !stat.isDirectory() : !stat.isFile() || stat.size < 1 || stat.size > 8192)) throw fail("STORE_DIRECTORY_INVALID");
|
|
25762
25779
|
if (name2 === "agent-process.json") {
|
|
25763
25780
|
let value;
|
|
25764
25781
|
try {
|
|
@@ -26154,7 +26171,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
|
|
|
26154
26171
|
return this.run(async () => {
|
|
26155
26172
|
const state = await this.readState();
|
|
26156
26173
|
if (guardActive === false && state?.guardRequired) throw fail("GUARD_RESTART_REQUIRED");
|
|
26157
|
-
return
|
|
26174
|
+
return structuredClone(state?.workspaces ?? []);
|
|
26158
26175
|
});
|
|
26159
26176
|
}
|
|
26160
26177
|
loadPrograms() {
|
|
@@ -26168,17 +26185,17 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
|
|
|
26168
26185
|
if (typeof workspaceGrantId !== "string" || !UUID.test(workspaceGrantId)) throw fail("WORKSPACE_INVALID");
|
|
26169
26186
|
const state = await this.readState();
|
|
26170
26187
|
if (!state?.enrollment) throw fail("ENROLLMENT_REQUIRED");
|
|
26171
|
-
const
|
|
26172
|
-
const workspace = state.workspaces?.find((w) => w.workspaceGrantId ===
|
|
26188
|
+
const id2 = workspaceGrantId.toLowerCase();
|
|
26189
|
+
const workspace = state.workspaces?.find((w) => w.workspaceGrantId === id2);
|
|
26173
26190
|
if (!workspace) {
|
|
26174
|
-
if (state.pendingWorkspaceRevokes?.includes(
|
|
26191
|
+
if (state.pendingWorkspaceRevokes?.includes(id2)) return;
|
|
26175
26192
|
throw fail("WORKSPACE_UNKNOWN");
|
|
26176
26193
|
}
|
|
26177
26194
|
if ((state.pendingWorkspaceRevokes?.length ?? 0) >= 32) throw fail("WORKSPACE_REVOKE_LIMIT");
|
|
26178
26195
|
const before = await this.rawHash();
|
|
26179
|
-
state.workspaces = state.workspaces.filter((w) => w.workspaceGrantId !==
|
|
26180
|
-
state.pendingWorkspaceRevokes = [...state.pendingWorkspaceRevokes ?? [],
|
|
26181
|
-
for (const name2 of Object.keys(state.programs ?? {})) if (!state.workspaces.some((w) => w.allowedCommands.includes(name2))) delete state.programs[name2];
|
|
26196
|
+
state.workspaces = state.workspaces.filter((w) => w.workspaceGrantId !== id2);
|
|
26197
|
+
state.pendingWorkspaceRevokes = [...state.pendingWorkspaceRevokes ?? [], id2];
|
|
26198
|
+
for (const name2 of Object.keys(state.programs ?? {})) if (!state.workspaces.some((w) => w.allowedCommands.includes(name2) || w.deniedCommands?.includes(name2))) delete state.programs[name2];
|
|
26182
26199
|
await this.writeState(state, before);
|
|
26183
26200
|
}));
|
|
26184
26201
|
}
|
|
@@ -26187,7 +26204,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
|
|
|
26187
26204
|
const state = await this.readState();
|
|
26188
26205
|
if (!state?.pendingWorkspaceRevokes?.includes(workspaceGrantId)) return;
|
|
26189
26206
|
const before = await this.rawHash();
|
|
26190
|
-
state.pendingWorkspaceRevokes = state.pendingWorkspaceRevokes.filter((
|
|
26207
|
+
state.pendingWorkspaceRevokes = state.pendingWorkspaceRevokes.filter((id2) => id2 !== workspaceGrantId);
|
|
26191
26208
|
await this.writeState(state, before);
|
|
26192
26209
|
}));
|
|
26193
26210
|
}
|
|
@@ -26220,7 +26237,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
|
|
|
26220
26237
|
const before = await this.rawHash();
|
|
26221
26238
|
state.workspaces = state.workspaces.map((w) => w.workspaceGrantId === verified.workspace.workspaceGrantId ? verified.workspace : w);
|
|
26222
26239
|
state.programs = verified.programs;
|
|
26223
|
-
for (const name2 of Object.keys(state.programs)) if (!state.workspaces.some((w) => w.allowedCommands.includes(name2))) delete state.programs[name2];
|
|
26240
|
+
for (const name2 of Object.keys(state.programs)) if (!state.workspaces.some((w) => w.allowedCommands.includes(name2) || w.deniedCommands?.includes(name2))) delete state.programs[name2];
|
|
26224
26241
|
const record2 = {
|
|
26225
26242
|
id: randomUUID3(),
|
|
26226
26243
|
changedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -26267,7 +26284,8 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
|
|
|
26267
26284
|
rootHash,
|
|
26268
26285
|
displayName: (path5.basename(root) || root).slice(0, 120),
|
|
26269
26286
|
policyVersion: 1,
|
|
26270
|
-
|
|
26287
|
+
...selected.mode === "all-drives" ? { fullAccess: true } : {},
|
|
26288
|
+
permissions: { readFiles: true, writeFiles: true, executeCommands: selected.mode === "all-drives", localhost: selected.mode === "all-drives" },
|
|
26271
26289
|
allowedCommands: [],
|
|
26272
26290
|
localhostPorts: []
|
|
26273
26291
|
};
|
|
@@ -26323,7 +26341,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
|
|
|
26323
26341
|
// agent/src/tools.ts
|
|
26324
26342
|
import { constants as constants3 } from "node:fs";
|
|
26325
26343
|
import { lstat as lstat5, open as open4, readdir as readdir3, realpath as realpath5, rename as rename3, rm as rm3 } from "node:fs/promises";
|
|
26326
|
-
import
|
|
26344
|
+
import path10 from "node:path";
|
|
26327
26345
|
import { createHash as createHash9, randomUUID as randomUUID4 } from "node:crypto";
|
|
26328
26346
|
|
|
26329
26347
|
// src/guard.ts
|
|
@@ -26567,11 +26585,31 @@ function invokeRead(bridge, file2, maxBytes, prefix, signal) {
|
|
|
26567
26585
|
});
|
|
26568
26586
|
}
|
|
26569
26587
|
|
|
26588
|
+
// src/process.ts
|
|
26589
|
+
import { statSync } from "node:fs";
|
|
26590
|
+
import path8 from "node:path";
|
|
26591
|
+
var WINDOWS_LAUNCH_EXTENSIONS = [".com", ".exe", ".bat", ".cmd"];
|
|
26592
|
+
function resolveWindowsLauncher(commandName, env = process.env) {
|
|
26593
|
+
const extensions = (env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").map((ext) => ext.trim().toLowerCase()).filter((ext) => WINDOWS_LAUNCH_EXTENSIONS.includes(ext));
|
|
26594
|
+
for (const entry of (env.PATH ?? "").split(";")) {
|
|
26595
|
+
const dir = entry.trim().replace(/^"(.*)"$/, "$1");
|
|
26596
|
+
if (!path8.win32.isAbsolute(dir)) continue;
|
|
26597
|
+
for (const ext of extensions) {
|
|
26598
|
+
const file2 = path8.win32.join(dir, commandName + ext);
|
|
26599
|
+
try {
|
|
26600
|
+
if (statSync(file2).isFile()) return { file: file2, shell: ext === ".bat" || ext === ".cmd" };
|
|
26601
|
+
} catch {
|
|
26602
|
+
}
|
|
26603
|
+
}
|
|
26604
|
+
}
|
|
26605
|
+
return void 0;
|
|
26606
|
+
}
|
|
26607
|
+
|
|
26570
26608
|
// agent/src/job-supervisor.ts
|
|
26571
26609
|
import { spawn as spawn2 } from "node:child_process";
|
|
26572
|
-
import
|
|
26610
|
+
import path9 from "node:path";
|
|
26573
26611
|
function absolute(value) {
|
|
26574
|
-
return typeof value === "string" && value.length > 0 && value.length < 32767 && !value.includes("\0") &&
|
|
26612
|
+
return typeof value === "string" && value.length > 0 && value.length < 32767 && !value.includes("\0") && path9.isAbsolute(value) && path9.resolve(value) === value;
|
|
26575
26613
|
}
|
|
26576
26614
|
async function runSupervised(helper, request, options = {}) {
|
|
26577
26615
|
if (process.platform !== "win32") throw Error("WINDOWS_SUPERVISOR_REQUIRED");
|
|
@@ -26587,7 +26625,7 @@ async function runSupervised(helper, request, options = {}) {
|
|
|
26587
26625
|
let pid = null, outcome = null;
|
|
26588
26626
|
let buffer = "", failure5 = null, closed = false, cancelSent = false;
|
|
26589
26627
|
let killTimer, hardTimer;
|
|
26590
|
-
const child = spawn2(helper, [], { cwd:
|
|
26628
|
+
const child = spawn2(helper, [], { cwd: path9.dirname(helper), stdio: ["pipe", "pipe", "pipe"], windowsHide: true, shell: false, env: buildChildEnvironment(process.env) });
|
|
26591
26629
|
const cancel = () => {
|
|
26592
26630
|
if (closed || cancelSent) return;
|
|
26593
26631
|
cancelSent = true;
|
|
@@ -26741,7 +26779,7 @@ var NativeTools = class {
|
|
|
26741
26779
|
options;
|
|
26742
26780
|
async readFile(file2, maxBytes, signal) {
|
|
26743
26781
|
try {
|
|
26744
|
-
return await readBoundedFile(file2, maxBytes, this.options.ownerBridgePath ??
|
|
26782
|
+
return await readBoundedFile(file2, maxBytes, this.options.ownerBridgePath ?? path10.join(path10.dirname(this.options.helperPath), "OwnerBridge.exe"), signal);
|
|
26745
26783
|
} catch (error62) {
|
|
26746
26784
|
if (error62.code === "ENOENT") throw error62;
|
|
26747
26785
|
if (error62 instanceof Error && /^[A-Z_]{1,40}$/.test(error62.message)) fail2(error62.message);
|
|
@@ -26766,15 +26804,15 @@ var NativeTools = class {
|
|
|
26766
26804
|
try {
|
|
26767
26805
|
const canonical2 = await realpath5(workspace.root);
|
|
26768
26806
|
if (!equalPath3(canonical2, workspace.root) || hash5(process.platform === "win32" ? canonical2.toLowerCase() : canonical2) !== workspace.rootHash) fail2("WORKSPACE_CHANGED");
|
|
26769
|
-
const runtimeDirectory =
|
|
26807
|
+
const runtimeDirectory = path10.dirname(this.options.helperPath);
|
|
26770
26808
|
const protectedPaths = [
|
|
26771
26809
|
this.options.stateDirectory,
|
|
26772
26810
|
this.options.helperPath,
|
|
26773
|
-
...["agent.mjs", "node.exe", "OwnerBridge.exe", "LocalCommanderAgent.exe"].map((name2) =>
|
|
26811
|
+
...["agent.mjs", "node.exe", "OwnerBridge.exe", "LocalCommanderAgent.exe"].map((name2) => path10.join(runtimeDirectory, name2))
|
|
26774
26812
|
];
|
|
26775
26813
|
if (this.options.ownerBridgePath) protectedPaths.push(this.options.ownerBridgePath);
|
|
26776
|
-
if (process.platform === "win32" && process.env.LOCALAPPDATA &&
|
|
26777
|
-
protectedPaths.push(
|
|
26814
|
+
if (process.platform === "win32" && process.env.LOCALAPPDATA && path10.isAbsolute(process.env.LOCALAPPDATA)) {
|
|
26815
|
+
protectedPaths.push(path10.join(process.env.LOCALAPPDATA, "LocalCommander"));
|
|
26778
26816
|
}
|
|
26779
26817
|
guard = await PathGuard.create([canonical2], false, { protectedPaths });
|
|
26780
26818
|
} catch (e) {
|
|
@@ -26806,7 +26844,7 @@ var NativeTools = class {
|
|
|
26806
26844
|
const bytes3 = await this.readFile(filename, 1048576, signal), contents = utf8(bytes3), lines = contents.split(/\r?\n/);
|
|
26807
26845
|
const selected = lines.slice(first - 1, Math.min(last, lines.length)).join("\n");
|
|
26808
26846
|
if (Buffer.byteLength(selected) > 12e4) fail2("OUTPUT_LIMIT_EXCEEDED");
|
|
26809
|
-
return result({ path:
|
|
26847
|
+
return result({ path: path10.relative(workspace.root, filename), sha256: hash5(bytes3), startLine: first, endLine: Math.min(last, lines.length), totalLines: lines.length, content: selected, truncated: last < lines.length });
|
|
26810
26848
|
} };
|
|
26811
26849
|
}
|
|
26812
26850
|
if (call.name === "fs_write" || call.name === "fs_replace") {
|
|
@@ -26842,7 +26880,7 @@ var NativeTools = class {
|
|
|
26842
26880
|
}
|
|
26843
26881
|
const bytes3 = Buffer.from(contents, "utf8");
|
|
26844
26882
|
if (bytes3.length > MAX_FILE_WRITE_BYTES) fail2("FILE_WRITE_LIMIT");
|
|
26845
|
-
const temp =
|
|
26883
|
+
const temp = path10.join(path10.dirname(target), ".lc-write-" + randomUUID4() + ".tmp");
|
|
26846
26884
|
const handle = await open4(temp, constants3.O_CREAT | constants3.O_EXCL | constants3.O_WRONLY, 384);
|
|
26847
26885
|
try {
|
|
26848
26886
|
await handle.writeFile(bytes3);
|
|
@@ -26859,7 +26897,7 @@ var NativeTools = class {
|
|
|
26859
26897
|
await link(temp, target);
|
|
26860
26898
|
await rm3(temp);
|
|
26861
26899
|
}
|
|
26862
|
-
return result({ path:
|
|
26900
|
+
return result({ path: path10.relative(workspace.root, target), bytes: bytes3.length, sha256: hash5(bytes3), ...call.name === "fs_replace" ? { replacements } : {} });
|
|
26863
26901
|
} catch (e) {
|
|
26864
26902
|
await handle.close().catch(() => {
|
|
26865
26903
|
});
|
|
@@ -26880,12 +26918,12 @@ var NativeTools = class {
|
|
|
26880
26918
|
stopped(signal);
|
|
26881
26919
|
if (matches2.length >= call.args.maxResults || scanned >= 300) break;
|
|
26882
26920
|
try {
|
|
26883
|
-
const filename = await guard.resolveExisting(
|
|
26921
|
+
const filename = await guard.resolveExisting(path10.join(base, entry.path));
|
|
26884
26922
|
guard.assertSafeFile(filename);
|
|
26885
26923
|
const data = utf8(await this.readFile(filename, 256e3, signal));
|
|
26886
26924
|
scanned++;
|
|
26887
26925
|
const lines = data.split(/\r?\n/);
|
|
26888
|
-
for (let i = 0; i < lines.length && matches2.length < call.args.maxResults; i++) if ((call.args.caseSensitive ? lines[i] : lines[i].toLowerCase()).includes(query)) matches2.push({ path:
|
|
26926
|
+
for (let i = 0; i < lines.length && matches2.length < call.args.maxResults; i++) if ((call.args.caseSensitive ? lines[i] : lines[i].toLowerCase()).includes(query)) matches2.push({ path: path10.relative(workspace.root, filename), line: i + 1, text: lines[i].slice(0, 500) });
|
|
26889
26927
|
} catch (error62) {
|
|
26890
26928
|
if (error62 instanceof NativeToolError && ["FILE_READ_FAILED", "CANCELLED"].includes(error62.code)) throw error62;
|
|
26891
26929
|
}
|
|
@@ -26895,7 +26933,7 @@ var NativeTools = class {
|
|
|
26895
26933
|
}
|
|
26896
26934
|
if (call.name === "localhost_request") {
|
|
26897
26935
|
const url2 = new URL(call.args.url), port = Number(url2.port || (url2.protocol === "https:" ? 443 : 80));
|
|
26898
|
-
if (!["http:", "https:"].includes(url2.protocol) || !["localhost", "127.0.0.1", "[::1]"].includes(url2.hostname) || url2.username || url2.password || url2.hash || !workspace.localhostPorts.includes(port) || this.options.protectedPorts?.includes(port)) fail2("LOCALHOST_NOT_ALLOWED");
|
|
26936
|
+
if (!["http:", "https:"].includes(url2.protocol) || !["localhost", "127.0.0.1", "[::1]"].includes(url2.hostname) || url2.username || url2.password || url2.hash || (workspace.fullAccess ? workspace.deniedLocalhostPorts?.includes(port) : !workspace.localhostPorts.includes(port)) || this.options.protectedPorts?.includes(port)) fail2("LOCALHOST_NOT_ALLOWED");
|
|
26899
26937
|
const headers = {};
|
|
26900
26938
|
for (const [name2, value] of Object.entries(call.args.headers ?? {})) {
|
|
26901
26939
|
if (!/^[A-Za-z0-9-]+$/.test(name2) || /[\r\n]/.test(value) || ["host", "connection", "content-length", "transfer-encoding", "upgrade", "proxy-authorization", "proxy-connection"].includes(name2.toLowerCase()) || Object.keys(headers).some((k) => k.toLowerCase() === name2.toLowerCase())) fail2("INVALID_HTTP_HEADER");
|
|
@@ -26935,10 +26973,10 @@ var NativeTools = class {
|
|
|
26935
26973
|
} };
|
|
26936
26974
|
}
|
|
26937
26975
|
if (call.name === "command_run") {
|
|
26938
|
-
const cwd2 = await resolve(call.args.cwd, true), program = this.resolveProgram(call.args.command, workspace);
|
|
26976
|
+
const cwd2 = await resolve(call.args.cwd, true), program = await this.resolveProgram(call.args.command, workspace, call.args.args);
|
|
26939
26977
|
const claims2 = writeClaim(cwd2);
|
|
26940
|
-
return { call, claims: claims2, execution: {
|
|
26941
|
-
const r = await runSupervised(this.options.helperPath, {
|
|
26978
|
+
return { call, claims: claims2, execution: { ...program, cwd: cwd2 }, run: async (signal, onStarted, onOutput) => {
|
|
26979
|
+
const r = await runSupervised(this.options.helperPath, { ...program, cwd: cwd2, timeoutMs: call.args.timeoutMs, maxProcesses: 32 }, { signal, maxOutputBytes: 9e4, onStarted, onOutput });
|
|
26942
26980
|
const { pid: _pid, ...output2 } = r;
|
|
26943
26981
|
return { ...output2, resultCode: r.cancelled ? "CANCELLED" : r.timedOut ? "TIMEOUT" : r.exitCode === 0 ? "SUCCESS" : "USER_PROGRAM_FAILED" };
|
|
26944
26982
|
} };
|
|
@@ -26946,15 +26984,16 @@ var NativeTools = class {
|
|
|
26946
26984
|
const cwd = await resolve(call.args.path, true), common = await this.gitCommonDir(cwd, workspace, guard);
|
|
26947
26985
|
const claims = readClaim(cwd);
|
|
26948
26986
|
if (common) claims.push({ path: common, namespace: "git", mode: "read" });
|
|
26987
|
+
if (call.name === "project_snapshot" && call.args.startup) claims.push({ path: workspace.root, mode: "read" });
|
|
26949
26988
|
let argv;
|
|
26950
26989
|
if (call.name === "project_snapshot" || call.name === "git_status") argv = ["status", "--short", "--branch"];
|
|
26951
26990
|
else if (call.name === "git_log") argv = ["log", "-" + call.args.limit, "--format=%H%x09%aI%x09%s"];
|
|
26952
26991
|
else if (call.name === "git_diff") {
|
|
26953
26992
|
argv = ["diff", "--no-ext-diff", "--no-textconv", ...call.args.staged ? ["--cached"] : []];
|
|
26954
26993
|
if (call.args.file) {
|
|
26955
|
-
const file2 = await resolve(
|
|
26956
|
-
const relative =
|
|
26957
|
-
if (relative.startsWith(".." +
|
|
26994
|
+
const file2 = await resolve(path10.resolve(cwd, call.args.file));
|
|
26995
|
+
const relative = path10.relative(cwd, file2);
|
|
26996
|
+
if (relative.startsWith(".." + path10.sep) || relative === ".." || path10.isAbsolute(relative)) fail2("PATH_NOT_ALLOWED");
|
|
26958
26997
|
argv.push("--", relative);
|
|
26959
26998
|
} else argv.push("--stat");
|
|
26960
26999
|
} else fail2("TOOL_MISSING");
|
|
@@ -26962,10 +27001,10 @@ var NativeTools = class {
|
|
|
26962
27001
|
const runGit = (signal, onStarted, onOutput) => runSupervised(this.options.helperPath, { ...execution, timeoutMs: 1e4, maxProcesses: 8 }, { signal, maxOutputBytes: 9e4, onStarted, onOutput });
|
|
26963
27002
|
return { call, claims, ...execution ? { execution } : {}, run: async (signal, onStarted, onOutput) => {
|
|
26964
27003
|
if (call.name === "project_snapshot") {
|
|
26965
|
-
const listing = await this.list(guard, cwd, 1, 150, signal);
|
|
27004
|
+
const listing = await this.list(guard, cwd, 1, call.args.startup ? 20 : 150, signal);
|
|
26966
27005
|
let packageInfo = null;
|
|
26967
27006
|
try {
|
|
26968
|
-
const name2 = await guard.resolveExisting(
|
|
27007
|
+
const name2 = await guard.resolveExisting(path10.join(cwd, "package.json"));
|
|
26969
27008
|
guard.assertSafeFile(name2);
|
|
26970
27009
|
const value = JSON.parse(utf8(await this.readFile(name2, 64e3, signal)));
|
|
26971
27010
|
packageInfo = { name: typeof value.name === "string" ? value.name : null, version: typeof value.version === "string" ? value.version : null, scripts: value.scripts && typeof value.scripts === "object" ? Object.keys(value.scripts).slice(0, 100) : [] };
|
|
@@ -26973,6 +27012,41 @@ var NativeTools = class {
|
|
|
26973
27012
|
if (error62 instanceof NativeToolError && ["FILE_READ_FAILED", "CANCELLED"].includes(error62.code)) throw error62;
|
|
26974
27013
|
}
|
|
26975
27014
|
const status = common ? await runGit(signal) : null;
|
|
27015
|
+
if (call.args.startup) {
|
|
27016
|
+
let primary = cwd;
|
|
27017
|
+
if (common) {
|
|
27018
|
+
const git = await this.gitExecution(cwd, ["worktree", "list", "--porcelain"]);
|
|
27019
|
+
const worktrees = await runSupervised(this.options.helperPath, { ...git, timeoutMs: 1e4, maxProcesses: 8 }, { signal, maxOutputBytes: 16384 });
|
|
27020
|
+
if (worktrees.exitCode !== 0) fail2("GIT_FAILED");
|
|
27021
|
+
const first = /^worktree (.+)$/m.exec(worktrees.stdout)?.[1]?.trim();
|
|
27022
|
+
if (!first) fail2("GIT_FAILED");
|
|
27023
|
+
primary = await guard.resolveExisting(first);
|
|
27024
|
+
}
|
|
27025
|
+
const contextFile = async (relative, limit, optional2 = false) => {
|
|
27026
|
+
try {
|
|
27027
|
+
const file2 = await guard.resolveExisting(path10.join(primary, relative));
|
|
27028
|
+
guard.assertSafeFile(file2);
|
|
27029
|
+
return utf8(await this.readFile(file2, limit, signal));
|
|
27030
|
+
} catch (error62) {
|
|
27031
|
+
if (optional2 && error62.code === "ENOENT") return null;
|
|
27032
|
+
throw error62;
|
|
27033
|
+
}
|
|
27034
|
+
};
|
|
27035
|
+
const policy = await contextFile("AGENTS.md", 16384);
|
|
27036
|
+
if (!policy?.trim()) fail2("AGENT_INSTRUCTIONS_INVALID");
|
|
27037
|
+
const board = call.args.taskId ? await contextFile("planning/ACTIVE_WORK.md", 1048576, true) : null;
|
|
27038
|
+
const entry = board?.split(/(?=^#{2,3} )/m).find((section) => new RegExp(`^#{2,3}\\s+${call.args.taskId}(?:\\s|/|$)`).test(section));
|
|
27039
|
+
const log = call.args.taskId ? await contextFile(`planning/tasks/${call.args.taskId}.md`, 262144, true) : null;
|
|
27040
|
+
return result({
|
|
27041
|
+
root: cwd,
|
|
27042
|
+
primary,
|
|
27043
|
+
package: packageInfo,
|
|
27044
|
+
git: status?.stdout ?? null,
|
|
27045
|
+
files: listing,
|
|
27046
|
+
instructions: { source: "AGENTS.md", sha256: hash5(policy), text: policy },
|
|
27047
|
+
task: call.args.taskId ? { taskId: call.args.taskId, entry: entry?.slice(0, 4096) ?? null, continuation: log?.slice(-4096) ?? null, truncated: !!entry && entry.length > 4096 || !!log && log.length > 4096 } : null
|
|
27048
|
+
});
|
|
27049
|
+
}
|
|
26976
27050
|
return result({ root: workspace.displayName, files: listing, package: packageInfo, git: status?.stdout ?? null });
|
|
26977
27051
|
}
|
|
26978
27052
|
if (!common) fail2("NOT_A_GIT_REPOSITORY");
|
|
@@ -26981,16 +27055,44 @@ var NativeTools = class {
|
|
|
26981
27055
|
return { ...output2, resultCode: r.exitCode === 0 ? "SUCCESS" : "GIT_FAILED" };
|
|
26982
27056
|
} };
|
|
26983
27057
|
}
|
|
26984
|
-
resolveProgram(name2, workspace) {
|
|
26985
|
-
const entry = Object.entries(this.options.programs).find(([key, value]) => key.toLowerCase() === name2.toLowerCase() ||
|
|
26986
|
-
if (
|
|
26987
|
-
|
|
27058
|
+
async resolveProgram(name2, workspace, args) {
|
|
27059
|
+
const entry = Object.entries(this.options.programs).find(([key, value]) => key.toLowerCase() === name2.toLowerCase() || path10.isAbsolute(name2) && equalPath3(value.executable, path10.resolve(name2)));
|
|
27060
|
+
if (workspace.fullAccess) {
|
|
27061
|
+
const commandKey = (value) => path10.basename(value).toLowerCase().replace(/\.(exe|com|cmd|bat)$/i, "");
|
|
27062
|
+
const denied = new Set((workspace.deniedCommands ?? []).map(commandKey));
|
|
27063
|
+
if (denied.has(commandKey(name2)) || entry && denied.has(commandKey(entry[0]))) fail2("COMMAND_NOT_ALLOWED");
|
|
27064
|
+
const extension2 = path10.extname(name2).toLowerCase();
|
|
27065
|
+
const candidate = entry?.[1].executable ?? (path10.isAbsolute(name2) ? name2 : /^[\w.-]+$/.test(name2) ? resolveWindowsLauncher(
|
|
27066
|
+
commandKey(name2),
|
|
27067
|
+
[".exe", ".com", ".cmd", ".bat"].includes(extension2) ? { ...process.env, PATHEXT: extension2 } : process.env
|
|
27068
|
+
)?.file : void 0);
|
|
27069
|
+
if (!candidate || !path10.isAbsolute(candidate)) fail2("COMMAND_NOT_FOUND");
|
|
27070
|
+
const executable = await realpath5(candidate).catch(() => fail2("COMMAND_NOT_FOUND"));
|
|
27071
|
+
if (!(await lstat5(executable)).isFile()) fail2("COMMAND_NOT_FOUND");
|
|
27072
|
+
if (denied.has(commandKey(executable))) fail2("COMMAND_NOT_ALLOWED");
|
|
27073
|
+
for (const key of workspace.deniedCommands ?? []) {
|
|
27074
|
+
const configured = this.options.programs[key]?.executable;
|
|
27075
|
+
if (configured && equalPath3(executable, await realpath5(configured).catch(() => configured))) fail2("COMMAND_NOT_ALLOWED");
|
|
27076
|
+
}
|
|
27077
|
+
if (/\.(cmd|bat)$/i.test(executable)) {
|
|
27078
|
+
if ([executable, ...args].some((value) => /[&|<>^%!"\r\n]/.test(value))) fail2("INVALID_SCRIPT_ARGUMENTS");
|
|
27079
|
+
const literal2 = (value) => "'" + value.replaceAll("'", "''") + "'";
|
|
27080
|
+
const shell = path10.join(process.env.SystemRoot ?? "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
27081
|
+
if (denied.has("powershell") || denied.has("cmd")) fail2("COMMAND_NOT_ALLOWED");
|
|
27082
|
+
const script = "& " + literal2(executable) + " @(" + args.map(literal2).join(",") + "); exit $LASTEXITCODE";
|
|
27083
|
+
return { executable: shell, args: ["-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(script, "utf16le").toString("base64")] };
|
|
27084
|
+
}
|
|
27085
|
+
if (!/\.(exe|com)$/i.test(executable)) fail2("COMMAND_NOT_ALLOWED");
|
|
27086
|
+
return { executable, args: [...entry?.[1].prefixArgs ?? [], ...args] };
|
|
27087
|
+
}
|
|
27088
|
+
if (!entry || !workspace.allowedCommands.some((v) => v.toLowerCase() === entry[0].toLowerCase()) || !path10.isAbsolute(entry[1].executable)) fail2("COMMAND_NOT_ALLOWED");
|
|
27089
|
+
return { executable: entry[1].executable, args: [...entry[1].prefixArgs ?? [], ...args] };
|
|
26988
27090
|
}
|
|
26989
27091
|
async gitExecution(cwd, args) {
|
|
26990
27092
|
const configured = this.options.programs.git;
|
|
26991
|
-
const candidates = configured ? [configured.executable] : process.platform === "win32" ? [[process.env.ProgramFiles, "Git"], [process.env["ProgramFiles(x86)"], "Git"], [process.env.LOCALAPPDATA, "Programs/Git"]].filter(([root]) => root &&
|
|
27093
|
+
const candidates = configured ? [configured.executable] : process.platform === "win32" ? [[process.env.ProgramFiles, "Git"], [process.env["ProgramFiles(x86)"], "Git"], [process.env.LOCALAPPDATA, "Programs/Git"]].filter(([root]) => root && path10.isAbsolute(root)).map(([root, suffix]) => path10.join(root, suffix, "cmd", "git.exe")) : [];
|
|
26992
27094
|
for (const candidate of candidates) {
|
|
26993
|
-
if (!
|
|
27095
|
+
if (!path10.isAbsolute(candidate)) continue;
|
|
26994
27096
|
try {
|
|
26995
27097
|
const stat = await lstat5(candidate);
|
|
26996
27098
|
if (!stat.isFile() || stat.isSymbolicLink() || !equalPath3(candidate, await realpath5(candidate))) continue;
|
|
@@ -27016,7 +27118,7 @@ var NativeTools = class {
|
|
|
27016
27118
|
break;
|
|
27017
27119
|
}
|
|
27018
27120
|
if (item.isSymbolicLink() || excluded.has(item.name.toLowerCase())) continue;
|
|
27019
|
-
const candidate =
|
|
27121
|
+
const candidate = path10.join(current2.path, item.name);
|
|
27020
27122
|
let resolved;
|
|
27021
27123
|
try {
|
|
27022
27124
|
resolved = await guard.resolveExisting(candidate);
|
|
@@ -27026,11 +27128,11 @@ var NativeTools = class {
|
|
|
27026
27128
|
}
|
|
27027
27129
|
if (!equalPath3(candidate, resolved)) continue;
|
|
27028
27130
|
if (item.isDirectory()) {
|
|
27029
|
-
entries.push({ path:
|
|
27131
|
+
entries.push({ path: path10.relative(root, resolved), type: "directory" });
|
|
27030
27132
|
if (current2.level < depth) queue.push({ path: resolved, level: current2.level + 1 });
|
|
27031
27133
|
} else if (item.isFile()) {
|
|
27032
27134
|
const stat = await lstat5(resolved);
|
|
27033
|
-
entries.push({ path:
|
|
27135
|
+
entries.push({ path: path10.relative(root, resolved), type: "file", size: stat.size });
|
|
27034
27136
|
}
|
|
27035
27137
|
}
|
|
27036
27138
|
if (truncated) break;
|
|
@@ -27040,7 +27142,7 @@ var NativeTools = class {
|
|
|
27040
27142
|
async gitCommonDir(cwd, workspace, guard) {
|
|
27041
27143
|
let directory = cwd;
|
|
27042
27144
|
while (guard.isWithin(directory, workspace.root)) {
|
|
27043
|
-
const dotGit =
|
|
27145
|
+
const dotGit = path10.join(directory, ".git");
|
|
27044
27146
|
try {
|
|
27045
27147
|
const stat = await lstat5(dotGit);
|
|
27046
27148
|
if (stat.isSymbolicLink()) fail2("GIT_METADATA_CHANGED");
|
|
@@ -27049,14 +27151,14 @@ var NativeTools = class {
|
|
|
27049
27151
|
else {
|
|
27050
27152
|
const content = utf8(await this.readFile(dotGit, 4096)).trim();
|
|
27051
27153
|
if (!content.startsWith("gitdir: ")) fail2("GIT_METADATA_CHANGED");
|
|
27052
|
-
gitDir = await realpath5(
|
|
27154
|
+
gitDir = await realpath5(path10.resolve(directory, content.slice(8)));
|
|
27053
27155
|
}
|
|
27054
27156
|
if (guard.isWithin(gitDir, this.options.stateDirectory) || !guard.isWithin(gitDir, workspace.root) && (!workspace.gitCommonDir || !guard.isWithin(gitDir, workspace.gitCommonDir))) fail2("GIT_COMMON_DIRECTORY_NOT_APPROVED");
|
|
27055
27157
|
let common = gitDir;
|
|
27056
27158
|
try {
|
|
27057
|
-
const content = utf8(await this.readFile(
|
|
27159
|
+
const content = utf8(await this.readFile(path10.join(gitDir, "commondir"), 4096)).trim();
|
|
27058
27160
|
if (!content) fail2("GIT_METADATA_CHANGED");
|
|
27059
|
-
common = await realpath5(
|
|
27161
|
+
common = await realpath5(path10.resolve(gitDir, content));
|
|
27060
27162
|
} catch (e) {
|
|
27061
27163
|
if (e.code !== "ENOENT") throw e;
|
|
27062
27164
|
}
|
|
@@ -27067,53 +27169,63 @@ var NativeTools = class {
|
|
|
27067
27169
|
if (e.code !== "ENOENT") throw e;
|
|
27068
27170
|
}
|
|
27069
27171
|
if (equalPath3(directory, workspace.root)) break;
|
|
27070
|
-
directory =
|
|
27172
|
+
directory = path10.dirname(directory);
|
|
27071
27173
|
}
|
|
27072
27174
|
return null;
|
|
27073
27175
|
}
|
|
27074
27176
|
};
|
|
27075
27177
|
|
|
27076
27178
|
// agent/src/scheduler.ts
|
|
27077
|
-
import
|
|
27179
|
+
import path11 from "node:path";
|
|
27078
27180
|
import os2 from "node:os";
|
|
27079
27181
|
function canonical(value) {
|
|
27080
|
-
const p =
|
|
27182
|
+
const p = path11.resolve(value);
|
|
27081
27183
|
return process.platform === "win32" ? p.toLowerCase() : p;
|
|
27082
27184
|
}
|
|
27083
27185
|
function ancestor(a, b) {
|
|
27084
|
-
const relative =
|
|
27085
|
-
return relative === "" || !
|
|
27186
|
+
const relative = path11.relative(a, b);
|
|
27187
|
+
return relative === "" || !path11.isAbsolute(relative) && relative !== ".." && !relative.startsWith(".." + path11.sep);
|
|
27086
27188
|
}
|
|
27087
27189
|
function claimsConflict(a, b) {
|
|
27088
27190
|
return a.some((x) => b.some((y) => (x.namespace ?? "filesystem") === (y.namespace ?? "filesystem") && (x.mode === "write" || y.mode === "write") && (ancestor(x.path, y.path) || ancestor(y.path, x.path))));
|
|
27089
27191
|
}
|
|
27090
27192
|
var NativeScheduler = class {
|
|
27091
|
-
safeSlots;
|
|
27092
|
-
active = /* @__PURE__ */ new Map();
|
|
27093
|
-
waiting = [];
|
|
27094
|
-
accepting = true;
|
|
27095
27193
|
constructor(options = {}) {
|
|
27194
|
+
this.options = options;
|
|
27096
27195
|
const capacity = Math.max(1, Math.min(16, Math.floor(Math.max(2, os2.availableParallelism?.() ?? os2.cpus().length) / 2)));
|
|
27097
27196
|
this.safeSlots = options.safeSlots ?? capacity;
|
|
27098
27197
|
this.maxQueued = options.maxQueued ?? 128;
|
|
27099
27198
|
if (!Number.isInteger(this.safeSlots) || this.safeSlots < 1 || this.safeSlots > 32 || !Number.isInteger(this.maxQueued) || this.maxQueued < 1 || this.maxQueued > 256) throw Error("INVALID_SCHEDULER_LIMIT");
|
|
27100
27199
|
}
|
|
27200
|
+
options;
|
|
27201
|
+
safeSlots;
|
|
27202
|
+
active = /* @__PURE__ */ new Map();
|
|
27203
|
+
waiting = [];
|
|
27204
|
+
accepting = true;
|
|
27101
27205
|
maxQueued;
|
|
27102
|
-
|
|
27206
|
+
observe(event) {
|
|
27207
|
+
try {
|
|
27208
|
+
void Promise.resolve(this.options.onEvent?.(event)).catch(() => {
|
|
27209
|
+
});
|
|
27210
|
+
} catch {
|
|
27211
|
+
}
|
|
27212
|
+
}
|
|
27213
|
+
schedule(id2, claims, deadlineAt, run, signal) {
|
|
27103
27214
|
if (!this.accepting) return Promise.reject(Error("AGENT_PAUSED"));
|
|
27104
|
-
if (!
|
|
27105
|
-
if (!Array.isArray(claims) || !claims.length || claims.length > 32 || claims.some((c) => !c || !
|
|
27215
|
+
if (!id2 || id2.length > 100 || this.active.has(id2) || this.waiting.some((j) => j.id === id2)) return Promise.reject(Error("DUPLICATE_SCHEDULED_EXECUTION"));
|
|
27216
|
+
if (!Array.isArray(claims) || !claims.length || claims.length > 32 || claims.some((c) => !c || !path11.isAbsolute(c.path) || !["read", "write"].includes(c.mode))) return Promise.reject(Error("INVALID_RESOURCE_CLAIM"));
|
|
27106
27217
|
const deadline = deadlineAt.getTime();
|
|
27107
27218
|
if (!Number.isFinite(deadline) || deadline <= Date.now()) return Promise.reject(Error("ADMISSION_DEADLINE_EXPIRED"));
|
|
27108
27219
|
if (signal?.aborted) return Promise.reject(Error("CANCELLED_BEFORE_ACCEPTANCE"));
|
|
27109
27220
|
if (this.waiting.length >= this.maxQueued) return Promise.reject(Error("RESOURCE_BUSY"));
|
|
27110
27221
|
return new Promise((resolve, reject) => {
|
|
27111
|
-
const job = { id, claims: claims.map((c) => ({ ...c, path: canonical(c.path) })), deadline, run, signal, resolve, reject };
|
|
27222
|
+
const job = { id: id2, claims: claims.map((c) => ({ ...c, path: canonical(c.path) })), deadline, run, signal, resolve, reject };
|
|
27112
27223
|
const remove = (reason) => {
|
|
27113
27224
|
const index = this.waiting.indexOf(job);
|
|
27114
27225
|
if (index < 0) return;
|
|
27115
27226
|
this.waiting.splice(index, 1);
|
|
27116
27227
|
this.cleanup(job);
|
|
27228
|
+
this.observe({ kind: "queue_rejected", executionId: id2, code: reason, terminalProof: true });
|
|
27117
27229
|
reject(Error(reason));
|
|
27118
27230
|
this.pump();
|
|
27119
27231
|
};
|
|
@@ -27121,6 +27233,7 @@ var NativeScheduler = class {
|
|
|
27121
27233
|
job.timer = setTimeout(() => remove("ADMISSION_DEADLINE_EXPIRED"), Math.min(2147483647, Math.max(1, deadline - Date.now())));
|
|
27122
27234
|
signal?.addEventListener("abort", job.aborted, { once: true });
|
|
27123
27235
|
this.waiting.push(job);
|
|
27236
|
+
this.observe({ kind: "queued", executionId: id2, deadlineAt: deadline });
|
|
27124
27237
|
this.pump();
|
|
27125
27238
|
});
|
|
27126
27239
|
}
|
|
@@ -27132,9 +27245,11 @@ var NativeScheduler = class {
|
|
|
27132
27245
|
for (let i = 0; i < this.waiting.length && this.active.size < this.safeSlots; ) {
|
|
27133
27246
|
const job = this.waiting[i];
|
|
27134
27247
|
if (!this.accepting || job.signal?.aborted || job.deadline <= Date.now()) {
|
|
27248
|
+
const code = !this.accepting ? "AGENT_PAUSED" : job.signal?.aborted ? "CANCELLED_BEFORE_ACCEPTANCE" : "ADMISSION_DEADLINE_EXPIRED";
|
|
27135
27249
|
this.waiting.splice(i, 1);
|
|
27136
27250
|
this.cleanup(job);
|
|
27137
|
-
|
|
27251
|
+
this.observe({ kind: "queue_rejected", executionId: job.id, code, terminalProof: true });
|
|
27252
|
+
job.reject(Error(code));
|
|
27138
27253
|
continue;
|
|
27139
27254
|
}
|
|
27140
27255
|
if ([...this.active.values()].some((claims) => claimsConflict(claims, job.claims))) {
|
|
@@ -27148,8 +27263,10 @@ var NativeScheduler = class {
|
|
|
27148
27263
|
this.waiting.splice(i, 1);
|
|
27149
27264
|
this.cleanup(job);
|
|
27150
27265
|
this.active.set(job.id, job.claims);
|
|
27266
|
+
this.observe({ kind: "admitted", executionId: job.id, deadlineAt: job.deadline });
|
|
27151
27267
|
void Promise.resolve().then(job.run).then(job.resolve, job.reject).finally(() => {
|
|
27152
27268
|
this.active.delete(job.id);
|
|
27269
|
+
this.observe({ kind: "released", executionId: job.id });
|
|
27153
27270
|
this.pump();
|
|
27154
27271
|
});
|
|
27155
27272
|
}
|
|
@@ -27731,6 +27848,7 @@ var NativeRuntime = class {
|
|
|
27731
27848
|
connection = null;
|
|
27732
27849
|
transport = null;
|
|
27733
27850
|
contexts = /* @__PURE__ */ new Map();
|
|
27851
|
+
completedResults = /* @__PURE__ */ new Map();
|
|
27734
27852
|
paused = false;
|
|
27735
27853
|
closing = false;
|
|
27736
27854
|
connected(connection, send) {
|
|
@@ -27747,6 +27865,15 @@ var NativeRuntime = class {
|
|
|
27747
27865
|
this.options.onActivity?.();
|
|
27748
27866
|
}
|
|
27749
27867
|
send(frame) {
|
|
27868
|
+
if (frame.type === "result") {
|
|
27869
|
+
this.completedResults.set(frame.binding.executionId, frame.result);
|
|
27870
|
+
if (this.completedResults.size > 64) this.completedResults.delete(this.completedResults.keys().next().value);
|
|
27871
|
+
}
|
|
27872
|
+
try {
|
|
27873
|
+
void Promise.resolve(this.options.onFrame?.(frame)).catch(() => {
|
|
27874
|
+
});
|
|
27875
|
+
} catch {
|
|
27876
|
+
}
|
|
27750
27877
|
try {
|
|
27751
27878
|
return this.transport?.(frame) ?? false;
|
|
27752
27879
|
} catch {
|
|
@@ -27941,7 +28068,7 @@ var NativeRuntime = class {
|
|
|
27941
28068
|
const fresh = await this.options.journal.get(binding2.executionId);
|
|
27942
28069
|
let result2;
|
|
27943
28070
|
if (fresh?.result) {
|
|
27944
|
-
result2 = context ? await outboundResult(context.tool.call, journalResult(fresh.result), binding2, this.options.efficiencyLedger) : journalResult(fresh.result);
|
|
28071
|
+
result2 = this.completedResults.get(binding2.executionId) ?? (context ? await outboundResult(context.tool.call, journalResult(fresh.result), binding2, this.options.efficiencyLedger) : journalResult(fresh.result));
|
|
27945
28072
|
if (frame.action === "output" && this.options.efficiencyLedger) {
|
|
27946
28073
|
const notice = await this.options.efficiencyLedger.consumeNoticeForExecution?.(binding2.executionId).catch(() => null);
|
|
27947
28074
|
if (notice) result2 = { ...result2, efficiencyNotice: notice };
|
|
@@ -28010,18 +28137,18 @@ var NativeRelayBridge = class {
|
|
|
28010
28137
|
async flushTerminal() {
|
|
28011
28138
|
if (!this.connection) return;
|
|
28012
28139
|
for (const event of await this.journal.listUnreportedResults()) {
|
|
28013
|
-
const
|
|
28140
|
+
const id2 = event.executionId, connection = this.connection;
|
|
28014
28141
|
if (!connection || event.tenantId !== connection.tenantId || event.deviceId !== connection.deviceId || !event.workspaceGrantId || !event.policyVersion || !event.resultCode) continue;
|
|
28015
|
-
if (this.terminalSending.has(
|
|
28016
|
-
this.terminalSending.add(
|
|
28142
|
+
if (this.terminalSending.has(id2)) continue;
|
|
28143
|
+
this.terminalSending.add(id2);
|
|
28017
28144
|
try {
|
|
28018
|
-
const binding2 = { tenantId: event.tenantId, deviceId: event.deviceId, grantId: event.grantId, sessionId: event.sessionId, operationId: event.operationId, executionId:
|
|
28145
|
+
const binding2 = { tenantId: event.tenantId, deviceId: event.deviceId, grantId: event.grantId, sessionId: event.sessionId, operationId: event.operationId, executionId: id2, connectionEpoch: event.connectionEpoch, workspaceGrantId: event.workspaceGrantId, policyVersion: event.policyVersion, payloadHash: event.payloadHash, deadlineAt: event.deadlineAt, ...event.accountId ? { accountId: event.accountId } : {} };
|
|
28019
28146
|
if (!["finished", "failed", "cancelled", "unknown"].includes(event.state)) continue;
|
|
28020
28147
|
await this.sendTerminal(binding2, event.state, event.resultCode, terminalMetrics(event.result));
|
|
28021
|
-
await this.journal.markReported(
|
|
28148
|
+
await this.journal.markReported(id2, event.resultCode);
|
|
28022
28149
|
} catch {
|
|
28023
28150
|
} finally {
|
|
28024
|
-
this.terminalSending.delete(
|
|
28151
|
+
this.terminalSending.delete(id2);
|
|
28025
28152
|
}
|
|
28026
28153
|
}
|
|
28027
28154
|
}
|
|
@@ -28083,7 +28210,7 @@ var NativeRelayBridge = class {
|
|
|
28083
28210
|
};
|
|
28084
28211
|
|
|
28085
28212
|
// agent/src/relay-client.ts
|
|
28086
|
-
import { createPrivateKey as createPrivateKey2, randomUUID as
|
|
28213
|
+
import { createPrivateKey as createPrivateKey2, randomUUID as randomUUID6, sign } from "node:crypto";
|
|
28087
28214
|
|
|
28088
28215
|
// ../../node_modules/ws/wrapper.mjs
|
|
28089
28216
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -28096,6 +28223,160 @@ var import_websocket = __toESM(require_websocket(), 1);
|
|
|
28096
28223
|
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
28097
28224
|
var wrapper_default = import_websocket.default;
|
|
28098
28225
|
|
|
28226
|
+
// agent/src/native-incident-producer.ts
|
|
28227
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
28228
|
+
var uuid16 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
28229
|
+
var results = /* @__PURE__ */ new Set(["accepted", "duplicate", "invalid", "stale", "unconfirmed", "capacity", "retry", "disabled", "busy"]);
|
|
28230
|
+
function nativeIncidentAck(candidate) {
|
|
28231
|
+
if (candidate.type !== "incidentBatchAck" || candidate.protocolVersion !== 1 || Object.keys(candidate).some((key) => !["type", "protocolVersion", "batchId", "result"].includes(key)) || typeof candidate.result !== "string" || !results.has(candidate.result) || candidate.batchId !== void 0 && (typeof candidate.batchId !== "string" || !uuid16.test(candidate.batchId))) return;
|
|
28232
|
+
return { result: candidate.result, ...candidate.batchId ? { batchId: String(candidate.batchId).toLowerCase() } : {} };
|
|
28233
|
+
}
|
|
28234
|
+
var NativeIncidentProducer = class {
|
|
28235
|
+
constructor(supervisor, references) {
|
|
28236
|
+
this.supervisor = supervisor;
|
|
28237
|
+
this.references = references;
|
|
28238
|
+
try {
|
|
28239
|
+
this.unsubscribe = supervisor.subscribe(() => this.activity());
|
|
28240
|
+
} catch {
|
|
28241
|
+
this.unsubscribe = () => {
|
|
28242
|
+
};
|
|
28243
|
+
this.rejected++;
|
|
28244
|
+
}
|
|
28245
|
+
}
|
|
28246
|
+
supervisor;
|
|
28247
|
+
references;
|
|
28248
|
+
sender;
|
|
28249
|
+
batch;
|
|
28250
|
+
inFlight = false;
|
|
28251
|
+
queued = false;
|
|
28252
|
+
nextSend = 0;
|
|
28253
|
+
closed = false;
|
|
28254
|
+
rejected = 0;
|
|
28255
|
+
overflow = 0;
|
|
28256
|
+
carry;
|
|
28257
|
+
unsubscribe;
|
|
28258
|
+
connected(sender) {
|
|
28259
|
+
this.disconnected();
|
|
28260
|
+
this.sender = sender;
|
|
28261
|
+
this.nextSend = 0;
|
|
28262
|
+
this.activity();
|
|
28263
|
+
}
|
|
28264
|
+
disconnected() {
|
|
28265
|
+
this.sender = void 0;
|
|
28266
|
+
this.inFlight = false;
|
|
28267
|
+
this.supervisor.cancelDeadline("incident-ack");
|
|
28268
|
+
this.supervisor.cancelDeadline("incident-send");
|
|
28269
|
+
}
|
|
28270
|
+
activity() {
|
|
28271
|
+
if (this.closed || !this.sender || this.queued || this.inFlight) return;
|
|
28272
|
+
this.queued = true;
|
|
28273
|
+
queueMicrotask(() => {
|
|
28274
|
+
this.queued = false;
|
|
28275
|
+
try {
|
|
28276
|
+
this.flush();
|
|
28277
|
+
} catch {
|
|
28278
|
+
this.rejected++;
|
|
28279
|
+
}
|
|
28280
|
+
});
|
|
28281
|
+
}
|
|
28282
|
+
ack(ack) {
|
|
28283
|
+
if (!this.inFlight || !this.batch || ack.batchId !== this.batch.batchId) return;
|
|
28284
|
+
this.supervisor.cancelDeadline("incident-ack");
|
|
28285
|
+
this.inFlight = false;
|
|
28286
|
+
if (ack.result === "accepted" || ack.result === "duplicate") {
|
|
28287
|
+
this.batch = void 0;
|
|
28288
|
+
this.activity();
|
|
28289
|
+
} else if (ack.result === "invalid") {
|
|
28290
|
+
this.batch = void 0;
|
|
28291
|
+
this.rejected++;
|
|
28292
|
+
} else if (ack.result === "stale" || ack.result === "disabled") this.disconnected();
|
|
28293
|
+
}
|
|
28294
|
+
classify(event, occurrences) {
|
|
28295
|
+
const incident = event.incident;
|
|
28296
|
+
if (!incident) return;
|
|
28297
|
+
const executionId = incident.executionId && uuid16.test(incident.executionId) ? incident.executionId.toLowerCase() : void 0;
|
|
28298
|
+
let refs = {};
|
|
28299
|
+
try {
|
|
28300
|
+
const confirmed = executionId && this.references?.(executionId);
|
|
28301
|
+
if (confirmed && confirmed.executionId === executionId && uuid16.test(confirmed.workerId)) {
|
|
28302
|
+
refs = { workerId: confirmed.workerId.toLowerCase(), ...confirmed.taskId && uuid16.test(confirmed.taskId) ? { taskId: confirmed.taskId.toLowerCase() } : {} };
|
|
28303
|
+
}
|
|
28304
|
+
} catch {
|
|
28305
|
+
}
|
|
28306
|
+
return {
|
|
28307
|
+
eventId: randomUUID5(),
|
|
28308
|
+
code: incident.code === "RELAY_DISCONNECTED" ? "relay_error" : incident.code === "LOCAL_QUEUE_EXPIRED" && executionId ? "queue_expired" : incident.code === "EXECUTION_UNKNOWN" && executionId ? "execution_unknown" : "supervisor_error",
|
|
28309
|
+
phase: event.kind === "incident_resolved" ? "resolved" : event.kind === "incident_open" ? "open" : "update",
|
|
28310
|
+
occurredAt: new Date(event.lastSeen).toISOString(),
|
|
28311
|
+
occurrences,
|
|
28312
|
+
...executionId ? { executionId } : {},
|
|
28313
|
+
...refs
|
|
28314
|
+
};
|
|
28315
|
+
}
|
|
28316
|
+
prepare() {
|
|
28317
|
+
const events = [];
|
|
28318
|
+
for (let inspected = 0; inspected < 256 && events.length < 31; inspected++) {
|
|
28319
|
+
if (!this.carry) {
|
|
28320
|
+
const taken = this.supervisor.buffer.take(1);
|
|
28321
|
+
this.overflow = Math.min(Number.MAX_SAFE_INTEGER, this.overflow + taken.dropped);
|
|
28322
|
+
const event2 = taken.events[0];
|
|
28323
|
+
if (!event2) break;
|
|
28324
|
+
if (!event2.incident) continue;
|
|
28325
|
+
this.carry = { event: event2, remaining: event2.kind === "incident_resolved" ? 1 : event2.count };
|
|
28326
|
+
}
|
|
28327
|
+
const occurrences = Math.min(1e4, this.carry.remaining);
|
|
28328
|
+
const event = this.classify(this.carry.event, occurrences);
|
|
28329
|
+
if (event) events.push(event);
|
|
28330
|
+
this.carry.remaining -= occurrences;
|
|
28331
|
+
if (this.carry.remaining <= 0) this.carry = void 0;
|
|
28332
|
+
}
|
|
28333
|
+
if (this.overflow) {
|
|
28334
|
+
const occurrences = Math.min(1e4, this.overflow);
|
|
28335
|
+
this.overflow -= occurrences;
|
|
28336
|
+
events.push({ eventId: randomUUID5(), code: "buffer_overflow", phase: "open", occurredAt: (/* @__PURE__ */ new Date()).toISOString(), occurrences });
|
|
28337
|
+
}
|
|
28338
|
+
if (!events.length) return;
|
|
28339
|
+
return { batchId: randomUUID5(), events };
|
|
28340
|
+
}
|
|
28341
|
+
flush() {
|
|
28342
|
+
if (this.closed || !this.sender || this.inFlight) return;
|
|
28343
|
+
this.batch ??= this.prepare();
|
|
28344
|
+
if (!this.batch) return;
|
|
28345
|
+
if (Date.now() < this.nextSend) {
|
|
28346
|
+
this.supervisor.watchDeadline("incident-send", this.nextSend, () => this.flush());
|
|
28347
|
+
return;
|
|
28348
|
+
}
|
|
28349
|
+
this.supervisor.cancelDeadline("incident-send");
|
|
28350
|
+
if (Buffer.byteLength(JSON.stringify(this.batch)) + 128 > 16384) {
|
|
28351
|
+
this.batch = void 0;
|
|
28352
|
+
this.rejected++;
|
|
28353
|
+
return;
|
|
28354
|
+
}
|
|
28355
|
+
this.inFlight = true;
|
|
28356
|
+
this.nextSend = Date.now() + 1e3;
|
|
28357
|
+
try {
|
|
28358
|
+
this.supervisor.watchDeadline("incident-ack", Date.now() + 1e4, () => {
|
|
28359
|
+
this.inFlight = false;
|
|
28360
|
+
});
|
|
28361
|
+
if (!this.sender(this.batch)) {
|
|
28362
|
+
this.inFlight = false;
|
|
28363
|
+
this.supervisor.cancelDeadline("incident-ack");
|
|
28364
|
+
}
|
|
28365
|
+
} catch {
|
|
28366
|
+
this.inFlight = false;
|
|
28367
|
+
this.supervisor.cancelDeadline("incident-ack");
|
|
28368
|
+
}
|
|
28369
|
+
}
|
|
28370
|
+
snapshot() {
|
|
28371
|
+
return { pendingBatch: !!this.batch, pendingEvents: this.batch?.events.length ?? 0, inFlight: this.inFlight, rejected: this.rejected };
|
|
28372
|
+
}
|
|
28373
|
+
close() {
|
|
28374
|
+
this.closed = true;
|
|
28375
|
+
this.disconnected();
|
|
28376
|
+
this.unsubscribe();
|
|
28377
|
+
}
|
|
28378
|
+
};
|
|
28379
|
+
|
|
28099
28380
|
// agent/src/relay-client.ts
|
|
28100
28381
|
var RelayClientError = class extends Error {
|
|
28101
28382
|
constructor(code) {
|
|
@@ -28131,7 +28412,7 @@ function relayUrlFromEnrollment(enrollment) {
|
|
|
28131
28412
|
url2.pathname = "/api/agent/relay";
|
|
28132
28413
|
return url2.toString();
|
|
28133
28414
|
}
|
|
28134
|
-
function
|
|
28415
|
+
function uuid17(value, code) {
|
|
28135
28416
|
if (typeof value !== "string" || !UUID2.test(value)) fail3(code);
|
|
28136
28417
|
return value.toLowerCase();
|
|
28137
28418
|
}
|
|
@@ -28261,41 +28542,43 @@ function sendJson(socket, value, maxBytes) {
|
|
|
28261
28542
|
function validateChallenge(frame, expectedProtocol) {
|
|
28262
28543
|
if (frame.type !== "challenge") fail3("RELAY_HANDSHAKE_INVALID");
|
|
28263
28544
|
protocol(frame.protocolVersion, expectedProtocol);
|
|
28264
|
-
|
|
28545
|
+
uuid17(frame.gatewayId, "RELAY_HANDSHAKE_INVALID");
|
|
28265
28546
|
if (typeof frame.nonce !== "string" || frame.nonce.length < 32 || frame.nonce.length > 512 || /[\u0000-\u001f\u007f]/u.test(frame.nonce)) fail3("RELAY_HANDSHAKE_INVALID");
|
|
28266
28547
|
if (typeof frame.expiresAt !== "string" || !Number.isFinite(Date.parse(frame.expiresAt)) || Date.parse(frame.expiresAt) <= Date.now()) fail3("RELAY_HANDSHAKE_INVALID");
|
|
28267
28548
|
return {
|
|
28268
|
-
challengeId:
|
|
28549
|
+
challengeId: uuid17(frame.challengeId, "RELAY_HANDSHAKE_INVALID"),
|
|
28269
28550
|
nonce: frame.nonce
|
|
28270
28551
|
};
|
|
28271
28552
|
}
|
|
28272
28553
|
function validateReady(frame, enrollment, expectedProtocol) {
|
|
28273
28554
|
if (frame.type !== "connected") fail3("RELAY_HANDSHAKE_INVALID");
|
|
28274
28555
|
protocol(frame.protocolVersion, expectedProtocol);
|
|
28275
|
-
if (
|
|
28276
|
-
if (
|
|
28556
|
+
if (uuid17(frame.tenantId, "RELAY_HANDSHAKE_INVALID") !== enrollment.tenantId.toLowerCase()) fail3("RELAY_ID_MISMATCH");
|
|
28557
|
+
if (uuid17(frame.deviceId, "RELAY_HANDSHAKE_INVALID") !== enrollment.deviceId.toLowerCase()) fail3("RELAY_ID_MISMATCH");
|
|
28277
28558
|
const terminalMetrics2 = Array.isArray(frame.capabilities) && frame.capabilities.includes(TERMINAL_METRICS_CAPABILITY);
|
|
28278
28559
|
return { connectionEpoch: epoch2(frame.connectionEpoch), terminalMetrics: terminalMetrics2 };
|
|
28279
28560
|
}
|
|
28280
28561
|
function validateRequest(frame, enrollment, expectedProtocol, connectionEpoch) {
|
|
28281
28562
|
if (frame.type !== "relayFrame") fail3("RELAY_REQUEST_INVALID");
|
|
28282
28563
|
protocol(frame.protocolVersion, expectedProtocol);
|
|
28283
|
-
const tenantId =
|
|
28284
|
-
const deviceId =
|
|
28564
|
+
const tenantId = uuid17(frame.tenantId, "RELAY_REQUEST_INVALID");
|
|
28565
|
+
const deviceId = uuid17(frame.deviceId, "RELAY_REQUEST_INVALID");
|
|
28285
28566
|
if (tenantId !== enrollment.tenantId.toLowerCase() || deviceId !== enrollment.deviceId.toLowerCase()) fail3("RELAY_ID_MISMATCH");
|
|
28286
28567
|
if (epoch2(frame.connectionEpoch) !== connectionEpoch) fail3("RELAY_EPOCH_MISMATCH");
|
|
28287
28568
|
const kind = frame.kind;
|
|
28288
28569
|
if (typeof kind !== "string" || !REQUEST_KINDS.has(kind)) fail3("RELAY_REQUEST_INVALID");
|
|
28289
28570
|
return {
|
|
28290
|
-
requestId:
|
|
28571
|
+
requestId: uuid17(frame.requestId, "RELAY_REQUEST_INVALID"),
|
|
28291
28572
|
tenantId,
|
|
28292
28573
|
deviceId,
|
|
28293
28574
|
connectionEpoch,
|
|
28294
|
-
operationId:
|
|
28295
|
-
executionId:
|
|
28575
|
+
operationId: uuid17(frame.operationId, "RELAY_REQUEST_INVALID"),
|
|
28576
|
+
executionId: uuid17(frame.executionId, "RELAY_REQUEST_INVALID"),
|
|
28296
28577
|
kind,
|
|
28297
28578
|
payload: frame.payload,
|
|
28298
|
-
deadlineAt: isoDate(frame.deadlineAt)
|
|
28579
|
+
deadlineAt: isoDate(frame.deadlineAt),
|
|
28580
|
+
// Invalid optional diagnostics never reject otherwise valid execution work.
|
|
28581
|
+
...EfficiencyProfileSchema.safeParse(frame.efficiencyProfile).success ? { efficiencyProfile: EfficiencyProfileSchema.parse(frame.efficiencyProfile) } : {}
|
|
28299
28582
|
};
|
|
28300
28583
|
}
|
|
28301
28584
|
function closedPromise(socket) {
|
|
@@ -28332,8 +28615,8 @@ async function connectOnce(options) {
|
|
|
28332
28615
|
const identity = await options.store.load();
|
|
28333
28616
|
if (!identity || !identity.enrollment) fail3("ENROLLMENT_MISSING");
|
|
28334
28617
|
const enrollment = identity.enrollment;
|
|
28335
|
-
const tenantId =
|
|
28336
|
-
const deviceId =
|
|
28618
|
+
const tenantId = uuid17(enrollment.tenantId, "ENROLLMENT_INVALID");
|
|
28619
|
+
const deviceId = uuid17(enrollment.deviceId, "ENROLLMENT_INVALID");
|
|
28337
28620
|
const url2 = relayUrlFromEnrollment(enrollment);
|
|
28338
28621
|
const socket = new wrapper_default(url2, [], {
|
|
28339
28622
|
followRedirects: false,
|
|
@@ -28368,7 +28651,21 @@ async function connectOnce(options) {
|
|
|
28368
28651
|
nonce: challenge.nonce,
|
|
28369
28652
|
signature
|
|
28370
28653
|
}, maxFrameBytes);
|
|
28371
|
-
const
|
|
28654
|
+
const readyFrame = await waitForMessage(socket, maxFrameBytes, connectTimeoutMs, "RELAY_HANDSHAKE_TIMEOUT");
|
|
28655
|
+
const { connectionEpoch, terminalMetrics: terminalMetrics2 } = validateReady(readyFrame, enrollment, protocolVersion2);
|
|
28656
|
+
const incidents = Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes("incidentBatchV1");
|
|
28657
|
+
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;
|
|
28658
|
+
if (monitorHeartbeat) socket.on("ping", (data) => {
|
|
28659
|
+
if (data.toString() !== "lcmcp-monitor:" + connectionEpoch) return;
|
|
28660
|
+
try {
|
|
28661
|
+
void Promise.resolve(options.onMonitorHeartbeat?.()).catch(() => {
|
|
28662
|
+
});
|
|
28663
|
+
} catch {
|
|
28664
|
+
}
|
|
28665
|
+
});
|
|
28666
|
+
if (Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes(NATIVE_CAPACITY_CAPABILITY)) {
|
|
28667
|
+
sendJson(socket, NativeCapacitySchema.parse({ type: "nativeCapacity", protocolVersion: protocolVersion2, connectionEpoch, safeSlots: options.safeSlots ?? 1, agentVersion: options.agentVersion }), maxFrameBytes);
|
|
28668
|
+
}
|
|
28372
28669
|
socket.off("message", bufferDuringReady);
|
|
28373
28670
|
if (handshakeOverflow) fail3("RELAY_FRAME_TOO_LARGE");
|
|
28374
28671
|
handshakeBuffer.shift();
|
|
@@ -28392,6 +28689,17 @@ async function connectOnce(options) {
|
|
|
28392
28689
|
void (async () => {
|
|
28393
28690
|
try {
|
|
28394
28691
|
const frame = parseFrame(data, maxFrameBytes);
|
|
28692
|
+
if (frame.type === "incidentBatchAck") {
|
|
28693
|
+
const ack = nativeIncidentAck(frame);
|
|
28694
|
+
if (incidents && ack) {
|
|
28695
|
+
try {
|
|
28696
|
+
void Promise.resolve(options.onIncidentAck?.(ack)).catch(() => {
|
|
28697
|
+
});
|
|
28698
|
+
} catch {
|
|
28699
|
+
}
|
|
28700
|
+
}
|
|
28701
|
+
return;
|
|
28702
|
+
}
|
|
28395
28703
|
if (frame.type === "executionResultAck") {
|
|
28396
28704
|
const ack = TerminalEventAckSchema.safeParse(frame);
|
|
28397
28705
|
if (!ack.success || !pendingTerminal.has(ack.data.requestId)) fail3("RELAY_FRAME_INVALID");
|
|
@@ -28453,9 +28761,19 @@ async function connectOnce(options) {
|
|
|
28453
28761
|
heartbeat: () => {
|
|
28454
28762
|
if (socket.readyState !== wrapper_default.OPEN) fail3("RELAY_SOCKET_CLOSED");
|
|
28455
28763
|
},
|
|
28764
|
+
...monitorHeartbeat ? { monitorFreshnessMs: monitorHeartbeat * 3 } : {},
|
|
28765
|
+
...incidents ? { sendIncidentBatch: (batch) => {
|
|
28766
|
+
try {
|
|
28767
|
+
if (socket.readyState !== wrapper_default.OPEN) return false;
|
|
28768
|
+
sendJson(socket, { type: "incidentBatch", protocolVersion: 1, batchId: batch.batchId, connectionEpoch, events: batch.events }, Math.min(maxFrameBytes, 16384));
|
|
28769
|
+
return true;
|
|
28770
|
+
} catch {
|
|
28771
|
+
return false;
|
|
28772
|
+
}
|
|
28773
|
+
} } : {},
|
|
28456
28774
|
sendTerminal: (binding2, state, resultCode, metrics) => {
|
|
28457
28775
|
if (pendingTerminal.size >= 64) return Promise.reject(new RelayClientError("RELAY_PENDING_LIMIT"));
|
|
28458
|
-
const requestId =
|
|
28776
|
+
const requestId = randomUUID6();
|
|
28459
28777
|
const event = { type: "executionResult", protocolVersion: 1, requestId, tenantId, deviceId, connectionEpoch, binding: binding2, state, resultCode, ...terminalMetrics2 && metrics ? { metrics } : {} };
|
|
28460
28778
|
return new Promise((resolve, reject) => {
|
|
28461
28779
|
const timer = setTimeout(() => {
|
|
@@ -28474,7 +28792,7 @@ async function connectOnce(options) {
|
|
|
28474
28792
|
},
|
|
28475
28793
|
registerWorkspace: (workspace) => {
|
|
28476
28794
|
if (pendingWorkspace.size >= 32) return Promise.reject(new RelayClientError("RELAY_PENDING_LIMIT"));
|
|
28477
|
-
const requestId =
|
|
28795
|
+
const requestId = randomUUID6();
|
|
28478
28796
|
const event = { type: "workspace_grant", version: 1, requestId, workspaceGrantId: workspace.workspaceGrantId, rootHash: workspace.rootHash, displayName: workspace.displayName, policyVersion: workspace.policyVersion };
|
|
28479
28797
|
return new Promise((resolve, reject) => {
|
|
28480
28798
|
const timer = setTimeout(() => {
|
|
@@ -28493,7 +28811,7 @@ async function connectOnce(options) {
|
|
|
28493
28811
|
},
|
|
28494
28812
|
revokeWorkspace: (workspaceGrantId) => {
|
|
28495
28813
|
if (pendingWorkspace.size >= 32) return Promise.reject(new RelayClientError("RELAY_PENDING_LIMIT"));
|
|
28496
|
-
const requestId =
|
|
28814
|
+
const requestId = randomUUID6();
|
|
28497
28815
|
const event = { type: "workspace_revoke", version: 1, requestId, workspaceGrantId };
|
|
28498
28816
|
return new Promise((resolve, reject) => {
|
|
28499
28817
|
const timer = setTimeout(() => {
|
|
@@ -28553,10 +28871,10 @@ function canonicalOrigin2(value) {
|
|
|
28553
28871
|
fail4("ORIGIN_INVALID");
|
|
28554
28872
|
}
|
|
28555
28873
|
}
|
|
28556
|
-
function endpoint(origin,
|
|
28557
|
-
return origin +
|
|
28874
|
+
function endpoint(origin, path18) {
|
|
28875
|
+
return origin + path18;
|
|
28558
28876
|
}
|
|
28559
|
-
function
|
|
28877
|
+
function uuid18(value, code) {
|
|
28560
28878
|
if (typeof value !== "string" || !UUID3.test(value)) fail4(code);
|
|
28561
28879
|
return value.toLowerCase();
|
|
28562
28880
|
}
|
|
@@ -28676,7 +28994,7 @@ var PairingClient = class {
|
|
|
28676
28994
|
publicKey: identity.publicKeyPem,
|
|
28677
28995
|
agentVersion: this.version
|
|
28678
28996
|
}));
|
|
28679
|
-
const pairingId =
|
|
28997
|
+
const pairingId = uuid18(response.pairingId, "PAIRING_RESPONSE_INVALID");
|
|
28680
28998
|
const expiresAt = parseDate(response.expiresAt, "PAIRING_RESPONSE_INVALID");
|
|
28681
28999
|
const now = this.nowMs();
|
|
28682
29000
|
if (expiresAt.getTime() <= now || expiresAt.getTime() - now > 30 * 6e4) fail4("PAIRING_RESPONSE_INVALID");
|
|
@@ -28710,7 +29028,7 @@ var PairingClient = class {
|
|
|
28710
29028
|
}
|
|
28711
29029
|
async completeOnce(beginResult, approved, displayNameValue) {
|
|
28712
29030
|
const pairing = this.validateBeginResult(beginResult);
|
|
28713
|
-
const tenantId =
|
|
29031
|
+
const tenantId = uuid18(approved.tenantId, "PAIRING_RESPONSE_INVALID");
|
|
28714
29032
|
const email3 = accountEmail(approved.accountEmail);
|
|
28715
29033
|
const name2 = displayName(displayNameValue);
|
|
28716
29034
|
const identity = await this.currentIdentity();
|
|
@@ -28724,15 +29042,15 @@ var PairingClient = class {
|
|
|
28724
29042
|
displayName: name2,
|
|
28725
29043
|
agentVersion: this.version
|
|
28726
29044
|
}));
|
|
28727
|
-
const completedTenant =
|
|
29045
|
+
const completedTenant = uuid18(response.tenantId, "PAIRING_RESPONSE_INVALID");
|
|
28728
29046
|
if (completedTenant !== tenantId) fail4("PAIRING_RESPONSE_INVALID");
|
|
28729
|
-
const deviceId =
|
|
29047
|
+
const deviceId = uuid18(response.deviceId, "PAIRING_RESPONSE_INVALID");
|
|
28730
29048
|
const enrollment = {
|
|
28731
29049
|
tenantId,
|
|
28732
29050
|
deviceId,
|
|
28733
29051
|
serverOrigin: this.origin,
|
|
28734
29052
|
accountEmail: email3,
|
|
28735
|
-
...response.accountId !== void 0 ? { accountId:
|
|
29053
|
+
...response.accountId !== void 0 ? { accountId: uuid18(response.accountId, "PAIRING_RESPONSE_INVALID") } : {}
|
|
28736
29054
|
};
|
|
28737
29055
|
await this.store.saveEnrollment(enrollment);
|
|
28738
29056
|
return { ...enrollment };
|
|
@@ -28746,7 +29064,7 @@ var PairingClient = class {
|
|
|
28746
29064
|
state: response.state,
|
|
28747
29065
|
expiresAt: parseDate(response.expiresAt, "PAIRING_RESPONSE_INVALID")
|
|
28748
29066
|
};
|
|
28749
|
-
if (response.tenantId !== void 0) result2.tenantId =
|
|
29067
|
+
if (response.tenantId !== void 0) result2.tenantId = uuid18(response.tenantId, "PAIRING_RESPONSE_INVALID");
|
|
28750
29068
|
if (response.accountEmail !== void 0) result2.accountEmail = accountEmail(response.accountEmail);
|
|
28751
29069
|
return result2;
|
|
28752
29070
|
}
|
|
@@ -28758,10 +29076,10 @@ var PairingClient = class {
|
|
|
28758
29076
|
}
|
|
28759
29077
|
validateBeginResult(value) {
|
|
28760
29078
|
return {
|
|
28761
|
-
pairingId:
|
|
29079
|
+
pairingId: uuid18(value.pairingId, "PAIRING_INVALID"),
|
|
28762
29080
|
pairingSecret: pairingSecret(value.pairingSecret),
|
|
28763
29081
|
confirmationCode: confirmationCode(value.confirmationCode),
|
|
28764
|
-
approvalUrl: approvalUrl(value.approvalUrl, this.origin,
|
|
29082
|
+
approvalUrl: approvalUrl(value.approvalUrl, this.origin, uuid18(value.pairingId, "PAIRING_INVALID")),
|
|
28765
29083
|
expiresAt: value.expiresAt instanceof Date ? new Date(value.expiresAt.getTime()) : parseDate(value.expiresAt, "PAIRING_INVALID"),
|
|
28766
29084
|
keyFingerprint: fingerprint2(value.keyFingerprint)
|
|
28767
29085
|
};
|
|
@@ -28793,7 +29111,7 @@ var PairingClient = class {
|
|
|
28793
29111
|
};
|
|
28794
29112
|
|
|
28795
29113
|
// agent/src/guard.ts
|
|
28796
|
-
import { randomUUID as
|
|
29114
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
28797
29115
|
var NativeGuard = class _NativeGuard {
|
|
28798
29116
|
constructor(config2, store, journal) {
|
|
28799
29117
|
this.config = config2;
|
|
@@ -28817,7 +29135,7 @@ var NativeGuard = class _NativeGuard {
|
|
|
28817
29135
|
return this.journal.appendGuardEvidence(action.request.requestId, {
|
|
28818
29136
|
event: {
|
|
28819
29137
|
protocolVersion: 1,
|
|
28820
|
-
evidenceId:
|
|
29138
|
+
evidenceId: randomUUID7(),
|
|
28821
29139
|
requestId: action.request.requestId,
|
|
28822
29140
|
decisionId: decision.decisionId,
|
|
28823
29141
|
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -28843,12 +29161,12 @@ var NativeGuard = class _NativeGuard {
|
|
|
28843
29161
|
try {
|
|
28844
29162
|
action = guardAction(binding2, tool, this.config, now);
|
|
28845
29163
|
} catch {
|
|
28846
|
-
const decisionId2 =
|
|
29164
|
+
const decisionId2 = randomUUID7();
|
|
28847
29165
|
for (const phase of ["request", "decision", "result"]) await this.journal.appendGuardEvidence(binding2.executionId, {
|
|
28848
29166
|
payloadHash: guardHash(tool.effective ?? tool.call),
|
|
28849
29167
|
event: {
|
|
28850
29168
|
protocolVersion: 1,
|
|
28851
|
-
evidenceId:
|
|
29169
|
+
evidenceId: randomUUID7(),
|
|
28852
29170
|
requestId: binding2.executionId,
|
|
28853
29171
|
decisionId: decisionId2,
|
|
28854
29172
|
occurredAt: now,
|
|
@@ -28869,7 +29187,7 @@ var NativeGuard = class _NativeGuard {
|
|
|
28869
29187
|
}
|
|
28870
29188
|
const permit = { action, expiresAt: binding2.deadlineAt, decision: {
|
|
28871
29189
|
protocolVersion: 1,
|
|
28872
|
-
decisionId:
|
|
29190
|
+
decisionId: randomUUID7(),
|
|
28873
29191
|
requestId: binding2.executionId,
|
|
28874
29192
|
policyId: this.config.policyId,
|
|
28875
29193
|
policyVersion: "unavailable",
|
|
@@ -29057,14 +29375,14 @@ async function deliverGuardEvidence(target, packet, options = {}) {
|
|
|
29057
29375
|
// agent/src/optimization-ledger.ts
|
|
29058
29376
|
import { constants as constants4 } from "node:fs";
|
|
29059
29377
|
import { lstat as lstat6, mkdir as mkdir4, open as open5, readFile as readFile4, realpath as realpath6 } from "node:fs/promises";
|
|
29060
|
-
import
|
|
29378
|
+
import path12 from "node:path";
|
|
29061
29379
|
var MAX_LEDGER_BYTES = 64 * 1024 * 1024;
|
|
29062
29380
|
var MAX_NOTICE_LEDGER_BYTES = 8 * 1024 * 1024;
|
|
29063
29381
|
function failure4(code) {
|
|
29064
29382
|
return Object.assign(new Error(code), { code });
|
|
29065
29383
|
}
|
|
29066
29384
|
async function safeDirectory2(directory) {
|
|
29067
|
-
const absolute2 =
|
|
29385
|
+
const absolute2 = path12.resolve(directory);
|
|
29068
29386
|
let current2 = absolute2;
|
|
29069
29387
|
for (; ; ) {
|
|
29070
29388
|
try {
|
|
@@ -29072,7 +29390,7 @@ async function safeDirectory2(directory) {
|
|
|
29072
29390
|
} catch (error62) {
|
|
29073
29391
|
if (error62.code !== "ENOENT") throw error62;
|
|
29074
29392
|
}
|
|
29075
|
-
const parent =
|
|
29393
|
+
const parent = path12.dirname(current2);
|
|
29076
29394
|
if (parent === current2) break;
|
|
29077
29395
|
current2 = parent;
|
|
29078
29396
|
}
|
|
@@ -29097,8 +29415,8 @@ var OptimizationLedger = class _OptimizationLedger {
|
|
|
29097
29415
|
closed = false;
|
|
29098
29416
|
static async open(directory) {
|
|
29099
29417
|
const dir = await safeDirectory2(directory);
|
|
29100
|
-
const filename =
|
|
29101
|
-
const noticesFilename =
|
|
29418
|
+
const filename = path12.join(dir, "live-efficiency.v1.jsonl");
|
|
29419
|
+
const noticesFilename = path12.join(dir, "live-efficiency-notices.v1.jsonl");
|
|
29102
29420
|
let existing = "";
|
|
29103
29421
|
try {
|
|
29104
29422
|
const stat = await lstat6(filename);
|
|
@@ -29230,8 +29548,1625 @@ var OptimizationLedger = class _OptimizationLedger {
|
|
|
29230
29548
|
}
|
|
29231
29549
|
};
|
|
29232
29550
|
|
|
29551
|
+
// agent/src/monitor.ts
|
|
29552
|
+
import { createHash as createHash10, randomUUID as randomUUID8 } from "node:crypto";
|
|
29553
|
+
import { lstat as lstat7, mkdir as mkdir5, open as open6, rename as rename4, rm as rm4 } from "node:fs/promises";
|
|
29554
|
+
import path13 from "node:path";
|
|
29555
|
+
import os3 from "node:os";
|
|
29556
|
+
function commandSummary(tool) {
|
|
29557
|
+
if (tool.name !== "command_run") return { name: tool.name, command: tool.name };
|
|
29558
|
+
const candidate = path13.win32.basename(tool.args.command).replace(/\.(exe|cmd|bat|com)$/i, "").toLowerCase();
|
|
29559
|
+
const name2 = ["node", "npm", "npx", "git", "rg", "powershell", "pwsh", "cmd", "tsc", "python", "dotnet"].includes(candidate) ? candidate : "command";
|
|
29560
|
+
let command = name2;
|
|
29561
|
+
if (name2 === "node" && tool.args.args.includes("--test") && !tool.args.args.some((arg) => ["-e", "--eval", "-p", "--print"].includes(arg))) command += " --test";
|
|
29562
|
+
else if (name2 === "git" && ["status", "diff", "log", "show", "fetch", "pull", "push", "commit"].includes(tool.args.args[0] ?? "")) command += " " + tool.args.args[0];
|
|
29563
|
+
else if (name2 === "npm" && ["test", "install", "ci", "pack", "publish"].includes(tool.args.args[0] ?? "")) command += " " + tool.args.args[0];
|
|
29564
|
+
else if (name2 === "npm" && tool.args.args[0] === "run" && ["test", "build", "typecheck", "lint", "dev", "start"].includes(tool.args.args[1] ?? "")) command += " run " + tool.args.args[1];
|
|
29565
|
+
else if (tool.args.args.length) command += " [args]";
|
|
29566
|
+
return { name: name2, command };
|
|
29567
|
+
}
|
|
29568
|
+
var ProductionMonitor = class {
|
|
29569
|
+
constructor(directory, stateDirectory, agentVersion3) {
|
|
29570
|
+
this.agentVersion = agentVersion3;
|
|
29571
|
+
const key = createHash10("sha256").update(path13.resolve(stateDirectory).toLowerCase()).digest("hex");
|
|
29572
|
+
this.file = path13.join(directory, key + ".json");
|
|
29573
|
+
}
|
|
29574
|
+
agentVersion;
|
|
29575
|
+
instanceId = randomUUID8();
|
|
29576
|
+
events = [];
|
|
29577
|
+
sessions = /* @__PURE__ */ new Map();
|
|
29578
|
+
executions = /* @__PURE__ */ new Map();
|
|
29579
|
+
models = /* @__PURE__ */ new Map();
|
|
29580
|
+
measured = /* @__PURE__ */ new Set();
|
|
29581
|
+
polls = { status: 0, output: 0 };
|
|
29582
|
+
efficiencyCalls = 0;
|
|
29583
|
+
computer = os3.hostname().replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 64) || "PC";
|
|
29584
|
+
sequence = 0;
|
|
29585
|
+
connection = {
|
|
29586
|
+
state: "starting",
|
|
29587
|
+
origin: null,
|
|
29588
|
+
epoch: null
|
|
29589
|
+
};
|
|
29590
|
+
writing = null;
|
|
29591
|
+
dirty = false;
|
|
29592
|
+
freshnessMs = 1e4;
|
|
29593
|
+
transportAt = null;
|
|
29594
|
+
file;
|
|
29595
|
+
record(event, details = {}) {
|
|
29596
|
+
this.events.push({ seq: ++this.sequence, at: (/* @__PURE__ */ new Date()).toISOString(), event, ...details });
|
|
29597
|
+
if (this.events.length > 100) this.events.shift();
|
|
29598
|
+
}
|
|
29599
|
+
configureOrigin(origin) {
|
|
29600
|
+
try {
|
|
29601
|
+
const url2 = new URL(origin);
|
|
29602
|
+
if (url2.origin === origin && !url2.username && !url2.password && (url2.protocol === "https:" || url2.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url2.hostname))) {
|
|
29603
|
+
this.connection.origin = url2.origin;
|
|
29604
|
+
}
|
|
29605
|
+
} catch {
|
|
29606
|
+
}
|
|
29607
|
+
}
|
|
29608
|
+
setConnection(state, connection) {
|
|
29609
|
+
if (connection) {
|
|
29610
|
+
try {
|
|
29611
|
+
this.configureOrigin(new URL(connection.url).origin.replace(/^ws/, "http"));
|
|
29612
|
+
} catch {
|
|
29613
|
+
}
|
|
29614
|
+
this.connection.epoch = connection.connectionEpoch;
|
|
29615
|
+
}
|
|
29616
|
+
this.connection.state = state;
|
|
29617
|
+
this.freshnessMs = state === "connected" ? connection?.monitorFreshnessMs ?? 1e4 : 1e4;
|
|
29618
|
+
this.transportAt = state === "connected" && connection?.monitorFreshnessMs ? (/* @__PURE__ */ new Date()).toISOString() : null;
|
|
29619
|
+
this.record(state);
|
|
29620
|
+
}
|
|
29621
|
+
transportActivity() {
|
|
29622
|
+
if (this.transportAt !== null) this.transportAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
29623
|
+
}
|
|
29624
|
+
request(request) {
|
|
29625
|
+
const payload = request.payload;
|
|
29626
|
+
const parsed = ExecutionBindingSchema.safeParse(payload?.binding);
|
|
29627
|
+
if (!parsed.success || parsed.data.tenantId !== request.tenantId || parsed.data.deviceId !== request.deviceId || parsed.data.executionId !== request.executionId || parsed.data.operationId !== request.operationId) return;
|
|
29628
|
+
const binding2 = parsed.data;
|
|
29629
|
+
this.sessions.delete(binding2.sessionId);
|
|
29630
|
+
this.sessions.set(binding2.sessionId, {
|
|
29631
|
+
sessionId: binding2.sessionId,
|
|
29632
|
+
workspaceGrantId: binding2.workspaceGrantId,
|
|
29633
|
+
lastSeenAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29634
|
+
model: null
|
|
29635
|
+
});
|
|
29636
|
+
if (this.sessions.size > 32) this.sessions.delete(this.sessions.keys().next().value);
|
|
29637
|
+
const tool = ToolCallSchema.safeParse(payload?.tool);
|
|
29638
|
+
if (request.kind === "status" || request.kind === "output") this.polls[request.kind]++;
|
|
29639
|
+
if (request.kind === "execute" && tool.success && !this.executions.has(binding2.executionId)) {
|
|
29640
|
+
const profile = EfficiencyProfileSchema.safeParse(request.efficiencyProfile);
|
|
29641
|
+
this.executions.set(binding2.executionId, {
|
|
29642
|
+
executionId: binding2.executionId,
|
|
29643
|
+
sessionId: binding2.sessionId,
|
|
29644
|
+
...commandSummary(tool.data),
|
|
29645
|
+
state: "requested",
|
|
29646
|
+
pid: null,
|
|
29647
|
+
profile: profile.success ? profile.data : null,
|
|
29648
|
+
originalBytes: null,
|
|
29649
|
+
sentBytes: null,
|
|
29650
|
+
savedBytes: null,
|
|
29651
|
+
reason: null
|
|
29652
|
+
});
|
|
29653
|
+
if (this.executions.size > 64) this.executions.delete(this.executions.keys().next().value);
|
|
29654
|
+
}
|
|
29655
|
+
this.record(request.kind, {
|
|
29656
|
+
sessionId: binding2.sessionId,
|
|
29657
|
+
executionId: binding2.executionId,
|
|
29658
|
+
...tool.success ? { tool: tool.data.name } : {}
|
|
29659
|
+
});
|
|
29660
|
+
}
|
|
29661
|
+
result(binding2, state, code) {
|
|
29662
|
+
const execution = this.executions.get(binding2.executionId);
|
|
29663
|
+
if (execution) execution.state = ["finished", "failed", "cancelled", "unknown"].includes(state) ? state : "unknown";
|
|
29664
|
+
this.record(["finished", "failed", "cancelled", "unknown"].includes(state) ? state : "result", {
|
|
29665
|
+
sessionId: binding2.sessionId,
|
|
29666
|
+
executionId: binding2.executionId,
|
|
29667
|
+
code: code === "SUCCESS" || ErrorCodeSchema.safeParse(code).success ? code : "RESULT"
|
|
29668
|
+
});
|
|
29669
|
+
}
|
|
29670
|
+
frame(frame) {
|
|
29671
|
+
if (!("binding" in frame)) return;
|
|
29672
|
+
const execution = this.executions.get(frame.binding.executionId);
|
|
29673
|
+
if (!execution) return;
|
|
29674
|
+
if (["prepared", "accepted", "running"].includes(frame.type)) execution.state = frame.type;
|
|
29675
|
+
if (frame.type === "running" && frame.pid) execution.pid = frame.pid;
|
|
29676
|
+
if (frame.type === "not_accepted") execution.state = frame.provedNotStarted ? "rejected" : "unknown";
|
|
29677
|
+
if (frame.type === "result") {
|
|
29678
|
+
const result2 = frame.result;
|
|
29679
|
+
execution.state = !result2.treeTerminated ? "unknown" : result2.cancelled ? "cancelled" : result2.timedOut || result2.exitCode !== 0 ? "failed" : "finished";
|
|
29680
|
+
}
|
|
29681
|
+
if (frame.type === "control_result") execution.state = frame.state;
|
|
29682
|
+
}
|
|
29683
|
+
efficiency(input2) {
|
|
29684
|
+
const parsed = LiveEfficiencyEventSchema.safeParse(input2);
|
|
29685
|
+
if (!parsed.success || this.measured.has(parsed.data.executionId)) return;
|
|
29686
|
+
const event = parsed.data, execution = this.executions.get(event.executionId);
|
|
29687
|
+
if (!execution || execution.sessionId !== event.sessionId) return;
|
|
29688
|
+
this.measured.add(event.executionId);
|
|
29689
|
+
if (this.measured.size > 64) this.measured.delete(this.measured.values().next().value);
|
|
29690
|
+
execution.originalBytes = event.originalStdoutBytes;
|
|
29691
|
+
execution.sentBytes = event.sentStdoutBytes;
|
|
29692
|
+
execution.savedBytes = event.savedStdoutBytes;
|
|
29693
|
+
execution.reason = event.reason;
|
|
29694
|
+
const profile = execution.profile;
|
|
29695
|
+
let key = profile?.model ?? "";
|
|
29696
|
+
if (!this.models.has(key) && this.models.size >= 31) key = "";
|
|
29697
|
+
const group = this.models.get(key) ?? { model: key || null, calls: 0, savedBytes: 0, sentBytes: 0 };
|
|
29698
|
+
group.calls++;
|
|
29699
|
+
group.savedBytes += event.savedStdoutBytes;
|
|
29700
|
+
group.sentBytes += event.sentStdoutBytes;
|
|
29701
|
+
this.models.set(key, group);
|
|
29702
|
+
this.efficiencyCalls++;
|
|
29703
|
+
this.record(event.applied ? "compacted" : "passthrough", {
|
|
29704
|
+
sessionId: event.sessionId,
|
|
29705
|
+
executionId: event.executionId,
|
|
29706
|
+
tool: event.toolName
|
|
29707
|
+
});
|
|
29708
|
+
}
|
|
29709
|
+
requestFailed() {
|
|
29710
|
+
this.record("request_failed");
|
|
29711
|
+
}
|
|
29712
|
+
connectionFailed(error62) {
|
|
29713
|
+
const code = error62 instanceof Error ? error62.message : "";
|
|
29714
|
+
this.record("connection_error", { code: [
|
|
29715
|
+
"RELAY_CONNECT_FAILED",
|
|
29716
|
+
"RELAY_CONNECT_CLOSED",
|
|
29717
|
+
"RELAY_CONNECT_TIMEOUT",
|
|
29718
|
+
"RELAY_HANDSHAKE_TIMEOUT",
|
|
29719
|
+
"RELAY_RESULT_TIMEOUT",
|
|
29720
|
+
"WORKSPACE_ACK_TIMEOUT"
|
|
29721
|
+
].includes(code) ? code : "CONNECTION_FAILED" });
|
|
29722
|
+
}
|
|
29723
|
+
response(value) {
|
|
29724
|
+
const result2 = value;
|
|
29725
|
+
if (result2?.accepted === false) this.record("rejected", {
|
|
29726
|
+
code: ErrorCodeSchema.safeParse(result2.code).success ? String(result2.code) : "REJECTED"
|
|
29727
|
+
});
|
|
29728
|
+
}
|
|
29729
|
+
snapshot() {
|
|
29730
|
+
return {
|
|
29731
|
+
schemaVersion: 1,
|
|
29732
|
+
instanceId: this.instanceId,
|
|
29733
|
+
pid: process.pid,
|
|
29734
|
+
computer: this.computer,
|
|
29735
|
+
processName: "lc-agent",
|
|
29736
|
+
agentVersion: this.agentVersion,
|
|
29737
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29738
|
+
freshnessMs: this.freshnessMs,
|
|
29739
|
+
...this.transportAt ? { transportAt: this.transportAt } : {},
|
|
29740
|
+
connection: { ...this.connection },
|
|
29741
|
+
sessions: [...this.sessions.values()].map((session) => ({ ...session })),
|
|
29742
|
+
events: this.events.map((event) => ({ ...event })),
|
|
29743
|
+
executions: [...this.executions.values()].map((execution) => ({ ...execution, profile: execution.profile && { ...execution.profile } })),
|
|
29744
|
+
efficiency: {
|
|
29745
|
+
scope: "this_run",
|
|
29746
|
+
calls: this.efficiencyCalls,
|
|
29747
|
+
polls: { ...this.polls },
|
|
29748
|
+
models: [...this.models.values()].map((group) => ({ ...group }))
|
|
29749
|
+
}
|
|
29750
|
+
};
|
|
29751
|
+
}
|
|
29752
|
+
flush() {
|
|
29753
|
+
this.dirty = true;
|
|
29754
|
+
if (this.writing) return this.writing;
|
|
29755
|
+
this.writing = (async () => {
|
|
29756
|
+
do {
|
|
29757
|
+
this.dirty = false;
|
|
29758
|
+
const directory = path13.dirname(this.file);
|
|
29759
|
+
await mkdir5(directory, { recursive: true, mode: 448 });
|
|
29760
|
+
const stat = await lstat7(directory);
|
|
29761
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) throw Error("MONITOR_DIRECTORY_INVALID");
|
|
29762
|
+
const temporary = this.file + "." + this.instanceId + ".tmp";
|
|
29763
|
+
const handle = await open6(temporary, "wx", 384);
|
|
29764
|
+
try {
|
|
29765
|
+
try {
|
|
29766
|
+
await handle.writeFile(JSON.stringify(this.snapshot()) + "\n");
|
|
29767
|
+
} finally {
|
|
29768
|
+
await handle.close();
|
|
29769
|
+
}
|
|
29770
|
+
await rename4(temporary, this.file);
|
|
29771
|
+
} finally {
|
|
29772
|
+
await rm4(temporary, { force: true });
|
|
29773
|
+
}
|
|
29774
|
+
} while (this.dirty);
|
|
29775
|
+
})().finally(() => {
|
|
29776
|
+
this.writing = null;
|
|
29777
|
+
});
|
|
29778
|
+
return this.writing;
|
|
29779
|
+
}
|
|
29780
|
+
async close() {
|
|
29781
|
+
await this.writing?.catch(() => {
|
|
29782
|
+
});
|
|
29783
|
+
await this.flush();
|
|
29784
|
+
}
|
|
29785
|
+
};
|
|
29786
|
+
|
|
29787
|
+
// agent/src/native-event-buffer.ts
|
|
29788
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
29789
|
+
function nativeFingerprint(code, executionId = "") {
|
|
29790
|
+
return createHash11("sha256").update(code + "\0" + executionId).digest("hex");
|
|
29791
|
+
}
|
|
29792
|
+
var NativeEventBuffer = class {
|
|
29793
|
+
pending = /* @__PURE__ */ new Map();
|
|
29794
|
+
dropped = 0;
|
|
29795
|
+
record(input2, at) {
|
|
29796
|
+
const key = input2.kind + ":" + input2.fingerprint + (input2.incident ? ":" + input2.incident.generation : "");
|
|
29797
|
+
const previous = this.pending.get(key);
|
|
29798
|
+
const event = {
|
|
29799
|
+
...input2,
|
|
29800
|
+
...input2.incident ? { incident: { ...input2.incident } } : {},
|
|
29801
|
+
firstSeen: previous?.firstSeen ?? at,
|
|
29802
|
+
lastSeen: at,
|
|
29803
|
+
count: Math.min(Number.MAX_SAFE_INTEGER, (previous?.count ?? 0) + 1)
|
|
29804
|
+
};
|
|
29805
|
+
this.pending.set(key, event);
|
|
29806
|
+
if (this.pending.size > 256) {
|
|
29807
|
+
this.pending.delete(this.pending.keys().next().value);
|
|
29808
|
+
this.dropped++;
|
|
29809
|
+
}
|
|
29810
|
+
}
|
|
29811
|
+
take(limit = 64) {
|
|
29812
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 128) throw Error("NATIVE_EVENT_BATCH_LIMIT");
|
|
29813
|
+
const events = [];
|
|
29814
|
+
for (const [key, event] of this.pending) {
|
|
29815
|
+
events.push({ ...event, ...event.incident ? { incident: { ...event.incident } } : {} });
|
|
29816
|
+
this.pending.delete(key);
|
|
29817
|
+
if (events.length === limit) break;
|
|
29818
|
+
}
|
|
29819
|
+
const dropped = this.dropped;
|
|
29820
|
+
this.dropped = 0;
|
|
29821
|
+
return { events, dropped };
|
|
29822
|
+
}
|
|
29823
|
+
get size() {
|
|
29824
|
+
return this.pending.size;
|
|
29825
|
+
}
|
|
29826
|
+
};
|
|
29827
|
+
|
|
29828
|
+
// agent/src/native-event-supervisor.ts
|
|
29829
|
+
var eventKinds = /* @__PURE__ */ new Set(["queued", "admitted", "released", "queue_rejected", "prepared", "accepted", "running", "result", "not_accepted", "connected", "disconnected", "mailbox_expired"]);
|
|
29830
|
+
var codes = /* @__PURE__ */ new Set(["SUCCESS", "EXECUTION_UNKNOWN", "ADMISSION_DEADLINE_EXPIRED", "CANCELLED_BEFORE_ACCEPTANCE", "RESOURCE_BUSY", "AGENT_PAUSED", "PREPARATION_EXPIRED", "CANCELLED", "TIMEOUT", "USER_PROGRAM_FAILED", "TOOL_FAILED", "MAILBOX_EXPIRED"]);
|
|
29831
|
+
var NativeEventSupervisor = class {
|
|
29832
|
+
constructor(onChange) {
|
|
29833
|
+
this.onChange = onChange;
|
|
29834
|
+
}
|
|
29835
|
+
onChange;
|
|
29836
|
+
buffer = new NativeEventBuffer();
|
|
29837
|
+
incidents = /* @__PURE__ */ new Map();
|
|
29838
|
+
active = /* @__PURE__ */ new Map();
|
|
29839
|
+
heap = [];
|
|
29840
|
+
positions = /* @__PURE__ */ new Map();
|
|
29841
|
+
timer;
|
|
29842
|
+
closed = false;
|
|
29843
|
+
wasConnected = false;
|
|
29844
|
+
omitted = 0;
|
|
29845
|
+
generation = 0;
|
|
29846
|
+
consumer;
|
|
29847
|
+
observe(input2) {
|
|
29848
|
+
try {
|
|
29849
|
+
if (this.closed || !input2 || !eventKinds.has(input2.kind)) return;
|
|
29850
|
+
const id2 = input2.executionId;
|
|
29851
|
+
if (id2 !== void 0 && (typeof id2 !== "string" || !/^[A-Za-z0-9_-]{1,100}$/.test(id2))) return;
|
|
29852
|
+
const at = Date.now();
|
|
29853
|
+
const code = input2.code === void 0 ? void 0 : codes.has(input2.code) ? input2.code : "TOOL_FAILED";
|
|
29854
|
+
const pid = Number.isSafeInteger(input2.pid) && input2.pid > 0 ? input2.pid : void 0;
|
|
29855
|
+
this.buffer.record({
|
|
29856
|
+
kind: input2.kind,
|
|
29857
|
+
fingerprint: nativeFingerprint(input2.kind, id2),
|
|
29858
|
+
...id2 ? { executionId: id2 } : {},
|
|
29859
|
+
...code ? { code } : {},
|
|
29860
|
+
...pid ? { pid } : {}
|
|
29861
|
+
}, at);
|
|
29862
|
+
if (input2.kind === "connected") {
|
|
29863
|
+
this.wasConnected = true;
|
|
29864
|
+
this.resolve(void 0, at, "RELAY_DISCONNECTED");
|
|
29865
|
+
}
|
|
29866
|
+
if (input2.kind === "mailbox_expired") this.incident("MAILBOX_EXPIRED", void 0, "warning", at);
|
|
29867
|
+
if (input2.kind === "disconnected" && this.wasConnected) this.incident("RELAY_DISCONNECTED", void 0, "warning", at);
|
|
29868
|
+
if (id2) {
|
|
29869
|
+
if (["queued", "prepared", "accepted", "running"].includes(input2.kind)) {
|
|
29870
|
+
if (!this.active.has(id2) && this.active.size >= 320) this.omitted++;
|
|
29871
|
+
else {
|
|
29872
|
+
this.active.set(id2, input2.kind);
|
|
29873
|
+
if (Number.isFinite(input2.deadlineAt) && input2.deadlineAt > 0 && !this.positions.has(id2)) this.insert({ id: id2, at: input2.deadlineAt });
|
|
29874
|
+
}
|
|
29875
|
+
}
|
|
29876
|
+
if (input2.kind === "result" || input2.kind === "not_accepted" || input2.kind === "queue_rejected") {
|
|
29877
|
+
this.active.delete(id2);
|
|
29878
|
+
this.remove(id2);
|
|
29879
|
+
if (input2.kind === "queue_rejected" && code === "ADMISSION_DEADLINE_EXPIRED" && input2.terminalProof === true) this.incident("LOCAL_QUEUE_EXPIRED", id2, "warning", at);
|
|
29880
|
+
if (input2.terminalProof === true) this.resolve(id2, at);
|
|
29881
|
+
else if (input2.kind !== "queue_rejected") this.incident("EXECUTION_UNKNOWN", id2, "error", at);
|
|
29882
|
+
}
|
|
29883
|
+
}
|
|
29884
|
+
this.arm();
|
|
29885
|
+
this.changed();
|
|
29886
|
+
} catch {
|
|
29887
|
+
}
|
|
29888
|
+
}
|
|
29889
|
+
frame(frame) {
|
|
29890
|
+
try {
|
|
29891
|
+
if (!("binding" in frame)) return;
|
|
29892
|
+
const base = { executionId: frame.binding.executionId, deadlineAt: Date.parse(frame.binding.deadlineAt) };
|
|
29893
|
+
if (frame.type === "prepared" || frame.type === "accepted" || frame.type === "running") {
|
|
29894
|
+
this.observe({ ...base, kind: frame.type, ...frame.type === "running" && frame.pid ? { pid: frame.pid } : {} });
|
|
29895
|
+
} else if (frame.type === "not_accepted") {
|
|
29896
|
+
this.observe({ ...base, kind: "not_accepted", code: frame.code, terminalProof: frame.provedNotStarted });
|
|
29897
|
+
} else if (frame.type === "result") {
|
|
29898
|
+
this.observe({
|
|
29899
|
+
...base,
|
|
29900
|
+
kind: "result",
|
|
29901
|
+
code: frame.result.resultCode,
|
|
29902
|
+
terminalProof: frame.result.treeTerminated && frame.result.resultCode !== "EXECUTION_UNKNOWN"
|
|
29903
|
+
});
|
|
29904
|
+
} else if (frame.type === "control_result" && frame.result && frame.result.resultCode !== "IN_PROGRESS") {
|
|
29905
|
+
this.observe({
|
|
29906
|
+
...base,
|
|
29907
|
+
kind: "result",
|
|
29908
|
+
code: frame.result.resultCode,
|
|
29909
|
+
terminalProof: frame.result.treeTerminated && frame.result.resultCode !== "EXECUTION_UNKNOWN"
|
|
29910
|
+
});
|
|
29911
|
+
}
|
|
29912
|
+
} catch {
|
|
29913
|
+
}
|
|
29914
|
+
}
|
|
29915
|
+
subscribe(consumer) {
|
|
29916
|
+
if (this.consumer || this.closed) throw Error("NATIVE_EVENT_CONSUMER_UNAVAILABLE");
|
|
29917
|
+
this.consumer = consumer;
|
|
29918
|
+
return () => {
|
|
29919
|
+
if (this.consumer === consumer) this.consumer = void 0;
|
|
29920
|
+
};
|
|
29921
|
+
}
|
|
29922
|
+
watchDeadline(key, at, expired) {
|
|
29923
|
+
if (this.closed || !/^[a-z-]{1,64}$/.test(key) || !Number.isFinite(at)) return;
|
|
29924
|
+
const id2 = "watch:" + key;
|
|
29925
|
+
if (!this.positions.has(id2) && this.heap.filter((value) => value.expired).length >= 8) throw Error("NATIVE_OBSERVER_DEADLINE_LIMIT");
|
|
29926
|
+
this.remove(id2);
|
|
29927
|
+
this.insert({ id: id2, at, expired });
|
|
29928
|
+
this.arm();
|
|
29929
|
+
}
|
|
29930
|
+
cancelDeadline(key) {
|
|
29931
|
+
this.remove("watch:" + key);
|
|
29932
|
+
this.arm();
|
|
29933
|
+
}
|
|
29934
|
+
changed() {
|
|
29935
|
+
try {
|
|
29936
|
+
void Promise.resolve(this.onChange?.()).catch(() => {
|
|
29937
|
+
});
|
|
29938
|
+
} catch {
|
|
29939
|
+
}
|
|
29940
|
+
try {
|
|
29941
|
+
this.consumer?.();
|
|
29942
|
+
} catch {
|
|
29943
|
+
}
|
|
29944
|
+
}
|
|
29945
|
+
incident(code, id2, severity, at) {
|
|
29946
|
+
const fingerprint3 = nativeFingerprint(code, id2), old = this.incidents.get(fingerprint3);
|
|
29947
|
+
const incident = {
|
|
29948
|
+
fingerprint: fingerprint3,
|
|
29949
|
+
...id2 ? { executionId: id2 } : {},
|
|
29950
|
+
code,
|
|
29951
|
+
severity,
|
|
29952
|
+
state: "open",
|
|
29953
|
+
generation: old?.state === "open" ? old.generation : ++this.generation,
|
|
29954
|
+
firstSeen: old?.state === "open" ? old.firstSeen : at,
|
|
29955
|
+
lastSeen: at,
|
|
29956
|
+
count: old?.state === "open" ? Math.min(Number.MAX_SAFE_INTEGER, old.count + 1) : 1
|
|
29957
|
+
};
|
|
29958
|
+
this.incidents.delete(fingerprint3);
|
|
29959
|
+
this.incidents.set(fingerprint3, incident);
|
|
29960
|
+
if (this.incidents.size > 128) {
|
|
29961
|
+
this.incidents.delete(this.incidents.keys().next().value);
|
|
29962
|
+
this.omitted++;
|
|
29963
|
+
}
|
|
29964
|
+
this.buffer.record({ kind: old?.state === "open" ? "incident_update" : "incident_open", fingerprint: fingerprint3, incident }, at);
|
|
29965
|
+
}
|
|
29966
|
+
resolve(id2, at, code) {
|
|
29967
|
+
for (const incident of this.incidents.values()) {
|
|
29968
|
+
if (incident.executionId !== id2 || incident.state !== "open" || code && incident.code !== code) continue;
|
|
29969
|
+
incident.state = "resolved";
|
|
29970
|
+
incident.lastSeen = at;
|
|
29971
|
+
this.buffer.record({ kind: "incident_resolved", fingerprint: incident.fingerprint, incident }, at);
|
|
29972
|
+
}
|
|
29973
|
+
}
|
|
29974
|
+
swap(a, b) {
|
|
29975
|
+
[this.heap[a], this.heap[b]] = [this.heap[b], this.heap[a]];
|
|
29976
|
+
this.positions.set(this.heap[a].id, a);
|
|
29977
|
+
this.positions.set(this.heap[b].id, b);
|
|
29978
|
+
}
|
|
29979
|
+
up(index) {
|
|
29980
|
+
while (index > 0) {
|
|
29981
|
+
const parent = index - 1 >> 1;
|
|
29982
|
+
if (this.heap[parent].at <= this.heap[index].at) break;
|
|
29983
|
+
this.swap(parent, index);
|
|
29984
|
+
index = parent;
|
|
29985
|
+
}
|
|
29986
|
+
return index;
|
|
29987
|
+
}
|
|
29988
|
+
down(index) {
|
|
29989
|
+
for (; ; ) {
|
|
29990
|
+
let next = index, left = index * 2 + 1, right = left + 1;
|
|
29991
|
+
if (left < this.heap.length && this.heap[left].at < this.heap[next].at) next = left;
|
|
29992
|
+
if (right < this.heap.length && this.heap[right].at < this.heap[next].at) next = right;
|
|
29993
|
+
if (next === index) return;
|
|
29994
|
+
this.swap(index, next);
|
|
29995
|
+
index = next;
|
|
29996
|
+
}
|
|
29997
|
+
}
|
|
29998
|
+
insert(deadline) {
|
|
29999
|
+
this.positions.set(deadline.id, this.heap.length);
|
|
30000
|
+
this.heap.push(deadline);
|
|
30001
|
+
this.up(this.heap.length - 1);
|
|
30002
|
+
}
|
|
30003
|
+
remove(id2) {
|
|
30004
|
+
const index = this.positions.get(id2);
|
|
30005
|
+
if (index === void 0) return;
|
|
30006
|
+
const last = this.heap.pop();
|
|
30007
|
+
this.positions.delete(id2);
|
|
30008
|
+
if (index < this.heap.length) {
|
|
30009
|
+
this.heap[index] = last;
|
|
30010
|
+
this.positions.set(last.id, index);
|
|
30011
|
+
this.down(this.up(index));
|
|
30012
|
+
}
|
|
30013
|
+
}
|
|
30014
|
+
arm() {
|
|
30015
|
+
clearTimeout(this.timer);
|
|
30016
|
+
this.timer = void 0;
|
|
30017
|
+
if (this.closed || !this.heap.length) return;
|
|
30018
|
+
this.timer = setTimeout(() => {
|
|
30019
|
+
this.timer = void 0;
|
|
30020
|
+
try {
|
|
30021
|
+
const at = Date.now();
|
|
30022
|
+
let observed = false;
|
|
30023
|
+
while (this.heap.length && this.heap[0].at <= at) {
|
|
30024
|
+
const deadline = this.heap[0], id2 = deadline.id;
|
|
30025
|
+
this.remove(id2);
|
|
30026
|
+
if (deadline.expired) {
|
|
30027
|
+
try {
|
|
30028
|
+
deadline.expired();
|
|
30029
|
+
} catch {
|
|
30030
|
+
}
|
|
30031
|
+
continue;
|
|
30032
|
+
}
|
|
30033
|
+
const state = this.active.get(id2);
|
|
30034
|
+
if (state) {
|
|
30035
|
+
observed = true;
|
|
30036
|
+
this.incident(state === "queued" || state === "prepared" ? "LOCAL_ADMISSION_OVERDUE" : "LOCAL_EXECUTION_OVERDUE", id2, state === "queued" || state === "prepared" ? "warning" : "error", at);
|
|
30037
|
+
}
|
|
30038
|
+
}
|
|
30039
|
+
if (observed) this.changed();
|
|
30040
|
+
} catch {
|
|
30041
|
+
} finally {
|
|
30042
|
+
this.arm();
|
|
30043
|
+
}
|
|
30044
|
+
}, Math.min(2147483647, Math.max(1, this.heap[0].at - Date.now())));
|
|
30045
|
+
this.timer.unref();
|
|
30046
|
+
}
|
|
30047
|
+
snapshot() {
|
|
30048
|
+
return {
|
|
30049
|
+
active: this.active.size,
|
|
30050
|
+
deadlines: this.heap.length,
|
|
30051
|
+
timerArmed: !!this.timer,
|
|
30052
|
+
pendingEvents: this.buffer.size,
|
|
30053
|
+
omitted: this.omitted,
|
|
30054
|
+
incidents: [...this.incidents.values()].map((value) => ({ ...value }))
|
|
30055
|
+
};
|
|
30056
|
+
}
|
|
30057
|
+
close() {
|
|
30058
|
+
this.closed = true;
|
|
30059
|
+
clearTimeout(this.timer);
|
|
30060
|
+
this.timer = void 0;
|
|
30061
|
+
this.heap.length = 0;
|
|
30062
|
+
this.positions.clear();
|
|
30063
|
+
this.active.clear();
|
|
30064
|
+
this.consumer = void 0;
|
|
30065
|
+
}
|
|
30066
|
+
};
|
|
30067
|
+
|
|
30068
|
+
// agent/src/native-fabric-observer.ts
|
|
30069
|
+
var uuid19 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
30070
|
+
var NativeFabricObserver = class {
|
|
30071
|
+
constructor(supervisor, source) {
|
|
30072
|
+
this.supervisor = supervisor;
|
|
30073
|
+
this.source = source;
|
|
30074
|
+
try {
|
|
30075
|
+
this.unsubscribe = source.subscribe?.(() => this.activity());
|
|
30076
|
+
} catch {
|
|
30077
|
+
}
|
|
30078
|
+
}
|
|
30079
|
+
supervisor;
|
|
30080
|
+
source;
|
|
30081
|
+
referencesByExecution = /* @__PURE__ */ new Map();
|
|
30082
|
+
reportedExpired = /* @__PURE__ */ new Set();
|
|
30083
|
+
deviceId;
|
|
30084
|
+
generation = 0;
|
|
30085
|
+
reading = false;
|
|
30086
|
+
dirty = false;
|
|
30087
|
+
closed = false;
|
|
30088
|
+
unsubscribe;
|
|
30089
|
+
connected(authenticatedDeviceId) {
|
|
30090
|
+
this.disconnected();
|
|
30091
|
+
if (uuid19.test(authenticatedDeviceId)) this.deviceId = authenticatedDeviceId.toLowerCase();
|
|
30092
|
+
this.activity();
|
|
30093
|
+
}
|
|
30094
|
+
disconnected() {
|
|
30095
|
+
this.deviceId = void 0;
|
|
30096
|
+
this.generation++;
|
|
30097
|
+
this.referencesByExecution.clear();
|
|
30098
|
+
this.supervisor.cancelDeadline("fabric-expiry");
|
|
30099
|
+
this.supervisor.cancelDeadline("fabric-read");
|
|
30100
|
+
}
|
|
30101
|
+
references(executionId) {
|
|
30102
|
+
const refs = this.referencesByExecution.get(executionId.toLowerCase());
|
|
30103
|
+
return refs && { ...refs };
|
|
30104
|
+
}
|
|
30105
|
+
activity() {
|
|
30106
|
+
if (this.closed || !this.deviceId) return;
|
|
30107
|
+
this.dirty = true;
|
|
30108
|
+
if (this.reading) return;
|
|
30109
|
+
this.reading = true;
|
|
30110
|
+
this.dirty = false;
|
|
30111
|
+
const generation = this.generation, deviceId = this.deviceId;
|
|
30112
|
+
let expired = false;
|
|
30113
|
+
try {
|
|
30114
|
+
this.supervisor.watchDeadline("fabric-read", Date.now() + 5e3, () => {
|
|
30115
|
+
expired = true;
|
|
30116
|
+
this.referencesByExecution.clear();
|
|
30117
|
+
this.supervisor.cancelDeadline("fabric-expiry");
|
|
30118
|
+
});
|
|
30119
|
+
} catch {
|
|
30120
|
+
this.reading = false;
|
|
30121
|
+
return;
|
|
30122
|
+
}
|
|
30123
|
+
void Promise.resolve().then(() => this.source.mailbox.snapshot()).then((state) => {
|
|
30124
|
+
if (this.closed || expired || generation !== this.generation) return;
|
|
30125
|
+
if (state.workers.length > 64 || state.assignments.length > 256 || state.messages.length > 1024) throw Error("FABRIC_BOUND_INVALID");
|
|
30126
|
+
const workers = new Set(state.workers.filter((w) => w.device?.deviceId.toLowerCase() === deviceId && uuid19.test(w.workerId)).map((w) => w.workerId));
|
|
30127
|
+
const assignments = new Map(state.assignments.filter((a) => workers.has(a.workerId)).map((a) => [a.assignmentId, a]));
|
|
30128
|
+
const refs = /* @__PURE__ */ new Map();
|
|
30129
|
+
for (const a of assignments.values()) {
|
|
30130
|
+
const id2 = a.execution?.executionId;
|
|
30131
|
+
if (!id2 || !uuid19.test(id2)) continue;
|
|
30132
|
+
if (refs.has(id2.toLowerCase())) throw Error("FABRIC_EXECUTION_CONFLICT");
|
|
30133
|
+
refs.set(id2.toLowerCase(), {
|
|
30134
|
+
executionId: id2.toLowerCase(),
|
|
30135
|
+
workerId: a.workerId.toLowerCase(),
|
|
30136
|
+
...uuid19.test(a.taskId) ? { taskId: a.taskId.toLowerCase() } : {}
|
|
30137
|
+
});
|
|
30138
|
+
}
|
|
30139
|
+
this.referencesByExecution.clear();
|
|
30140
|
+
for (const [id2, value] of refs) this.referencesByExecution.set(id2, value);
|
|
30141
|
+
const retained = new Set(state.messages.map((m) => m.messageId));
|
|
30142
|
+
for (const id2 of this.reportedExpired) if (!retained.has(id2)) this.reportedExpired.delete(id2);
|
|
30143
|
+
const now = Date.now();
|
|
30144
|
+
let next;
|
|
30145
|
+
for (const m of state.messages) {
|
|
30146
|
+
const a = assignments.get(m.assignmentId), expiry = Date.parse(m.expiresAt);
|
|
30147
|
+
if (!a || m.acknowledgedAt || !Number.isFinite(expiry)) continue;
|
|
30148
|
+
if (expiry > now) {
|
|
30149
|
+
next = next === void 0 ? expiry : Math.min(next, expiry);
|
|
30150
|
+
continue;
|
|
30151
|
+
}
|
|
30152
|
+
if (this.reportedExpired.has(m.messageId)) continue;
|
|
30153
|
+
this.reportedExpired.add(m.messageId);
|
|
30154
|
+
this.supervisor.observe({ kind: "mailbox_expired", code: "MAILBOX_EXPIRED" });
|
|
30155
|
+
try {
|
|
30156
|
+
void Promise.resolve(this.source.onExpired?.({ workerId: a.workerId, assignmentId: a.assignmentId, messageId: m.messageId })).catch(() => {
|
|
30157
|
+
});
|
|
30158
|
+
} catch {
|
|
30159
|
+
}
|
|
30160
|
+
}
|
|
30161
|
+
if (next === void 0) this.supervisor.cancelDeadline("fabric-expiry");
|
|
30162
|
+
else this.supervisor.watchDeadline("fabric-expiry", next, () => this.activity());
|
|
30163
|
+
}).catch(() => {
|
|
30164
|
+
if (generation === this.generation) {
|
|
30165
|
+
this.referencesByExecution.clear();
|
|
30166
|
+
this.supervisor.cancelDeadline("fabric-expiry");
|
|
30167
|
+
}
|
|
30168
|
+
}).finally(() => {
|
|
30169
|
+
this.reading = false;
|
|
30170
|
+
if (generation === this.generation) this.supervisor.cancelDeadline("fabric-read");
|
|
30171
|
+
if (this.dirty) this.activity();
|
|
30172
|
+
});
|
|
30173
|
+
}
|
|
30174
|
+
snapshot() {
|
|
30175
|
+
return { references: this.referencesByExecution.size, reading: this.reading, reportedExpired: this.reportedExpired.size };
|
|
30176
|
+
}
|
|
30177
|
+
close() {
|
|
30178
|
+
this.closed = true;
|
|
30179
|
+
this.disconnected();
|
|
30180
|
+
try {
|
|
30181
|
+
this.unsubscribe?.();
|
|
30182
|
+
} catch {
|
|
30183
|
+
}
|
|
30184
|
+
}
|
|
30185
|
+
};
|
|
30186
|
+
|
|
30187
|
+
// agent/src/native-fabric-startup.ts
|
|
30188
|
+
import { lstat as lstat9, mkdir as mkdir8, open as open8, readFile as readFile5 } from "node:fs/promises";
|
|
30189
|
+
import path16 from "node:path";
|
|
30190
|
+
|
|
30191
|
+
// src/agent-fabric-service.ts
|
|
30192
|
+
import { lstat as lstat8, mkdir as mkdir7, realpath as realpath7 } from "node:fs/promises";
|
|
30193
|
+
import { watch } from "node:fs";
|
|
30194
|
+
import path15 from "node:path";
|
|
30195
|
+
|
|
30196
|
+
// src/agent-runtime-identity.ts
|
|
30197
|
+
import { createHash as createHash12, randomBytes as randomBytes4, randomUUID as randomUUID10, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
|
|
30198
|
+
|
|
30199
|
+
// src/agent-fabric-state.ts
|
|
30200
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
30201
|
+
import { mkdir as mkdir6, open as open7, rename as rename5, unlink } from "node:fs/promises";
|
|
30202
|
+
import path14 from "node:path";
|
|
30203
|
+
var queues = /* @__PURE__ */ new Map();
|
|
30204
|
+
var FabricStateFile = class {
|
|
30205
|
+
constructor(file2, maxBytes, parse3) {
|
|
30206
|
+
this.maxBytes = maxBytes;
|
|
30207
|
+
this.parse = parse3;
|
|
30208
|
+
this.file = path14.resolve(file2);
|
|
30209
|
+
}
|
|
30210
|
+
maxBytes;
|
|
30211
|
+
parse;
|
|
30212
|
+
file;
|
|
30213
|
+
serial(fn) {
|
|
30214
|
+
const key = process.platform === "win32" ? this.file.toLowerCase() : this.file;
|
|
30215
|
+
const result2 = (queues.get(key) ?? Promise.resolve()).then(fn);
|
|
30216
|
+
const tail = result2.then(() => {
|
|
30217
|
+
}, () => {
|
|
30218
|
+
});
|
|
30219
|
+
queues.set(key, tail);
|
|
30220
|
+
void tail.then(() => {
|
|
30221
|
+
if (queues.get(key) === tail) queues.delete(key);
|
|
30222
|
+
});
|
|
30223
|
+
return result2;
|
|
30224
|
+
}
|
|
30225
|
+
async load() {
|
|
30226
|
+
const handle = await open7(this.file, "r");
|
|
30227
|
+
try {
|
|
30228
|
+
const info = await handle.stat();
|
|
30229
|
+
if (!info.isFile() || info.size > this.maxBytes) throw Error("FABRIC_STATE_LIMIT");
|
|
30230
|
+
const bytes3 = Buffer.alloc(this.maxBytes + 1);
|
|
30231
|
+
let length = 0;
|
|
30232
|
+
while (length < bytes3.length) {
|
|
30233
|
+
const read = await handle.read(bytes3, length, bytes3.length - length, null);
|
|
30234
|
+
if (!read.bytesRead) break;
|
|
30235
|
+
length += read.bytesRead;
|
|
30236
|
+
}
|
|
30237
|
+
if (length > this.maxBytes) throw Error("FABRIC_STATE_LIMIT");
|
|
30238
|
+
try {
|
|
30239
|
+
return this.parse(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes3.subarray(0, length))));
|
|
30240
|
+
} catch {
|
|
30241
|
+
throw Error("FABRIC_STATE_CORRUPT");
|
|
30242
|
+
}
|
|
30243
|
+
} finally {
|
|
30244
|
+
await handle.close();
|
|
30245
|
+
}
|
|
30246
|
+
}
|
|
30247
|
+
read() {
|
|
30248
|
+
return this.serial(() => this.load());
|
|
30249
|
+
}
|
|
30250
|
+
update(fn, create) {
|
|
30251
|
+
return this.serial(async () => {
|
|
30252
|
+
if (create) await mkdir6(path14.dirname(this.file), { recursive: true });
|
|
30253
|
+
const lockPath = this.file + ".lock";
|
|
30254
|
+
const token = randomUUID9();
|
|
30255
|
+
const lock = await open7(lockPath, "wx", 384).catch((error62) => {
|
|
30256
|
+
if (error62.code === "EEXIST") throw Error("FABRIC_STATE_BUSY");
|
|
30257
|
+
throw error62;
|
|
30258
|
+
});
|
|
30259
|
+
try {
|
|
30260
|
+
await lock.writeFile(JSON.stringify({ token, pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString() }));
|
|
30261
|
+
await lock.datasync();
|
|
30262
|
+
let state;
|
|
30263
|
+
try {
|
|
30264
|
+
state = await this.load();
|
|
30265
|
+
} catch (error62) {
|
|
30266
|
+
if (error62.code !== "ENOENT" || !create) throw error62;
|
|
30267
|
+
state = create();
|
|
30268
|
+
}
|
|
30269
|
+
const result2 = await fn(state);
|
|
30270
|
+
const encoded = JSON.stringify(this.parse(state));
|
|
30271
|
+
if (Buffer.byteLength(encoded) > this.maxBytes) throw Error("FABRIC_STATE_LIMIT");
|
|
30272
|
+
const temporary = this.file + "." + token + ".tmp";
|
|
30273
|
+
const handle = await open7(temporary, "wx", 384);
|
|
30274
|
+
try {
|
|
30275
|
+
try {
|
|
30276
|
+
await handle.writeFile(encoded, "utf8");
|
|
30277
|
+
await handle.datasync();
|
|
30278
|
+
} finally {
|
|
30279
|
+
await handle.close();
|
|
30280
|
+
}
|
|
30281
|
+
await rename5(temporary, this.file);
|
|
30282
|
+
} finally {
|
|
30283
|
+
await unlink(temporary).catch((error62) => {
|
|
30284
|
+
if (error62.code !== "ENOENT") throw error62;
|
|
30285
|
+
});
|
|
30286
|
+
}
|
|
30287
|
+
return result2;
|
|
30288
|
+
} finally {
|
|
30289
|
+
await lock.close();
|
|
30290
|
+
const current2 = await open7(lockPath, "r");
|
|
30291
|
+
try {
|
|
30292
|
+
if ((await current2.stat()).size > 1024 || JSON.parse(await current2.readFile("utf8")).token !== token)
|
|
30293
|
+
throw Error("FABRIC_STATE_LOCK_CHANGED");
|
|
30294
|
+
} finally {
|
|
30295
|
+
await current2.close();
|
|
30296
|
+
}
|
|
30297
|
+
await unlink(lockPath);
|
|
30298
|
+
}
|
|
30299
|
+
});
|
|
30300
|
+
}
|
|
30301
|
+
};
|
|
30302
|
+
|
|
30303
|
+
// src/agent-runtime-identity.ts
|
|
30304
|
+
var id = external_exports.string().regex(/^rt-[0-9a-f-]{36}$/);
|
|
30305
|
+
var hash6 = external_exports.string().regex(/^[a-f0-9]{64}$/);
|
|
30306
|
+
var MAX_BINDINGS = 128;
|
|
30307
|
+
var MAX_BYTES = 128 * 1024;
|
|
30308
|
+
var BindingSchema = external_exports.strictObject({
|
|
30309
|
+
runtimeId: id,
|
|
30310
|
+
keyHash: hash6,
|
|
30311
|
+
createdAt: external_exports.number().int().positive(),
|
|
30312
|
+
lastUsedAt: external_exports.number().int().positive(),
|
|
30313
|
+
revoked: external_exports.boolean()
|
|
30314
|
+
});
|
|
30315
|
+
var StateSchema = external_exports.strictObject({
|
|
30316
|
+
version: external_exports.literal(1),
|
|
30317
|
+
bindings: external_exports.array(BindingSchema).max(MAX_BINDINGS)
|
|
30318
|
+
});
|
|
30319
|
+
function digest4(value) {
|
|
30320
|
+
return createHash12("sha256").update(value, "utf8").digest();
|
|
30321
|
+
}
|
|
30322
|
+
function encodedDigest(value) {
|
|
30323
|
+
return digest4(value).toString("hex");
|
|
30324
|
+
}
|
|
30325
|
+
function validKey(value) {
|
|
30326
|
+
return typeof value === "string" && /^[A-Za-z0-9_-]{43}$/.test(value);
|
|
30327
|
+
}
|
|
30328
|
+
var AgentRuntimeIdentityStore = class {
|
|
30329
|
+
constructor(file2, now = Date.now) {
|
|
30330
|
+
this.now = now;
|
|
30331
|
+
this.state = new FabricStateFile(file2, MAX_BYTES, (value) => {
|
|
30332
|
+
const state = StateSchema.parse(value);
|
|
30333
|
+
if (new Set(state.bindings.map((item) => item.runtimeId)).size !== state.bindings.length)
|
|
30334
|
+
throw Error("RUNTIME_IDENTITY_STATE_CORRUPT");
|
|
30335
|
+
return state;
|
|
30336
|
+
});
|
|
30337
|
+
}
|
|
30338
|
+
now;
|
|
30339
|
+
state;
|
|
30340
|
+
serial(fn) {
|
|
30341
|
+
return this.state.update(fn, () => ({ version: 1, bindings: [] })).catch((error62) => {
|
|
30342
|
+
if (error62 instanceof Error && error62.message.startsWith("FABRIC_STATE_"))
|
|
30343
|
+
throw Error(error62.message.replace("FABRIC_STATE_", "RUNTIME_IDENTITY_STATE_"));
|
|
30344
|
+
throw error62;
|
|
30345
|
+
});
|
|
30346
|
+
}
|
|
30347
|
+
issue() {
|
|
30348
|
+
return this.serial((state) => {
|
|
30349
|
+
if (state.bindings.length >= MAX_BINDINGS) throw Error("RUNTIME_IDENTITY_LIMIT");
|
|
30350
|
+
const runtimeId = "rt-" + randomUUID10();
|
|
30351
|
+
const runtimeKey = randomBytes4(32).toString("base64url");
|
|
30352
|
+
const now = this.now();
|
|
30353
|
+
state.bindings.push({ runtimeId, keyHash: encodedDigest(runtimeKey), createdAt: now, lastUsedAt: now, revoked: false });
|
|
30354
|
+
return { runtimeId, runtimeKey };
|
|
30355
|
+
});
|
|
30356
|
+
}
|
|
30357
|
+
authenticate(runtimeId, runtimeKey) {
|
|
30358
|
+
return this.serial((state) => {
|
|
30359
|
+
if (!id.safeParse(runtimeId).success || !validKey(runtimeKey)) throw Error("RUNTIME_IDENTITY_INVALID");
|
|
30360
|
+
const binding2 = state.bindings.find((item) => item.runtimeId === runtimeId);
|
|
30361
|
+
if (!binding2 || binding2.revoked) throw Error("RUNTIME_IDENTITY_DENIED");
|
|
30362
|
+
const expected = Buffer.from(binding2.keyHash, "hex");
|
|
30363
|
+
const actual = digest4(runtimeKey);
|
|
30364
|
+
if (expected.length !== actual.length || !timingSafeEqual2(expected, actual)) throw Error("RUNTIME_IDENTITY_DENIED");
|
|
30365
|
+
binding2.lastUsedAt = this.now();
|
|
30366
|
+
});
|
|
30367
|
+
}
|
|
30368
|
+
revoke(runtimeId, runtimeKey) {
|
|
30369
|
+
return this.serial((state) => {
|
|
30370
|
+
if (!id.safeParse(runtimeId).success || !validKey(runtimeKey)) throw Error("RUNTIME_IDENTITY_INVALID");
|
|
30371
|
+
const binding2 = state.bindings.find((item) => item.runtimeId === runtimeId);
|
|
30372
|
+
if (!binding2 || binding2.revoked) throw Error("RUNTIME_IDENTITY_DENIED");
|
|
30373
|
+
const expected = Buffer.from(binding2.keyHash, "hex");
|
|
30374
|
+
const actual = digest4(runtimeKey);
|
|
30375
|
+
if (expected.length !== actual.length || !timingSafeEqual2(expected, actual)) throw Error("RUNTIME_IDENTITY_DENIED");
|
|
30376
|
+
binding2.revoked = true;
|
|
30377
|
+
binding2.lastUsedAt = this.now();
|
|
30378
|
+
});
|
|
30379
|
+
}
|
|
30380
|
+
};
|
|
30381
|
+
|
|
30382
|
+
// src/agent-fabric-mailbox.ts
|
|
30383
|
+
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
30384
|
+
|
|
30385
|
+
// src/agent-fabric-timeline.ts
|
|
30386
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
30387
|
+
import { performance } from "node:perf_hooks";
|
|
30388
|
+
var FabricId = external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9_.:-]{0,95}$/);
|
|
30389
|
+
var FabricUtc = external_exports.string().datetime({ precision: 3 }).refine((value) => new Date(value).toISOString() === value);
|
|
30390
|
+
var FabricStampSchema = external_exports.strictObject({
|
|
30391
|
+
atUtc: FabricUtc,
|
|
30392
|
+
clockId: FabricId,
|
|
30393
|
+
monotonicMs: external_exports.number().finite().nonnegative().max(Number.MAX_SAFE_INTEGER)
|
|
30394
|
+
});
|
|
30395
|
+
var processClockId = "clock-" + randomUUID11();
|
|
30396
|
+
function createFabricClock() {
|
|
30397
|
+
return () => ({ atUtc: (/* @__PURE__ */ new Date()).toISOString(), clockId: processClockId, monotonicMs: performance.now() });
|
|
30398
|
+
}
|
|
30399
|
+
var FABRIC_STAGES = ["admitted", "queued", "worker_started", "execution_started", "execution_finished", "result_received", "result_delivered"];
|
|
30400
|
+
var MarkSchema = external_exports.strictObject({
|
|
30401
|
+
stamp: FabricStampSchema,
|
|
30402
|
+
source: external_exports.enum(["cloud", "controller", "native", "adapter"]),
|
|
30403
|
+
evidenceRef: FabricId
|
|
30404
|
+
});
|
|
30405
|
+
var FabricTimelineSchema = external_exports.strictObject({
|
|
30406
|
+
admitted: MarkSchema.nullable().default(null),
|
|
30407
|
+
queued: MarkSchema.nullable().default(null),
|
|
30408
|
+
worker_started: MarkSchema.nullable().default(null),
|
|
30409
|
+
execution_started: MarkSchema.nullable().default(null),
|
|
30410
|
+
execution_finished: MarkSchema.nullable().default(null),
|
|
30411
|
+
result_received: MarkSchema.nullable().default(null),
|
|
30412
|
+
result_delivered: MarkSchema.nullable().default(null)
|
|
30413
|
+
});
|
|
30414
|
+
function markFabricTimeline(timeline, stage, input2) {
|
|
30415
|
+
if (!FABRIC_STAGES.includes(stage)) throw Error("FABRIC_TIMING_STAGE_INVALID");
|
|
30416
|
+
const mark = MarkSchema.parse(input2), previous = timeline[stage];
|
|
30417
|
+
if (previous) {
|
|
30418
|
+
if (JSON.stringify(previous) !== JSON.stringify(mark)) throw Error("FABRIC_TIMING_CONFLICT");
|
|
30419
|
+
return;
|
|
30420
|
+
}
|
|
30421
|
+
const next = { ...timeline, [stage]: mark };
|
|
30422
|
+
const clocks = /* @__PURE__ */ new Map();
|
|
30423
|
+
for (const name2 of FABRIC_STAGES) {
|
|
30424
|
+
const stamp = next[name2]?.stamp;
|
|
30425
|
+
if (!stamp) continue;
|
|
30426
|
+
const before = clocks.get(stamp.clockId);
|
|
30427
|
+
if (before !== void 0 && stamp.monotonicMs < before) throw Error("FABRIC_TIMING_ORDER_INVALID");
|
|
30428
|
+
clocks.set(stamp.clockId, stamp.monotonicMs);
|
|
30429
|
+
}
|
|
30430
|
+
timeline[stage] = mark;
|
|
30431
|
+
}
|
|
30432
|
+
|
|
30433
|
+
// src/controller-runtime-router.ts
|
|
30434
|
+
var LOCAL_RUNTIME_PROVIDERS = ["chatgpt", "claude", "cursor"];
|
|
30435
|
+
|
|
30436
|
+
// src/agent-fabric-worker.ts
|
|
30437
|
+
var fact = (value) => external_exports.strictObject({
|
|
30438
|
+
value,
|
|
30439
|
+
confirmedAt: FabricUtc,
|
|
30440
|
+
evidenceRef: FabricId,
|
|
30441
|
+
source: external_exports.enum(["registered_integration", "adapter_receipt"])
|
|
30442
|
+
});
|
|
30443
|
+
var WorkerAttributionSchema = external_exports.strictObject({
|
|
30444
|
+
provider: fact(external_exports.enum(["openai", "anthropic", "cursor"])).nullable().default(null),
|
|
30445
|
+
runtime: fact(external_exports.enum(["codex", "claude-code", "cursor-agent"])).nullable().default(null),
|
|
30446
|
+
model: fact(external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,127}$/)).nullable().default(null)
|
|
30447
|
+
});
|
|
30448
|
+
var FabricWorkerSchema = external_exports.strictObject({
|
|
30449
|
+
workerId: external_exports.string().uuid(),
|
|
30450
|
+
key: FabricId,
|
|
30451
|
+
controllerId: FabricId,
|
|
30452
|
+
parentWorkerId: external_exports.string().uuid().nullable(),
|
|
30453
|
+
device: external_exports.strictObject({ deviceId: FabricId, enrollmentEvidenceRef: FabricId }).nullable(),
|
|
30454
|
+
runtimeId: external_exports.string().regex(/^rt-[0-9a-f-]{36}$/).nullable(),
|
|
30455
|
+
attribution: WorkerAttributionSchema,
|
|
30456
|
+
createdAt: FabricUtc,
|
|
30457
|
+
updatedAt: FabricUtc
|
|
30458
|
+
});
|
|
30459
|
+
var FabricPayloadRefSchema = external_exports.strictObject({
|
|
30460
|
+
id: FabricId,
|
|
30461
|
+
sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
|
|
30462
|
+
bytes: external_exports.number().int().min(0).max(4 * 1024 * 1024)
|
|
30463
|
+
});
|
|
30464
|
+
var FabricExecutionLinkSchema = external_exports.strictObject({
|
|
30465
|
+
sessionId: FabricId.nullable(),
|
|
30466
|
+
pid: external_exports.number().int().positive().max(4294967295).nullable(),
|
|
30467
|
+
executionId: external_exports.string().uuid().toLowerCase().nullable().default(null),
|
|
30468
|
+
confirmedAt: FabricUtc,
|
|
30469
|
+
evidenceRef: FabricId
|
|
30470
|
+
}).refine((link) => link.sessionId !== null || link.pid !== null || link.executionId !== null);
|
|
30471
|
+
var FabricAssignmentSchema = external_exports.strictObject({
|
|
30472
|
+
assignmentId: external_exports.string().uuid(),
|
|
30473
|
+
workerId: external_exports.string().uuid(),
|
|
30474
|
+
taskId: FabricId,
|
|
30475
|
+
runId: external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/),
|
|
30476
|
+
role: external_exports.enum(["implementer", "verifier"]),
|
|
30477
|
+
selectedRuntime: external_exports.enum(LOCAL_RUNTIME_PROVIDERS),
|
|
30478
|
+
payloadRef: FabricPayloadRefSchema,
|
|
30479
|
+
phase: external_exports.enum(["assigned", "launching", "running", "unknown", "exited", "not_started"]),
|
|
30480
|
+
createdAt: FabricUtc,
|
|
30481
|
+
updatedAt: FabricUtc,
|
|
30482
|
+
timeline: FabricTimelineSchema,
|
|
30483
|
+
attribution: WorkerAttributionSchema,
|
|
30484
|
+
execution: FabricExecutionLinkSchema.nullable()
|
|
30485
|
+
});
|
|
30486
|
+
function assignmentActive(assignment) {
|
|
30487
|
+
return assignment.phase !== "exited" && assignment.phase !== "not_started";
|
|
30488
|
+
}
|
|
30489
|
+
|
|
30490
|
+
// src/agent-fabric-mailbox.ts
|
|
30491
|
+
var MAX_WORKERS = 64;
|
|
30492
|
+
var MAX_ASSIGNMENTS = 256;
|
|
30493
|
+
var MAX_MESSAGES = 1024;
|
|
30494
|
+
var MAX_TTL_MS = 864e5;
|
|
30495
|
+
var Control = external_exports.enum(["CANCEL", "WAKE"]);
|
|
30496
|
+
var Report = external_exports.enum(["PROGRESS", "BLOCKED", "RESULT"]);
|
|
30497
|
+
var MessageSchema = external_exports.strictObject({
|
|
30498
|
+
messageId: external_exports.string().uuid(),
|
|
30499
|
+
key: FabricId,
|
|
30500
|
+
assignmentId: external_exports.string().uuid(),
|
|
30501
|
+
origin: external_exports.enum(["controller", "worker", "adapter"]),
|
|
30502
|
+
direction: external_exports.enum(["to_worker", "to_controller"]),
|
|
30503
|
+
kind: external_exports.enum(["ASSIGN", ...Control.options, ...Report.options]),
|
|
30504
|
+
payloadRef: FabricPayloadRefSchema,
|
|
30505
|
+
createdAt: FabricUtc,
|
|
30506
|
+
expiresAt: FabricUtc,
|
|
30507
|
+
acknowledgedAt: FabricUtc.nullable()
|
|
30508
|
+
});
|
|
30509
|
+
var StateSchema2 = external_exports.strictObject({
|
|
30510
|
+
version: external_exports.literal(2),
|
|
30511
|
+
controllerId: FabricId,
|
|
30512
|
+
workers: external_exports.array(FabricWorkerSchema).max(MAX_WORKERS),
|
|
30513
|
+
assignments: external_exports.array(FabricAssignmentSchema).max(MAX_ASSIGNMENTS),
|
|
30514
|
+
messages: external_exports.array(MessageSchema).max(MAX_MESSAGES)
|
|
30515
|
+
});
|
|
30516
|
+
var Registration = external_exports.strictObject({
|
|
30517
|
+
key: FabricId,
|
|
30518
|
+
parentWorkerId: external_exports.string().uuid().nullable().default(null),
|
|
30519
|
+
device: FabricWorkerSchema.shape.device.default(null)
|
|
30520
|
+
});
|
|
30521
|
+
var AssignmentInput = FabricAssignmentSchema.pick({
|
|
30522
|
+
workerId: true,
|
|
30523
|
+
taskId: true,
|
|
30524
|
+
runId: true,
|
|
30525
|
+
role: true,
|
|
30526
|
+
selectedRuntime: true,
|
|
30527
|
+
payloadRef: true
|
|
30528
|
+
});
|
|
30529
|
+
var MessageInput = external_exports.strictObject({
|
|
30530
|
+
key: FabricId,
|
|
30531
|
+
payloadRef: FabricPayloadRefSchema,
|
|
30532
|
+
ttlMs: external_exports.number().int().min(1e3).max(MAX_TTL_MS).default(6e4)
|
|
30533
|
+
});
|
|
30534
|
+
var ConfirmInput = external_exports.strictObject({
|
|
30535
|
+
provider: WorkerAttributionSchema.shape.provider.removeDefault().optional(),
|
|
30536
|
+
runtime: WorkerAttributionSchema.shape.runtime.removeDefault().optional(),
|
|
30537
|
+
model: WorkerAttributionSchema.shape.model.removeDefault().optional()
|
|
30538
|
+
});
|
|
30539
|
+
function parseState(value) {
|
|
30540
|
+
const state = StateSchema2.parse(value);
|
|
30541
|
+
for (const values of [
|
|
30542
|
+
state.workers.map((w) => w.workerId),
|
|
30543
|
+
state.workers.map((w) => w.key),
|
|
30544
|
+
state.assignments.map((a) => a.assignmentId),
|
|
30545
|
+
state.assignments.map((a) => JSON.stringify([a.runId, a.selectedRuntime])),
|
|
30546
|
+
state.assignments.flatMap((a) => a.execution?.executionId ? [a.execution.executionId] : []),
|
|
30547
|
+
state.messages.map((m) => m.messageId),
|
|
30548
|
+
state.messages.map((m) => JSON.stringify([m.assignmentId, m.origin, m.key]))
|
|
30549
|
+
])
|
|
30550
|
+
if (new Set(values).size !== values.length) throw Error("FABRIC_STATE_CORRUPT");
|
|
30551
|
+
for (const worker of state.workers) {
|
|
30552
|
+
if (worker.controllerId !== state.controllerId) throw Error("FABRIC_STATE_CORRUPT");
|
|
30553
|
+
const seen = /* @__PURE__ */ new Set([worker.workerId]);
|
|
30554
|
+
let parent = worker.parentWorkerId;
|
|
30555
|
+
while (parent) {
|
|
30556
|
+
if (seen.has(parent)) throw Error("FABRIC_STATE_CORRUPT");
|
|
30557
|
+
seen.add(parent);
|
|
30558
|
+
const ancestor2 = state.workers.find((w) => w.workerId === parent);
|
|
30559
|
+
if (!ancestor2) throw Error("FABRIC_STATE_CORRUPT");
|
|
30560
|
+
parent = ancestor2.parentWorkerId;
|
|
30561
|
+
}
|
|
30562
|
+
}
|
|
30563
|
+
const activeWorkers = /* @__PURE__ */ new Set(), activeRuns = /* @__PURE__ */ new Set();
|
|
30564
|
+
for (const assignment of state.assignments) {
|
|
30565
|
+
if (!state.workers.some((w) => w.workerId === assignment.workerId)) throw Error("FABRIC_STATE_CORRUPT");
|
|
30566
|
+
if (assignmentActive(assignment)) {
|
|
30567
|
+
if (activeWorkers.has(assignment.workerId) || activeRuns.has(assignment.runId)) throw Error("FABRIC_STATE_CORRUPT");
|
|
30568
|
+
activeWorkers.add(assignment.workerId);
|
|
30569
|
+
activeRuns.add(assignment.runId);
|
|
30570
|
+
}
|
|
30571
|
+
const validated = FabricTimelineSchema.parse({});
|
|
30572
|
+
for (const [stage, mark] of Object.entries(assignment.timeline))
|
|
30573
|
+
if (mark) markFabricTimeline(validated, stage, mark);
|
|
30574
|
+
}
|
|
30575
|
+
for (const message2 of state.messages) {
|
|
30576
|
+
if (!state.assignments.some((a) => a.assignmentId === message2.assignmentId) || message2.expiresAt <= message2.createdAt || Date.parse(message2.expiresAt) - Date.parse(message2.createdAt) > MAX_TTL_MS || message2.direction === "to_worker" !== ["ASSIGN", "CANCEL", "WAKE"].includes(message2.kind) || message2.direction === "to_worker" !== (message2.origin === "controller") || message2.origin === "adapter" && message2.kind !== "RESULT") throw Error("FABRIC_STATE_CORRUPT");
|
|
30577
|
+
}
|
|
30578
|
+
return state;
|
|
30579
|
+
}
|
|
30580
|
+
var AgentWorkerMailbox = class {
|
|
30581
|
+
constructor(file2, controllerId, identities, clock = createFabricClock(), notify) {
|
|
30582
|
+
this.identities = identities;
|
|
30583
|
+
this.clock = clock;
|
|
30584
|
+
this.notify = notify;
|
|
30585
|
+
this.controllerId = FabricId.parse(controllerId);
|
|
30586
|
+
this.state = new FabricStateFile(file2, 2 * 1024 * 1024, (value) => {
|
|
30587
|
+
const state = parseState(value);
|
|
30588
|
+
if (state.controllerId !== this.controllerId) throw Error("FABRIC_CONTROLLER_MISMATCH");
|
|
30589
|
+
return state;
|
|
30590
|
+
});
|
|
30591
|
+
}
|
|
30592
|
+
identities;
|
|
30593
|
+
clock;
|
|
30594
|
+
notify;
|
|
30595
|
+
state;
|
|
30596
|
+
controllerId;
|
|
30597
|
+
initialize() {
|
|
30598
|
+
let created = false;
|
|
30599
|
+
return this.state.update(() => {
|
|
30600
|
+
if (!created) throw Error("FABRIC_STATE_EXISTS");
|
|
30601
|
+
}, () => {
|
|
30602
|
+
created = true;
|
|
30603
|
+
return { version: 2, controllerId: this.controllerId, workers: [], assignments: [], messages: [] };
|
|
30604
|
+
});
|
|
30605
|
+
}
|
|
30606
|
+
worker(state, id2) {
|
|
30607
|
+
const worker = state.workers.find((w) => w.workerId === id2);
|
|
30608
|
+
if (!worker) throw Error("FABRIC_WORKER_UNKNOWN");
|
|
30609
|
+
return worker;
|
|
30610
|
+
}
|
|
30611
|
+
assignment(state, id2) {
|
|
30612
|
+
const assignment = state.assignments.find((a) => a.assignmentId === id2);
|
|
30613
|
+
if (!assignment) throw Error("FABRIC_ASSIGNMENT_UNKNOWN");
|
|
30614
|
+
return assignment;
|
|
30615
|
+
}
|
|
30616
|
+
bound(state, workerId, credential) {
|
|
30617
|
+
const worker = this.worker(state, workerId);
|
|
30618
|
+
if (worker.runtimeId !== credential.runtimeId) throw Error("FABRIC_WORKER_DENIED");
|
|
30619
|
+
return worker;
|
|
30620
|
+
}
|
|
30621
|
+
emit(state, message2) {
|
|
30622
|
+
const assignment = this.assignment(state, message2.assignmentId);
|
|
30623
|
+
try {
|
|
30624
|
+
void Promise.resolve(this.notify?.({
|
|
30625
|
+
controllerId: this.controllerId,
|
|
30626
|
+
workerId: assignment.workerId,
|
|
30627
|
+
assignmentId: assignment.assignmentId,
|
|
30628
|
+
messageId: message2.messageId,
|
|
30629
|
+
direction: message2.direction,
|
|
30630
|
+
kind: message2.kind,
|
|
30631
|
+
origin: message2.origin,
|
|
30632
|
+
expiresAt: message2.expiresAt
|
|
30633
|
+
})).catch(() => {
|
|
30634
|
+
});
|
|
30635
|
+
} catch {
|
|
30636
|
+
}
|
|
30637
|
+
}
|
|
30638
|
+
register(input2) {
|
|
30639
|
+
const registration = Registration.parse(input2);
|
|
30640
|
+
return this.state.update((state) => {
|
|
30641
|
+
const existing = state.workers.find((w) => w.key === registration.key);
|
|
30642
|
+
if (existing) {
|
|
30643
|
+
if (existing.parentWorkerId !== registration.parentWorkerId || JSON.stringify(existing.device) !== JSON.stringify(registration.device))
|
|
30644
|
+
throw Error("FABRIC_WORKER_ID_CONFLICT");
|
|
30645
|
+
return existing;
|
|
30646
|
+
}
|
|
30647
|
+
if (state.workers.length >= MAX_WORKERS) throw Error("FABRIC_WORKER_LIMIT");
|
|
30648
|
+
if (registration.parentWorkerId) this.worker(state, registration.parentWorkerId);
|
|
30649
|
+
const now = this.clock().atUtc;
|
|
30650
|
+
const worker = {
|
|
30651
|
+
...registration,
|
|
30652
|
+
workerId: randomUUID12(),
|
|
30653
|
+
controllerId: this.controllerId,
|
|
30654
|
+
runtimeId: null,
|
|
30655
|
+
attribution: WorkerAttributionSchema.parse({}),
|
|
30656
|
+
createdAt: now,
|
|
30657
|
+
updatedAt: now
|
|
30658
|
+
};
|
|
30659
|
+
state.workers.push(worker);
|
|
30660
|
+
return worker;
|
|
30661
|
+
});
|
|
30662
|
+
}
|
|
30663
|
+
async bindRuntime(workerId, credential) {
|
|
30664
|
+
await this.identities.authenticate(credential.runtimeId, credential.runtimeKey);
|
|
30665
|
+
await this.state.update((state) => {
|
|
30666
|
+
const worker = this.worker(state, workerId);
|
|
30667
|
+
if (worker.runtimeId !== credential.runtimeId) {
|
|
30668
|
+
worker.runtimeId = credential.runtimeId;
|
|
30669
|
+
worker.attribution = WorkerAttributionSchema.parse({});
|
|
30670
|
+
worker.updatedAt = this.clock().atUtc;
|
|
30671
|
+
}
|
|
30672
|
+
});
|
|
30673
|
+
}
|
|
30674
|
+
append(state, assignment, kind, origin, input2) {
|
|
30675
|
+
const request = MessageInput.parse(input2);
|
|
30676
|
+
const direction = origin === "controller" ? "to_worker" : "to_controller";
|
|
30677
|
+
if (kind === "RESULT" && request.key !== "result") throw Error("FABRIC_RESULT_KEY_INVALID");
|
|
30678
|
+
const existing = state.messages.find((m) => m.assignmentId === assignment.assignmentId && m.origin === origin && m.key === request.key);
|
|
30679
|
+
if (existing) {
|
|
30680
|
+
if (existing.kind !== kind || JSON.stringify(existing.payloadRef) !== JSON.stringify(request.payloadRef) || Date.parse(existing.expiresAt) - Date.parse(existing.createdAt) !== request.ttlMs) throw Error("FABRIC_MESSAGE_ID_CONFLICT");
|
|
30681
|
+
return { message: existing, added: false };
|
|
30682
|
+
}
|
|
30683
|
+
if (state.messages.length >= MAX_MESSAGES) throw Error("FABRIC_MESSAGE_LIMIT");
|
|
30684
|
+
const now = this.clock();
|
|
30685
|
+
const message2 = {
|
|
30686
|
+
messageId: randomUUID12(),
|
|
30687
|
+
key: request.key,
|
|
30688
|
+
assignmentId: assignment.assignmentId,
|
|
30689
|
+
direction,
|
|
30690
|
+
origin,
|
|
30691
|
+
kind,
|
|
30692
|
+
payloadRef: request.payloadRef,
|
|
30693
|
+
createdAt: now.atUtc,
|
|
30694
|
+
expiresAt: new Date(Date.parse(now.atUtc) + request.ttlMs).toISOString(),
|
|
30695
|
+
acknowledgedAt: null
|
|
30696
|
+
};
|
|
30697
|
+
state.messages.push(message2);
|
|
30698
|
+
if (origin === "adapter") markFabricTimeline(assignment.timeline, "result_received", { stamp: now, source: "controller", evidenceRef: message2.messageId });
|
|
30699
|
+
return { message: message2, added: true };
|
|
30700
|
+
}
|
|
30701
|
+
async assign(input2) {
|
|
30702
|
+
const request = AssignmentInput.parse(input2);
|
|
30703
|
+
const saved = await this.state.update((state) => {
|
|
30704
|
+
this.worker(state, request.workerId);
|
|
30705
|
+
const existing = state.assignments.find((a) => a.runId === request.runId && a.selectedRuntime === request.selectedRuntime);
|
|
30706
|
+
if (existing) {
|
|
30707
|
+
if (JSON.stringify(AssignmentInput.strip().parse(existing)) !== JSON.stringify(request)) throw Error("FABRIC_ASSIGNMENT_ID_CONFLICT");
|
|
30708
|
+
return { state, assignment: existing, notice: null };
|
|
30709
|
+
}
|
|
30710
|
+
if (state.assignments.length >= MAX_ASSIGNMENTS) throw Error("FABRIC_ASSIGNMENT_LIMIT");
|
|
30711
|
+
if (state.assignments.some((a) => assignmentActive(a) && (a.workerId === request.workerId || a.runId === request.runId)))
|
|
30712
|
+
throw Error("FABRIC_WORKER_BUSY");
|
|
30713
|
+
const now = this.clock().atUtc;
|
|
30714
|
+
const assignment = {
|
|
30715
|
+
...request,
|
|
30716
|
+
assignmentId: randomUUID12(),
|
|
30717
|
+
phase: "assigned",
|
|
30718
|
+
createdAt: now,
|
|
30719
|
+
updatedAt: now,
|
|
30720
|
+
timeline: FabricTimelineSchema.parse({}),
|
|
30721
|
+
attribution: WorkerAttributionSchema.parse({}),
|
|
30722
|
+
execution: null
|
|
30723
|
+
};
|
|
30724
|
+
const worker = this.worker(state, request.workerId);
|
|
30725
|
+
worker.attribution = WorkerAttributionSchema.parse({});
|
|
30726
|
+
worker.updatedAt = now;
|
|
30727
|
+
state.assignments.push(assignment);
|
|
30728
|
+
const { message: message2 } = this.append(state, assignment, "ASSIGN", "controller", { key: "assign", payloadRef: request.payloadRef });
|
|
30729
|
+
return { state, assignment, notice: message2 };
|
|
30730
|
+
});
|
|
30731
|
+
if (saved.notice) this.emit(saved.state, saved.notice);
|
|
30732
|
+
return saved.assignment;
|
|
30733
|
+
}
|
|
30734
|
+
async control(assignmentId, kind, input2) {
|
|
30735
|
+
Control.parse(kind);
|
|
30736
|
+
const saved = await this.state.update((state) => {
|
|
30737
|
+
const assignment = this.assignment(state, assignmentId);
|
|
30738
|
+
if (!assignmentActive(assignment)) throw Error("FABRIC_ASSIGNMENT_INACTIVE");
|
|
30739
|
+
return { state, ...this.append(state, assignment, kind, "controller", input2) };
|
|
30740
|
+
});
|
|
30741
|
+
if (saved.added) this.emit(saved.state, saved.message);
|
|
30742
|
+
return saved.message;
|
|
30743
|
+
}
|
|
30744
|
+
async report(workerId, credential, assignmentId, kind, input2) {
|
|
30745
|
+
Report.parse(kind);
|
|
30746
|
+
await this.identities.authenticate(credential.runtimeId, credential.runtimeKey);
|
|
30747
|
+
const saved = await this.state.update((state) => {
|
|
30748
|
+
this.bound(state, workerId, credential);
|
|
30749
|
+
const assignment = this.assignment(state, assignmentId);
|
|
30750
|
+
if (assignment.workerId !== workerId || assignment.phase === "not_started") throw Error("FABRIC_ASSIGNMENT_DENIED");
|
|
30751
|
+
return { state, ...this.append(state, assignment, kind, "worker", input2) };
|
|
30752
|
+
});
|
|
30753
|
+
if (saved.added) this.emit(saved.state, saved.message);
|
|
30754
|
+
return saved.message;
|
|
30755
|
+
}
|
|
30756
|
+
pending(state, direction, workerId) {
|
|
30757
|
+
const now = this.clock().atUtc;
|
|
30758
|
+
return state.messages.filter((m) => m.direction === direction && !m.acknowledgedAt && m.expiresAt > now && (direction !== "to_worker" || state.assignments.some((a) => a.assignmentId === m.assignmentId && a.workerId === workerId && assignmentActive(a))));
|
|
30759
|
+
}
|
|
30760
|
+
async inbox(workerId, credential, limit = 32) {
|
|
30761
|
+
external_exports.number().int().min(1).max(64).parse(limit);
|
|
30762
|
+
await this.identities.authenticate(credential.runtimeId, credential.runtimeKey);
|
|
30763
|
+
const state = await this.state.read();
|
|
30764
|
+
this.bound(state, workerId, credential);
|
|
30765
|
+
return this.pending(state, "to_worker", workerId).slice(0, limit);
|
|
30766
|
+
}
|
|
30767
|
+
async controllerInbox(limit = 32) {
|
|
30768
|
+
external_exports.number().int().min(1).max(64).parse(limit);
|
|
30769
|
+
return this.pending(await this.state.read(), "to_controller").slice(0, limit);
|
|
30770
|
+
}
|
|
30771
|
+
acknowledge(state, messageId, direction, workerId) {
|
|
30772
|
+
const message2 = state.messages.find((m) => m.messageId === messageId && m.direction === direction);
|
|
30773
|
+
if (!message2) return false;
|
|
30774
|
+
const assignment = this.assignment(state, message2.assignmentId);
|
|
30775
|
+
if (direction === "to_worker" && assignment.workerId !== workerId) return false;
|
|
30776
|
+
if (message2.acknowledgedAt) return true;
|
|
30777
|
+
const now = this.clock();
|
|
30778
|
+
if (message2.expiresAt <= now.atUtc) return false;
|
|
30779
|
+
message2.acknowledgedAt = now.atUtc;
|
|
30780
|
+
if (message2.origin === "adapter") markFabricTimeline(assignment.timeline, "result_delivered", { stamp: now, source: "controller", evidenceRef: message2.messageId });
|
|
30781
|
+
return true;
|
|
30782
|
+
}
|
|
30783
|
+
async ack(workerId, credential, messageId) {
|
|
30784
|
+
await this.identities.authenticate(credential.runtimeId, credential.runtimeKey);
|
|
30785
|
+
return this.state.update((state) => {
|
|
30786
|
+
this.bound(state, workerId, credential);
|
|
30787
|
+
return this.acknowledge(state, messageId, "to_worker", workerId);
|
|
30788
|
+
});
|
|
30789
|
+
}
|
|
30790
|
+
controllerAck(messageId) {
|
|
30791
|
+
return this.state.update((state) => this.acknowledge(state, messageId, "to_controller"));
|
|
30792
|
+
}
|
|
30793
|
+
async adapterResult(assignmentId, payloadRef) {
|
|
30794
|
+
const saved = await this.state.update((state) => {
|
|
30795
|
+
const assignment = this.assignment(state, assignmentId);
|
|
30796
|
+
if (assignment.phase !== "exited") throw Error("FABRIC_RESULT_UNCONFIRMED");
|
|
30797
|
+
return { state, ...this.append(state, assignment, "RESULT", "adapter", { key: "result", payloadRef }) };
|
|
30798
|
+
});
|
|
30799
|
+
if (saved.added) this.emit(saved.state, saved.message);
|
|
30800
|
+
}
|
|
30801
|
+
claimLaunch(assignmentId) {
|
|
30802
|
+
return this.state.update((state) => {
|
|
30803
|
+
const assignment = this.assignment(state, assignmentId);
|
|
30804
|
+
if (assignment.phase !== "assigned" && assignment.phase !== "not_started") return false;
|
|
30805
|
+
assignment.phase = "launching";
|
|
30806
|
+
assignment.updatedAt = this.clock().atUtc;
|
|
30807
|
+
return true;
|
|
30808
|
+
});
|
|
30809
|
+
}
|
|
30810
|
+
timing(assignmentId, stage, mark) {
|
|
30811
|
+
return this.state.update((state) => {
|
|
30812
|
+
markFabricTimeline(this.assignment(state, assignmentId).timeline, stage, mark);
|
|
30813
|
+
});
|
|
30814
|
+
}
|
|
30815
|
+
confirmExecution(assignmentId, input2) {
|
|
30816
|
+
const execution = FabricExecutionLinkSchema.parse(input2);
|
|
30817
|
+
return this.state.update((state) => {
|
|
30818
|
+
const assignment = this.assignment(state, assignmentId);
|
|
30819
|
+
if (assignment.execution && JSON.stringify(assignment.execution) !== JSON.stringify(execution)) throw Error("FABRIC_EXECUTION_CONFLICT");
|
|
30820
|
+
if (execution.executionId && state.assignments.some((a) => a.assignmentId !== assignmentId && a.execution?.executionId === execution.executionId))
|
|
30821
|
+
throw Error("FABRIC_EXECUTION_CONFLICT");
|
|
30822
|
+
assignment.execution = execution;
|
|
30823
|
+
});
|
|
30824
|
+
}
|
|
30825
|
+
/** Trusted transport adapter passes its authenticated device, never a worker-reported label.
|
|
30826
|
+
* References remain device-reported diagnostics in the cloud, not ownership/authentication. */
|
|
30827
|
+
async incidentReferences(deviceId, executionId) {
|
|
30828
|
+
FabricId.parse(deviceId);
|
|
30829
|
+
const execution = external_exports.string().uuid().toLowerCase().parse(executionId);
|
|
30830
|
+
const state = await this.state.read();
|
|
30831
|
+
const assignment = state.assignments.find((a) => a.execution?.executionId === execution);
|
|
30832
|
+
if (!assignment || this.worker(state, assignment.workerId).device?.deviceId !== deviceId) return null;
|
|
30833
|
+
const task = external_exports.string().uuid().toLowerCase().safeParse(assignment.taskId);
|
|
30834
|
+
return { executionId: execution, workerId: assignment.workerId, ...task.success ? { taskId: task.data } : {} };
|
|
30835
|
+
}
|
|
30836
|
+
confirmAttribution(assignmentId, input2) {
|
|
30837
|
+
const confirmed = ConfirmInput.parse(input2);
|
|
30838
|
+
for (const key of ["provider", "runtime", "model"])
|
|
30839
|
+
if (confirmed[key] === void 0) delete confirmed[key];
|
|
30840
|
+
return this.state.update((state) => {
|
|
30841
|
+
const assignment = this.assignment(state, assignmentId);
|
|
30842
|
+
for (const key of ["provider", "runtime", "model"])
|
|
30843
|
+
if (assignment.attribution[key] && confirmed[key] !== void 0 && JSON.stringify(assignment.attribution[key]) !== JSON.stringify(confirmed[key])) throw Error("FABRIC_ATTRIBUTION_CONFLICT");
|
|
30844
|
+
Object.assign(assignment.attribution, confirmed);
|
|
30845
|
+
const latest = state.assignments.filter((a) => a.workerId === assignment.workerId).at(-1);
|
|
30846
|
+
if (latest?.assignmentId === assignmentId) Object.assign(this.worker(state, assignment.workerId).attribution, confirmed);
|
|
30847
|
+
});
|
|
30848
|
+
}
|
|
30849
|
+
phase(assignmentId, next) {
|
|
30850
|
+
return this.state.update((state) => {
|
|
30851
|
+
const assignment = this.assignment(state, assignmentId);
|
|
30852
|
+
const allowed = {
|
|
30853
|
+
assigned: ["launching", "not_started", "unknown"],
|
|
30854
|
+
launching: ["running", "not_started", "unknown", "exited"],
|
|
30855
|
+
running: ["unknown", "exited"],
|
|
30856
|
+
unknown: ["exited"],
|
|
30857
|
+
exited: [],
|
|
30858
|
+
not_started: ["launching"]
|
|
30859
|
+
};
|
|
30860
|
+
if (assignment.phase === next) return;
|
|
30861
|
+
if (!allowed[assignment.phase].includes(next)) throw Error("FABRIC_ASSIGNMENT_PHASE_INVALID");
|
|
30862
|
+
assignment.phase = next;
|
|
30863
|
+
assignment.updatedAt = this.clock().atUtc;
|
|
30864
|
+
});
|
|
30865
|
+
}
|
|
30866
|
+
async snapshot() {
|
|
30867
|
+
const state = await this.state.read(), now = this.clock().atUtc;
|
|
30868
|
+
const nextExpiry = state.messages.filter((m) => !m.acknowledgedAt && m.expiresAt > now).reduce((next, m) => next === null || m.expiresAt < next ? m.expiresAt : next, null);
|
|
30869
|
+
return { ...state, nextExpiry };
|
|
30870
|
+
}
|
|
30871
|
+
};
|
|
30872
|
+
|
|
30873
|
+
// src/agent-fabric-service.ts
|
|
30874
|
+
var Binding = external_exports.strictObject({
|
|
30875
|
+
version: external_exports.literal(1),
|
|
30876
|
+
controllerId: FabricId,
|
|
30877
|
+
device: FabricWorkerSchema.shape.device,
|
|
30878
|
+
initialized: external_exports.boolean()
|
|
30879
|
+
});
|
|
30880
|
+
var WorkerRequest = external_exports.discriminatedUnion("operation", [
|
|
30881
|
+
external_exports.strictObject({ operation: external_exports.literal("inbox"), workerId: external_exports.string().uuid(), limit: external_exports.number().int().min(1).max(64).default(32) }),
|
|
30882
|
+
external_exports.strictObject({ operation: external_exports.literal("ack"), workerId: external_exports.string().uuid(), messageId: external_exports.string().uuid() }),
|
|
30883
|
+
external_exports.strictObject({
|
|
30884
|
+
operation: external_exports.literal("report"),
|
|
30885
|
+
workerId: external_exports.string().uuid(),
|
|
30886
|
+
assignmentId: external_exports.string().uuid(),
|
|
30887
|
+
kind: external_exports.enum(["PROGRESS", "BLOCKED", "RESULT"]),
|
|
30888
|
+
key: FabricId,
|
|
30889
|
+
payloadRef: FabricPayloadRefSchema,
|
|
30890
|
+
ttlMs: external_exports.number().int().min(1e3).max(864e5).default(6e4)
|
|
30891
|
+
})
|
|
30892
|
+
]);
|
|
30893
|
+
var AgentFabricService = class _AgentFabricService {
|
|
30894
|
+
constructor(directory, controllerId) {
|
|
30895
|
+
this.directory = directory;
|
|
30896
|
+
this.identities = new AgentRuntimeIdentityStore(path15.join(directory, "identities.json"));
|
|
30897
|
+
this.mailbox = new AgentWorkerMailbox(
|
|
30898
|
+
path15.join(directory, "mailbox.json"),
|
|
30899
|
+
controllerId,
|
|
30900
|
+
this.identities,
|
|
30901
|
+
void 0,
|
|
30902
|
+
() => this.changed()
|
|
30903
|
+
);
|
|
30904
|
+
}
|
|
30905
|
+
directory;
|
|
30906
|
+
identities;
|
|
30907
|
+
mailbox;
|
|
30908
|
+
listeners = /* @__PURE__ */ new Set();
|
|
30909
|
+
watcher;
|
|
30910
|
+
closed = false;
|
|
30911
|
+
static async open(directory, controllerId, device = null, initialize = true) {
|
|
30912
|
+
const expected = Binding.parse({ version: 1, controllerId, device, initialized: false });
|
|
30913
|
+
const absolute2 = path15.resolve(directory);
|
|
30914
|
+
for (let current2 = absolute2; ; current2 = path15.dirname(current2)) {
|
|
30915
|
+
try {
|
|
30916
|
+
if ((await lstat8(current2)).isSymbolicLink()) throw Error("FABRIC_DIRECTORY_INVALID");
|
|
30917
|
+
} catch (error62) {
|
|
30918
|
+
if (error62.code !== "ENOENT") throw error62;
|
|
30919
|
+
}
|
|
30920
|
+
if (path15.dirname(current2) === current2) break;
|
|
30921
|
+
}
|
|
30922
|
+
if (initialize) await mkdir7(absolute2, { recursive: true, mode: 448 });
|
|
30923
|
+
if (!(await lstat8(absolute2)).isDirectory() || (await realpath7(absolute2)).toLowerCase() !== absolute2.toLowerCase())
|
|
30924
|
+
throw Error("FABRIC_DIRECTORY_INVALID");
|
|
30925
|
+
const present = /* @__PURE__ */ new Set();
|
|
30926
|
+
for (const name2 of ["binding.json", "mailbox.json", "identities.json"]) {
|
|
30927
|
+
const file2 = await lstat8(path15.join(absolute2, name2)).catch((error62) => {
|
|
30928
|
+
if (error62.code === "ENOENT") return null;
|
|
30929
|
+
throw error62;
|
|
30930
|
+
});
|
|
30931
|
+
if (file2 && (!file2.isFile() || file2.isSymbolicLink())) throw Error("FABRIC_FILE_INVALID");
|
|
30932
|
+
if (file2) present.add(name2);
|
|
30933
|
+
}
|
|
30934
|
+
if (!present.has("binding.json") && present.size) throw Error("FABRIC_BINDING_MISSING");
|
|
30935
|
+
const binding2 = new FabricStateFile(path15.join(absolute2, "binding.json"), 2048, (value) => Binding.parse(value));
|
|
30936
|
+
const service = new _AgentFabricService(absolute2, controllerId);
|
|
30937
|
+
await binding2.update(async (state) => {
|
|
30938
|
+
if (state.controllerId !== expected.controllerId || JSON.stringify(state.device) !== JSON.stringify(expected.device))
|
|
30939
|
+
throw Error("FABRIC_BINDING_CHANGED");
|
|
30940
|
+
if (!state.initialized) {
|
|
30941
|
+
if (!initialize) throw Error("FABRIC_INITIALIZATION_INCOMPLETE");
|
|
30942
|
+
try {
|
|
30943
|
+
await service.mailbox.initialize();
|
|
30944
|
+
} catch (error62) {
|
|
30945
|
+
if (!(error62 instanceof Error) || error62.message !== "FABRIC_STATE_EXISTS") throw error62;
|
|
30946
|
+
}
|
|
30947
|
+
state.initialized = true;
|
|
30948
|
+
}
|
|
30949
|
+
const snapshot2 = await service.mailbox.snapshot();
|
|
30950
|
+
if (snapshot2.workers.some((worker) => worker.runtimeId !== null)) await lstat8(path15.join(absolute2, "identities.json"));
|
|
30951
|
+
}, initialize ? () => expected : void 0);
|
|
30952
|
+
return service;
|
|
30953
|
+
}
|
|
30954
|
+
changed() {
|
|
30955
|
+
for (const callback of this.listeners) {
|
|
30956
|
+
try {
|
|
30957
|
+
callback();
|
|
30958
|
+
} catch {
|
|
30959
|
+
}
|
|
30960
|
+
}
|
|
30961
|
+
}
|
|
30962
|
+
subscribe = (callback) => {
|
|
30963
|
+
if (this.closed || this.listeners.size >= 32) throw Error("FABRIC_OBSERVER_LIMIT");
|
|
30964
|
+
this.listeners.add(callback);
|
|
30965
|
+
try {
|
|
30966
|
+
if (!this.watcher) {
|
|
30967
|
+
this.watcher = watch(this.directory, { persistent: false }, (_event, file2) => {
|
|
30968
|
+
if (file2?.toString().toLowerCase() === "mailbox.json") this.changed();
|
|
30969
|
+
});
|
|
30970
|
+
this.watcher.on("error", () => {
|
|
30971
|
+
this.watcher?.close();
|
|
30972
|
+
this.watcher = void 0;
|
|
30973
|
+
});
|
|
30974
|
+
}
|
|
30975
|
+
} catch {
|
|
30976
|
+
}
|
|
30977
|
+
return () => {
|
|
30978
|
+
this.listeners.delete(callback);
|
|
30979
|
+
if (!this.listeners.size) {
|
|
30980
|
+
this.watcher?.close();
|
|
30981
|
+
this.watcher = void 0;
|
|
30982
|
+
}
|
|
30983
|
+
};
|
|
30984
|
+
};
|
|
30985
|
+
async worker(input2, credential) {
|
|
30986
|
+
const request = WorkerRequest.parse(input2);
|
|
30987
|
+
if (request.operation === "inbox") return this.mailbox.inbox(request.workerId, credential, request.limit);
|
|
30988
|
+
if (request.operation === "ack") return this.mailbox.ack(request.workerId, credential, request.messageId);
|
|
30989
|
+
return this.mailbox.report(
|
|
30990
|
+
request.workerId,
|
|
30991
|
+
credential,
|
|
30992
|
+
request.assignmentId,
|
|
30993
|
+
request.kind,
|
|
30994
|
+
{ key: request.key, payloadRef: request.payloadRef, ttlMs: request.ttlMs }
|
|
30995
|
+
);
|
|
30996
|
+
}
|
|
30997
|
+
close() {
|
|
30998
|
+
this.closed = true;
|
|
30999
|
+
this.watcher?.close();
|
|
31000
|
+
this.watcher = void 0;
|
|
31001
|
+
this.listeners.clear();
|
|
31002
|
+
}
|
|
31003
|
+
};
|
|
31004
|
+
|
|
31005
|
+
// agent/src/native-fabric-startup.ts
|
|
31006
|
+
var Credential = external_exports.strictObject({
|
|
31007
|
+
workerId: external_exports.string().uuid(),
|
|
31008
|
+
controllerId: FabricId,
|
|
31009
|
+
runtimeId: external_exports.string().regex(/^rt-[0-9a-f-]{36}$/),
|
|
31010
|
+
runtimeKey: external_exports.string().regex(/^[A-Za-z0-9_-]{43}$/)
|
|
31011
|
+
});
|
|
31012
|
+
var OwnerRequest = external_exports.discriminatedUnion("operation", [
|
|
31013
|
+
external_exports.strictObject({ operation: external_exports.literal("status") }),
|
|
31014
|
+
external_exports.strictObject({ operation: external_exports.literal("register"), key: FabricId, parentWorkerId: external_exports.string().uuid().nullable().default(null) }),
|
|
31015
|
+
external_exports.strictObject({ operation: external_exports.literal("revoke"), workerId: external_exports.string().uuid() }),
|
|
31016
|
+
external_exports.strictObject({ operation: external_exports.literal("assign"), ...FabricAssignmentSchema.pick({
|
|
31017
|
+
workerId: true,
|
|
31018
|
+
taskId: true,
|
|
31019
|
+
runId: true,
|
|
31020
|
+
role: true,
|
|
31021
|
+
selectedRuntime: true,
|
|
31022
|
+
payloadRef: true
|
|
31023
|
+
}).shape }),
|
|
31024
|
+
external_exports.strictObject({
|
|
31025
|
+
operation: external_exports.literal("control"),
|
|
31026
|
+
assignmentId: external_exports.string().uuid(),
|
|
31027
|
+
kind: external_exports.enum(["WAKE", "CANCEL"]),
|
|
31028
|
+
key: FabricId,
|
|
31029
|
+
payloadRef: FabricPayloadRefSchema,
|
|
31030
|
+
ttlMs: external_exports.number().int().min(1e3).max(864e5).default(6e4)
|
|
31031
|
+
})
|
|
31032
|
+
]);
|
|
31033
|
+
var Delivery = external_exports.strictObject({ capability: external_exports.string().regex(/^[A-Za-z0-9+/]+={0,2}$/).max(4096), request: external_exports.unknown() });
|
|
31034
|
+
async function openNativeFabric(stateDirectory, enrollment, box, initialize = true) {
|
|
31035
|
+
const controllerId = "device-" + external_exports.string().uuid().parse(enrollment.deviceId).toLowerCase();
|
|
31036
|
+
const tenantId = external_exports.string().uuid().parse(enrollment.tenantId).toLowerCase();
|
|
31037
|
+
const parent = path16.join(stateDirectory, ".local-commander"), marker = path16.join(parent, "fabric-established.json");
|
|
31038
|
+
try {
|
|
31039
|
+
await mkdir8(parent, { mode: 448 });
|
|
31040
|
+
} catch (error62) {
|
|
31041
|
+
if (error62.code !== "EEXIST") throw error62;
|
|
31042
|
+
}
|
|
31043
|
+
const parentInfo = await lstat9(parent);
|
|
31044
|
+
if (!parentInfo.isDirectory() || parentInfo.isSymbolicLink()) throw Error("FABRIC_DIRECTORY_INVALID");
|
|
31045
|
+
const expected = JSON.stringify({ version: 1, controllerId, tenantId });
|
|
31046
|
+
let fresh = false;
|
|
31047
|
+
try {
|
|
31048
|
+
const info = await lstat9(marker);
|
|
31049
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > 2048 || await readFile5(marker, "utf8") !== expected)
|
|
31050
|
+
throw Error("FABRIC_BINDING_CHANGED");
|
|
31051
|
+
} catch (error62) {
|
|
31052
|
+
if (error62.code !== "ENOENT" || !initialize) throw error62;
|
|
31053
|
+
const file2 = await open8(marker, "wx", 384);
|
|
31054
|
+
try {
|
|
31055
|
+
await file2.writeFile(expected);
|
|
31056
|
+
await file2.datasync();
|
|
31057
|
+
} finally {
|
|
31058
|
+
await file2.close();
|
|
31059
|
+
}
|
|
31060
|
+
fresh = true;
|
|
31061
|
+
}
|
|
31062
|
+
const service = await AgentFabricService.open(
|
|
31063
|
+
path16.join(stateDirectory, ".local-commander", "fabric"),
|
|
31064
|
+
controllerId,
|
|
31065
|
+
{ deviceId: enrollment.deviceId.toLowerCase(), enrollmentEvidenceRef: "enrollment-" + tenantId },
|
|
31066
|
+
fresh
|
|
31067
|
+
);
|
|
31068
|
+
const purpose = "native-fabric:" + tenantId + ":" + controllerId;
|
|
31069
|
+
const credentialFile = (workerId) => path16.join(service.directory, external_exports.string().uuid().parse(workerId) + ".capability");
|
|
31070
|
+
const decode4 = (value) => {
|
|
31071
|
+
const credential = Credential.parse(JSON.parse(box.open(Buffer.from(value, "base64"), purpose).toString("utf8")));
|
|
31072
|
+
if (credential.controllerId !== controllerId) throw Error("FABRIC_WORKER_DENIED");
|
|
31073
|
+
return credential;
|
|
31074
|
+
};
|
|
31075
|
+
async function capability(workerId) {
|
|
31076
|
+
const file2 = credentialFile(workerId), info = await lstat9(file2);
|
|
31077
|
+
if (!info.isFile() || info.isSymbolicLink() || info.size > 4096) throw Error("FABRIC_CREDENTIAL_UNKNOWN");
|
|
31078
|
+
const encoded = await readFile5(file2, "utf8");
|
|
31079
|
+
if (decode4(encoded).workerId !== workerId) throw Error("FABRIC_WORKER_DENIED");
|
|
31080
|
+
return encoded;
|
|
31081
|
+
}
|
|
31082
|
+
return {
|
|
31083
|
+
service,
|
|
31084
|
+
source: { mailbox: service.mailbox, subscribe: service.subscribe },
|
|
31085
|
+
async owner(input2) {
|
|
31086
|
+
const request = OwnerRequest.parse(input2);
|
|
31087
|
+
if (request.operation === "status") return service.mailbox.snapshot();
|
|
31088
|
+
if (request.operation === "revoke") {
|
|
31089
|
+
const credential = decode4(await capability(request.workerId));
|
|
31090
|
+
await service.identities.revoke(credential.runtimeId, credential.runtimeKey);
|
|
31091
|
+
return { revoked: true };
|
|
31092
|
+
}
|
|
31093
|
+
if (request.operation === "register") {
|
|
31094
|
+
const worker = await service.mailbox.register({
|
|
31095
|
+
key: request.key,
|
|
31096
|
+
parentWorkerId: request.parentWorkerId,
|
|
31097
|
+
device: { deviceId: enrollment.deviceId.toLowerCase(), enrollmentEvidenceRef: "enrollment-" + tenantId }
|
|
31098
|
+
});
|
|
31099
|
+
const previous = await capability(worker.workerId).catch((error62) => {
|
|
31100
|
+
if (error62.code === "ENOENT" && !worker.runtimeId) return void 0;
|
|
31101
|
+
throw Error("FABRIC_CREDENTIAL_UNKNOWN");
|
|
31102
|
+
});
|
|
31103
|
+
if (previous) {
|
|
31104
|
+
const credential = decode4(previous);
|
|
31105
|
+
await service.identities.authenticate(credential.runtimeId, credential.runtimeKey);
|
|
31106
|
+
if (worker.runtimeId && worker.runtimeId !== credential.runtimeId) throw Error("FABRIC_CREDENTIAL_UNKNOWN");
|
|
31107
|
+
if (!worker.runtimeId) await service.mailbox.bindRuntime(worker.workerId, credential);
|
|
31108
|
+
} else {
|
|
31109
|
+
const credential = await service.identities.issue();
|
|
31110
|
+
const encoded = box.seal(Buffer.from(JSON.stringify({ ...credential, workerId: worker.workerId, controllerId })), purpose).toString("base64");
|
|
31111
|
+
const file2 = await open8(credentialFile(worker.workerId), "wx", 384);
|
|
31112
|
+
try {
|
|
31113
|
+
await file2.writeFile(encoded);
|
|
31114
|
+
await file2.datasync();
|
|
31115
|
+
} finally {
|
|
31116
|
+
await file2.close();
|
|
31117
|
+
}
|
|
31118
|
+
await service.mailbox.bindRuntime(worker.workerId, credential);
|
|
31119
|
+
}
|
|
31120
|
+
return { workerId: worker.workerId, credentialFile: credentialFile(worker.workerId) };
|
|
31121
|
+
}
|
|
31122
|
+
if (request.operation === "assign") {
|
|
31123
|
+
const { operation: _, ...assignment } = request;
|
|
31124
|
+
return service.mailbox.assign(assignment);
|
|
31125
|
+
}
|
|
31126
|
+
return service.mailbox.control(
|
|
31127
|
+
request.assignmentId,
|
|
31128
|
+
request.kind,
|
|
31129
|
+
{ key: request.key, payloadRef: request.payloadRef, ttlMs: request.ttlMs }
|
|
31130
|
+
);
|
|
31131
|
+
},
|
|
31132
|
+
async confirmExecution(assignmentId, executionId, journal) {
|
|
31133
|
+
const receipt = await journal.get(external_exports.string().uuid().parse(executionId));
|
|
31134
|
+
if (!receipt || receipt.tenantId !== tenantId || receipt.deviceId !== enrollment.deviceId.toLowerCase())
|
|
31135
|
+
throw Error("FABRIC_EXECUTION_UNCONFIRMED");
|
|
31136
|
+
await service.mailbox.confirmExecution(external_exports.string().uuid().parse(assignmentId), {
|
|
31137
|
+
executionId: receipt.executionId,
|
|
31138
|
+
sessionId: receipt.sessionId,
|
|
31139
|
+
pid: null,
|
|
31140
|
+
confirmedAt: receipt.createdAt,
|
|
31141
|
+
evidenceRef: receipt.operationId
|
|
31142
|
+
});
|
|
31143
|
+
},
|
|
31144
|
+
async worker(input2) {
|
|
31145
|
+
const delivery = Delivery.parse(input2), credential = decode4(delivery.capability);
|
|
31146
|
+
if (!delivery.request || typeof delivery.request !== "object" || Array.isArray(delivery.request) || delivery.request.workerId !== credential.workerId) throw Error("FABRIC_WORKER_DENIED");
|
|
31147
|
+
return service.worker(delivery.request, credential);
|
|
31148
|
+
},
|
|
31149
|
+
close: () => service.close()
|
|
31150
|
+
};
|
|
31151
|
+
}
|
|
31152
|
+
async function readFabricRequest(input2 = process.stdin) {
|
|
31153
|
+
const chunks = [];
|
|
31154
|
+
let bytes3 = 0;
|
|
31155
|
+
for await (const chunk of input2) {
|
|
31156
|
+
const value = Buffer.from(chunk);
|
|
31157
|
+
bytes3 += value.length;
|
|
31158
|
+
if (bytes3 > 16384) throw Error("FABRIC_REQUEST_LIMIT");
|
|
31159
|
+
chunks.push(value);
|
|
31160
|
+
}
|
|
31161
|
+
try {
|
|
31162
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(Buffer.concat(chunks)));
|
|
31163
|
+
} catch {
|
|
31164
|
+
throw Error("FABRIC_REQUEST_INVALID");
|
|
31165
|
+
}
|
|
31166
|
+
}
|
|
31167
|
+
|
|
29233
31168
|
// agent/src/main.ts
|
|
29234
|
-
var AGENT_VERSION2 = true ? "0.3.
|
|
31169
|
+
var AGENT_VERSION2 = true ? "0.3.9-issue11.1" : "0.3.2";
|
|
29235
31170
|
function processAlive(pid) {
|
|
29236
31171
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
29237
31172
|
try {
|
|
@@ -29242,11 +31177,11 @@ function processAlive(pid) {
|
|
|
29242
31177
|
}
|
|
29243
31178
|
}
|
|
29244
31179
|
async function claimAgentProcess(stateDir, runtimeDir, version2) {
|
|
29245
|
-
await
|
|
29246
|
-
const file2 =
|
|
31180
|
+
await mkdir9(stateDir, { recursive: true });
|
|
31181
|
+
const file2 = path17.join(stateDir, "agent-process.json");
|
|
29247
31182
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
29248
31183
|
try {
|
|
29249
|
-
const handle = await
|
|
31184
|
+
const handle = await open9(file2, "wx", 384);
|
|
29250
31185
|
try {
|
|
29251
31186
|
await handle.writeFile(JSON.stringify({ pid: process.pid, runtimeDir, version: version2, startedAt: (/* @__PURE__ */ new Date()).toISOString() }) + "\n", "utf8");
|
|
29252
31187
|
} finally {
|
|
@@ -29254,8 +31189,8 @@ async function claimAgentProcess(stateDir, runtimeDir, version2) {
|
|
|
29254
31189
|
}
|
|
29255
31190
|
return async () => {
|
|
29256
31191
|
try {
|
|
29257
|
-
const current2 = JSON.parse(await
|
|
29258
|
-
if (current2.pid === process.pid) await
|
|
31192
|
+
const current2 = JSON.parse(await readFile6(file2, "utf8"));
|
|
31193
|
+
if (current2.pid === process.pid) await rm5(file2, { force: true });
|
|
29259
31194
|
} catch {
|
|
29260
31195
|
}
|
|
29261
31196
|
};
|
|
@@ -29263,12 +31198,12 @@ async function claimAgentProcess(stateDir, runtimeDir, version2) {
|
|
|
29263
31198
|
if (!error62 || typeof error62 !== "object" || !("code" in error62) || error62.code !== "EEXIST") throw error62;
|
|
29264
31199
|
let stale = true;
|
|
29265
31200
|
try {
|
|
29266
|
-
const current2 = JSON.parse(await
|
|
31201
|
+
const current2 = JSON.parse(await readFile6(file2, "utf8"));
|
|
29267
31202
|
stale = typeof current2.pid !== "number" || !processAlive(current2.pid);
|
|
29268
31203
|
} catch {
|
|
29269
31204
|
}
|
|
29270
31205
|
if (!stale) throw Error("AGENT_ALREADY_RUNNING");
|
|
29271
|
-
await
|
|
31206
|
+
await rm5(file2, { force: true });
|
|
29272
31207
|
}
|
|
29273
31208
|
}
|
|
29274
31209
|
throw Error("AGENT_ALREADY_RUNNING");
|
|
@@ -29287,21 +31222,65 @@ function aborted2(signal, ms) {
|
|
|
29287
31222
|
}
|
|
29288
31223
|
async function runAgent(options) {
|
|
29289
31224
|
const delay = options.reconnectDelayMs ?? 2e3;
|
|
31225
|
+
const monitor = (update) => {
|
|
31226
|
+
try {
|
|
31227
|
+
update();
|
|
31228
|
+
void options.monitor?.flush().catch(() => {
|
|
31229
|
+
});
|
|
31230
|
+
} catch {
|
|
31231
|
+
}
|
|
31232
|
+
};
|
|
29290
31233
|
try {
|
|
29291
31234
|
if (!Number.isInteger(delay) || delay < 0 || delay > 3e4) throw Error("RECONNECT_DELAY_INVALID");
|
|
29292
31235
|
const identity = await options.store.load();
|
|
29293
31236
|
if (!identity?.enrollment) throw Error("ENROLLMENT_MISSING");
|
|
31237
|
+
const origin = identity.enrollment.serverOrigin;
|
|
31238
|
+
monitor(() => options.monitor?.configureOrigin(origin));
|
|
29294
31239
|
await options.journal.recoverAfterRestart();
|
|
29295
31240
|
await options.store.loadWorkspaces();
|
|
29296
31241
|
} catch (error62) {
|
|
29297
31242
|
await options.journal.close();
|
|
29298
31243
|
throw error62;
|
|
29299
31244
|
}
|
|
29300
|
-
const
|
|
31245
|
+
const ledger = options.efficiencyLedger;
|
|
31246
|
+
const efficiencyLedger = ledger && {
|
|
31247
|
+
record: async (input2) => {
|
|
31248
|
+
const recorded = await ledger.record(input2);
|
|
31249
|
+
if (recorded) monitor(() => options.monitor?.efficiency(input2));
|
|
31250
|
+
return recorded;
|
|
31251
|
+
},
|
|
31252
|
+
...ledger.consumeNoticeForExecution ? { consumeNoticeForExecution: ledger.consumeNoticeForExecution.bind(ledger) } : {}
|
|
31253
|
+
};
|
|
31254
|
+
const supervisor = options.supervisor ?? new NativeEventSupervisor();
|
|
31255
|
+
const fabric = options.fabric && new NativeFabricObserver(supervisor, options.fabric);
|
|
31256
|
+
const incidentProducer = new NativeIncidentProducer(supervisor, (executionId) => fabric?.references(executionId));
|
|
31257
|
+
const runtime = new NativeRuntime({
|
|
31258
|
+
journal: options.journal,
|
|
31259
|
+
tools: options.tools,
|
|
31260
|
+
scheduler: new NativeScheduler({ onEvent: (event) => supervisor.observe(event) }),
|
|
31261
|
+
onFrame: (frame) => {
|
|
31262
|
+
supervisor.frame(frame);
|
|
31263
|
+
fabric?.activity();
|
|
31264
|
+
monitor(() => options.monitor?.frame(frame));
|
|
31265
|
+
},
|
|
31266
|
+
workspaces: () => options.store.loadWorkspaces(Boolean(options.guard)),
|
|
31267
|
+
guard: options.guard,
|
|
31268
|
+
efficiencyLedger
|
|
31269
|
+
});
|
|
29301
31270
|
let connection = null;
|
|
31271
|
+
let legacyMonitorTimer;
|
|
29302
31272
|
const bridge = new NativeRelayBridge(runtime, (binding2, state, code, metrics) => {
|
|
31273
|
+
supervisor.observe({
|
|
31274
|
+
kind: "result",
|
|
31275
|
+
executionId: binding2.executionId,
|
|
31276
|
+
code,
|
|
31277
|
+
terminalProof: state !== "unknown" && code !== "EXECUTION_UNKNOWN"
|
|
31278
|
+
});
|
|
31279
|
+
monitor(() => options.monitor?.result(binding2, state, code));
|
|
29303
31280
|
if (!connection) throw Error("RELAY_SOCKET_CLOSED");
|
|
29304
|
-
return connection.sendTerminal(binding2, state, code, metrics)
|
|
31281
|
+
return connection.sendTerminal(binding2, state, code, metrics).then(() => {
|
|
31282
|
+
incidentProducer.activity();
|
|
31283
|
+
});
|
|
29305
31284
|
}, options.journal);
|
|
29306
31285
|
const connect = options.connect ?? ((connectionOptions) => connectOnce(connectionOptions));
|
|
29307
31286
|
try {
|
|
@@ -29311,17 +31290,45 @@ async function runAgent(options) {
|
|
|
29311
31290
|
ready = resolve;
|
|
29312
31291
|
});
|
|
29313
31292
|
try {
|
|
29314
|
-
|
|
29315
|
-
|
|
29316
|
-
|
|
29317
|
-
|
|
31293
|
+
monitor(() => options.monitor?.setConnection("connecting"));
|
|
31294
|
+
connection = await connect({
|
|
31295
|
+
store: options.store,
|
|
31296
|
+
agentVersion: options.agentVersion,
|
|
31297
|
+
safeSlots: runtime.status().safeSlots,
|
|
31298
|
+
onIncidentAck: (ack) => incidentProducer.ack(ack),
|
|
31299
|
+
handleRequest: async (request) => {
|
|
31300
|
+
await readyPromise;
|
|
31301
|
+
monitor(() => {
|
|
31302
|
+
options.monitor?.transportActivity();
|
|
31303
|
+
options.monitor?.request(request);
|
|
31304
|
+
});
|
|
31305
|
+
try {
|
|
31306
|
+
const result2 = await bridge.handle(request);
|
|
31307
|
+
monitor(() => options.monitor?.response(result2));
|
|
31308
|
+
return result2;
|
|
31309
|
+
} catch (error62) {
|
|
31310
|
+
monitor(() => options.monitor?.requestFailed());
|
|
31311
|
+
throw error62;
|
|
31312
|
+
}
|
|
31313
|
+
},
|
|
31314
|
+
onMonitorHeartbeat: () => monitor(() => options.monitor?.transportActivity())
|
|
31315
|
+
});
|
|
31316
|
+
fabric?.connected(connection.deviceId);
|
|
29318
31317
|
await bridge.connected(connection);
|
|
31318
|
+
incidentProducer.connected(connection.sendIncidentBatch);
|
|
31319
|
+
supervisor.observe({ kind: "connected" });
|
|
31320
|
+
monitor(() => options.monitor?.setConnection("connected", connection));
|
|
31321
|
+
if (options.monitor && !connection.monitorFreshnessMs) {
|
|
31322
|
+
legacyMonitorTimer = setInterval(() => monitor(() => {
|
|
31323
|
+
}), 2e3);
|
|
31324
|
+
legacyMonitorTimer.unref();
|
|
31325
|
+
}
|
|
29319
31326
|
ready();
|
|
29320
31327
|
if (options.signal.aborted) connection.close("agent_shutdown");
|
|
29321
31328
|
else {
|
|
29322
|
-
for (const
|
|
29323
|
-
await connection.revokeWorkspace(
|
|
29324
|
-
await options.store.acknowledgeWorkspaceRevoke(
|
|
31329
|
+
for (const id2 of await options.store.loadPendingWorkspaceRevokes()) {
|
|
31330
|
+
await connection.revokeWorkspace(id2);
|
|
31331
|
+
await options.store.acknowledgeWorkspaceRevoke(id2);
|
|
29325
31332
|
}
|
|
29326
31333
|
for (const workspace of await options.store.loadWorkspaces()) {
|
|
29327
31334
|
if ((await options.store.loadWorkspaces()).some((current2) => current2.workspaceGrantId === workspace.workspaceGrantId)) await connection.registerWorkspace(workspace);
|
|
@@ -29337,9 +31344,16 @@ async function runAgent(options) {
|
|
|
29337
31344
|
}
|
|
29338
31345
|
} catch (error62) {
|
|
29339
31346
|
ready();
|
|
31347
|
+
monitor(() => options.monitor?.connectionFailed(error62));
|
|
29340
31348
|
if (error62 instanceof RelayClientError && ["RELAY_CONNECT_FAILED", "RELAY_CONNECT_CLOSED", "RELAY_CONNECT_TIMEOUT", "RELAY_HANDSHAKE_TIMEOUT"].includes(error62.code)) {
|
|
29341
31349
|
} else throw error62;
|
|
29342
31350
|
} finally {
|
|
31351
|
+
fabric?.disconnected();
|
|
31352
|
+
clearInterval(legacyMonitorTimer);
|
|
31353
|
+
legacyMonitorTimer = void 0;
|
|
31354
|
+
incidentProducer.disconnected();
|
|
31355
|
+
if (!options.signal.aborted) supervisor.observe({ kind: "disconnected" });
|
|
31356
|
+
monitor(() => options.monitor?.setConnection("disconnected"));
|
|
29343
31357
|
connection?.close("agent_disconnect");
|
|
29344
31358
|
await bridge.disconnected();
|
|
29345
31359
|
connection = null;
|
|
@@ -29347,17 +31361,23 @@ async function runAgent(options) {
|
|
|
29347
31361
|
if (!options.signal.aborted) await aborted2(options.signal, delay);
|
|
29348
31362
|
}
|
|
29349
31363
|
} finally {
|
|
29350
|
-
|
|
29351
|
-
|
|
31364
|
+
try {
|
|
31365
|
+
await runtime.close();
|
|
31366
|
+
} finally {
|
|
31367
|
+
fabric?.close();
|
|
31368
|
+
incidentProducer.close();
|
|
31369
|
+
supervisor.close();
|
|
31370
|
+
await options.journal.close();
|
|
31371
|
+
}
|
|
29352
31372
|
}
|
|
29353
31373
|
}
|
|
29354
31374
|
async function main() {
|
|
29355
31375
|
if (process.platform !== "win32") throw Error("WINDOWS_REQUIRED");
|
|
29356
31376
|
const appData = process.env.LOCALAPPDATA;
|
|
29357
|
-
if (!appData || !
|
|
29358
|
-
const stateDir = process.env.LC_AGENT_STATE_DIR ??
|
|
29359
|
-
const binaryDir =
|
|
29360
|
-
const ownerBridgePath = process.env.LC_OWNER_BRIDGE ??
|
|
31377
|
+
if (!appData || !path17.isAbsolute(appData)) throw Error("APP_DATA_MISSING");
|
|
31378
|
+
const stateDir = process.env.LC_AGENT_STATE_DIR ?? path17.join(appData, "LocalCommander", "Agent");
|
|
31379
|
+
const binaryDir = path17.dirname(process.execPath);
|
|
31380
|
+
const ownerBridgePath = process.env.LC_OWNER_BRIDGE ?? path17.join(binaryDir, "OwnerBridge.exe");
|
|
29361
31381
|
const store = await WindowsPrivateStore.open(stateDir, ownerBridgePath);
|
|
29362
31382
|
const command = process.argv[2] ?? "run";
|
|
29363
31383
|
if (command === "pair") {
|
|
@@ -29366,7 +31386,7 @@ async function main() {
|
|
|
29366
31386
|
const pairing = new PairingClient(store, { controlPlaneOrigin: origin, agentVersion: AGENT_VERSION2 });
|
|
29367
31387
|
const begun = await pairing.begin();
|
|
29368
31388
|
process.stdout.write(JSON.stringify({ approvalUrl: begun.approvalUrl, confirmationCode: begun.confirmationCode, expiresAt: begun.expiresAt.toISOString() }) + "\n");
|
|
29369
|
-
await pairing.waitAndComplete(begun,
|
|
31389
|
+
await pairing.waitAndComplete(begun, os4.hostname().slice(0, 120));
|
|
29370
31390
|
process.stdout.write("DEVICE_PAIRED\n");
|
|
29371
31391
|
return;
|
|
29372
31392
|
}
|
|
@@ -29395,6 +31415,9 @@ async function main() {
|
|
|
29395
31415
|
displayName: w.displayName,
|
|
29396
31416
|
path: w.root,
|
|
29397
31417
|
permissions: w.permissions,
|
|
31418
|
+
accessMode: w.fullAccess ? "full" : "scoped",
|
|
31419
|
+
deniedCommands: w.deniedCommands ?? [],
|
|
31420
|
+
deniedLocalhostPorts: w.deniedLocalhostPorts ?? [],
|
|
29398
31421
|
allowedCommands: w.allowedCommands,
|
|
29399
31422
|
executables: Object.fromEntries(w.allowedCommands.map((name2) => [name2, programs[name2]?.executable ?? null])),
|
|
29400
31423
|
localhostPorts: w.localhostPorts,
|
|
@@ -29403,9 +31426,28 @@ async function main() {
|
|
|
29403
31426
|
return;
|
|
29404
31427
|
}
|
|
29405
31428
|
const args = process.argv.slice(3);
|
|
31429
|
+
if (command === "fabric-owner" || command === "fabric-worker") {
|
|
31430
|
+
if (args.length) throw Error("AGENT_COMMAND_INVALID");
|
|
31431
|
+
const enrollment = (await store.load())?.enrollment;
|
|
31432
|
+
if (!enrollment) throw Error("ENROLLMENT_MISSING");
|
|
31433
|
+
const input2 = await readFabricRequest();
|
|
31434
|
+
const fabric = await openNativeFabric(
|
|
31435
|
+
stateDir,
|
|
31436
|
+
enrollment,
|
|
31437
|
+
new SecretBox({ "1": await store.loadDataKey() }),
|
|
31438
|
+
command === "fabric-owner"
|
|
31439
|
+
);
|
|
31440
|
+
try {
|
|
31441
|
+
const result2 = command === "fabric-owner" ? await fabric.owner(input2) : await fabric.worker(input2);
|
|
31442
|
+
process.stdout.write(JSON.stringify(result2) + "\n");
|
|
31443
|
+
} finally {
|
|
31444
|
+
fabric.close();
|
|
31445
|
+
}
|
|
31446
|
+
return;
|
|
31447
|
+
}
|
|
29406
31448
|
if (command === "efficiency-report") {
|
|
29407
31449
|
if (args.length) throw Error("AGENT_COMMAND_INVALID");
|
|
29408
|
-
const ledger = await OptimizationLedger.open(
|
|
31450
|
+
const ledger = await OptimizationLedger.open(path17.join(stateDir, "optimization"));
|
|
29409
31451
|
try {
|
|
29410
31452
|
process.stdout.write(JSON.stringify(await ledger.report(), null, 2) + "\n");
|
|
29411
31453
|
} finally {
|
|
@@ -29415,7 +31457,7 @@ async function main() {
|
|
|
29415
31457
|
}
|
|
29416
31458
|
if (command === "guard-configure") {
|
|
29417
31459
|
if (args.length !== 1) throw Error("AGENT_COMMAND_INVALID");
|
|
29418
|
-
const filename = await (await import("node:fs/promises")).realpath(
|
|
31460
|
+
const filename = await (await import("node:fs/promises")).realpath(path17.resolve(args[0]));
|
|
29419
31461
|
const input2 = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readWindowsFile(ownerBridgePath, filename, 2e5)));
|
|
29420
31462
|
if (!input2 || typeof input2 !== "object" || Object.keys(input2).sort().join(",") !== "compact,settings") throw Error("GUARD_CONFIGURATION_INVALID");
|
|
29421
31463
|
await store.configureGuard(input2.settings, input2.compact);
|
|
@@ -29434,7 +31476,7 @@ async function main() {
|
|
|
29434
31476
|
}
|
|
29435
31477
|
if (command === "guard-evidence") {
|
|
29436
31478
|
if (args.length) throw Error("AGENT_COMMAND_INVALID");
|
|
29437
|
-
const journal = await NativeJournal.open(
|
|
31479
|
+
const journal = await NativeJournal.open(path17.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
|
|
29438
31480
|
try {
|
|
29439
31481
|
process.stdout.write(JSON.stringify(await journal.guardEvidence()) + "\n");
|
|
29440
31482
|
} finally {
|
|
@@ -29446,7 +31488,7 @@ async function main() {
|
|
|
29446
31488
|
if (args.length !== (command === "guard-export" ? 0 : 1)) throw Error("AGENT_COMMAND_INVALID");
|
|
29447
31489
|
const identity = await store.load();
|
|
29448
31490
|
if (!identity?.enrollment) throw Error("ENROLLMENT_MISSING");
|
|
29449
|
-
const journal = await NativeJournal.open(
|
|
31491
|
+
const journal = await NativeJournal.open(path17.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
|
|
29450
31492
|
try {
|
|
29451
31493
|
const { tenantId, deviceId } = identity.enrollment;
|
|
29452
31494
|
const records = (await journal.guardEvidence()).filter((record2) => record2.tenantId === tenantId && record2.deviceId === deviceId);
|
|
@@ -29484,25 +31526,62 @@ async function main() {
|
|
|
29484
31526
|
if (args.length) throw Error("AGENT_COMMAND_INVALID");
|
|
29485
31527
|
if (!(await store.load())?.enrollment) throw Error("ENROLLMENT_MISSING");
|
|
29486
31528
|
const releaseProcess = await claimAgentProcess(stateDir, binaryDir, AGENT_VERSION2);
|
|
31529
|
+
const monitor = new ProductionMonitor(path17.join(appData, "LocalCommander", "Monitor"), stateDir, AGENT_VERSION2);
|
|
31530
|
+
const publishMonitor = () => monitor.flush().catch(() => {
|
|
31531
|
+
process.stderr.write("MONITOR_WRITE_FAILED\n");
|
|
31532
|
+
});
|
|
31533
|
+
await publishMonitor();
|
|
29487
31534
|
try {
|
|
29488
|
-
const journal = await NativeJournal.open(
|
|
29489
|
-
const efficiencyLedger = await OptimizationLedger.open(
|
|
31535
|
+
const journal = await NativeJournal.open(path17.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
|
|
31536
|
+
const efficiencyLedger = await OptimizationLedger.open(path17.join(stateDir, "optimization"));
|
|
29490
31537
|
try {
|
|
29491
|
-
const tools = new NativeTools({ stateDirectory: stateDir, helperPath: process.env.LC_JOB_HOST ??
|
|
31538
|
+
const tools = new NativeTools({ stateDirectory: stateDir, helperPath: process.env.LC_JOB_HOST ?? path17.join(binaryDir, "JobHost.exe"), ownerBridgePath, programs: await store.loadPrograms() });
|
|
29492
31539
|
const stop = new AbortController();
|
|
29493
31540
|
process.once("SIGINT", () => stop.abort());
|
|
29494
31541
|
process.once("SIGTERM", () => stop.abort());
|
|
29495
31542
|
const guard = await NativeGuard.open(store, journal);
|
|
29496
|
-
|
|
31543
|
+
const enrollment = (await store.load()).enrollment;
|
|
31544
|
+
const fabric = await openNativeFabric(stateDir, enrollment, new SecretBox({ "1": await store.loadDataKey() })).catch(() => {
|
|
31545
|
+
process.stderr.write("FABRIC_STARTUP_FAILED\n");
|
|
31546
|
+
return void 0;
|
|
31547
|
+
});
|
|
31548
|
+
try {
|
|
31549
|
+
await runAgent({
|
|
31550
|
+
store,
|
|
31551
|
+
journal,
|
|
31552
|
+
tools,
|
|
31553
|
+
signal: stop.signal,
|
|
31554
|
+
agentVersion: AGENT_VERSION2,
|
|
31555
|
+
guard,
|
|
31556
|
+
efficiencyLedger,
|
|
31557
|
+
monitor,
|
|
31558
|
+
...fabric ? { fabric: fabric.source } : {}
|
|
31559
|
+
});
|
|
31560
|
+
} finally {
|
|
31561
|
+
fabric?.close();
|
|
31562
|
+
}
|
|
31563
|
+
try {
|
|
31564
|
+
monitor.setConnection("stopped");
|
|
31565
|
+
} catch {
|
|
31566
|
+
}
|
|
29497
31567
|
} finally {
|
|
29498
31568
|
await efficiencyLedger.close();
|
|
29499
31569
|
await journal.close();
|
|
29500
31570
|
}
|
|
31571
|
+
} catch (error62) {
|
|
31572
|
+
try {
|
|
31573
|
+
monitor.setConnection("failed");
|
|
31574
|
+
} catch {
|
|
31575
|
+
}
|
|
31576
|
+
throw error62;
|
|
29501
31577
|
} finally {
|
|
31578
|
+
await monitor.close().catch(() => {
|
|
31579
|
+
process.stderr.write("MONITOR_WRITE_FAILED\n");
|
|
31580
|
+
});
|
|
29502
31581
|
await releaseProcess();
|
|
29503
31582
|
}
|
|
29504
31583
|
}
|
|
29505
|
-
if (process.argv[1] &&
|
|
31584
|
+
if (process.argv[1] && path17.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
29506
31585
|
void main().catch((error62) => {
|
|
29507
31586
|
const code = error62 instanceof Error && /^[A-Z0-9_]{1,64}$/.test(error62.message) ? error62.message : "AGENT_START_FAILED";
|
|
29508
31587
|
process.stderr.write(code + "\n");
|