@agentdocumentformat/cli 0.7.5 → 0.7.7
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/dist/adf.mjs +3 -3
- package/dist/chunks/{App-ZRQS3U7S.mjs → App-5KXVPMBV.mjs} +6 -6
- package/dist/chunks/{chunk-2WSQ7V6K.mjs → chunk-4N4ASPH6.mjs} +1 -0
- package/dist/chunks/chunk-KXEF4F4E.mjs +113 -0
- package/dist/chunks/{chunk-EYX2YLJW.mjs → chunk-PRMGZZM5.mjs} +40 -20
- package/dist/chunks/{chunk-GEKSJHIV.mjs → chunk-QPLEAE6V.mjs} +1 -1
- package/dist/chunks/{chunk-3UCKYP7P.mjs → chunk-VN7UH7I5.mjs} +9 -0
- package/dist/chunks/{cli-JDBN7CBR.mjs → cli-AFHQ2XTN.mjs} +1 -1
- package/dist/chunks/{daemon-6RA2DIJ2.mjs → daemon-CHZHTLGR.mjs} +2672 -193
- package/dist/chunks/{discord-IWDQJA7A.mjs → discord-DSP4HUWI.mjs} +3 -3
- package/dist/chunks/{email-V4Q4VJON.mjs → email-BRG7KUO2.mjs} +3 -2
- package/dist/chunks/{open-OTQDGDH5.mjs → open-VAU7PXT6.mjs} +2 -2
- package/dist/chunks/{slack-3L5QTDZX.mjs → slack-OCNNF4DX.mjs} +3 -3
- package/dist/chunks/{telegram-V4VH4PNE.mjs → telegram-YI2OHNTD.mjs} +21 -21
- package/dist/chunks/{theme-NORU4J74.mjs → theme-SFE3JMA2.mjs} +1 -1
- package/dist/chunks/{themes-F2FKU7CP.mjs → themes-YLXLOIJF.mjs} +2 -2
- package/dist/chunks/{tui-I5LEARAV.mjs → tui-4ZWZKD4C.mjs} +6 -6
- package/dist/chunks/{whatsapp-RDOC54X5.mjs → whatsapp-AVKT3CTJ.mjs} +3 -3
- package/package.json +1 -1
- package/dist/chunks/chunk-SLUKGXKH.mjs +0 -68
|
@@ -18,8 +18,9 @@ import {
|
|
|
18
18
|
checkFetchTarget,
|
|
19
19
|
contextCategories,
|
|
20
20
|
contextTotal,
|
|
21
|
-
resolveCompactThreshold
|
|
22
|
-
|
|
21
|
+
resolveCompactThreshold,
|
|
22
|
+
resolveLoopThreshold
|
|
23
|
+
} from "./chunk-4N4ASPH6.mjs";
|
|
23
24
|
import {
|
|
24
25
|
startCallbackServer
|
|
25
26
|
} from "./chunk-2NAP2ZF7.mjs";
|
|
@@ -434,8 +435,8 @@ var require_types = __commonJS({
|
|
|
434
435
|
TokenType2[TokenType2.IS_POSTFIX = IS_POSTFIX] = "IS_POSTFIX";
|
|
435
436
|
let IS_EXPRESSION_START = 512;
|
|
436
437
|
TokenType2[TokenType2.IS_EXPRESSION_START = IS_EXPRESSION_START] = "IS_EXPRESSION_START";
|
|
437
|
-
let
|
|
438
|
-
TokenType2[TokenType2.num =
|
|
438
|
+
let num2 = 512;
|
|
439
|
+
TokenType2[TokenType2.num = num2] = "num";
|
|
439
440
|
let bigint = 1536;
|
|
440
441
|
TokenType2[TokenType2.bigint = bigint] = "bigint";
|
|
441
442
|
let decimal = 2560;
|
|
@@ -12388,14 +12389,14 @@ var require_sourcemap_codec_umd = __commonJS({
|
|
|
12388
12389
|
let shouldNegate = value & 1;
|
|
12389
12390
|
return value >>>= 1, shouldNegate && (value = -2147483648 | -value), relative4 + value;
|
|
12390
12391
|
}
|
|
12391
|
-
function encodeInteger(builder,
|
|
12392
|
-
let delta =
|
|
12392
|
+
function encodeInteger(builder, num2, relative4) {
|
|
12393
|
+
let delta = num2 - relative4;
|
|
12393
12394
|
delta = delta < 0 ? -delta << 1 | 1 : delta << 1;
|
|
12394
12395
|
do {
|
|
12395
12396
|
let clamped = delta & 31;
|
|
12396
12397
|
delta >>>= 5, delta > 0 && (clamped |= 32), builder.write(intToChar[clamped]);
|
|
12397
12398
|
} while (delta > 0);
|
|
12398
|
-
return
|
|
12399
|
+
return num2;
|
|
12399
12400
|
}
|
|
12400
12401
|
function hasMoreVlq(reader, max) {
|
|
12401
12402
|
return reader.pos >= max ? !1 : reader.peek() !== comma;
|
|
@@ -23557,10 +23558,10 @@ var require_serializer = __commonJS({
|
|
|
23557
23558
|
return "" + integer;
|
|
23558
23559
|
}
|
|
23559
23560
|
asNumber(i) {
|
|
23560
|
-
let
|
|
23561
|
-
if (
|
|
23561
|
+
let num2 = Number(i);
|
|
23562
|
+
if (num2 !== num2)
|
|
23562
23563
|
throw new Error(`The value "${i}" cannot be converted to a number.`);
|
|
23563
|
-
return
|
|
23564
|
+
return num2 === 1 / 0 || num2 === -1 / 0 ? "null" : "" + num2;
|
|
23564
23565
|
}
|
|
23565
23566
|
asBoolean(bool) {
|
|
23566
23567
|
return bool && "true" || "false";
|
|
@@ -25317,21 +25318,21 @@ var require_secure_json_parse = __commonJS({
|
|
|
25317
25318
|
return obj;
|
|
25318
25319
|
return filter2(obj, { protoAction, constructorAction, safe: options && options.safe });
|
|
25319
25320
|
}
|
|
25320
|
-
function filter2(obj, { protoAction = "error", constructorAction = "error", safe } = {}) {
|
|
25321
|
+
function filter2(obj, { protoAction = "error", constructorAction = "error", safe: safe2 } = {}) {
|
|
25321
25322
|
let next = [obj];
|
|
25322
25323
|
for (; next.length; ) {
|
|
25323
25324
|
let nodes = next;
|
|
25324
25325
|
next = [];
|
|
25325
25326
|
for (let node of nodes) {
|
|
25326
25327
|
if (protoAction !== "ignore" && Object.prototype.hasOwnProperty.call(node, "__proto__")) {
|
|
25327
|
-
if (
|
|
25328
|
+
if (safe2 === !0)
|
|
25328
25329
|
return null;
|
|
25329
25330
|
if (protoAction === "error")
|
|
25330
25331
|
throw new SyntaxError("Object contains forbidden prototype property");
|
|
25331
25332
|
delete node.__proto__;
|
|
25332
25333
|
}
|
|
25333
25334
|
if (constructorAction !== "ignore" && Object.prototype.hasOwnProperty.call(node, "constructor") && node.constructor !== null && typeof node.constructor == "object" && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
|
|
25334
|
-
if (
|
|
25335
|
+
if (safe2 === !0)
|
|
25335
25336
|
return null;
|
|
25336
25337
|
if (constructorAction === "error")
|
|
25337
25338
|
throw new SyntaxError("Object contains forbidden prototype property");
|
|
@@ -31799,8 +31800,8 @@ var require_parse = __commonJS({
|
|
|
31799
31800
|
break;
|
|
31800
31801
|
case "timestamp": {
|
|
31801
31802
|
parseString(cxt);
|
|
31802
|
-
let vts = (0, util_1.useFunc)(gen, timestamp_1.default), { allowDate, parseDate } = self2.opts, notValid = allowDate ? (0, codegen_1._)`!${vts}(${data}, true)` : (0, codegen_1._)`!${vts}(${data})`,
|
|
31803
|
-
gen.if(
|
|
31803
|
+
let vts = (0, util_1.useFunc)(gen, timestamp_1.default), { allowDate, parseDate } = self2.opts, notValid = allowDate ? (0, codegen_1._)`!${vts}(${data}, true)` : (0, codegen_1._)`!${vts}(${data})`, fail3 = parseDate ? (0, codegen_1.or)(notValid, (0, codegen_1._)`(${data} = new Date(${data}), false)`, (0, codegen_1._)`isNaN(${data}.valueOf())`) : notValid;
|
|
31804
|
+
gen.if(fail3, () => parsingError(cxt, (0, codegen_1.str)`invalid timestamp`));
|
|
31804
31805
|
break;
|
|
31805
31806
|
}
|
|
31806
31807
|
case "float32":
|
|
@@ -31834,10 +31835,10 @@ var require_parse = __commonJS({
|
|
|
31834
31835
|
let { gen } = cxt;
|
|
31835
31836
|
skipWhitespace(cxt), gen.if((0, codegen_1._)`"-0123456789".indexOf(${jsonSlice(1)}) < 0`, () => jsonSyntaxError(cxt), () => parseWith(cxt, parseJson_1.parseJsonNumber, maxDigits));
|
|
31836
31837
|
}
|
|
31837
|
-
function parseBooleanToken(bool,
|
|
31838
|
+
function parseBooleanToken(bool, fail3) {
|
|
31838
31839
|
return (cxt) => {
|
|
31839
31840
|
let { gen, data } = cxt;
|
|
31840
|
-
tryParseToken(cxt, `${bool}`, () =>
|
|
31841
|
+
tryParseToken(cxt, `${bool}`, () => fail3(cxt), () => gen.assign(data, bool));
|
|
31841
31842
|
};
|
|
31842
31843
|
}
|
|
31843
31844
|
function parseRef(cxt) {
|
|
@@ -31865,11 +31866,11 @@ var require_parse = __commonJS({
|
|
|
31865
31866
|
function parseToken(cxt, tok) {
|
|
31866
31867
|
tryParseToken(cxt, tok, jsonSyntaxError);
|
|
31867
31868
|
}
|
|
31868
|
-
function tryParseToken(cxt, tok,
|
|
31869
|
+
function tryParseToken(cxt, tok, fail3, success) {
|
|
31869
31870
|
let { gen } = cxt, n = tok.length;
|
|
31870
31871
|
skipWhitespace(cxt), gen.if((0, codegen_1._)`${jsonSlice(n)} === ${tok}`, () => {
|
|
31871
31872
|
gen.add(names_1.default.jsonPos, n), success?.(cxt);
|
|
31872
|
-
}, () =>
|
|
31873
|
+
}, () => fail3(cxt));
|
|
31873
31874
|
}
|
|
31874
31875
|
function skipWhitespace({ gen, char: c }) {
|
|
31875
31876
|
gen.code((0, codegen_1._)`while((${c}=${names_1.default.json}[${names_1.default.jsonPos}],${c}===" "||${c}==="\\n"||${c}==="\\r"||${c}==="\\t"))${names_1.default.jsonPos}++;`);
|
|
@@ -32686,10 +32687,10 @@ var require_serializer2 = __commonJS({
|
|
|
32686
32687
|
return "" + integer;
|
|
32687
32688
|
}
|
|
32688
32689
|
asNumber(i) {
|
|
32689
|
-
let
|
|
32690
|
-
if (
|
|
32690
|
+
let num2 = Number(i);
|
|
32691
|
+
if (num2 !== num2)
|
|
32691
32692
|
throw new Error(`The value "${i}" cannot be converted to a number.`);
|
|
32692
|
-
return
|
|
32693
|
+
return num2 === 1 / 0 || num2 === -1 / 0 ? "null" : "" + num2;
|
|
32693
32694
|
}
|
|
32694
32695
|
asBoolean(bool) {
|
|
32695
32696
|
return bool && "true" || "false";
|
|
@@ -34861,8 +34862,8 @@ var require_re = __commonJS({
|
|
|
34861
34862
|
value = value.split(`${token}*`).join(`${token}{0,${max}}`).split(`${token}+`).join(`${token}{1,${max}}`);
|
|
34862
34863
|
return value;
|
|
34863
34864
|
}, createToken = (name21, value, isGlobal) => {
|
|
34864
|
-
let
|
|
34865
|
-
debug(name21, index, value), t[name21] = index, src[index] = value, safeSrc[index] =
|
|
34865
|
+
let safe2 = makeSafeRegex(value), index = R++;
|
|
34866
|
+
debug(name21, index, value), t[name21] = index, src[index] = value, safeSrc[index] = safe2, re2[index] = new RegExp(value, isGlobal ? "g" : void 0), safeRe[index] = new RegExp(safe2, isGlobal ? "g" : void 0);
|
|
34866
34867
|
};
|
|
34867
34868
|
createToken("NUMERICIDENTIFIER", "0|[1-9]\\d*");
|
|
34868
34869
|
createToken("NUMERICIDENTIFIERLOOSE", "\\d+");
|
|
@@ -34967,9 +34968,9 @@ var require_semver = __commonJS({
|
|
|
34967
34968
|
throw new TypeError("Invalid patch version");
|
|
34968
34969
|
m[4] ? this.prerelease = m[4].split(".").map((id) => {
|
|
34969
34970
|
if (/^[0-9]+$/.test(id)) {
|
|
34970
|
-
let
|
|
34971
|
-
if (
|
|
34972
|
-
return
|
|
34971
|
+
let num2 = +id;
|
|
34972
|
+
if (num2 >= 0 && num2 < MAX_SAFE_INTEGER)
|
|
34973
|
+
return num2;
|
|
34973
34974
|
}
|
|
34974
34975
|
return id;
|
|
34975
34976
|
}) : this.prerelease = [], this.build = m[5] ? m[5].split(".") : [], this.format();
|
|
@@ -43451,8 +43452,8 @@ var require_parse4 = __commonJS({
|
|
|
43451
43452
|
tokens
|
|
43452
43453
|
};
|
|
43453
43454
|
input = utils2.removePrefix(input, state), len = input.length;
|
|
43454
|
-
let extglobs = [], braces = [], stack = [], prev = bos, value, eos = () => state.index === len - 1, peek = state.peek = (n = 1) => input[state.index + n], advance = state.advance = () => input[++state.index] || "", remaining = () => input.slice(state.index + 1), consume = (value2 = "",
|
|
43455
|
-
state.consumed += value2, state.index +=
|
|
43455
|
+
let extglobs = [], braces = [], stack = [], prev = bos, value, eos = () => state.index === len - 1, peek = state.peek = (n = 1) => input[state.index + n], advance = state.advance = () => input[++state.index] || "", remaining = () => input.slice(state.index + 1), consume = (value2 = "", num2 = 0) => {
|
|
43456
|
+
state.consumed += value2, state.index += num2;
|
|
43456
43457
|
}, append = (token) => {
|
|
43457
43458
|
state.output += token.output != null ? token.output : token.value, consume(token.value);
|
|
43458
43459
|
}, negate = () => {
|
|
@@ -45114,10 +45115,10 @@ function base58btcEncode(data) {
|
|
|
45114
45115
|
let zeros = 0;
|
|
45115
45116
|
for (let i = 0; i < data.length && data[i] === 0; i++)
|
|
45116
45117
|
zeros++;
|
|
45117
|
-
let
|
|
45118
|
-
for (;
|
|
45119
|
-
let remainder = Number(
|
|
45120
|
-
|
|
45118
|
+
let num2 = BigInt("0x" + (data.length > 0 ? data.toString("hex") : "0")), chars = [];
|
|
45119
|
+
for (; num2 > 0n; ) {
|
|
45120
|
+
let remainder = Number(num2 % 58n);
|
|
45121
|
+
num2 = num2 / 58n, chars.push(BASE58_ALPHABET[remainder]);
|
|
45121
45122
|
}
|
|
45122
45123
|
for (let i = 0; i < zeros; i++)
|
|
45123
45124
|
chars.push("1");
|
|
@@ -45147,18 +45148,18 @@ function rawPublicKeyToSpki(rawKey) {
|
|
|
45147
45148
|
return Buffer.concat([header, rawKey]);
|
|
45148
45149
|
}
|
|
45149
45150
|
function base58btcDecode(str2) {
|
|
45150
|
-
let
|
|
45151
|
+
let num2 = 0n;
|
|
45151
45152
|
for (let char of str2) {
|
|
45152
45153
|
let idx = BASE58_ALPHABET.indexOf(char);
|
|
45153
45154
|
if (idx === -1) throw new Error(`Invalid base58 character: ${char}`);
|
|
45154
|
-
|
|
45155
|
+
num2 = num2 * 58n + BigInt(idx);
|
|
45155
45156
|
}
|
|
45156
45157
|
let leadingZeros = 0;
|
|
45157
45158
|
for (let char of str2) {
|
|
45158
45159
|
if (char !== "1") break;
|
|
45159
45160
|
leadingZeros++;
|
|
45160
45161
|
}
|
|
45161
|
-
let hex =
|
|
45162
|
+
let hex = num2 === 0n ? "" : num2.toString(16), paddedHex = hex.length % 2 ? "0" + hex : hex, dataBytes = Buffer.from(paddedHex, "hex"), zeros = Buffer.alloc(leadingZeros);
|
|
45162
45163
|
return Buffer.concat([zeros, dataBytes]);
|
|
45163
45164
|
}
|
|
45164
45165
|
function didToPublicKey(did) {
|
|
@@ -46680,8 +46681,15 @@ CREATE INDEX IF NOT EXISTS idx_adf_logs_origin ON adf_logs(origin);
|
|
|
46680
46681
|
return _AdfDatabase.peekReadonly(filePath, (db) => {
|
|
46681
46682
|
let row = db.prepare("SELECT config_json FROM adf_config WHERE id = 1").get();
|
|
46682
46683
|
if (!row) return null;
|
|
46683
|
-
let config = JSON.parse(row.config_json);
|
|
46684
|
+
let config = JSON.parse(row.config_json), did;
|
|
46685
|
+
try {
|
|
46686
|
+
let meta = db.prepare("SELECT value FROM adf_meta WHERE key = 'adf_did'").get();
|
|
46687
|
+
did = (meta ? Buffer.isBuffer(meta.value) ? meta.value.toString("utf-8") : String(meta.value) : "") || void 0;
|
|
46688
|
+
} catch {
|
|
46689
|
+
did = void 0;
|
|
46690
|
+
}
|
|
46684
46691
|
return {
|
|
46692
|
+
did,
|
|
46685
46693
|
id: config.id,
|
|
46686
46694
|
name: config.name,
|
|
46687
46695
|
receive: config.messaging?.receive ?? !1,
|
|
@@ -47940,6 +47948,7 @@ CREATE INDEX IF NOT EXISTS idx_adf_logs_origin ON adf_logs(origin);
|
|
|
47940
47948
|
// src/main/adf/adf-workspace.ts
|
|
47941
47949
|
import { brotliCompress, brotliCompressSync, brotliDecompressSync as brotliDecompressSync2, constants as zlibConstants } from "zlib";
|
|
47942
47950
|
import { promisify } from "util";
|
|
47951
|
+
import { createPrivateKey as createPrivateKey3, createPublicKey as createPublicKey3 } from "crypto";
|
|
47943
47952
|
|
|
47944
47953
|
// src/main/adf/skill-indexer.ts
|
|
47945
47954
|
init_execution_context();
|
|
@@ -48425,13 +48434,25 @@ var LoopCompactionSupersededError = class extends Error {
|
|
|
48425
48434
|
super(`compactLoop: source seq ${seq} no longer exists \u2014 another compaction or clear landed first`), this.name = "LoopCompactionSupersededError";
|
|
48426
48435
|
}
|
|
48427
48436
|
}, LOOP_REVISION_CHANGED = /* @__PURE__ */ Symbol("adf:loop-revision-changed");
|
|
48428
|
-
var CONTEXT_BASELINE_META_KEY = "context_baseline_tokens", ENVELOPE_NAMES = ["identity", "credentials"], ENVELOPE_PURPOSE_PREFIX = "crypto:envelope:"
|
|
48437
|
+
var CONTEXT_BASELINE_META_KEY = "context_baseline_tokens", ENVELOPE_NAMES = ["identity", "credentials"], ENVELOPE_PURPOSE_PREFIX = "crypto:envelope:";
|
|
48438
|
+
function numberedPath(path, n) {
|
|
48439
|
+
if (n <= 1) return path;
|
|
48440
|
+
let slash = path.lastIndexOf("/"), dot = path.lastIndexOf(".");
|
|
48441
|
+
return dot <= slash + 1 ? `${path}-${n}` : `${path.slice(0, dot)}-${n}${path.slice(dot)}`;
|
|
48442
|
+
}
|
|
48443
|
+
var MCP_OAUTH_PURPOSE_RE = /^mcp:[^:]+:oauth$/, MCP_CREDENTIAL_FILE_PURPOSE_RE = /^mcp:[^:]+:file:/;
|
|
48429
48444
|
function isReservedMcpRuntimePurpose(purpose) {
|
|
48430
48445
|
return MCP_OAUTH_PURPOSE_RE.test(purpose) || MCP_CREDENTIAL_FILE_PURPOSE_RE.test(purpose);
|
|
48431
48446
|
}
|
|
48432
48447
|
function mcpRuntimeIdentityAccess(purpose) {
|
|
48433
48448
|
return isReservedMcpRuntimePurpose(purpose) ? { readUnlocked: !1, writeUnlocked: !1 } : { readUnlocked: !0, writeUnlocked: !0 };
|
|
48434
48449
|
}
|
|
48450
|
+
function assertEd25519Pair(privateKey, publicKey) {
|
|
48451
|
+
let priv = createPrivateKey3({ key: privateKey, format: "der", type: "pkcs8" });
|
|
48452
|
+
if (priv.asymmetricKeyType !== "ed25519") throw new Error("Adopted identity key is not Ed25519");
|
|
48453
|
+
let derived = createPublicKey3(priv).export({ type: "spki", format: "der" });
|
|
48454
|
+
if (!Buffer.from(derived).equals(publicKey)) throw new Error("Adopted identity public key does not match its private key");
|
|
48455
|
+
}
|
|
48435
48456
|
var AdfWorkspace = class _AdfWorkspace {
|
|
48436
48457
|
db;
|
|
48437
48458
|
filePath;
|
|
@@ -48975,9 +48996,15 @@ var AdfWorkspace = class _AdfWorkspace {
|
|
|
48975
48996
|
/**
|
|
48976
48997
|
* Generate Ed25519 key pair + DID for an ADF that doesn't have one.
|
|
48977
48998
|
* If a password is active, the new keys are encrypted with the given derivedKey.
|
|
48978
|
-
|
|
48979
|
-
|
|
48980
|
-
|
|
48999
|
+
*
|
|
49000
|
+
* `adopt` stores a keypair minted earlier (an identity draft from the create
|
|
49001
|
+
* screen) instead of a fresh one. The rows, sealing, and adf_did are exactly
|
|
49002
|
+
* what a fresh mint writes. The pair is checked first: the public key must
|
|
49003
|
+
* be the Ed25519 public half of the private key.
|
|
49004
|
+
*/
|
|
49005
|
+
generateIdentityKeys(derivedKey, adopt) {
|
|
49006
|
+
adopt && assertEd25519Pair(adopt.privateKey, adopt.publicKey);
|
|
49007
|
+
let keyPair = adopt ?? generateEd25519KeyPair(), rawPubKey = extractRawPublicKey(keyPair.publicKey), did = publicKeyToDid(rawPubKey), identityDek = this.envelopeDeks.get("identity");
|
|
48981
49008
|
if (identityDek)
|
|
48982
49009
|
this.db.setIdentityRaw("crypto:signing:private_key", sealWithDek(keyPair.privateKey, identityDek), envelopeAlgo("identity"), null, null), this.db.setIdentityRaw("crypto:signing:public_key", keyPair.publicKey, "plain", null, null);
|
|
48983
49010
|
else if (derivedKey) {
|
|
@@ -49737,6 +49764,22 @@ var AdfWorkspace = class _AdfWorkspace {
|
|
|
49737
49764
|
let existed = this.db.fileExists(relativePath), previous = this.onFileChangeCallback ? this.db.readFile(relativePath)?.content : void 0, protection = relativePath === "mind.md" || relativePath === "README.md" || relativePath === "document.md" ? "no_delete" : "none";
|
|
49738
49765
|
this.db.writeFile(relativePath, content, mimeType, protection), this.emitUmbilical("file.written", { path: relativePath, bytes: content.length }), this.emitFileChange(relativePath, existed ? "modified" : "created", content, previous, this.fileChangeMeta(relativePath));
|
|
49739
49766
|
}
|
|
49767
|
+
/**
|
|
49768
|
+
* Write a file without replacing a different one already at that path.
|
|
49769
|
+
* A taken name gets a number before its extension (`report.pdf` →
|
|
49770
|
+
* `report-2.pdf`). The same bytes already stored under the name or one of
|
|
49771
|
+
* its numbered copies are reused rather than written again, so a re-delivered
|
|
49772
|
+
* attachment or a re-uploaded file does not pile up copies.
|
|
49773
|
+
* Returns the path the content lives at.
|
|
49774
|
+
*/
|
|
49775
|
+
writeFileBufferUnique(relativePath, content, mimeType) {
|
|
49776
|
+
for (let n = 1; ; n++) {
|
|
49777
|
+
let candidate = numberedPath(relativePath, n), existing = this.db.readFile(candidate);
|
|
49778
|
+
if (!existing)
|
|
49779
|
+
return this.writeFileBuffer(candidate, content, mimeType), candidate;
|
|
49780
|
+
if (existing.content.equals(content)) return candidate;
|
|
49781
|
+
}
|
|
49782
|
+
}
|
|
49740
49783
|
/** File metadata for a change event — skipped entirely when no sink is registered. */
|
|
49741
49784
|
fileChangeMeta(path) {
|
|
49742
49785
|
return this.onFileChangeCallback ? this.getFileMeta(path) : null;
|
|
@@ -52526,6 +52569,26 @@ var ToolRegistry = class _ToolRegistry {
|
|
|
52526
52569
|
let result = this.tools.delete(name21);
|
|
52527
52570
|
return result && this.toolCache.clear(), result;
|
|
52528
52571
|
}
|
|
52572
|
+
/** Host-built tools that exist while their declaration does (provideDeclared). */
|
|
52573
|
+
declaredFactories = /* @__PURE__ */ new Map();
|
|
52574
|
+
/**
|
|
52575
|
+
* Register `name` for as long as the agent config declares it (enabled or
|
|
52576
|
+
* not), now and again on every config change via syncDeclared. For host
|
|
52577
|
+
* tools whose registration follows declaration presence — sys_code,
|
|
52578
|
+
* sys_lambda, npm_install, npm_uninstall. Without the re-sync, a tool the
|
|
52579
|
+
* owner declared on a running agent stayed unregistered ("not available")
|
|
52580
|
+
* until a restart. Access is still gated by the declaration on every call
|
|
52581
|
+
* path; this only decides whether an instance exists to be gated.
|
|
52582
|
+
*/
|
|
52583
|
+
provideDeclared(name21, make, declarations) {
|
|
52584
|
+
this.declaredFactories.set(name21, make), this.syncDeclared(declarations);
|
|
52585
|
+
}
|
|
52586
|
+
/** Re-apply provideDeclared against a new config's declarations. */
|
|
52587
|
+
syncDeclared(declarations) {
|
|
52588
|
+
let declared = new Set(declarations.map((d) => d.name));
|
|
52589
|
+
for (let [name21, make] of this.declaredFactories)
|
|
52590
|
+
declared.has(name21) ? this.tools.has(name21) || this.register(make()) : this.unregister(name21);
|
|
52591
|
+
}
|
|
52529
52592
|
get(name21) {
|
|
52530
52593
|
return this.tools.get(name21);
|
|
52531
52594
|
}
|
|
@@ -53724,8 +53787,8 @@ var InputSchema = external_exports.object({
|
|
|
53724
53787
|
let entry = workspace.getDatabase().readFile(path);
|
|
53725
53788
|
if (!entry)
|
|
53726
53789
|
return { content: `File not found: "${path}"`, isError: !0 };
|
|
53727
|
-
let
|
|
53728
|
-
if (
|
|
53790
|
+
let isText2 = isTextMime(entry.mime_type), fileContent;
|
|
53791
|
+
if (isText2) {
|
|
53729
53792
|
let text2 = entry.content.toString("utf-8");
|
|
53730
53793
|
if (start_line || end_line) {
|
|
53731
53794
|
let lines = text2.split(`
|
|
@@ -57372,6 +57435,8 @@ var WARM_IDLE_TTL_MS = 5 * 6e4, COLD_IDLE_TTL_MS = 6e4, ADMISSION_MAX_WAIT_MS =
|
|
|
57372
57435
|
stdlibModules = [];
|
|
57373
57436
|
userPkgBasePath = null;
|
|
57374
57437
|
userPkgModules = [];
|
|
57438
|
+
/** Per-agent package lists, keyed by owning agent (see setAgentPackageSource). */
|
|
57439
|
+
agentPackageSources = /* @__PURE__ */ new Map();
|
|
57375
57440
|
/** Sandbox ids each agent has created, so destroyForAgent() reaps exactly
|
|
57376
57441
|
* those. Prefix matching used to do this, but sandbox ids are absolute
|
|
57377
57442
|
* Windows paths — an agent whose `.adf` declares `id: "C"` made
|
|
@@ -57392,13 +57457,48 @@ var WARM_IDLE_TTL_MS = 5 * 6e4, COLD_IDLE_TTL_MS = 6e4, ADMISSION_MAX_WAIT_MS =
|
|
|
57392
57457
|
setStdlib(basePath, modules) {
|
|
57393
57458
|
this.stdlibBasePath = basePath, this.stdlibModules = modules;
|
|
57394
57459
|
}
|
|
57395
|
-
/**
|
|
57460
|
+
/**
|
|
57461
|
+
* Configure the installed-package path and the RUNTIME packages (Settings >
|
|
57462
|
+
* Packages), which every agent's sandboxes can import. Pass a reader to
|
|
57463
|
+
* follow the setting live; it runs at each execution. An agent's own
|
|
57464
|
+
* packages come on top of these, from setAgentPackageSource.
|
|
57465
|
+
*/
|
|
57396
57466
|
setUserPackages(basePath, modules) {
|
|
57397
57467
|
this.userPkgBasePath = basePath, this.userPkgModules = modules;
|
|
57398
57468
|
}
|
|
57399
|
-
|
|
57400
|
-
|
|
57401
|
-
|
|
57469
|
+
runtimePackageModules() {
|
|
57470
|
+
if (typeof this.userPkgModules != "function") return this.userPkgModules;
|
|
57471
|
+
try {
|
|
57472
|
+
return this.userPkgModules();
|
|
57473
|
+
} catch {
|
|
57474
|
+
return [];
|
|
57475
|
+
}
|
|
57476
|
+
}
|
|
57477
|
+
/**
|
|
57478
|
+
* The packages one agent installed (its code_execution.packages), importable
|
|
57479
|
+
* only by sandboxes that agent owns. `read` runs at each execution, so a
|
|
57480
|
+
* package the agent just installed is importable on its next run with no
|
|
57481
|
+
* refresh step. `keys` are every id the agent's sandboxes are owned under —
|
|
57482
|
+
* the `agent` execute option, which is the file path for most callers and
|
|
57483
|
+
* the config id for some (mesh routes, middleware).
|
|
57484
|
+
*/
|
|
57485
|
+
setAgentPackageSource(keys, read) {
|
|
57486
|
+
for (let key of keys) this.agentPackageSources.set(key, read);
|
|
57487
|
+
}
|
|
57488
|
+
clearAgentPackageSource(keys, read) {
|
|
57489
|
+
for (let key of keys)
|
|
57490
|
+
read && this.agentPackageSources.get(key) !== read || this.agentPackageSources.delete(key);
|
|
57491
|
+
}
|
|
57492
|
+
/** Module names visible to `agent`'s sandboxes: runtime packages plus its own. */
|
|
57493
|
+
getUserPackageModules(agent) {
|
|
57494
|
+
let runtime2 = this.runtimePackageModules(), read = agent ? this.agentPackageSources.get(agent) : void 0;
|
|
57495
|
+
if (!read) return [...runtime2];
|
|
57496
|
+
let own = [];
|
|
57497
|
+
try {
|
|
57498
|
+
own = read();
|
|
57499
|
+
} catch {
|
|
57500
|
+
}
|
|
57501
|
+
return [.../* @__PURE__ */ new Set([...runtime2, ...own])];
|
|
57402
57502
|
}
|
|
57403
57503
|
/**
|
|
57404
57504
|
* Set the global ceiling on concurrent cold-lambda workers (user setting —
|
|
@@ -57459,7 +57559,9 @@ var WARM_IDLE_TTL_MS = 5 * 6e4, COLD_IDLE_TTL_MS = 6e4, ADMISSION_MAX_WAIT_MS =
|
|
|
57459
57559
|
stdlibBasePath: this.stdlibBasePath,
|
|
57460
57560
|
stdlibModules: this.stdlibModules,
|
|
57461
57561
|
userPkgBasePath: this.userPkgBasePath,
|
|
57462
|
-
|
|
57562
|
+
// Per execution: a worker serves one owner, but the list must follow
|
|
57563
|
+
// that agent's installs and the runtime list as they change.
|
|
57564
|
+
userPkgModules: this.getUserPackageModules(options?.agent ?? agentId)
|
|
57463
57565
|
});
|
|
57464
57566
|
let execId = `exec_${++this.execCounter}`, isAuthorized = options?.handlerAuthorized ?? toolConfig?.isAuthorized ?? !1;
|
|
57465
57567
|
entry.authLevels.add(isAuthorized), entry.inflight++;
|
|
@@ -58861,15 +58963,15 @@ function estimateObjectChars(obj) {
|
|
|
58861
58963
|
if (typeof obj == "string") return obj.length + 2;
|
|
58862
58964
|
if (typeof obj == "number" || typeof obj == "boolean") return 5;
|
|
58863
58965
|
if (Array.isArray(obj)) {
|
|
58864
|
-
let
|
|
58865
|
-
for (let item of obj)
|
|
58866
|
-
return
|
|
58966
|
+
let sum2 = 2;
|
|
58967
|
+
for (let item of obj) sum2 += estimateObjectChars(item) + 1;
|
|
58968
|
+
return sum2;
|
|
58867
58969
|
}
|
|
58868
58970
|
if (typeof obj == "object") {
|
|
58869
|
-
let
|
|
58971
|
+
let sum2 = 2;
|
|
58870
58972
|
for (let key of Object.keys(obj))
|
|
58871
|
-
|
|
58872
|
-
return
|
|
58973
|
+
sum2 += key.length + estimateObjectChars(obj[key]) + 2;
|
|
58974
|
+
return sum2;
|
|
58873
58975
|
}
|
|
58874
58976
|
return 10;
|
|
58875
58977
|
}
|
|
@@ -59119,9 +59221,9 @@ function escapeAttr(value) {
|
|
|
59119
59221
|
function renderInjectedFile(path, content) {
|
|
59120
59222
|
if (content === MISSING_FILE_SENTINEL)
|
|
59121
59223
|
return `<${INJECTED_TAG} path="${escapeAttr(path)}" missing="true"/>`;
|
|
59122
|
-
let
|
|
59224
|
+
let safe2 = content.split(`</${INJECTED_TAG}`).join(`<\\/${INJECTED_TAG}`);
|
|
59123
59225
|
return `<${INJECTED_TAG} path="${escapeAttr(path)}">
|
|
59124
|
-
${
|
|
59226
|
+
${safe2}
|
|
59125
59227
|
</${INJECTED_TAG}>`;
|
|
59126
59228
|
}
|
|
59127
59229
|
function collectInjectedFiles(sources, read, snapshot) {
|
|
@@ -59391,9 +59493,17 @@ var LLM_PRICING = {
|
|
|
59391
59493
|
}
|
|
59392
59494
|
};
|
|
59393
59495
|
function estimateLlmCallCostUsd(metadata) {
|
|
59394
|
-
|
|
59496
|
+
return estimateTokenCostUsd(metadata.model, {
|
|
59497
|
+
input: metadata.input_tokens,
|
|
59498
|
+
output: metadata.output_tokens,
|
|
59499
|
+
cache_read: metadata.cache_read_tokens,
|
|
59500
|
+
cache_write: metadata.cache_write_tokens
|
|
59501
|
+
});
|
|
59502
|
+
}
|
|
59503
|
+
function estimateTokenCostUsd(model, tokens) {
|
|
59504
|
+
let pricing = LLM_PRICING[model];
|
|
59395
59505
|
if (!pricing) return;
|
|
59396
|
-
let cacheRead =
|
|
59506
|
+
let cacheRead = tokens.cache_read ?? 0, cacheWrite = tokens.cache_write ?? 0, inputCost = Math.max(0, (tokens.input ?? 0) - cacheRead - cacheWrite) * pricing.input_per_million / 1e6, cacheCost = cacheRead * (pricing.cache_read_per_million ?? pricing.input_per_million) / 1e6 + cacheWrite * (pricing.cache_write_per_million ?? pricing.input_per_million) / 1e6, outputCost = (tokens.output ?? 0) * pricing.output_per_million / 1e6;
|
|
59397
59507
|
return Number((inputCost + cacheCost + outputCost).toFixed(8));
|
|
59398
59508
|
}
|
|
59399
59509
|
|
|
@@ -62182,8 +62292,8 @@ Retry error: ${String(retryError)}
|
|
|
62182
62292
|
let content = row.content;
|
|
62183
62293
|
if (!content) return result;
|
|
62184
62294
|
let lines = content.split(`
|
|
62185
|
-
`), totalLines = lines.length, totalChars = content.length,
|
|
62186
|
-
if (
|
|
62295
|
+
`), totalLines = lines.length, totalChars = content.length, approxTokens2 = Math.ceil(totalChars / 4), maxTokens = this.config.limits?.max_file_read_tokens ?? 3e4;
|
|
62296
|
+
if (approxTokens2 > maxTokens) {
|
|
62187
62297
|
let maxChars = maxTokens * 4, truncatedLines = content.slice(0, maxChars).split(`
|
|
62188
62298
|
`);
|
|
62189
62299
|
return truncatedLines.pop(), row.content = truncatedLines.join(`
|
|
@@ -62195,7 +62305,7 @@ Use start_line/end_line to read specific sections.`, { ...result, content: JSON.
|
|
|
62195
62305
|
if (totalLines > 300) {
|
|
62196
62306
|
let sizeStr = formatSize(Buffer.byteLength(content, "utf8")), preview = lines.slice(0, 50).join(`
|
|
62197
62307
|
`);
|
|
62198
|
-
return row.content = `[Large file: ${totalLines} lines, ${sizeStr}, ~${
|
|
62308
|
+
return row.content = `[Large file: ${totalLines} lines, ${sizeStr}, ~${approxTokens2.toLocaleString()} tokens]
|
|
62199
62309
|
Use start_line/end_line to read sections (e.g. start_line=1, end_line=100).
|
|
62200
62310
|
|
|
62201
62311
|
--- Preview (first 50 lines) ---
|
|
@@ -65339,12 +65449,134 @@ var execFileAsync = promisify2(execFile), IS_WIN = process.platform === "win32",
|
|
|
65339
65449
|
var inputSchema = external_exports.object({
|
|
65340
65450
|
name: external_exports.string().min(1).describe('npm package name (e.g. "lodash", "vega-lite", "@resvg/resvg-wasm")'),
|
|
65341
65451
|
version: external_exports.string().optional().describe('Semver version or range (e.g. "^5.30.0", "4.17.21"). Defaults to "latest".')
|
|
65342
|
-
})
|
|
65452
|
+
}), MAX_PACKAGES = 50, NpmInstallTool = class {
|
|
65453
|
+
constructor(packagesService, onPackageInstalled) {
|
|
65454
|
+
this.packagesService = packagesService;
|
|
65455
|
+
this.onPackageInstalled = onPackageInstalled;
|
|
65456
|
+
}
|
|
65457
|
+
packagesService;
|
|
65458
|
+
onPackageInstalled;
|
|
65459
|
+
name = "npm_install";
|
|
65460
|
+
description = 'Install an npm package for use in code execution (sys_code / sys_lambda). Pure JavaScript packages only \u2014 native addons are blocked. The package becomes available to import starting next turn. Example: npm_install({ name: "vega-lite", version: "^5.21.0" })';
|
|
65461
|
+
inputSchema = inputSchema;
|
|
65462
|
+
category = "system";
|
|
65463
|
+
async execute(input, workspace) {
|
|
65464
|
+
let { name: name21, version } = input, currentPackages = workspace.getAgentConfig().code_execution?.packages ?? [];
|
|
65465
|
+
if (currentPackages.length >= MAX_PACKAGES)
|
|
65466
|
+
return {
|
|
65467
|
+
content: JSON.stringify({
|
|
65468
|
+
success: !1,
|
|
65469
|
+
error: "package_limit",
|
|
65470
|
+
message: `Maximum ${MAX_PACKAGES} packages allowed. Remove unused packages with npm_uninstall first.`
|
|
65471
|
+
}),
|
|
65472
|
+
isError: !0
|
|
65473
|
+
};
|
|
65474
|
+
let existing = currentPackages.find((p) => p.name === name21);
|
|
65475
|
+
if (existing && version && existing.version === version)
|
|
65476
|
+
return {
|
|
65477
|
+
content: JSON.stringify({
|
|
65478
|
+
success: !0,
|
|
65479
|
+
name: name21,
|
|
65480
|
+
version: existing.version,
|
|
65481
|
+
already_installed: !0
|
|
65482
|
+
}),
|
|
65483
|
+
isError: !1
|
|
65484
|
+
};
|
|
65485
|
+
try {
|
|
65486
|
+
let agentName = workspace.getAgentConfig().name, result = await this.packagesService.install(name21, version, void 0, agentName), freshConfig = workspace.getAgentConfig(), packages = (freshConfig.code_execution?.packages ?? []).filter((p) => p.name !== name21);
|
|
65487
|
+
return packages.push({ name: name21, version: result.version }), workspace.setAgentConfig({
|
|
65488
|
+
...freshConfig,
|
|
65489
|
+
code_execution: {
|
|
65490
|
+
...freshConfig.code_execution,
|
|
65491
|
+
packages
|
|
65492
|
+
}
|
|
65493
|
+
}), this.onPackageInstalled?.(name21, result.version), {
|
|
65494
|
+
content: JSON.stringify({
|
|
65495
|
+
success: !0,
|
|
65496
|
+
name: name21,
|
|
65497
|
+
version: result.version,
|
|
65498
|
+
size_mb: result.size_mb,
|
|
65499
|
+
already_installed: result.already_installed
|
|
65500
|
+
}),
|
|
65501
|
+
isError: !1
|
|
65502
|
+
};
|
|
65503
|
+
} catch (error) {
|
|
65504
|
+
return error instanceof NativeAddonError ? {
|
|
65505
|
+
content: JSON.stringify({
|
|
65506
|
+
success: !1,
|
|
65507
|
+
error: "native_addon",
|
|
65508
|
+
message: "Package requires native code and cannot run in the sandbox."
|
|
65509
|
+
}),
|
|
65510
|
+
isError: !0
|
|
65511
|
+
} : error instanceof SizeLimitError ? {
|
|
65512
|
+
content: JSON.stringify({
|
|
65513
|
+
success: !1,
|
|
65514
|
+
error: "size_limit",
|
|
65515
|
+
message: error.message
|
|
65516
|
+
}),
|
|
65517
|
+
isError: !0
|
|
65518
|
+
} : {
|
|
65519
|
+
content: JSON.stringify({
|
|
65520
|
+
success: !1,
|
|
65521
|
+
error: "npm_error",
|
|
65522
|
+
message: String(error instanceof Error ? error.message : error)
|
|
65523
|
+
}),
|
|
65524
|
+
isError: !0
|
|
65525
|
+
};
|
|
65526
|
+
}
|
|
65527
|
+
}
|
|
65528
|
+
toProviderFormat() {
|
|
65529
|
+
return {
|
|
65530
|
+
name: this.name,
|
|
65531
|
+
description: this.description,
|
|
65532
|
+
input_schema: zodToJsonSchema(this.inputSchema)
|
|
65533
|
+
};
|
|
65534
|
+
}
|
|
65535
|
+
};
|
|
65343
65536
|
|
|
65344
65537
|
// src/main/tools/built-in/npm-uninstall.tool.ts
|
|
65345
65538
|
var inputSchema2 = external_exports.object({
|
|
65346
65539
|
name: external_exports.string().min(1).describe('npm package name to remove (e.g. "lodash")')
|
|
65347
|
-
})
|
|
65540
|
+
}), NpmUninstallTool = class {
|
|
65541
|
+
constructor(onPackageRemoved) {
|
|
65542
|
+
this.onPackageRemoved = onPackageRemoved;
|
|
65543
|
+
}
|
|
65544
|
+
onPackageRemoved;
|
|
65545
|
+
name = "npm_uninstall";
|
|
65546
|
+
description = "Remove an npm package from this agent's available packages. The package becomes unavailable to import starting next turn. Does not delete the package from disk (other agents may use it).";
|
|
65547
|
+
inputSchema = inputSchema2;
|
|
65548
|
+
category = "system";
|
|
65549
|
+
async execute(input, workspace) {
|
|
65550
|
+
let { name: name21 } = input, config = workspace.getAgentConfig(), packages = config.code_execution?.packages ?? [];
|
|
65551
|
+
if (packages.findIndex((p) => p.name === name21) === -1)
|
|
65552
|
+
return {
|
|
65553
|
+
content: JSON.stringify({
|
|
65554
|
+
success: !1,
|
|
65555
|
+
error: "not_found",
|
|
65556
|
+
message: `Package "${name21}" is not in this agent's installed packages.`
|
|
65557
|
+
}),
|
|
65558
|
+
isError: !0
|
|
65559
|
+
};
|
|
65560
|
+
let updated = packages.filter((p) => p.name !== name21);
|
|
65561
|
+
return workspace.setAgentConfig({
|
|
65562
|
+
...config,
|
|
65563
|
+
code_execution: {
|
|
65564
|
+
...config.code_execution,
|
|
65565
|
+
packages: updated
|
|
65566
|
+
}
|
|
65567
|
+
}), this.onPackageRemoved?.(name21), {
|
|
65568
|
+
content: JSON.stringify({ success: !0, name: name21 }),
|
|
65569
|
+
isError: !1
|
|
65570
|
+
};
|
|
65571
|
+
}
|
|
65572
|
+
toProviderFormat() {
|
|
65573
|
+
return {
|
|
65574
|
+
name: this.name,
|
|
65575
|
+
description: this.description,
|
|
65576
|
+
input_schema: zodToJsonSchema(this.inputSchema)
|
|
65577
|
+
};
|
|
65578
|
+
}
|
|
65579
|
+
};
|
|
65348
65580
|
|
|
65349
65581
|
// src/main/tools/built-in/fs-transfer.tool.ts
|
|
65350
65582
|
import {
|
|
@@ -66206,8 +66438,8 @@ function isHostPortFree(port2, host2) {
|
|
|
66206
66438
|
});
|
|
66207
66439
|
}
|
|
66208
66440
|
function isolatedContainerName(agentName, agentId) {
|
|
66209
|
-
let
|
|
66210
|
-
return `adf-${
|
|
66441
|
+
let safe2 = agentName.toLowerCase().replace(/[^a-z0-9]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 30), shortId = agentId.slice(0, 8);
|
|
66442
|
+
return `adf-${safe2 || shortId}-${shortId}`;
|
|
66211
66443
|
}
|
|
66212
66444
|
function containerWorkspacePath(isolated, agentId) {
|
|
66213
66445
|
return isolated ? "/workspace" : `/workspace/${agentId}`;
|
|
@@ -69821,6 +70053,8 @@ function assembleAgent(options) {
|
|
|
69821
70053
|
})));
|
|
69822
70054
|
}
|
|
69823
70055
|
adfCallHandler?.attachSession(session);
|
|
70056
|
+
let packageKeys = [workspace.getFilePath(), config.id].filter((key) => !!key), readAgentPackages = () => (workspace.getAgentConfig().code_execution?.packages ?? []).map((pkg) => pkg.name);
|
|
70057
|
+
codeSandboxService2?.setAgentPackageSource(packageKeys, readAgentPackages);
|
|
69824
70058
|
let preLlmHookRunner = codeSandboxService2 && adfCallHandler ? new PreLlmHookRunner(workspace, codeSandboxService2, adfCallHandler, config.id) : null, executor = new AgentExecutor(
|
|
69825
70059
|
config,
|
|
69826
70060
|
provider,
|
|
@@ -69842,7 +70076,7 @@ function assembleAgent(options) {
|
|
|
69842
70076
|
toolPrompts: options.toolPrompts ?? {},
|
|
69843
70077
|
compactionPrompt: options.compactionPrompt,
|
|
69844
70078
|
sources,
|
|
69845
|
-
sandboxModules: codeSandboxService2?.getUserPackageModules()
|
|
70079
|
+
sandboxModules: codeSandboxService2?.getUserPackageModules(packageKeys[0])
|
|
69846
70080
|
}));
|
|
69847
70081
|
};
|
|
69848
70082
|
refreshEffectiveRuntime(), options.effectiveRuntime && executor.setProviderChangeListener(() => refreshEffectiveRuntime()), options.systemScopeHandler && executor.setSystemScopeHandler(options.systemScopeHandler);
|
|
@@ -70087,7 +70321,7 @@ ${json2.slice(0, room)}${note}`;
|
|
|
70087
70321
|
};
|
|
70088
70322
|
syncLoopToolRegistration(config);
|
|
70089
70323
|
let sysUpdateTool = registry3.get("sys_update_config"), applyConfigChange = (updatedConfig, configOptions) => {
|
|
70090
|
-
if (stripLoopNameMarker(updatedConfig), rawConfig = updatedConfig, snapshotConfig = updatedConfig, executor.updateConfig(updatedConfig), triggerEvaluator.updateConfig(updatedConfig), adfCallHandler?.updateConfig(updatedConfig), syncLoopToolRegistration(updatedConfig), loopPool.reconcile(updatedConfig), refreshEffectiveRuntime(), configOptions?.notifyHost !== !1)
|
|
70324
|
+
if (stripLoopNameMarker(updatedConfig), rawConfig = updatedConfig, snapshotConfig = updatedConfig, executor.updateConfig(updatedConfig), triggerEvaluator.updateConfig(updatedConfig), adfCallHandler?.updateConfig(updatedConfig), syncLoopToolRegistration(updatedConfig), registry3.syncDeclared(updatedConfig.tools ?? []), loopPool.reconcile(updatedConfig), refreshEffectiveRuntime(), configOptions?.notifyHost !== !1)
|
|
70091
70325
|
for (let bindings of hostBindings()) bindings.onConfigChanged?.(updatedConfig);
|
|
70092
70326
|
}, sysUpdateOnConfigChanged = (updatedConfig) => {
|
|
70093
70327
|
applyConfigChange(updatedConfig);
|
|
@@ -70143,7 +70377,7 @@ ${json2.slice(0, room)}${note}`;
|
|
|
70143
70377
|
adapterManager?.off("inbound", onAdapterInbound);
|
|
70144
70378
|
} catch {
|
|
70145
70379
|
}
|
|
70146
|
-
executor.onToolCallIntercepted = void 0, executor.onTaskCreated = void 0, executor.onTaskCompleted = void 0, executor.onLlmCall = void 0, adfCallHandler && (adfCallHandler.onEvent = void 0, adfCallHandler.onTaskCompleted = void 0, adfCallHandler.onLambdaToolEndTurn = void 0, adfCallHandler.onHilApproved = void 0, adfCallHandler.requestProtectionApproval = void 0, adfCallHandler.onLlmCall = void 0), sysUpdateTool && sysUpdateTool.onConfigChanged === sysUpdateOnConfigChanged && (sysUpdateTool.onConfigChanged = void 0), createAdfTool && createAdfTool.onAutostartChild === createAdfOnAutostartChild && (createAdfTool.onAutostartChild = void 0), shellTool && (shellTool.onToolCallIntercepted === shellOnToolCallIntercepted && (shellTool.onToolCallIntercepted = void 0), shellTool.onApprovalRequired === shellOnApprovalRequired && (shellTool.onApprovalRequired = void 0), shellTool.onProtectionBlocked === shellOnProtectionBlocked && (shellTool.onProtectionBlocked = void 0)), activeHost = null, executor.removeAllListeners();
|
|
70380
|
+
codeSandboxService2?.clearAgentPackageSource(packageKeys, readAgentPackages), executor.onToolCallIntercepted = void 0, executor.onTaskCreated = void 0, executor.onTaskCompleted = void 0, executor.onLlmCall = void 0, adfCallHandler && (adfCallHandler.onEvent = void 0, adfCallHandler.onTaskCompleted = void 0, adfCallHandler.onLambdaToolEndTurn = void 0, adfCallHandler.onHilApproved = void 0, adfCallHandler.requestProtectionApproval = void 0, adfCallHandler.onLlmCall = void 0), sysUpdateTool && sysUpdateTool.onConfigChanged === sysUpdateOnConfigChanged && (sysUpdateTool.onConfigChanged = void 0), createAdfTool && createAdfTool.onAutostartChild === createAdfOnAutostartChild && (createAdfTool.onAutostartChild = void 0), shellTool && (shellTool.onToolCallIntercepted === shellOnToolCallIntercepted && (shellTool.onToolCallIntercepted = void 0), shellTool.onApprovalRequired === shellOnApprovalRequired && (shellTool.onApprovalRequired = void 0), shellTool.onProtectionBlocked === shellOnProtectionBlocked && (shellTool.onProtectionBlocked = void 0)), activeHost = null, executor.removeAllListeners();
|
|
70147
70381
|
}
|
|
70148
70382
|
}, teardownPromise = null, teardown = () => teardownPromise || (teardownPromise = (async () => {
|
|
70149
70383
|
try {
|
|
@@ -70348,7 +70582,7 @@ var Pipeline = class {
|
|
|
70348
70582
|
};
|
|
70349
70583
|
|
|
70350
70584
|
// src/main/crypto/message-crypto.ts
|
|
70351
|
-
import { hkdfSync as hkdfSync2, diffieHellman as diffieHellman2, createPrivateKey as
|
|
70585
|
+
import { hkdfSync as hkdfSync2, diffieHellman as diffieHellman2, createPrivateKey as createPrivateKey4, createPublicKey as createPublicKey4 } from "crypto";
|
|
70352
70586
|
|
|
70353
70587
|
// node_modules/@noble/hashes/utils.js
|
|
70354
70588
|
function isBytes(a) {
|
|
@@ -70452,12 +70686,12 @@ function kdfInputToBytes(data, errorTitle = "") {
|
|
|
70452
70686
|
return typeof data == "string" ? utf8ToBytes(data) : abytes(data, void 0, errorTitle);
|
|
70453
70687
|
}
|
|
70454
70688
|
function concatBytes(...arrays) {
|
|
70455
|
-
let
|
|
70689
|
+
let sum2 = 0;
|
|
70456
70690
|
for (let i = 0; i < arrays.length; i++) {
|
|
70457
70691
|
let a = arrays[i];
|
|
70458
|
-
abytes(a),
|
|
70692
|
+
abytes(a), sum2 += a.length;
|
|
70459
70693
|
}
|
|
70460
|
-
let res = new Uint8Array(
|
|
70694
|
+
let res = new Uint8Array(sum2);
|
|
70461
70695
|
for (let i = 0, pad = 0; i < arrays.length; i++) {
|
|
70462
70696
|
let a = arrays[i];
|
|
70463
70697
|
res.set(a, pad), pad += a.length;
|
|
@@ -71060,7 +71294,7 @@ function tonelliShanks(P) {
|
|
|
71060
71294
|
function FpSqrt(P) {
|
|
71061
71295
|
return P % _4n === _3n ? sqrt3mod4 : P % _8n === _5n ? sqrt5mod8 : P % _16n === _9n ? sqrt9mod16(P) : tonelliShanks(P);
|
|
71062
71296
|
}
|
|
71063
|
-
var isNegativeLE = (
|
|
71297
|
+
var isNegativeLE = (num2, modulo) => (mod(num2, modulo) & _1n2) === _1n2, FIELD_FIELDS = [
|
|
71064
71298
|
"create",
|
|
71065
71299
|
"isValid",
|
|
71066
71300
|
"is0",
|
|
@@ -71091,22 +71325,22 @@ function validateField(field) {
|
|
|
71091
71325
|
throw new Error("invalid field: expected ORDER > 1, got " + field.ORDER);
|
|
71092
71326
|
return field;
|
|
71093
71327
|
}
|
|
71094
|
-
function FpPow(Fp2,
|
|
71328
|
+
function FpPow(Fp2, num2, power) {
|
|
71095
71329
|
let F = Fp2;
|
|
71096
71330
|
if (power < _0n2)
|
|
71097
71331
|
throw new Error("invalid exponent, negatives unsupported");
|
|
71098
71332
|
if (power === _0n2)
|
|
71099
71333
|
return F.ONE;
|
|
71100
71334
|
if (power === _1n2)
|
|
71101
|
-
return
|
|
71102
|
-
let p = F.ONE, d =
|
|
71335
|
+
return num2;
|
|
71336
|
+
let p = F.ONE, d = num2;
|
|
71103
71337
|
for (; power > _0n2; )
|
|
71104
71338
|
power & _1n2 && (p = F.mul(p, d)), d = F.sqr(d), power >>= _1n2;
|
|
71105
71339
|
return p;
|
|
71106
71340
|
}
|
|
71107
71341
|
function FpInvertBatch(Fp2, nums, passZero = !1) {
|
|
71108
|
-
let F = Fp2, inverted = new Array(nums.length).fill(passZero ? F.ZERO : void 0), multipliedAcc = nums.reduce((acc,
|
|
71109
|
-
return nums.reduceRight((acc,
|
|
71342
|
+
let F = Fp2, inverted = new Array(nums.length).fill(passZero ? F.ZERO : void 0), multipliedAcc = nums.reduce((acc, num2, i) => F.is0(num2) ? acc : (inverted[i] = acc, F.mul(acc, num2)), F.ONE), invertedAcc = F.inv(multipliedAcc);
|
|
71343
|
+
return nums.reduceRight((acc, num2, i) => F.is0(num2) ? acc : (inverted[i] = F.mul(acc, inverted[i]), F.mul(acc, num2)), invertedAcc), inverted;
|
|
71110
71344
|
}
|
|
71111
71345
|
function FpLegendre(Fp2, n) {
|
|
71112
71346
|
let F = Fp2, p1mod2 = (F.ORDER - _1n2) / _2n, powered = F.pow(n, p1mod2), yes = F.eql(powered, F.ONE), zero = F.eql(powered, F.ZERO), no = F.eql(powered, F.neg(F.ONE));
|
|
@@ -71144,32 +71378,32 @@ var FIELD_SQRT = /* @__PURE__ */ new WeakMap(), _Field = class {
|
|
|
71144
71378
|
throw new Error("invalid field: expected ORDER of <= 2048 bytes");
|
|
71145
71379
|
this.ORDER = ORDER, this.BITS = nBitLength, this.BYTES = nByteLength, Object.freeze(this);
|
|
71146
71380
|
}
|
|
71147
|
-
create(
|
|
71148
|
-
return mod(
|
|
71381
|
+
create(num2) {
|
|
71382
|
+
return mod(num2, this.ORDER);
|
|
71149
71383
|
}
|
|
71150
|
-
isValid(
|
|
71151
|
-
if (typeof
|
|
71152
|
-
throw new TypeError("invalid field element: expected bigint, got " + typeof
|
|
71153
|
-
return _0n2 <=
|
|
71384
|
+
isValid(num2) {
|
|
71385
|
+
if (typeof num2 != "bigint")
|
|
71386
|
+
throw new TypeError("invalid field element: expected bigint, got " + typeof num2);
|
|
71387
|
+
return _0n2 <= num2 && num2 < this.ORDER;
|
|
71154
71388
|
}
|
|
71155
|
-
is0(
|
|
71156
|
-
return
|
|
71389
|
+
is0(num2) {
|
|
71390
|
+
return num2 === _0n2;
|
|
71157
71391
|
}
|
|
71158
71392
|
// is valid and invertible
|
|
71159
|
-
isValidNot0(
|
|
71160
|
-
return !this.is0(
|
|
71393
|
+
isValidNot0(num2) {
|
|
71394
|
+
return !this.is0(num2) && this.isValid(num2);
|
|
71161
71395
|
}
|
|
71162
|
-
isOdd(
|
|
71163
|
-
return (
|
|
71396
|
+
isOdd(num2) {
|
|
71397
|
+
return (num2 & _1n2) === _1n2;
|
|
71164
71398
|
}
|
|
71165
|
-
neg(
|
|
71166
|
-
return mod(-
|
|
71399
|
+
neg(num2) {
|
|
71400
|
+
return mod(-num2, this.ORDER);
|
|
71167
71401
|
}
|
|
71168
71402
|
eql(lhs, rhs) {
|
|
71169
71403
|
return lhs === rhs;
|
|
71170
71404
|
}
|
|
71171
|
-
sqr(
|
|
71172
|
-
return mod(
|
|
71405
|
+
sqr(num2) {
|
|
71406
|
+
return mod(num2 * num2, this.ORDER);
|
|
71173
71407
|
}
|
|
71174
71408
|
add(lhs, rhs) {
|
|
71175
71409
|
return mod(lhs + rhs, this.ORDER);
|
|
@@ -71180,15 +71414,15 @@ var FIELD_SQRT = /* @__PURE__ */ new WeakMap(), _Field = class {
|
|
|
71180
71414
|
mul(lhs, rhs) {
|
|
71181
71415
|
return mod(lhs * rhs, this.ORDER);
|
|
71182
71416
|
}
|
|
71183
|
-
pow(
|
|
71184
|
-
return FpPow(this,
|
|
71417
|
+
pow(num2, power) {
|
|
71418
|
+
return FpPow(this, num2, power);
|
|
71185
71419
|
}
|
|
71186
71420
|
div(lhs, rhs) {
|
|
71187
71421
|
return mod(lhs * invert(rhs, this.ORDER), this.ORDER);
|
|
71188
71422
|
}
|
|
71189
71423
|
// Same as above, but doesn't normalize
|
|
71190
|
-
sqrN(
|
|
71191
|
-
return
|
|
71424
|
+
sqrN(num2) {
|
|
71425
|
+
return num2 * num2;
|
|
71192
71426
|
}
|
|
71193
71427
|
addN(lhs, rhs) {
|
|
71194
71428
|
return lhs + rhs;
|
|
@@ -71199,15 +71433,15 @@ var FIELD_SQRT = /* @__PURE__ */ new WeakMap(), _Field = class {
|
|
|
71199
71433
|
mulN(lhs, rhs) {
|
|
71200
71434
|
return lhs * rhs;
|
|
71201
71435
|
}
|
|
71202
|
-
inv(
|
|
71203
|
-
return invert(
|
|
71436
|
+
inv(num2) {
|
|
71437
|
+
return invert(num2, this.ORDER);
|
|
71204
71438
|
}
|
|
71205
|
-
sqrt(
|
|
71439
|
+
sqrt(num2) {
|
|
71206
71440
|
let sqrt = FIELD_SQRT.get(this);
|
|
71207
|
-
return sqrt || FIELD_SQRT.set(this, sqrt = FpSqrt(this.ORDER)), sqrt(this,
|
|
71441
|
+
return sqrt || FIELD_SQRT.set(this, sqrt = FpSqrt(this.ORDER)), sqrt(this, num2);
|
|
71208
71442
|
}
|
|
71209
|
-
toBytes(
|
|
71210
|
-
return this.isLE ? numberToBytesLE(
|
|
71443
|
+
toBytes(num2) {
|
|
71444
|
+
return this.isLE ? numberToBytesLE(num2, this.BYTES) : numberToBytesBE(num2, this.BYTES);
|
|
71211
71445
|
}
|
|
71212
71446
|
fromBytes(bytes, skipValidation = !1) {
|
|
71213
71447
|
abytes2(bytes);
|
|
@@ -71999,8 +72233,8 @@ function encryptPayloadForDid(payload, recipientDid) {
|
|
|
71999
72233
|
return null;
|
|
72000
72234
|
}
|
|
72001
72235
|
let ephemeral = generateX25519KeyPair(), ephemeralPubRaw = extractRawX25519PublicKey(ephemeral.publicKey), sharedSecret = diffieHellman2({
|
|
72002
|
-
privateKey:
|
|
72003
|
-
publicKey:
|
|
72236
|
+
privateKey: createPrivateKey4({ key: ephemeral.privateKey, format: "der", type: "pkcs8" }),
|
|
72237
|
+
publicKey: createPublicKey4({ key: rawX25519PublicToSpki(recipientXPub), format: "der", type: "spki" })
|
|
72004
72238
|
}), key = deriveMessageKey(sharedSecret, ephemeralPubRaw), sealed = sealWithDek(Buffer.from(JSON.stringify(payload), "utf-8"), key), enc = { v: 1, alg: "x25519-hkdf-aes256gcm", epk: ephemeralPubRaw.toString("base64") };
|
|
72005
72239
|
return {
|
|
72006
72240
|
content: sealed.toString("base64"),
|
|
@@ -72016,8 +72250,8 @@ function decryptPayloadWithEd25519(payload, ed25519PrivatePkcs8) {
|
|
|
72016
72250
|
if (!isEncryptedPayload(payload) || typeof payload.content != "string") return null;
|
|
72017
72251
|
try {
|
|
72018
72252
|
let enc = payload.meta.enc, ephemeralPubRaw = Buffer.from(enc.epk, "base64"), xPriv = ed25519PrivateToX25519Pkcs8(ed25519PrivatePkcs8), sharedSecret = diffieHellman2({
|
|
72019
|
-
privateKey:
|
|
72020
|
-
publicKey:
|
|
72253
|
+
privateKey: createPrivateKey4({ key: xPriv, format: "der", type: "pkcs8" }),
|
|
72254
|
+
publicKey: createPublicKey4({ key: rawX25519PublicToSpki(ephemeralPubRaw), format: "der", type: "spki" })
|
|
72021
72255
|
}), key = deriveMessageKey(sharedSecret, ephemeralPubRaw), plain = openWithDek(Buffer.from(payload.content, "base64"), key);
|
|
72022
72256
|
return plain ? JSON.parse(plain.toString("utf-8")) : null;
|
|
72023
72257
|
} catch {
|
|
@@ -76448,9 +76682,7 @@ var ChannelAdapterManager = class extends EventEmitter7 {
|
|
|
76448
76682
|
}
|
|
76449
76683
|
return { ingested: state.ingested, deduped: state.deduped };
|
|
76450
76684
|
},
|
|
76451
|
-
writeAttachment: (path, data, mimeType) =>
|
|
76452
|
-
workspace.writeFileBuffer(path, data, mimeType);
|
|
76453
|
-
},
|
|
76685
|
+
writeAttachment: (path, data, mimeType) => workspace.writeFileBufferUnique(path, data, mimeType),
|
|
76454
76686
|
getConfig: () => config,
|
|
76455
76687
|
getCredential: (key) => workspace.getIdentityDecrypted(`adapter:${type}:${key}`, derivedKey) ?? null,
|
|
76456
76688
|
log: (level, message) => {
|
|
@@ -76528,11 +76760,11 @@ var ChannelAdapterManager = class extends EventEmitter7 {
|
|
|
76528
76760
|
|
|
76529
76761
|
// src/main/adapters/built-in-loaders.ts
|
|
76530
76762
|
var BUILT_IN_ADAPTER_LOADERS = {
|
|
76531
|
-
telegram: async () => (await import("./telegram-
|
|
76532
|
-
email: async () => (await import("./email-
|
|
76533
|
-
discord: async () => (await import("./discord-
|
|
76534
|
-
slack: async () => (await import("./slack-
|
|
76535
|
-
whatsapp: async () => (await import("./whatsapp-
|
|
76763
|
+
telegram: async () => (await import("./telegram-YI2OHNTD.mjs")).createAdapter,
|
|
76764
|
+
email: async () => (await import("./email-BRG7KUO2.mjs")).createAdapter,
|
|
76765
|
+
discord: async () => (await import("./discord-DSP4HUWI.mjs")).createAdapter,
|
|
76766
|
+
slack: async () => (await import("./slack-OCNNF4DX.mjs")).createAdapter,
|
|
76767
|
+
whatsapp: async () => (await import("./whatsapp-AVKT3CTJ.mjs")).createAdapter
|
|
76536
76768
|
};
|
|
76537
76769
|
async function loadBuiltInAdapter(adapterType) {
|
|
76538
76770
|
let loader = BUILT_IN_ADAPTER_LOADERS[adapterType];
|
|
@@ -76931,6 +77163,7 @@ function buildOAuthProviderFactory(resolveStore, io = SILENT_OAUTH_IO, resolveOp
|
|
|
76931
77163
|
var MCP_CONNECT_BUDGET_MS = 25e3, AgentRuntimeBuilder = class {
|
|
76932
77164
|
settings;
|
|
76933
77165
|
codeSandboxService;
|
|
77166
|
+
sandboxPackagesService;
|
|
76934
77167
|
podmanService;
|
|
76935
77168
|
wsConnectionManager;
|
|
76936
77169
|
mcpPackageResolver;
|
|
@@ -76943,7 +77176,7 @@ var MCP_CONNECT_BUDGET_MS = 25e3, AgentRuntimeBuilder = class {
|
|
|
76943
77176
|
mcpAuthPreflight;
|
|
76944
77177
|
credentialEnvelopeLockedHint;
|
|
76945
77178
|
constructor(opts = {}) {
|
|
76946
|
-
this.settings = opts.settings, this.codeSandboxService = opts.codeSandboxService ?? null, this.podmanService = opts.podmanService ?? null, this.wsConnectionManager = opts.wsConnectionManager ?? null, this.mcpPackageResolver = opts.mcpPackageResolver ?? new PackageResolver("mcp-servers"), this.adapterPackageResolver = opts.adapterPackageResolver ?? new PackageResolver("channel-adapters"), this.uvxPackageResolver = opts.uvxPackageResolver ?? null, this.uvManager = opts.uvManager ?? null, this.basePrompt = opts.basePrompt ?? "", this.toolPrompts = opts.toolPrompts ?? {}, this.compactionPrompt = opts.compactionPrompt, this.mcpAuthPreflight = opts.mcpAuthPreflight ?? createHeadlessMcpAuthPreflight(), this.credentialEnvelopeLockedHint = opts.credentialEnvelopeLockedHint;
|
|
77179
|
+
this.settings = opts.settings, this.codeSandboxService = opts.codeSandboxService ?? null, this.sandboxPackagesService = opts.sandboxPackagesService ?? null, this.podmanService = opts.podmanService ?? null, this.wsConnectionManager = opts.wsConnectionManager ?? null, this.mcpPackageResolver = opts.mcpPackageResolver ?? new PackageResolver("mcp-servers"), this.adapterPackageResolver = opts.adapterPackageResolver ?? new PackageResolver("channel-adapters"), this.uvxPackageResolver = opts.uvxPackageResolver ?? null, this.uvManager = opts.uvManager ?? null, this.basePrompt = opts.basePrompt ?? "", this.toolPrompts = opts.toolPrompts ?? {}, this.compactionPrompt = opts.compactionPrompt, this.mcpAuthPreflight = opts.mcpAuthPreflight ?? createHeadlessMcpAuthPreflight(), this.credentialEnvelopeLockedHint = opts.credentialEnvelopeLockedHint;
|
|
76947
77180
|
}
|
|
76948
77181
|
async build(opts) {
|
|
76949
77182
|
let { workspace, filePath, config, provider } = opts, agentId = filePath ?? config.id;
|
|
@@ -77118,17 +77351,21 @@ var MCP_CONNECT_BUDGET_MS = 25e3, AgentRuntimeBuilder = class {
|
|
|
77118
77351
|
});
|
|
77119
77352
|
}
|
|
77120
77353
|
registerCodeTools(registry3, config, agentId, adfCallHandler) {
|
|
77121
|
-
|
|
77122
|
-
|
|
77354
|
+
let sandbox = this.codeSandboxService;
|
|
77355
|
+
if (!sandbox) return;
|
|
77356
|
+
registry3.provideDeclared("sys_code", () => new SysCodeTool(
|
|
77357
|
+
sandbox,
|
|
77123
77358
|
agentId,
|
|
77124
77359
|
adfCallHandler ?? void 0,
|
|
77125
77360
|
config.limits?.execution_timeout_ms
|
|
77126
|
-
)), adfCallHandler &&
|
|
77127
|
-
|
|
77361
|
+
), config.tools), adfCallHandler && registry3.provideDeclared("sys_lambda", () => new SysLambdaTool(
|
|
77362
|
+
sandbox,
|
|
77128
77363
|
adfCallHandler,
|
|
77129
77364
|
agentId,
|
|
77130
77365
|
config.limits?.execution_timeout_ms
|
|
77131
|
-
))
|
|
77366
|
+
), config.tools);
|
|
77367
|
+
let packages = this.sandboxPackagesService;
|
|
77368
|
+
packages && (registry3.provideDeclared("npm_install", () => new NpmInstallTool(packages), config.tools), registry3.provideDeclared("npm_uninstall", () => new NpmUninstallTool(), config.tools));
|
|
77132
77369
|
}
|
|
77133
77370
|
registerComputeTools(registry3, config, filePath) {
|
|
77134
77371
|
let agentHostAllowed = !!config.compute?.host_access, computeSettings = this.settings?.get("compute"), runtimeHostAllowed = this.getComputeRoutingSettings().hostAccessEnabled, hostInfo = agentHostAllowed && runtimeHostAllowed ? describeHostEnv() : void 0, targetSelection = resolveAgentComputeTargetSelection(computeSettings, config.compute), caps = {
|
|
@@ -78747,6 +78984,26 @@ var RuntimeLoopError = class extends Error {
|
|
|
78747
78984
|
listAgents() {
|
|
78748
78985
|
return Array.from(this.agents.values()).map((managed) => this.toSummary(managed));
|
|
78749
78986
|
}
|
|
78987
|
+
/**
|
|
78988
|
+
* Loaded file-backed agents with their live executor state, context gauge
|
|
78989
|
+
* and open workspace. Agent vitals reads a running agent out of this
|
|
78990
|
+
* workspace instead of reopening its file.
|
|
78991
|
+
*/
|
|
78992
|
+
listLiveAgents() {
|
|
78993
|
+
let out = [];
|
|
78994
|
+
for (let managed of this.agents.values()) {
|
|
78995
|
+
if (!managed.filePath) continue;
|
|
78996
|
+
let executor = managed.agent.executor;
|
|
78997
|
+
out.push({
|
|
78998
|
+
agentId: managed.id,
|
|
78999
|
+
filePath: managed.filePath,
|
|
79000
|
+
executorState: executor.getState(),
|
|
79001
|
+
workspace: managed.agent.workspace,
|
|
79002
|
+
getContextGauge: () => executor.getContextGauge()
|
|
79003
|
+
});
|
|
79004
|
+
}
|
|
79005
|
+
return out;
|
|
79006
|
+
}
|
|
78750
79007
|
on(event, listener) {
|
|
78751
79008
|
return super.on(event, listener);
|
|
78752
79009
|
}
|
|
@@ -100700,45 +100957,67 @@ data: {"cursor":42,"event":{"seq":7,"event_type":"agent.state.changed","turn_id"
|
|
|
100700
100957
|
}
|
|
100701
100958
|
}
|
|
100702
100959
|
},
|
|
100703
|
-
"/agents/{id}/
|
|
100704
|
-
|
|
100960
|
+
"/agents/{id}/vitals": {
|
|
100961
|
+
get: {
|
|
100705
100962
|
tags: [
|
|
100706
100963
|
"Agents"
|
|
100707
100964
|
],
|
|
100708
|
-
summary: "
|
|
100709
|
-
description: "`id`
|
|
100710
|
-
operationId: "
|
|
100965
|
+
summary: "Agent vitals",
|
|
100966
|
+
description: "Studio's overview card for one agent: header facts (context size, next wake, 7-day cost, model, age) and four levelled stats: Reach, Access and Autonomy (levels from config points, with the factors behind them) and Experience (a level from maturity counts). `{id}` names a loaded agent (id, handle or name, as every /agents/{id} route) or, when no loaded agent matches, a tracked agent that is not loaded (agent id or handle from its file). A loaded agent is read from its open workspace (`live: true`); any other file is read with a readonly open. Results are cached: a live agent's for at most 2 s and until its database changes, any other file's until its mtime or size changes. `force=1` skips the cache. `agentsSpawned` counts tracked agents whose parent DID names this agent, from a fleet scan at most 30 s old (`force=1` rescans). `contextTokens` and `contextThreshold` are present only for a loaded agent whose executor has reported usage; `cost7dUsd` only when some adf_loop row of the last 7 local days has a price (the row's recorded `cost_usd`; rows from before 2026-08-27 without one are priced from Studio's pricing table).",
|
|
100967
|
+
operationId: "getAgentVitals",
|
|
100711
100968
|
parameters: [
|
|
100712
100969
|
{
|
|
100713
100970
|
$ref: "#/components/parameters/AgentIdPath"
|
|
100971
|
+
},
|
|
100972
|
+
{
|
|
100973
|
+
name: "force",
|
|
100974
|
+
in: "query",
|
|
100975
|
+
required: !1,
|
|
100976
|
+
description: "Skip the cache: `1` or `true`. `0` and `false` are accepted and change nothing.",
|
|
100977
|
+
schema: {
|
|
100978
|
+
type: "string",
|
|
100979
|
+
enum: [
|
|
100980
|
+
"1",
|
|
100981
|
+
"0",
|
|
100982
|
+
"true",
|
|
100983
|
+
"false"
|
|
100984
|
+
]
|
|
100985
|
+
}
|
|
100714
100986
|
}
|
|
100715
100987
|
],
|
|
100716
100988
|
responses: {
|
|
100717
100989
|
"200": {
|
|
100718
|
-
description: "
|
|
100990
|
+
description: "Vitals",
|
|
100719
100991
|
content: {
|
|
100720
100992
|
"application/json": {
|
|
100721
100993
|
schema: {
|
|
100722
|
-
$ref: "#/components/schemas/
|
|
100994
|
+
$ref: "#/components/schemas/AgentVitals"
|
|
100723
100995
|
}
|
|
100724
100996
|
}
|
|
100725
100997
|
}
|
|
100726
100998
|
},
|
|
100999
|
+
"400": {
|
|
101000
|
+
$ref: "#/components/responses/BadRequest"
|
|
101001
|
+
},
|
|
100727
101002
|
"401": {
|
|
100728
101003
|
$ref: "#/components/responses/Unauthorized"
|
|
100729
101004
|
},
|
|
100730
101005
|
"403": {
|
|
100731
|
-
$ref: "#/components/responses/
|
|
101006
|
+
$ref: "#/components/responses/Forbidden"
|
|
100732
101007
|
},
|
|
100733
101008
|
"404": {
|
|
100734
101009
|
$ref: "#/components/responses/NotFound"
|
|
100735
101010
|
},
|
|
100736
101011
|
"409": {
|
|
100737
|
-
description: "The
|
|
101012
|
+
description: "The agent is loaded without an .adf file; vitals are read from the file",
|
|
100738
101013
|
content: {
|
|
100739
101014
|
"application/json": {
|
|
100740
101015
|
schema: {
|
|
100741
|
-
$ref: "#/components/schemas/
|
|
101016
|
+
$ref: "#/components/schemas/ErrorResponse"
|
|
101017
|
+
},
|
|
101018
|
+
example: {
|
|
101019
|
+
error: "Agent has no .adf file; vitals are read from the file.",
|
|
101020
|
+
code: "conflict"
|
|
100742
101021
|
}
|
|
100743
101022
|
}
|
|
100744
101023
|
}
|
|
@@ -100749,30 +101028,48 @@ data: {"cursor":42,"event":{"seq":7,"event_type":"agent.state.changed","turn_id"
|
|
|
100749
101028
|
}
|
|
100750
101029
|
}
|
|
100751
101030
|
},
|
|
100752
|
-
"/agents/{id}/
|
|
100753
|
-
|
|
101031
|
+
"/agents/{id}/activity": {
|
|
101032
|
+
get: {
|
|
100754
101033
|
tags: [
|
|
100755
101034
|
"Agents"
|
|
100756
101035
|
],
|
|
100757
|
-
summary: "
|
|
100758
|
-
description: "
|
|
100759
|
-
operationId: "
|
|
101036
|
+
summary: "Agent activity",
|
|
101037
|
+
description: "The lower sections of Studio's agent overview: the next three timer wakes (raw lambda and input, or loop and prompt), 14 local days of messages and cost per day, and what the file holds (`mind/` files and skills with approximate tokens, `local_*` tables with rows). `{id}` resolves as in `GET /agents/{id}/vitals`. Everything is read from the .adf file. Messages per day: `adf_loop` rows of every role by `created_at`, plus compacted rows archived in `adf_audit` (metadata only, never the archived data): each archive's `entry_count` is spread evenly over an estimated span ending at its `created_at` and at most 24 h long, and days that include such counts have `estimated: true`. Cost per day: the sum of the day's priced loop rows; `costPartial` when some call had no recorded price or was compacted. The first read scans the window's loop rows once; later reads add only new rows. Skills follow the vitals rule: written more than 10 s after `adf_created_at`, `skills-registry.json` excluded. Cached like vitals (and per local day); `force=1` skips the cache. Pending approvals, asks and unread counts are not here: read `GET /agents/{id}/asks` and `GET /agents/{id}/inbox`.",
|
|
101038
|
+
operationId: "getAgentActivity",
|
|
100760
101039
|
parameters: [
|
|
100761
101040
|
{
|
|
100762
101041
|
$ref: "#/components/parameters/AgentIdPath"
|
|
101042
|
+
},
|
|
101043
|
+
{
|
|
101044
|
+
name: "force",
|
|
101045
|
+
in: "query",
|
|
101046
|
+
required: !1,
|
|
101047
|
+
description: "Skip the cache: `1` or `true`. `0` and `false` are accepted and change nothing.",
|
|
101048
|
+
schema: {
|
|
101049
|
+
type: "string",
|
|
101050
|
+
enum: [
|
|
101051
|
+
"1",
|
|
101052
|
+
"0",
|
|
101053
|
+
"true",
|
|
101054
|
+
"false"
|
|
101055
|
+
]
|
|
101056
|
+
}
|
|
100763
101057
|
}
|
|
100764
101058
|
],
|
|
100765
101059
|
responses: {
|
|
100766
101060
|
"200": {
|
|
100767
|
-
description: "
|
|
101061
|
+
description: "Activity",
|
|
100768
101062
|
content: {
|
|
100769
101063
|
"application/json": {
|
|
100770
101064
|
schema: {
|
|
100771
|
-
$ref: "#/components/schemas/
|
|
101065
|
+
$ref: "#/components/schemas/AgentActivity"
|
|
100772
101066
|
}
|
|
100773
101067
|
}
|
|
100774
101068
|
}
|
|
100775
101069
|
},
|
|
101070
|
+
"400": {
|
|
101071
|
+
$ref: "#/components/responses/BadRequest"
|
|
101072
|
+
},
|
|
100776
101073
|
"401": {
|
|
100777
101074
|
$ref: "#/components/responses/Unauthorized"
|
|
100778
101075
|
},
|
|
@@ -100782,20 +101079,34 @@ data: {"cursor":42,"event":{"seq":7,"event_type":"agent.state.changed","turn_id"
|
|
|
100782
101079
|
"404": {
|
|
100783
101080
|
$ref: "#/components/responses/NotFound"
|
|
100784
101081
|
},
|
|
101082
|
+
"409": {
|
|
101083
|
+
description: "The agent is loaded without an .adf file; activity is read from the file",
|
|
101084
|
+
content: {
|
|
101085
|
+
"application/json": {
|
|
101086
|
+
schema: {
|
|
101087
|
+
$ref: "#/components/schemas/ErrorResponse"
|
|
101088
|
+
},
|
|
101089
|
+
example: {
|
|
101090
|
+
error: "Agent has no .adf file; activity is read from the file.",
|
|
101091
|
+
code: "conflict"
|
|
101092
|
+
}
|
|
101093
|
+
}
|
|
101094
|
+
}
|
|
101095
|
+
},
|
|
100785
101096
|
"500": {
|
|
100786
101097
|
$ref: "#/components/responses/ServerError"
|
|
100787
101098
|
}
|
|
100788
101099
|
}
|
|
100789
101100
|
}
|
|
100790
101101
|
},
|
|
100791
|
-
"/agents/{id}/
|
|
101102
|
+
"/agents/{id}/start": {
|
|
100792
101103
|
post: {
|
|
100793
101104
|
tags: [
|
|
100794
101105
|
"Agents"
|
|
100795
101106
|
],
|
|
100796
|
-
summary: "
|
|
100797
|
-
description: "No body.",
|
|
100798
|
-
operationId: "
|
|
101107
|
+
summary: "Start an agent, loading it from a tracked folder when needed",
|
|
101108
|
+
description: "`id` may also name an agent that is not loaded: an .adf path, or an id / handle / name found in the tracked folders. The daemon loads it (review gate applies: 403) and starts it; `loaded` says whether it did. `startupTriggered` is true when the agent's start state fired its startup event. An identifier that matches several files answers 409 `ambiguous_agent` with the `candidates`: start one by its file path. No body.",
|
|
101109
|
+
operationId: "startAgent",
|
|
100799
101110
|
parameters: [
|
|
100800
101111
|
{
|
|
100801
101112
|
$ref: "#/components/parameters/AgentIdPath"
|
|
@@ -100803,11 +101114,11 @@ data: {"cursor":42,"event":{"seq":7,"event_type":"agent.state.changed","turn_id"
|
|
|
100803
101114
|
],
|
|
100804
101115
|
responses: {
|
|
100805
101116
|
"200": {
|
|
100806
|
-
description: "
|
|
101117
|
+
description: "Started",
|
|
100807
101118
|
content: {
|
|
100808
101119
|
"application/json": {
|
|
100809
101120
|
schema: {
|
|
100810
|
-
$ref: "#/components/schemas/
|
|
101121
|
+
$ref: "#/components/schemas/StartAgentResponse"
|
|
100811
101122
|
}
|
|
100812
101123
|
}
|
|
100813
101124
|
}
|
|
@@ -100816,51 +101127,86 @@ data: {"cursor":42,"event":{"seq":7,"event_type":"agent.state.changed","turn_id"
|
|
|
100816
101127
|
$ref: "#/components/responses/Unauthorized"
|
|
100817
101128
|
},
|
|
100818
101129
|
"403": {
|
|
100819
|
-
$ref: "#/components/responses/
|
|
101130
|
+
$ref: "#/components/responses/ReviewRequired"
|
|
100820
101131
|
},
|
|
100821
101132
|
"404": {
|
|
100822
101133
|
$ref: "#/components/responses/NotFound"
|
|
100823
101134
|
},
|
|
101135
|
+
"409": {
|
|
101136
|
+
description: "The identifier matches several agent files (`ambiguous_agent`)",
|
|
101137
|
+
content: {
|
|
101138
|
+
"application/json": {
|
|
101139
|
+
schema: {
|
|
101140
|
+
$ref: "#/components/schemas/AmbiguousAgentResponse"
|
|
101141
|
+
}
|
|
101142
|
+
}
|
|
101143
|
+
}
|
|
101144
|
+
},
|
|
100824
101145
|
"500": {
|
|
100825
101146
|
$ref: "#/components/responses/ServerError"
|
|
100826
101147
|
}
|
|
100827
101148
|
}
|
|
100828
101149
|
}
|
|
100829
101150
|
},
|
|
100830
|
-
"/agents/{id}/
|
|
101151
|
+
"/agents/{id}/stop": {
|
|
100831
101152
|
post: {
|
|
100832
101153
|
tags: [
|
|
100833
101154
|
"Agents"
|
|
100834
101155
|
],
|
|
100835
|
-
summary: "
|
|
100836
|
-
description: "
|
|
100837
|
-
operationId: "
|
|
101156
|
+
summary: "Stop and unload an agent",
|
|
101157
|
+
description: "Graceful: a running turn gets a 5 s grace period, then the agent is unloaded (its file stays on disk). No body.",
|
|
101158
|
+
operationId: "stopAgent",
|
|
100838
101159
|
parameters: [
|
|
100839
101160
|
{
|
|
100840
101161
|
$ref: "#/components/parameters/AgentIdPath"
|
|
100841
|
-
},
|
|
100842
|
-
{
|
|
100843
|
-
$ref: "#/components/parameters/LoopQuery"
|
|
100844
101162
|
}
|
|
100845
101163
|
],
|
|
100846
|
-
|
|
100847
|
-
|
|
100848
|
-
|
|
100849
|
-
|
|
100850
|
-
|
|
100851
|
-
|
|
100852
|
-
|
|
101164
|
+
responses: {
|
|
101165
|
+
"200": {
|
|
101166
|
+
description: "Stopped and unloaded",
|
|
101167
|
+
content: {
|
|
101168
|
+
"application/json": {
|
|
101169
|
+
schema: {
|
|
101170
|
+
$ref: "#/components/schemas/SuccessResponse"
|
|
101171
|
+
}
|
|
100853
101172
|
}
|
|
100854
101173
|
}
|
|
101174
|
+
},
|
|
101175
|
+
"401": {
|
|
101176
|
+
$ref: "#/components/responses/Unauthorized"
|
|
101177
|
+
},
|
|
101178
|
+
"403": {
|
|
101179
|
+
$ref: "#/components/responses/Forbidden"
|
|
101180
|
+
},
|
|
101181
|
+
"404": {
|
|
101182
|
+
$ref: "#/components/responses/NotFound"
|
|
101183
|
+
},
|
|
101184
|
+
"500": {
|
|
101185
|
+
$ref: "#/components/responses/ServerError"
|
|
100855
101186
|
}
|
|
100856
|
-
}
|
|
101187
|
+
}
|
|
101188
|
+
}
|
|
101189
|
+
},
|
|
101190
|
+
"/agents/{id}/unload": {
|
|
101191
|
+
post: {
|
|
101192
|
+
tags: [
|
|
101193
|
+
"Agents"
|
|
101194
|
+
],
|
|
101195
|
+
summary: "Unload an agent (alias of stop)",
|
|
101196
|
+
description: "No body.",
|
|
101197
|
+
operationId: "unloadAgent",
|
|
101198
|
+
parameters: [
|
|
101199
|
+
{
|
|
101200
|
+
$ref: "#/components/parameters/AgentIdPath"
|
|
101201
|
+
}
|
|
101202
|
+
],
|
|
100857
101203
|
responses: {
|
|
100858
101204
|
"200": {
|
|
100859
|
-
description: "
|
|
101205
|
+
description: "Unloaded",
|
|
100860
101206
|
content: {
|
|
100861
101207
|
"application/json": {
|
|
100862
101208
|
schema: {
|
|
100863
|
-
$ref: "#/components/schemas/
|
|
101209
|
+
$ref: "#/components/schemas/SuccessResponse"
|
|
100864
101210
|
}
|
|
100865
101211
|
}
|
|
100866
101212
|
}
|
|
@@ -100874,23 +101220,76 @@ data: {"cursor":42,"event":{"seq":7,"event_type":"agent.state.changed","turn_id"
|
|
|
100874
101220
|
"404": {
|
|
100875
101221
|
$ref: "#/components/responses/NotFound"
|
|
100876
101222
|
},
|
|
100877
|
-
"409": {
|
|
100878
|
-
$ref: "#/components/responses/Conflict"
|
|
100879
|
-
},
|
|
100880
101223
|
"500": {
|
|
100881
101224
|
$ref: "#/components/responses/ServerError"
|
|
100882
101225
|
}
|
|
100883
101226
|
}
|
|
100884
101227
|
}
|
|
100885
101228
|
},
|
|
100886
|
-
"/agents/{id}/
|
|
101229
|
+
"/agents/{id}/abort": {
|
|
100887
101230
|
post: {
|
|
100888
101231
|
tags: [
|
|
100889
101232
|
"Agents"
|
|
100890
101233
|
],
|
|
100891
|
-
summary: "
|
|
100892
|
-
description: "
|
|
100893
|
-
operationId: "
|
|
101234
|
+
summary: "Abort the current turn without unloading",
|
|
101235
|
+
description: "A hard stop: the executor of main (or the named inner loop) is left `stopped` and runs no further turns, triggers or timers until the agent is reloaded. To end a turn and keep working, use /interrupt. Chats still queued behind the turn are discarded, never silently: a `chat.discarded` event names their `turnId`s and a System notice lands in the loop. Unknown loop 404; a loop with no running executor 409.",
|
|
101236
|
+
operationId: "abortAgent",
|
|
101237
|
+
parameters: [
|
|
101238
|
+
{
|
|
101239
|
+
$ref: "#/components/parameters/AgentIdPath"
|
|
101240
|
+
},
|
|
101241
|
+
{
|
|
101242
|
+
$ref: "#/components/parameters/LoopQuery"
|
|
101243
|
+
}
|
|
101244
|
+
],
|
|
101245
|
+
requestBody: {
|
|
101246
|
+
required: !1,
|
|
101247
|
+
description: "Optional; `?loop=` wins.",
|
|
101248
|
+
content: {
|
|
101249
|
+
"application/json": {
|
|
101250
|
+
schema: {
|
|
101251
|
+
$ref: "#/components/schemas/LoopBody"
|
|
101252
|
+
}
|
|
101253
|
+
}
|
|
101254
|
+
}
|
|
101255
|
+
},
|
|
101256
|
+
responses: {
|
|
101257
|
+
"200": {
|
|
101258
|
+
description: "Aborted",
|
|
101259
|
+
content: {
|
|
101260
|
+
"application/json": {
|
|
101261
|
+
schema: {
|
|
101262
|
+
$ref: "#/components/schemas/AbortResponse"
|
|
101263
|
+
}
|
|
101264
|
+
}
|
|
101265
|
+
}
|
|
101266
|
+
},
|
|
101267
|
+
"401": {
|
|
101268
|
+
$ref: "#/components/responses/Unauthorized"
|
|
101269
|
+
},
|
|
101270
|
+
"403": {
|
|
101271
|
+
$ref: "#/components/responses/Forbidden"
|
|
101272
|
+
},
|
|
101273
|
+
"404": {
|
|
101274
|
+
$ref: "#/components/responses/NotFound"
|
|
101275
|
+
},
|
|
101276
|
+
"409": {
|
|
101277
|
+
$ref: "#/components/responses/Conflict"
|
|
101278
|
+
},
|
|
101279
|
+
"500": {
|
|
101280
|
+
$ref: "#/components/responses/ServerError"
|
|
101281
|
+
}
|
|
101282
|
+
}
|
|
101283
|
+
}
|
|
101284
|
+
},
|
|
101285
|
+
"/agents/{id}/interrupt": {
|
|
101286
|
+
post: {
|
|
101287
|
+
tags: [
|
|
101288
|
+
"Agents"
|
|
101289
|
+
],
|
|
101290
|
+
summary: "Interrupt the running turn and leave the loop idle",
|
|
101291
|
+
description: "Ends main's (or the named loop's) running turn and sets that executor idle; it keeps accepting chats, triggers and timers. Unlike /abort it never stops the executor, and chats queued behind the turn are kept and run next. `interrupted` is false when nothing was running; 409 when the loop is stopped or errored.",
|
|
101292
|
+
operationId: "interruptAgent",
|
|
100894
101293
|
parameters: [
|
|
100895
101294
|
{
|
|
100896
101295
|
$ref: "#/components/parameters/AgentIdPath"
|
|
@@ -117808,6 +118207,645 @@ data: {"cursor":42,"event":{"seq":7,"event_type":"agent.state.changed","turn_id"
|
|
|
117808
118207
|
}
|
|
117809
118208
|
]
|
|
117810
118209
|
}
|
|
118210
|
+
},
|
|
118211
|
+
AgentVitals: {
|
|
118212
|
+
type: "object",
|
|
118213
|
+
required: [
|
|
118214
|
+
"filePath",
|
|
118215
|
+
"computedAt",
|
|
118216
|
+
"live",
|
|
118217
|
+
"handle",
|
|
118218
|
+
"ageDays",
|
|
118219
|
+
"public",
|
|
118220
|
+
"ownerVerified",
|
|
118221
|
+
"stats",
|
|
118222
|
+
"maturity",
|
|
118223
|
+
"metrics"
|
|
118224
|
+
],
|
|
118225
|
+
properties: {
|
|
118226
|
+
filePath: {
|
|
118227
|
+
type: "string"
|
|
118228
|
+
},
|
|
118229
|
+
computedAt: {
|
|
118230
|
+
type: "number",
|
|
118231
|
+
description: "When the stats and counts were computed (ms epoch)"
|
|
118232
|
+
},
|
|
118233
|
+
live: {
|
|
118234
|
+
type: "boolean",
|
|
118235
|
+
description: "True when read from the workspace of a loaded agent"
|
|
118236
|
+
},
|
|
118237
|
+
handle: {
|
|
118238
|
+
type: "string",
|
|
118239
|
+
example: "agent-1"
|
|
118240
|
+
},
|
|
118241
|
+
name: {
|
|
118242
|
+
type: "string"
|
|
118243
|
+
},
|
|
118244
|
+
did: {
|
|
118245
|
+
type: "string"
|
|
118246
|
+
},
|
|
118247
|
+
agentId: {
|
|
118248
|
+
type: "string"
|
|
118249
|
+
},
|
|
118250
|
+
model: {
|
|
118251
|
+
type: "string"
|
|
118252
|
+
},
|
|
118253
|
+
createdAt: {
|
|
118254
|
+
type: "string",
|
|
118255
|
+
description: "adf_created_at (ISO 8601)"
|
|
118256
|
+
},
|
|
118257
|
+
ageDays: {
|
|
118258
|
+
type: "number"
|
|
118259
|
+
},
|
|
118260
|
+
status: {
|
|
118261
|
+
type: "string",
|
|
118262
|
+
description: "The agent's own status line (adf_meta `status`); absent when unset"
|
|
118263
|
+
},
|
|
118264
|
+
description: {
|
|
118265
|
+
type: "string",
|
|
118266
|
+
description: "config.description, as on the ALF card; absent when blank"
|
|
118267
|
+
},
|
|
118268
|
+
public: {
|
|
118269
|
+
type: "boolean",
|
|
118270
|
+
description: "config.serving.public.enabled, the ALF card's `public`"
|
|
118271
|
+
},
|
|
118272
|
+
ownerVerified: {
|
|
118273
|
+
type: "boolean",
|
|
118274
|
+
description: "An owner attestation about the current DID is stored, unexpired and its signature verifies (whether or not the card publishes it)"
|
|
118275
|
+
},
|
|
118276
|
+
contextTokens: {
|
|
118277
|
+
type: "integer",
|
|
118278
|
+
description: "Last API-reported context size (loaded agents only)"
|
|
118279
|
+
},
|
|
118280
|
+
contextThreshold: {
|
|
118281
|
+
type: "integer",
|
|
118282
|
+
description: "Compact threshold (present with contextTokens)"
|
|
118283
|
+
},
|
|
118284
|
+
nextWakeAt: {
|
|
118285
|
+
type: "number",
|
|
118286
|
+
description: "Earliest next_wake_at among non-expired timers (ms epoch)"
|
|
118287
|
+
},
|
|
118288
|
+
cost7dUsd: {
|
|
118289
|
+
type: "number",
|
|
118290
|
+
description: "USD over the last 7 local days, summed from the agent's priced adf_loop rows (the activity read's daily cost)"
|
|
118291
|
+
},
|
|
118292
|
+
cost7dPartial: {
|
|
118293
|
+
type: "boolean",
|
|
118294
|
+
description: "True when some calls in the window had no recorded price or were compacted (cost7dUsd is a lower bound)"
|
|
118295
|
+
},
|
|
118296
|
+
metrics: {
|
|
118297
|
+
type: "array",
|
|
118298
|
+
description: 'adf_meta rows whose key starts with `metric:`, by key, at most 20. A value is a plain string, or a JSON object `{"value": number|string, "label"?, "unit"?, "min"?, "max"?, "target"?}`; parsed fields are returned beside `raw`. A value that is not such an object is returned as `value` = `raw`. Not part of any stat.',
|
|
118299
|
+
items: {
|
|
118300
|
+
type: "object",
|
|
118301
|
+
required: [
|
|
118302
|
+
"name",
|
|
118303
|
+
"label",
|
|
118304
|
+
"value",
|
|
118305
|
+
"raw"
|
|
118306
|
+
],
|
|
118307
|
+
properties: {
|
|
118308
|
+
name: {
|
|
118309
|
+
type: "string",
|
|
118310
|
+
description: "Key without the `metric:` prefix",
|
|
118311
|
+
example: "weight"
|
|
118312
|
+
},
|
|
118313
|
+
label: {
|
|
118314
|
+
type: "string",
|
|
118315
|
+
description: "The object's `label` when given, else `name`",
|
|
118316
|
+
example: "Weight"
|
|
118317
|
+
},
|
|
118318
|
+
value: {
|
|
118319
|
+
oneOf: [
|
|
118320
|
+
{
|
|
118321
|
+
type: "number"
|
|
118322
|
+
},
|
|
118323
|
+
{
|
|
118324
|
+
type: "string"
|
|
118325
|
+
}
|
|
118326
|
+
],
|
|
118327
|
+
description: "The object's `value`, or the raw string when the stored value is not a metric object",
|
|
118328
|
+
example: 82.4
|
|
118329
|
+
},
|
|
118330
|
+
unit: {
|
|
118331
|
+
type: "string",
|
|
118332
|
+
example: "kg"
|
|
118333
|
+
},
|
|
118334
|
+
min: {
|
|
118335
|
+
type: "number",
|
|
118336
|
+
description: "Bar start when `max` is set (default 0)"
|
|
118337
|
+
},
|
|
118338
|
+
max: {
|
|
118339
|
+
type: "number",
|
|
118340
|
+
example: 100
|
|
118341
|
+
},
|
|
118342
|
+
target: {
|
|
118343
|
+
type: "number",
|
|
118344
|
+
example: 78
|
|
118345
|
+
},
|
|
118346
|
+
raw: {
|
|
118347
|
+
type: "string",
|
|
118348
|
+
description: "The stored adf_meta value as is",
|
|
118349
|
+
example: '{"value":82.4,"label":"Weight","unit":"kg","target":78}'
|
|
118350
|
+
}
|
|
118351
|
+
}
|
|
118352
|
+
}
|
|
118353
|
+
},
|
|
118354
|
+
stats: {
|
|
118355
|
+
type: "object",
|
|
118356
|
+
required: [
|
|
118357
|
+
"reach",
|
|
118358
|
+
"access",
|
|
118359
|
+
"autonomy",
|
|
118360
|
+
"experience"
|
|
118361
|
+
],
|
|
118362
|
+
properties: {
|
|
118363
|
+
reach: {
|
|
118364
|
+
$ref: "#/components/schemas/AgentPowerStat"
|
|
118365
|
+
},
|
|
118366
|
+
access: {
|
|
118367
|
+
$ref: "#/components/schemas/AgentPowerStat"
|
|
118368
|
+
},
|
|
118369
|
+
autonomy: {
|
|
118370
|
+
$ref: "#/components/schemas/AgentPowerStat"
|
|
118371
|
+
},
|
|
118372
|
+
experience: {
|
|
118373
|
+
$ref: "#/components/schemas/AgentExperienceStat"
|
|
118374
|
+
}
|
|
118375
|
+
}
|
|
118376
|
+
},
|
|
118377
|
+
maturity: {
|
|
118378
|
+
$ref: "#/components/schemas/AgentMaturity"
|
|
118379
|
+
}
|
|
118380
|
+
}
|
|
118381
|
+
},
|
|
118382
|
+
AgentPowerStat: {
|
|
118383
|
+
type: "object",
|
|
118384
|
+
description: "Reach, Access or Autonomy: a capped level on a 1-20 scale. fill = clamp(points / max, 0, 1); level = 1 + round(19 * fill), so an empty config is Lv 1 and a maxed-out one Lv 20. `max` is the sum of every capped positive factor of the stat (counts such as MCP servers and chat adapters only count their heaviest few). Gated points count toward the level. `points` is `open` + `gated`.",
|
|
118385
|
+
required: [
|
|
118386
|
+
"level",
|
|
118387
|
+
"points",
|
|
118388
|
+
"max",
|
|
118389
|
+
"fill",
|
|
118390
|
+
"open",
|
|
118391
|
+
"gated",
|
|
118392
|
+
"high",
|
|
118393
|
+
"rawPoints",
|
|
118394
|
+
"factors"
|
|
118395
|
+
],
|
|
118396
|
+
properties: {
|
|
118397
|
+
level: {
|
|
118398
|
+
type: "integer",
|
|
118399
|
+
minimum: 1,
|
|
118400
|
+
maximum: 20
|
|
118401
|
+
},
|
|
118402
|
+
points: {
|
|
118403
|
+
type: "number",
|
|
118404
|
+
minimum: 0,
|
|
118405
|
+
description: "Points behind the level, after mitigations"
|
|
118406
|
+
},
|
|
118407
|
+
max: {
|
|
118408
|
+
type: "number",
|
|
118409
|
+
exclusiveMinimum: 0,
|
|
118410
|
+
description: "Points of a maxed-out config for this stat"
|
|
118411
|
+
},
|
|
118412
|
+
fill: {
|
|
118413
|
+
type: "number",
|
|
118414
|
+
minimum: 0,
|
|
118415
|
+
maximum: 1,
|
|
118416
|
+
description: "points / max, clamped: how much of the possible power the agent has"
|
|
118417
|
+
},
|
|
118418
|
+
open: {
|
|
118419
|
+
type: "number",
|
|
118420
|
+
description: "Points whose capability runs without approval (mitigations come off these first)"
|
|
118421
|
+
},
|
|
118422
|
+
gated: {
|
|
118423
|
+
type: "number",
|
|
118424
|
+
description: "Points whose capability needs approval"
|
|
118425
|
+
},
|
|
118426
|
+
high: {
|
|
118427
|
+
type: "boolean",
|
|
118428
|
+
description: "True when open / max >= 0.6 (open level 12 or more): much of this runs without anyone asking"
|
|
118429
|
+
},
|
|
118430
|
+
rawPoints: {
|
|
118431
|
+
type: "number",
|
|
118432
|
+
description: "Sum of factor points, mitigations included"
|
|
118433
|
+
},
|
|
118434
|
+
factors: {
|
|
118435
|
+
type: "array",
|
|
118436
|
+
items: {
|
|
118437
|
+
$ref: "#/components/schemas/AgentStatFactor"
|
|
118438
|
+
}
|
|
118439
|
+
}
|
|
118440
|
+
}
|
|
118441
|
+
},
|
|
118442
|
+
AgentStatFactor: {
|
|
118443
|
+
type: "object",
|
|
118444
|
+
description: "One line of a stat breakdown.",
|
|
118445
|
+
required: [
|
|
118446
|
+
"id",
|
|
118447
|
+
"label",
|
|
118448
|
+
"points",
|
|
118449
|
+
"gated",
|
|
118450
|
+
"configPath"
|
|
118451
|
+
],
|
|
118452
|
+
properties: {
|
|
118453
|
+
id: {
|
|
118454
|
+
type: "string",
|
|
118455
|
+
description: "Stable id, e.g. `tool:compute_exec`, `mcp:github`, `visibility`",
|
|
118456
|
+
example: "tool:compute_exec"
|
|
118457
|
+
},
|
|
118458
|
+
label: {
|
|
118459
|
+
type: "string"
|
|
118460
|
+
},
|
|
118461
|
+
points: {
|
|
118462
|
+
type: "number",
|
|
118463
|
+
description: "Points this factor adds; negative for mitigations; 0 for an item past its kind's cap (7th MCP server, 4th chat adapter), listed but not counted"
|
|
118464
|
+
},
|
|
118465
|
+
gated: {
|
|
118466
|
+
type: "boolean",
|
|
118467
|
+
description: "True when the capability needs human approval"
|
|
118468
|
+
},
|
|
118469
|
+
configPath: {
|
|
118470
|
+
type: "string",
|
|
118471
|
+
description: "Config path (or table) that controls this factor"
|
|
118472
|
+
}
|
|
118473
|
+
}
|
|
118474
|
+
},
|
|
118475
|
+
AgentExperienceStat: {
|
|
118476
|
+
type: "object",
|
|
118477
|
+
description: "Experience. xpForLevel(L) = 5 * (L - 1)^2.25; level = largest L with xpForLevel(L) <= score.",
|
|
118478
|
+
required: [
|
|
118479
|
+
"level",
|
|
118480
|
+
"progress",
|
|
118481
|
+
"score",
|
|
118482
|
+
"levelStart",
|
|
118483
|
+
"nextLevelAt",
|
|
118484
|
+
"breakdown",
|
|
118485
|
+
"nextLevel"
|
|
118486
|
+
],
|
|
118487
|
+
properties: {
|
|
118488
|
+
level: {
|
|
118489
|
+
type: "integer",
|
|
118490
|
+
minimum: 1
|
|
118491
|
+
},
|
|
118492
|
+
progress: {
|
|
118493
|
+
type: "number",
|
|
118494
|
+
minimum: 0,
|
|
118495
|
+
maximum: 1,
|
|
118496
|
+
description: "Progress within the current level"
|
|
118497
|
+
},
|
|
118498
|
+
score: {
|
|
118499
|
+
type: "number",
|
|
118500
|
+
description: "Total XP (sum of signal XP)"
|
|
118501
|
+
},
|
|
118502
|
+
levelStart: {
|
|
118503
|
+
type: "number",
|
|
118504
|
+
description: "XP at which the current level starts"
|
|
118505
|
+
},
|
|
118506
|
+
nextLevelAt: {
|
|
118507
|
+
type: "number",
|
|
118508
|
+
description: "XP at which the next level starts"
|
|
118509
|
+
},
|
|
118510
|
+
breakdown: {
|
|
118511
|
+
type: "array",
|
|
118512
|
+
items: {
|
|
118513
|
+
type: "object",
|
|
118514
|
+
required: [
|
|
118515
|
+
"id",
|
|
118516
|
+
"label",
|
|
118517
|
+
"value",
|
|
118518
|
+
"xp"
|
|
118519
|
+
],
|
|
118520
|
+
properties: {
|
|
118521
|
+
id: {
|
|
118522
|
+
type: "string",
|
|
118523
|
+
enum: [
|
|
118524
|
+
"contextsWorked",
|
|
118525
|
+
"memoryTokens",
|
|
118526
|
+
"skills",
|
|
118527
|
+
"localTables",
|
|
118528
|
+
"localRows",
|
|
118529
|
+
"filesWritten",
|
|
118530
|
+
"agentsSpawned",
|
|
118531
|
+
"messages",
|
|
118532
|
+
"ageDays"
|
|
118533
|
+
]
|
|
118534
|
+
},
|
|
118535
|
+
label: {
|
|
118536
|
+
type: "string"
|
|
118537
|
+
},
|
|
118538
|
+
value: {
|
|
118539
|
+
type: "number",
|
|
118540
|
+
description: "Raw count"
|
|
118541
|
+
},
|
|
118542
|
+
xp: {
|
|
118543
|
+
type: "number",
|
|
118544
|
+
description: "XP this signal adds"
|
|
118545
|
+
}
|
|
118546
|
+
}
|
|
118547
|
+
}
|
|
118548
|
+
},
|
|
118549
|
+
nextLevel: {
|
|
118550
|
+
type: "object",
|
|
118551
|
+
description: "What one more level takes (xp = nextLevelAt - score), in units of the cheapest signals",
|
|
118552
|
+
required: [
|
|
118553
|
+
"xp",
|
|
118554
|
+
"contexts",
|
|
118555
|
+
"memoryTokens",
|
|
118556
|
+
"skills",
|
|
118557
|
+
"hint"
|
|
118558
|
+
],
|
|
118559
|
+
properties: {
|
|
118560
|
+
xp: {
|
|
118561
|
+
type: "number"
|
|
118562
|
+
},
|
|
118563
|
+
contexts: {
|
|
118564
|
+
type: "integer",
|
|
118565
|
+
description: "Contexts of work worth the remaining XP"
|
|
118566
|
+
},
|
|
118567
|
+
memoryTokens: {
|
|
118568
|
+
type: "integer",
|
|
118569
|
+
description: "Memory tokens worth the remaining XP"
|
|
118570
|
+
},
|
|
118571
|
+
skills: {
|
|
118572
|
+
type: "integer",
|
|
118573
|
+
description: "Skills worth the remaining XP"
|
|
118574
|
+
},
|
|
118575
|
+
hint: {
|
|
118576
|
+
type: "string"
|
|
118577
|
+
}
|
|
118578
|
+
}
|
|
118579
|
+
}
|
|
118580
|
+
}
|
|
118581
|
+
},
|
|
118582
|
+
AgentMaturity: {
|
|
118583
|
+
type: "object",
|
|
118584
|
+
description: "Raw maturity counts read from the agent's file.",
|
|
118585
|
+
required: [
|
|
118586
|
+
"contextsWorked",
|
|
118587
|
+
"filesWritten",
|
|
118588
|
+
"memoryTokens",
|
|
118589
|
+
"localTables",
|
|
118590
|
+
"localRows",
|
|
118591
|
+
"skills",
|
|
118592
|
+
"agentsSpawned",
|
|
118593
|
+
"messages",
|
|
118594
|
+
"ageDays"
|
|
118595
|
+
],
|
|
118596
|
+
properties: {
|
|
118597
|
+
contextsWorked: {
|
|
118598
|
+
type: "number",
|
|
118599
|
+
minimum: 0,
|
|
118600
|
+
description: "Contexts of work over every loop (main, side, deleted): archived loop snapshots in adf_audit (one context at half the loop's compaction threshold or more, else its share) or live compaction summaries when loop audit is off, plus each live loop's current fill as a 0..1 share of its compaction threshold"
|
|
118601
|
+
},
|
|
118602
|
+
filesWritten: {
|
|
118603
|
+
type: "integer",
|
|
118604
|
+
description: "adf_files rows changed after the agent was created, `mind/` excluded"
|
|
118605
|
+
},
|
|
118606
|
+
memoryTokens: {
|
|
118607
|
+
type: "integer",
|
|
118608
|
+
description: "Approximate tokens in `mind/` files: total bytes, less the seeded `mind/log.md` header, / 4"
|
|
118609
|
+
},
|
|
118610
|
+
localTables: {
|
|
118611
|
+
type: "integer",
|
|
118612
|
+
description: "`local_*` tables"
|
|
118613
|
+
},
|
|
118614
|
+
localRows: {
|
|
118615
|
+
type: "integer",
|
|
118616
|
+
description: "Rows across `local_*` tables (the first 50 by name)"
|
|
118617
|
+
},
|
|
118618
|
+
skills: {
|
|
118619
|
+
type: "integer",
|
|
118620
|
+
description: "Distinct skills the agent installed or changed"
|
|
118621
|
+
},
|
|
118622
|
+
agentsSpawned: {
|
|
118623
|
+
type: [
|
|
118624
|
+
"integer",
|
|
118625
|
+
"null"
|
|
118626
|
+
],
|
|
118627
|
+
description: "Tracked agents whose adf_parent_did names this agent; null when no fleet scan has run"
|
|
118628
|
+
},
|
|
118629
|
+
messages: {
|
|
118630
|
+
type: "integer",
|
|
118631
|
+
description: "Loop messages ever written, every loop current and past (adf_loop's shared AUTOINCREMENT high-water mark; compaction, clears and loop deletion do not lower it)"
|
|
118632
|
+
},
|
|
118633
|
+
ageDays: {
|
|
118634
|
+
type: "number",
|
|
118635
|
+
description: "Days since adf_created_at"
|
|
118636
|
+
}
|
|
118637
|
+
}
|
|
118638
|
+
},
|
|
118639
|
+
AgentActivity: {
|
|
118640
|
+
type: "object",
|
|
118641
|
+
required: [
|
|
118642
|
+
"filePath",
|
|
118643
|
+
"computedAt",
|
|
118644
|
+
"live",
|
|
118645
|
+
"upcoming",
|
|
118646
|
+
"daily",
|
|
118647
|
+
"contents"
|
|
118648
|
+
],
|
|
118649
|
+
properties: {
|
|
118650
|
+
filePath: {
|
|
118651
|
+
type: "string"
|
|
118652
|
+
},
|
|
118653
|
+
computedAt: {
|
|
118654
|
+
type: "number",
|
|
118655
|
+
description: "When this read was computed (ms epoch)"
|
|
118656
|
+
},
|
|
118657
|
+
live: {
|
|
118658
|
+
type: "boolean",
|
|
118659
|
+
description: "True when read from the workspace of a loaded agent"
|
|
118660
|
+
},
|
|
118661
|
+
upcoming: {
|
|
118662
|
+
type: "array",
|
|
118663
|
+
maxItems: 3,
|
|
118664
|
+
description: "Next non-expired timers, soonest first",
|
|
118665
|
+
items: {
|
|
118666
|
+
$ref: "#/components/schemas/AgentUpcomingWake"
|
|
118667
|
+
}
|
|
118668
|
+
},
|
|
118669
|
+
daily: {
|
|
118670
|
+
type: "array",
|
|
118671
|
+
minItems: 14,
|
|
118672
|
+
maxItems: 14,
|
|
118673
|
+
description: "14 local days, oldest first; the last is today",
|
|
118674
|
+
items: {
|
|
118675
|
+
$ref: "#/components/schemas/AgentActivityDay"
|
|
118676
|
+
}
|
|
118677
|
+
},
|
|
118678
|
+
contents: {
|
|
118679
|
+
type: "object",
|
|
118680
|
+
description: "What the file holds, in three groups. Tokens are approximate (bytes / 4, rounded) and given for mind and skills only: table data is rarely read into context.",
|
|
118681
|
+
required: [
|
|
118682
|
+
"mind",
|
|
118683
|
+
"skills",
|
|
118684
|
+
"tables"
|
|
118685
|
+
],
|
|
118686
|
+
properties: {
|
|
118687
|
+
mind: {
|
|
118688
|
+
type: "object",
|
|
118689
|
+
description: "Files under mind/",
|
|
118690
|
+
required: [
|
|
118691
|
+
"files",
|
|
118692
|
+
"tokens",
|
|
118693
|
+
"updatedThisWeek",
|
|
118694
|
+
"strata"
|
|
118695
|
+
],
|
|
118696
|
+
properties: {
|
|
118697
|
+
files: {
|
|
118698
|
+
type: "integer"
|
|
118699
|
+
},
|
|
118700
|
+
tokens: {
|
|
118701
|
+
type: "integer",
|
|
118702
|
+
description: "SUM(size) / 4, rounded, the seeded mind/log.md header taken off that file"
|
|
118703
|
+
},
|
|
118704
|
+
updatedThisWeek: {
|
|
118705
|
+
type: "integer",
|
|
118706
|
+
description: "mind/ files whose updated_at is within the last 7 days"
|
|
118707
|
+
},
|
|
118708
|
+
strata: {
|
|
118709
|
+
type: "object",
|
|
118710
|
+
description: "Current mind/ tokens (size / 4, rounded, the seeded mind/log.md header taken off that file) split by each file's updated_at. A boundary belongs to the younger band.",
|
|
118711
|
+
required: [
|
|
118712
|
+
"older",
|
|
118713
|
+
"quarter",
|
|
118714
|
+
"month",
|
|
118715
|
+
"week"
|
|
118716
|
+
],
|
|
118717
|
+
properties: {
|
|
118718
|
+
older: {
|
|
118719
|
+
type: "integer",
|
|
118720
|
+
description: "Last updated more than 90 days ago"
|
|
118721
|
+
},
|
|
118722
|
+
quarter: {
|
|
118723
|
+
type: "integer",
|
|
118724
|
+
description: "Last updated more than 30 and at most 90 days ago"
|
|
118725
|
+
},
|
|
118726
|
+
month: {
|
|
118727
|
+
type: "integer",
|
|
118728
|
+
description: "Last updated more than 7 and at most 30 days ago"
|
|
118729
|
+
},
|
|
118730
|
+
week: {
|
|
118731
|
+
type: "integer",
|
|
118732
|
+
description: "Last updated at most 7 days ago"
|
|
118733
|
+
}
|
|
118734
|
+
}
|
|
118735
|
+
}
|
|
118736
|
+
}
|
|
118737
|
+
},
|
|
118738
|
+
skills: {
|
|
118739
|
+
type: "object",
|
|
118740
|
+
description: "Skills the agent installed or changed (the Experience stat rule)",
|
|
118741
|
+
required: [
|
|
118742
|
+
"count",
|
|
118743
|
+
"tokens"
|
|
118744
|
+
],
|
|
118745
|
+
properties: {
|
|
118746
|
+
count: {
|
|
118747
|
+
type: "integer"
|
|
118748
|
+
},
|
|
118749
|
+
tokens: {
|
|
118750
|
+
type: "integer",
|
|
118751
|
+
description: "Size of every file under those skills' directories / 4; registry entries without files add 0"
|
|
118752
|
+
}
|
|
118753
|
+
}
|
|
118754
|
+
},
|
|
118755
|
+
tables: {
|
|
118756
|
+
type: "object",
|
|
118757
|
+
description: "local_* tables (at most 50 read)",
|
|
118758
|
+
required: [
|
|
118759
|
+
"count",
|
|
118760
|
+
"rows"
|
|
118761
|
+
],
|
|
118762
|
+
properties: {
|
|
118763
|
+
count: {
|
|
118764
|
+
type: "integer",
|
|
118765
|
+
maximum: 50
|
|
118766
|
+
},
|
|
118767
|
+
rows: {
|
|
118768
|
+
type: "integer",
|
|
118769
|
+
description: "Total rows"
|
|
118770
|
+
}
|
|
118771
|
+
}
|
|
118772
|
+
}
|
|
118773
|
+
}
|
|
118774
|
+
}
|
|
118775
|
+
}
|
|
118776
|
+
},
|
|
118777
|
+
AgentUpcomingWake: {
|
|
118778
|
+
type: "object",
|
|
118779
|
+
description: "One timer due soon, as raw pieces. `system` timers carry `lambda` and `input`; `agent` timers carry `loop` and `prompt`. Both texts are the timer payload as stored, cut to 1000 characters (ending in an ellipsis).",
|
|
118780
|
+
required: [
|
|
118781
|
+
"id",
|
|
118782
|
+
"at",
|
|
118783
|
+
"scope"
|
|
118784
|
+
],
|
|
118785
|
+
properties: {
|
|
118786
|
+
id: {
|
|
118787
|
+
type: "integer"
|
|
118788
|
+
},
|
|
118789
|
+
at: {
|
|
118790
|
+
type: "number",
|
|
118791
|
+
description: "next_wake_at (ms epoch)"
|
|
118792
|
+
},
|
|
118793
|
+
scope: {
|
|
118794
|
+
type: "string",
|
|
118795
|
+
enum: [
|
|
118796
|
+
"system",
|
|
118797
|
+
"agent"
|
|
118798
|
+
],
|
|
118799
|
+
description: "`system` runs a lambda; `agent` wakes a loop"
|
|
118800
|
+
},
|
|
118801
|
+
lambda: {
|
|
118802
|
+
type: "string",
|
|
118803
|
+
description: "system: lambda reference, e.g. `lib/sync.ts:run`"
|
|
118804
|
+
},
|
|
118805
|
+
input: {
|
|
118806
|
+
type: "string",
|
|
118807
|
+
maxLength: 1e3,
|
|
118808
|
+
description: "system: payload passed to the lambda"
|
|
118809
|
+
},
|
|
118810
|
+
loop: {
|
|
118811
|
+
type: "string",
|
|
118812
|
+
description: "agent: loop the wake dispatches to (`main` when the timer names none)"
|
|
118813
|
+
},
|
|
118814
|
+
prompt: {
|
|
118815
|
+
type: "string",
|
|
118816
|
+
maxLength: 1e3,
|
|
118817
|
+
description: "agent: payload the loop wakes with"
|
|
118818
|
+
}
|
|
118819
|
+
}
|
|
118820
|
+
},
|
|
118821
|
+
AgentActivityDay: {
|
|
118822
|
+
type: "object",
|
|
118823
|
+
required: [
|
|
118824
|
+
"date",
|
|
118825
|
+
"messages"
|
|
118826
|
+
],
|
|
118827
|
+
properties: {
|
|
118828
|
+
date: {
|
|
118829
|
+
type: "string",
|
|
118830
|
+
description: "Local YYYY-MM-DD"
|
|
118831
|
+
},
|
|
118832
|
+
messages: {
|
|
118833
|
+
type: "integer",
|
|
118834
|
+
description: "adf_loop rows of every role created that day, plus the day's estimated share of compacted rows archived in adf_audit"
|
|
118835
|
+
},
|
|
118836
|
+
estimated: {
|
|
118837
|
+
type: "boolean",
|
|
118838
|
+
description: "Some of the day's messages are compacted history whose timing is estimated (spread evenly over a span ending at the archive's creation)"
|
|
118839
|
+
},
|
|
118840
|
+
costUsd: {
|
|
118841
|
+
type: "number",
|
|
118842
|
+
description: "USD of the day's priced adf_loop rows (cost_usd in the row's usage record); absent when none had a price"
|
|
118843
|
+
},
|
|
118844
|
+
costPartial: {
|
|
118845
|
+
type: "boolean",
|
|
118846
|
+
description: "Some calls that day had no recorded price, or were compacted (their cost is not recorded); costUsd is a lower bound"
|
|
118847
|
+
}
|
|
118848
|
+
}
|
|
117811
118849
|
}
|
|
117812
118850
|
}
|
|
117813
118851
|
}
|
|
@@ -117837,7 +118875,7 @@ import { createHash as createHash6 } from "crypto";
|
|
|
117837
118875
|
import { dirname as dirname16, join as join35, resolve as resolve12 } from "path";
|
|
117838
118876
|
|
|
117839
118877
|
// src/main/crypto/mnemonic-identity.ts
|
|
117840
|
-
import { createHmac, createPrivateKey as
|
|
118878
|
+
import { createHmac, createPrivateKey as createPrivateKey5, createPublicKey as createPublicKey5 } from "crypto";
|
|
117841
118879
|
|
|
117842
118880
|
// node_modules/@noble/hashes/hmac.js
|
|
117843
118881
|
var _HMAC = class {
|
|
@@ -118073,16 +119111,16 @@ function convertRadix2(data, from, to, padding2) {
|
|
|
118073
119111
|
return padding2 && pos > 0 && res.push(carry >>> 0), res;
|
|
118074
119112
|
}
|
|
118075
119113
|
// @__NO_SIDE_EFFECTS__
|
|
118076
|
-
function radix(
|
|
118077
|
-
anumber3(
|
|
119114
|
+
function radix(num2) {
|
|
119115
|
+
anumber3(num2);
|
|
118078
119116
|
let _256 = 2 ** 8;
|
|
118079
119117
|
return {
|
|
118080
119118
|
encode: (bytes) => {
|
|
118081
119119
|
if (!isBytes3(bytes))
|
|
118082
119120
|
throw new TypeError("radix.encode input should be Uint8Array");
|
|
118083
|
-
return convertRadix(Array.from(bytes), _256,
|
|
119121
|
+
return convertRadix(Array.from(bytes), _256, num2);
|
|
118084
119122
|
},
|
|
118085
|
-
decode: (digits) => (anumArr("radix.decode", digits), Uint8Array.from(convertRadix(digits,
|
|
119123
|
+
decode: (digits) => (anumArr("radix.decode", digits), Uint8Array.from(convertRadix(digits, num2, _256)))
|
|
118086
119124
|
};
|
|
118087
119125
|
}
|
|
118088
119126
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -118109,8 +119147,8 @@ function checksum(len, fn) {
|
|
|
118109
119147
|
encode(data) {
|
|
118110
119148
|
if (!isBytes3(data))
|
|
118111
119149
|
throw new TypeError("checksum.encode: input should be Uint8Array");
|
|
118112
|
-
let
|
|
118113
|
-
return res.set(data), res.set(
|
|
119150
|
+
let sum2 = _fn(data).slice(0, len), res = new Uint8Array(data.length + len);
|
|
119151
|
+
return res.set(data), res.set(sum2, data.length), res;
|
|
118114
119152
|
},
|
|
118115
119153
|
decode(data) {
|
|
118116
119154
|
if (!isBytes3(data))
|
|
@@ -120276,11 +121314,11 @@ function rawEd25519SeedToPkcs8(seed32) {
|
|
|
120276
121314
|
return Buffer.concat([header, seed32]);
|
|
120277
121315
|
}
|
|
120278
121316
|
function deriveOwnerIdentity(mnemonic) {
|
|
120279
|
-
let seed = mnemonicToSeed(mnemonic), { key } = slip10DeriveEd25519(seed, OWNER_KEY_PATH), privateKeyPkcs8 = rawEd25519SeedToPkcs8(key), keyObject =
|
|
121317
|
+
let seed = mnemonicToSeed(mnemonic), { key } = slip10DeriveEd25519(seed, OWNER_KEY_PATH), privateKeyPkcs8 = rawEd25519SeedToPkcs8(key), keyObject = createPrivateKey5({ key: privateKeyPkcs8, format: "der", type: "pkcs8" }), publicKeySpki = createPublicKey5(keyObject).export({ format: "der", type: "spki" }), did = publicKeyToDid(extractRawPublicKey(Buffer.from(publicKeySpki)));
|
|
120280
121318
|
return { privateKeyPkcs8, publicKeySpki: Buffer.from(publicKeySpki), did };
|
|
120281
121319
|
}
|
|
120282
121320
|
function deriveOwnerEncryptionKey(mnemonic) {
|
|
120283
|
-
let seed = mnemonicToSeed(mnemonic), { key } = slip10DeriveEd25519(seed, OWNER_ENCRYPTION_KEY_PATH), privateKeyPkcs8 = rawX25519PrivateToPkcs8(key), keyObject =
|
|
121321
|
+
let seed = mnemonicToSeed(mnemonic), { key } = slip10DeriveEd25519(seed, OWNER_ENCRYPTION_KEY_PATH), privateKeyPkcs8 = rawX25519PrivateToPkcs8(key), keyObject = createPrivateKey5({ key: privateKeyPkcs8, format: "der", type: "pkcs8" }), publicKeySpki = createPublicKey5(keyObject).export({ format: "der", type: "spki" });
|
|
120284
121322
|
return { privateKeyPkcs8, publicKeyRaw: extractRawX25519PublicKey(Buffer.from(publicKeySpki)) };
|
|
120285
121323
|
}
|
|
120286
121324
|
|
|
@@ -120291,13 +121329,13 @@ import { join as join34 } from "path";
|
|
|
120291
121329
|
// src/main/daemon/daemon-enc-key.ts
|
|
120292
121330
|
import { chmodSync as chmodSync2, existsSync as existsSync18, mkdirSync as mkdirSync14, readFileSync as readFileSync12, writeFileSync as writeFileSync13 } from "fs";
|
|
120293
121331
|
import { join as join33 } from "path";
|
|
120294
|
-
import { createHash as createHash5, createPrivateKey as
|
|
121332
|
+
import { createHash as createHash5, createPrivateKey as createPrivateKey6, createPublicKey as createPublicKey6 } from "crypto";
|
|
120295
121333
|
var KEY_FILENAME = "runtime-enc-key";
|
|
120296
121334
|
function daemonEncKeyLabel(publicKeyRaw) {
|
|
120297
121335
|
return `daemon:${createHash5("sha256").update(publicKeyRaw).digest("hex").slice(0, 16)}`;
|
|
120298
121336
|
}
|
|
120299
121337
|
function publicFromPrivate(privateKeyPkcs8) {
|
|
120300
|
-
let pub =
|
|
121338
|
+
let pub = createPublicKey6(createPrivateKey6({ key: privateKeyPkcs8, format: "der", type: "pkcs8" }));
|
|
120301
121339
|
return extractRawX25519PublicKey(pub.export({ format: "der", type: "spki" }));
|
|
120302
121340
|
}
|
|
120303
121341
|
function ensureDaemonEncKey(settingsDir) {
|
|
@@ -120723,6 +121761,11 @@ var OWNER_SEED_DERIVED_KEY = "ownerDidSeedDerived", OwnerIdentityService = class
|
|
|
120723
121761
|
* a stripped-identity file is untrusted (anyone can strip and reshare), and
|
|
120724
121762
|
* stamping our owner DID into it before the user accepts review would make
|
|
120725
121763
|
* rejection meaningless. Minting happens on review-accept instead.
|
|
121764
|
+
*
|
|
121765
|
+
* adoptKeys: when keys are minted, store this pair instead of a fresh one
|
|
121766
|
+
* (an identity draft from the create screen). Everything else is the same
|
|
121767
|
+
* as a fresh mint: envelopes, sealing, stamps, attestations. Ignored when
|
|
121768
|
+
* the file already has signing keys, so it can never replace an identity.
|
|
120726
121769
|
*/
|
|
120727
121770
|
ensureWorkspaceIdentity(workspace, opts = {}) {
|
|
120728
121771
|
if (workspace.isPasswordProtected())
|
|
@@ -120739,7 +121782,7 @@ var OWNER_SEED_DERIVED_KEY = "ownerDidSeedDerived", OwnerIdentityService = class
|
|
|
120739
121782
|
runtimePrivateKey: this.getRuntimeSigningKey()
|
|
120740
121783
|
});
|
|
120741
121784
|
}, signingRow = workspace.getIdentityRow("crypto:signing:private_key");
|
|
120742
|
-
signingRow === null ? (workspace.generateIdentityKeys(null), keysGenerated = !0, stampAndAttest()) : signingRow.encryption_algo === "plain" && workspace.getDid() && !workspace.getMeta("adf_owner_did") && this.getOwnerSigningKey() && stampAndAttest();
|
|
121785
|
+
signingRow === null ? (workspace.generateIdentityKeys(null, opts.adoptKeys), keysGenerated = !0, stampAndAttest()) : signingRow.encryption_algo === "plain" && workspace.getDid() && !workspace.getMeta("adf_owner_did") && this.getOwnerSigningKey() && stampAndAttest();
|
|
120743
121786
|
let sealed = workspace.sealPlainRowsIntoEnvelopes();
|
|
120744
121787
|
return { keysGenerated, sealed };
|
|
120745
121788
|
}
|
|
@@ -122174,8 +123217,1323 @@ function fail(reply, err) {
|
|
|
122174
123217
|
return err instanceof RuntimeLoopError ? reply.code(err.statusCode).send({ ...err.details ?? {}, error: err.message, code: err.code ?? (err.statusCode === 404 ? "not_found" : err.statusCode === 409 ? "conflict" : err.statusCode === 502 ? "upstream_error" : "bad_request") }) : reply.code(500).send({ error: err instanceof Error ? err.message : String(err) });
|
|
122175
123218
|
}
|
|
122176
123219
|
|
|
123220
|
+
// src/main/services/agent-vitals.ts
|
|
123221
|
+
import { promises as fsp4, statSync as statSync10 } from "fs";
|
|
123222
|
+
|
|
123223
|
+
// src/shared/types/agent-vitals.types.ts
|
|
123224
|
+
var MEMORY_STRATA_DAYS = { week: 7, month: 30, quarter: 90 };
|
|
123225
|
+
|
|
123226
|
+
// src/shared/utils/agent-stats.ts
|
|
123227
|
+
var EXPERIENCE_CURVE = { scale: 5, exponent: 2.25 }, POWER_LEVEL_MAX = 20, POWER_HIGH_OPEN_SHARE = 0.6;
|
|
123228
|
+
function powerLevel(points, max) {
|
|
123229
|
+
return 1 + Math.round((POWER_LEVEL_MAX - 1) * powerFill(points, max));
|
|
123230
|
+
}
|
|
123231
|
+
function powerFill(points, max) {
|
|
123232
|
+
return !(max > 0) || !Number.isFinite(points) ? 0 : Math.min(1, Math.max(0, points / max));
|
|
123233
|
+
}
|
|
123234
|
+
function xpForLevel(level, curve) {
|
|
123235
|
+
return level > 1 ? curve.scale * (level - 1) ** curve.exponent : 0;
|
|
123236
|
+
}
|
|
123237
|
+
function levelForXp(xp, curve) {
|
|
123238
|
+
if (!(xp > 0) || !Number.isFinite(xp)) return 1;
|
|
123239
|
+
let level = 1 + Math.floor((xp / curve.scale) ** (1 / curve.exponent));
|
|
123240
|
+
for (; xpForLevel(level + 1, curve) <= xp; ) level++;
|
|
123241
|
+
for (; level > 1 && xpForLevel(level, curve) > xp; ) level--;
|
|
123242
|
+
return level;
|
|
123243
|
+
}
|
|
123244
|
+
function levelPosition(xp, curve) {
|
|
123245
|
+
let x = Number.isFinite(xp) && xp > 0 ? xp : 0, level = levelForXp(x, curve), levelStart = xpForLevel(level, curve), nextLevelAt = xpForLevel(level + 1, curve), progress = Math.min(1, Math.max(0, (x - levelStart) / (nextLevelAt - levelStart)));
|
|
123246
|
+
return { level, progress, levelStart, nextLevelAt };
|
|
123247
|
+
}
|
|
123248
|
+
var ACCESS_TOOL_POINTS = {
|
|
123249
|
+
fs_read: { points: 0.25, label: "Reads its own files" },
|
|
123250
|
+
fs_write: { points: 0.25, label: "Writes its own files" },
|
|
123251
|
+
fs_delete: { points: 0.25, label: "Deletes its own files" },
|
|
123252
|
+
sys_code: { points: 0.5, label: "Runs code in the sandbox" },
|
|
123253
|
+
sys_lambda: { points: 0.25, label: "Runs stored lambdas" },
|
|
123254
|
+
sys_fetch: { points: 0.5, label: "Fetches URLs over HTTP" },
|
|
123255
|
+
db_execute: { points: 0.25, label: "Writes to its database tables" },
|
|
123256
|
+
adf_shell: { points: 0.5, label: "Runs shell commands in its workspace" },
|
|
123257
|
+
ws_connect: { points: 0.5, label: "Opens WebSocket connections" },
|
|
123258
|
+
stream_bind: { points: 0.5, label: "Binds network streams" },
|
|
123259
|
+
fs_transfer: { points: 0.5, label: "Transfers files to other agents" },
|
|
123260
|
+
mcp_install: { points: 1, label: "Installs MCP servers" },
|
|
123261
|
+
compute_exec: { points: 1, label: "Runs commands on compute targets" }
|
|
123262
|
+
}, ACCESS_POINTS = {
|
|
123263
|
+
mcpServer: 0.5,
|
|
123264
|
+
mcpCredentials: 0.25,
|
|
123265
|
+
/** Servers that count: the heaviest (server + credentials) six; open first on a tie. */
|
|
123266
|
+
mcpServerCap: 6,
|
|
123267
|
+
npmPackage: 0.25,
|
|
123268
|
+
npmPackageCap: 1,
|
|
123269
|
+
codeNetwork: 1,
|
|
123270
|
+
computeEnabled: 0.5,
|
|
123271
|
+
hostAccess: 2,
|
|
123272
|
+
computeHostTarget: 1.5,
|
|
123273
|
+
credential: 0.25,
|
|
123274
|
+
credentialCap: 1.5,
|
|
123275
|
+
privateKeyPlain: 1,
|
|
123276
|
+
privateKeySealed: 0.5
|
|
123277
|
+
}, VISIBILITY_POINTS = {
|
|
123278
|
+
off: 0,
|
|
123279
|
+
directory: 0.5,
|
|
123280
|
+
localhost: 1,
|
|
123281
|
+
lan: 2,
|
|
123282
|
+
public: 4
|
|
123283
|
+
}, REACH_POINTS = {
|
|
123284
|
+
sendProactive: 1,
|
|
123285
|
+
sendRespondOnly: 0.5,
|
|
123286
|
+
publicPage: 3,
|
|
123287
|
+
apiRoute: 0.5,
|
|
123288
|
+
apiRouteCap: 3,
|
|
123289
|
+
sharedFiles: 1,
|
|
123290
|
+
adapter: 2.5,
|
|
123291
|
+
adapterRestrictedDm: 1,
|
|
123292
|
+
/** Adapters that count: the heaviest three. */
|
|
123293
|
+
adapterCap: 3,
|
|
123294
|
+
wsConnection: 0.5,
|
|
123295
|
+
wsConnectionCap: 2,
|
|
123296
|
+
/** Mitigation: messages must be signed. */
|
|
123297
|
+
signedOnly: -0.5
|
|
123298
|
+
}, AUTONOMY_POINTS = {
|
|
123299
|
+
autonomous: 3,
|
|
123300
|
+
autostart: 2,
|
|
123301
|
+
timers: 1,
|
|
123302
|
+
timerFast: 2,
|
|
123303
|
+
// fastest interval <= 5 min
|
|
123304
|
+
timerHourly: 1,
|
|
123305
|
+
// fastest interval <= 1 h
|
|
123306
|
+
trigger: 0.25,
|
|
123307
|
+
triggerCap: 1.5,
|
|
123308
|
+
proactive: 0.5,
|
|
123309
|
+
createAgents: 3,
|
|
123310
|
+
updateConfig: 1,
|
|
123311
|
+
sideLoop: 0.5,
|
|
123312
|
+
sideLoopCap: 1.5,
|
|
123313
|
+
/** Mitigation per enabled restricted tool. */
|
|
123314
|
+
restrictedTool: -0.25,
|
|
123315
|
+
restrictedToolCap: -1
|
|
123316
|
+
}, sum = (ns) => ns.reduce((s, n) => s + n, 0), POWER_MAX = {
|
|
123317
|
+
access: sum(Object.values(ACCESS_TOOL_POINTS).map((t) => t.points)) + ACCESS_POINTS.computeHostTarget + ACCESS_POINTS.computeEnabled + ACCESS_POINTS.hostAccess + ACCESS_POINTS.codeNetwork + ACCESS_POINTS.npmPackageCap + ACCESS_POINTS.mcpServerCap * (ACCESS_POINTS.mcpServer + ACCESS_POINTS.mcpCredentials) + ACCESS_POINTS.credentialCap + Math.max(ACCESS_POINTS.privateKeyPlain, ACCESS_POINTS.privateKeySealed),
|
|
123318
|
+
reach: Math.max(...Object.values(VISIBILITY_POINTS)) + Math.max(REACH_POINTS.sendProactive, REACH_POINTS.sendRespondOnly) + REACH_POINTS.publicPage + REACH_POINTS.apiRouteCap + REACH_POINTS.sharedFiles + REACH_POINTS.adapterCap * Math.max(REACH_POINTS.adapter, REACH_POINTS.adapterRestrictedDm) + REACH_POINTS.wsConnectionCap,
|
|
123319
|
+
autonomy: AUTONOMY_POINTS.autonomous + AUTONOMY_POINTS.autostart + AUTONOMY_POINTS.timers + Math.max(AUTONOMY_POINTS.timerFast, AUTONOMY_POINTS.timerHourly) + AUTONOMY_POINTS.triggerCap + AUTONOMY_POINTS.proactive + AUTONOMY_POINTS.createAgents + AUTONOMY_POINTS.updateConfig + AUTONOMY_POINTS.sideLoopCap
|
|
123320
|
+
};
|
|
123321
|
+
function toPowerStat(factors, max) {
|
|
123322
|
+
let open3 = 0, gated = 0, mitigation = 0;
|
|
123323
|
+
for (let f of factors)
|
|
123324
|
+
f.points < 0 ? mitigation += f.points : f.gated ? gated += f.points : open3 += f.points;
|
|
123325
|
+
open3 += mitigation, open3 < 0 && (gated = Math.max(0, gated + open3), open3 = 0);
|
|
123326
|
+
let points = open3 + gated, rawPoints = factors.reduce((s, f) => s + f.points, 0);
|
|
123327
|
+
return {
|
|
123328
|
+
level: powerLevel(points, max),
|
|
123329
|
+
points,
|
|
123330
|
+
max,
|
|
123331
|
+
fill: powerFill(points, max),
|
|
123332
|
+
open: open3,
|
|
123333
|
+
gated,
|
|
123334
|
+
high: powerFill(open3, max) >= POWER_HIGH_OPEN_SHARE,
|
|
123335
|
+
rawPoints,
|
|
123336
|
+
factors
|
|
123337
|
+
};
|
|
123338
|
+
}
|
|
123339
|
+
function countedIndices(items, cap, weight, gated) {
|
|
123340
|
+
let order = items.map((t, i) => ({ i, w: weight(t), g: gated(t) })).sort((a, b) => b.w - a.w || Number(a.g) - Number(b.g) || a.i - b.i);
|
|
123341
|
+
return new Set(order.slice(0, cap).map((o) => o.i));
|
|
123342
|
+
}
|
|
123343
|
+
function toolMap(inputs) {
|
|
123344
|
+
let map = /* @__PURE__ */ new Map();
|
|
123345
|
+
for (let t of inputs.tools) t.enabled && map.set(t.name, { restricted: !!t.restricted });
|
|
123346
|
+
return map;
|
|
123347
|
+
}
|
|
123348
|
+
function plural(n, one, many = `${one}s`) {
|
|
123349
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
123350
|
+
}
|
|
123351
|
+
function formatInterval(ms) {
|
|
123352
|
+
return ms < 6e4 ? `${Math.round(ms / 1e3)}s` : ms < 36e5 ? `${Math.round(ms / 6e4)} min` : `${Math.round(ms / 36e5)} h`;
|
|
123353
|
+
}
|
|
123354
|
+
function scoreAccess(inputs) {
|
|
123355
|
+
let tools = toolMap(inputs), factors = [];
|
|
123356
|
+
for (let [name21, def] of Object.entries(ACCESS_TOOL_POINTS)) {
|
|
123357
|
+
let t = tools.get(name21);
|
|
123358
|
+
t && factors.push({
|
|
123359
|
+
id: `tool:${name21}`,
|
|
123360
|
+
label: t.restricted ? `${def.label} (needs approval)` : def.label,
|
|
123361
|
+
points: def.points,
|
|
123362
|
+
gated: t.restricted,
|
|
123363
|
+
configPath: `tools.${name21}`
|
|
123364
|
+
});
|
|
123365
|
+
}
|
|
123366
|
+
let exec2 = tools.get("compute_exec");
|
|
123367
|
+
exec2 && inputs.compute.allowedTargets.includes("host") && factors.push({
|
|
123368
|
+
id: "compute:host_target",
|
|
123369
|
+
label: "Runs commands on the host machine",
|
|
123370
|
+
points: ACCESS_POINTS.computeHostTarget,
|
|
123371
|
+
gated: exec2.restricted,
|
|
123372
|
+
configPath: "compute.allowed_targets"
|
|
123373
|
+
}), inputs.compute.enabled && factors.push({
|
|
123374
|
+
id: "compute:enabled",
|
|
123375
|
+
label: "Has its own compute container",
|
|
123376
|
+
points: ACCESS_POINTS.computeEnabled,
|
|
123377
|
+
gated: !1,
|
|
123378
|
+
configPath: "compute.enabled"
|
|
123379
|
+
}), inputs.compute.hostAccess && factors.push({
|
|
123380
|
+
id: "compute:host_access",
|
|
123381
|
+
label: "May run MCP servers on the host machine",
|
|
123382
|
+
points: ACCESS_POINTS.hostAccess,
|
|
123383
|
+
gated: !1,
|
|
123384
|
+
configPath: "compute.host_access"
|
|
123385
|
+
}), inputs.codeNetwork && factors.push({
|
|
123386
|
+
id: "code:network",
|
|
123387
|
+
label: "Sandbox code has direct network access",
|
|
123388
|
+
points: ACCESS_POINTS.codeNetwork,
|
|
123389
|
+
gated: !1,
|
|
123390
|
+
configPath: "code_execution.network"
|
|
123391
|
+
}), inputs.npmPackageCount > 0 && factors.push({
|
|
123392
|
+
id: "code:packages",
|
|
123393
|
+
label: `${plural(inputs.npmPackageCount, "npm package")} installed`,
|
|
123394
|
+
points: Math.min(ACCESS_POINTS.npmPackageCap, inputs.npmPackageCount * ACCESS_POINTS.npmPackage),
|
|
123395
|
+
gated: !1,
|
|
123396
|
+
configPath: "code_execution.packages"
|
|
123397
|
+
});
|
|
123398
|
+
let countedMcp = countedIndices(
|
|
123399
|
+
inputs.mcpServers,
|
|
123400
|
+
ACCESS_POINTS.mcpServerCap,
|
|
123401
|
+
(s) => ACCESS_POINTS.mcpServer + (s.hasCredentials ? ACCESS_POINTS.mcpCredentials : 0),
|
|
123402
|
+
(s) => s.restricted
|
|
123403
|
+
);
|
|
123404
|
+
inputs.mcpServers.forEach((s, i) => {
|
|
123405
|
+
let counts = countedMcp.has(i);
|
|
123406
|
+
factors.push({
|
|
123407
|
+
id: `mcp:${s.name}`,
|
|
123408
|
+
label: s.restricted ? `MCP server ${s.name} (tools need approval)` : `MCP server ${s.name}`,
|
|
123409
|
+
points: counts ? ACCESS_POINTS.mcpServer : 0,
|
|
123410
|
+
gated: s.restricted,
|
|
123411
|
+
configPath: "mcp.servers"
|
|
123412
|
+
}), s.hasCredentials && factors.push({
|
|
123413
|
+
id: `mcp:${s.name}:credentials`,
|
|
123414
|
+
label: `MCP server ${s.name} holds credentials`,
|
|
123415
|
+
points: counts ? ACCESS_POINTS.mcpCredentials : 0,
|
|
123416
|
+
gated: s.restricted,
|
|
123417
|
+
configPath: "mcp.servers"
|
|
123418
|
+
});
|
|
123419
|
+
});
|
|
123420
|
+
let credBudget = ACCESS_POINTS.credentialCap, credPoints = (n) => {
|
|
123421
|
+
let p = Math.min(credBudget, n * ACCESS_POINTS.credential);
|
|
123422
|
+
return credBudget -= p, p;
|
|
123423
|
+
};
|
|
123424
|
+
return inputs.credentials.plain > 0 && factors.push({
|
|
123425
|
+
id: "identity:credentials_plain",
|
|
123426
|
+
label: `${plural(inputs.credentials.plain, "stored credential")}, unsealed`,
|
|
123427
|
+
points: credPoints(inputs.credentials.plain),
|
|
123428
|
+
gated: !1,
|
|
123429
|
+
configPath: "adf_identity"
|
|
123430
|
+
}), inputs.credentials.sealed > 0 && factors.push({
|
|
123431
|
+
id: "identity:credentials_sealed",
|
|
123432
|
+
label: `${plural(inputs.credentials.sealed, "stored credential")}, sealed`,
|
|
123433
|
+
points: credPoints(inputs.credentials.sealed),
|
|
123434
|
+
gated: !0,
|
|
123435
|
+
configPath: "adf_identity"
|
|
123436
|
+
}), inputs.privateKey === "plain" ? factors.push({
|
|
123437
|
+
id: "identity:private_key",
|
|
123438
|
+
label: "Signing key stored unsealed",
|
|
123439
|
+
points: ACCESS_POINTS.privateKeyPlain,
|
|
123440
|
+
gated: !1,
|
|
123441
|
+
configPath: "adf_identity.crypto:signing:private_key"
|
|
123442
|
+
}) : inputs.privateKey === "sealed" && factors.push({
|
|
123443
|
+
id: "identity:private_key",
|
|
123444
|
+
label: "Signing key (sealed)",
|
|
123445
|
+
points: ACCESS_POINTS.privateKeySealed,
|
|
123446
|
+
gated: !0,
|
|
123447
|
+
configPath: "adf_identity.crypto:signing:private_key"
|
|
123448
|
+
}), toPowerStat(factors, POWER_MAX.access);
|
|
123449
|
+
}
|
|
123450
|
+
function scoreReach(inputs) {
|
|
123451
|
+
let tools = toolMap(inputs), factors = [], m = inputs.messaging, inbound = m.receive ? VISIBILITY_POINTS[m.visibility] ?? 0 : 0;
|
|
123452
|
+
inbound > 0 && (factors.push({
|
|
123453
|
+
id: "messaging:visibility",
|
|
123454
|
+
label: `Receives messages from ${m.visibility === "directory" ? "agents in its directory" : `the ${m.visibility} tier`}`,
|
|
123455
|
+
points: inbound,
|
|
123456
|
+
gated: !1,
|
|
123457
|
+
configPath: "messaging.visibility"
|
|
123458
|
+
}), m.allowListCount > 0 && factors.push({
|
|
123459
|
+
id: "messaging:allow_list",
|
|
123460
|
+
label: `Inbox limited to ${plural(m.allowListCount, "allowed sender")}`,
|
|
123461
|
+
points: -inbound / 2,
|
|
123462
|
+
gated: !1,
|
|
123463
|
+
configPath: "messaging.allow_list"
|
|
123464
|
+
}), (!inputs.security.allowUnsigned || inputs.security.requireSignature) && factors.push({
|
|
123465
|
+
id: "security:signed_only",
|
|
123466
|
+
label: "Only accepts signed messages",
|
|
123467
|
+
points: REACH_POINTS.signedOnly,
|
|
123468
|
+
gated: !1,
|
|
123469
|
+
configPath: inputs.security.requireSignature ? "security.require_signature" : "security.allow_unsigned"
|
|
123470
|
+
}));
|
|
123471
|
+
let send = tools.get("msg_send");
|
|
123472
|
+
if (send && m.mode !== "listen_only") {
|
|
123473
|
+
let proactive = m.mode === "proactive";
|
|
123474
|
+
factors.push({
|
|
123475
|
+
id: "messaging:send",
|
|
123476
|
+
label: proactive ? "Sends messages on its own" : "Replies to messages it receives",
|
|
123477
|
+
points: proactive ? REACH_POINTS.sendProactive : REACH_POINTS.sendRespondOnly,
|
|
123478
|
+
gated: send.restricted,
|
|
123479
|
+
configPath: "messaging.mode"
|
|
123480
|
+
});
|
|
123481
|
+
}
|
|
123482
|
+
inputs.serving.publicEnabled && factors.push({
|
|
123483
|
+
id: "serving:public",
|
|
123484
|
+
label: "Serves a public web page",
|
|
123485
|
+
points: REACH_POINTS.publicPage,
|
|
123486
|
+
gated: !1,
|
|
123487
|
+
configPath: "serving.public.enabled"
|
|
123488
|
+
}), inputs.serving.apiRouteCount > 0 && factors.push({
|
|
123489
|
+
id: "serving:api",
|
|
123490
|
+
label: `${plural(inputs.serving.apiRouteCount, "HTTP API route")}`,
|
|
123491
|
+
points: Math.min(REACH_POINTS.apiRouteCap, inputs.serving.apiRouteCount * REACH_POINTS.apiRoute),
|
|
123492
|
+
gated: !1,
|
|
123493
|
+
configPath: "serving.api"
|
|
123494
|
+
}), inputs.serving.sharedEnabled && factors.push({
|
|
123495
|
+
id: "serving:shared",
|
|
123496
|
+
label: "Shares files with peers",
|
|
123497
|
+
points: REACH_POINTS.sharedFiles,
|
|
123498
|
+
gated: !1,
|
|
123499
|
+
configPath: "serving.shared.enabled"
|
|
123500
|
+
});
|
|
123501
|
+
let adapterPoints = (a) => a.restrictedDm ? REACH_POINTS.adapterRestrictedDm : REACH_POINTS.adapter, countedAdapters = countedIndices(inputs.adapters, REACH_POINTS.adapterCap, adapterPoints, () => !1);
|
|
123502
|
+
return inputs.adapters.forEach((a, i) => {
|
|
123503
|
+
factors.push({
|
|
123504
|
+
id: `adapter:${a.type}`,
|
|
123505
|
+
label: a.restrictedDm ? `${a.type} adapter (DMs restricted)` : `${a.type} adapter`,
|
|
123506
|
+
points: countedAdapters.has(i) ? adapterPoints(a) : 0,
|
|
123507
|
+
gated: !1,
|
|
123508
|
+
configPath: `adapters.${a.type}`
|
|
123509
|
+
});
|
|
123510
|
+
}), inputs.wsConnectionCount > 0 && factors.push({
|
|
123511
|
+
id: "ws_connections",
|
|
123512
|
+
label: `${plural(inputs.wsConnectionCount, "standing WebSocket connection")}`,
|
|
123513
|
+
points: Math.min(REACH_POINTS.wsConnectionCap, inputs.wsConnectionCount * REACH_POINTS.wsConnection),
|
|
123514
|
+
gated: !1,
|
|
123515
|
+
configPath: "ws_connections"
|
|
123516
|
+
}), toPowerStat(factors, POWER_MAX.reach);
|
|
123517
|
+
}
|
|
123518
|
+
function scoreAutonomy(inputs) {
|
|
123519
|
+
let tools = toolMap(inputs), factors = [];
|
|
123520
|
+
if (inputs.autonomous && factors.push({ id: "autonomous", label: "Acts without waiting for a human", points: AUTONOMY_POINTS.autonomous, gated: !1, configPath: "autonomous" }), inputs.autostart && factors.push({ id: "autostart", label: "Starts when the runtime starts", points: AUTONOMY_POINTS.autostart, gated: !1, configPath: "autostart" }), inputs.timers.active > 0) {
|
|
123521
|
+
factors.push({ id: "timers", label: `${plural(inputs.timers.active, "active timer")}`, points: AUTONOMY_POINTS.timers, gated: !1, configPath: "adf_timers" });
|
|
123522
|
+
let fastest = inputs.timers.fastestIntervalMs;
|
|
123523
|
+
fastest !== void 0 && fastest <= 36e5 && factors.push({
|
|
123524
|
+
id: "timers:fastest",
|
|
123525
|
+
label: `Wakes every ${formatInterval(fastest)}`,
|
|
123526
|
+
points: fastest <= 3e5 ? AUTONOMY_POINTS.timerFast : AUTONOMY_POINTS.timerHourly,
|
|
123527
|
+
gated: !1,
|
|
123528
|
+
configPath: "adf_timers"
|
|
123529
|
+
});
|
|
123530
|
+
}
|
|
123531
|
+
let triggerTargets = inputs.triggers.reduce((s, t) => s + t.targets, 0);
|
|
123532
|
+
triggerTargets > 0 && factors.push({
|
|
123533
|
+
id: "triggers",
|
|
123534
|
+
label: `Wakes on ${plural(inputs.triggers.length, "event type")} (${inputs.triggers.map((t) => t.type).join(", ")})`,
|
|
123535
|
+
points: Math.min(AUTONOMY_POINTS.triggerCap, triggerTargets * AUTONOMY_POINTS.trigger),
|
|
123536
|
+
gated: !1,
|
|
123537
|
+
configPath: "triggers"
|
|
123538
|
+
});
|
|
123539
|
+
let send = tools.get("msg_send");
|
|
123540
|
+
send && inputs.messaging.mode === "proactive" && factors.push({ id: "messaging:proactive", label: "Starts conversations", points: AUTONOMY_POINTS.proactive, gated: send.restricted, configPath: "messaging.mode" });
|
|
123541
|
+
let spawn5 = tools.get("sys_create_adf");
|
|
123542
|
+
spawn5 && factors.push({ id: "tool:sys_create_adf", label: spawn5.restricted ? "Creates new agents (needs approval)" : "Creates new agents", points: AUTONOMY_POINTS.createAgents, gated: spawn5.restricted, configPath: "tools.sys_create_adf" });
|
|
123543
|
+
let update = tools.get("sys_update_config");
|
|
123544
|
+
update && factors.push({ id: "tool:sys_update_config", label: update.restricted ? "Changes its own config (needs approval)" : "Changes its own config", points: AUTONOMY_POINTS.updateConfig, gated: update.restricted, configPath: "tools.sys_update_config" }), inputs.sideLoopCount > 0 && factors.push({
|
|
123545
|
+
id: "loops",
|
|
123546
|
+
label: `${plural(inputs.sideLoopCount, "inner loop")}`,
|
|
123547
|
+
points: Math.min(AUTONOMY_POINTS.sideLoopCap, inputs.sideLoopCount * AUTONOMY_POINTS.sideLoop),
|
|
123548
|
+
gated: !1,
|
|
123549
|
+
configPath: "loops"
|
|
123550
|
+
});
|
|
123551
|
+
let restricted = [...tools.values()].filter((t) => t.restricted).length;
|
|
123552
|
+
return restricted > 0 && factors.push({
|
|
123553
|
+
id: "tools:restricted",
|
|
123554
|
+
label: `${plural(restricted, "tool")} need${restricted === 1 ? "s" : ""} approval`,
|
|
123555
|
+
points: Math.max(AUTONOMY_POINTS.restrictedToolCap, restricted * AUTONOMY_POINTS.restrictedTool),
|
|
123556
|
+
gated: !1,
|
|
123557
|
+
configPath: "tools[].restricted"
|
|
123558
|
+
}), toPowerStat(factors, POWER_MAX.autonomy);
|
|
123559
|
+
}
|
|
123560
|
+
var EXPERIENCE_WEIGHTS = {
|
|
123561
|
+
/** Per context worked: one compaction, or a loop's current fill as a share of its compaction threshold. */
|
|
123562
|
+
contextsWorked: 10,
|
|
123563
|
+
/**
|
|
123564
|
+
* Multiplied by sqrt(approximate tokens in `mind/` files), so 10x memory is
|
|
123565
|
+
* about 3.2x the XP and a bulk dump cannot buy levels (1M tokens alone is
|
|
123566
|
+
* Lv 17). 2.6 keeps the first-session anchor (300 tokens) at Lv 3 with
|
|
123567
|
+
* margin; skills, rows and children carry the heavy anchor instead.
|
|
123568
|
+
*/
|
|
123569
|
+
memoryTokensSqrt: 2.6,
|
|
123570
|
+
/** Per skill installed or changed. */
|
|
123571
|
+
skills: 80,
|
|
123572
|
+
/** Per `local_*` table. */
|
|
123573
|
+
localTables: 10,
|
|
123574
|
+
/** Multiplied by sqrt(total local rows). */
|
|
123575
|
+
localRowsSqrt: 7,
|
|
123576
|
+
/** Per file written or changed after creation. */
|
|
123577
|
+
filesWritten: 2,
|
|
123578
|
+
/** Per child agent. */
|
|
123579
|
+
agentsSpawned: 75,
|
|
123580
|
+
/** Per loop message ever written (all loops, current and past). Small: volume alone must not level an agent. */
|
|
123581
|
+
messages: 0.01,
|
|
123582
|
+
/** Per day of age, scaled by activity = min(1, contextsWorked / ageActivityContexts) so an idle file does not level up by waiting. */
|
|
123583
|
+
ageDays: 0.5,
|
|
123584
|
+
ageActivityContexts: 10
|
|
123585
|
+
}, EXPERIENCE_LABELS = {
|
|
123586
|
+
contextsWorked: "Contexts of work",
|
|
123587
|
+
filesWritten: "Files written",
|
|
123588
|
+
memoryTokens: "Memory tokens",
|
|
123589
|
+
skills: "Skills",
|
|
123590
|
+
localTables: "Database tables",
|
|
123591
|
+
localRows: "Database rows",
|
|
123592
|
+
agentsSpawned: "Agents created",
|
|
123593
|
+
messages: "Messages",
|
|
123594
|
+
ageDays: "Days active"
|
|
123595
|
+
};
|
|
123596
|
+
function experienceSignals(inputs) {
|
|
123597
|
+
let w = EXPERIENCE_WEIGHTS, n = (v) => typeof v == "number" && Number.isFinite(v) && v > 0 ? v : 0, activity = Math.min(1, n(inputs.contextsWorked) / w.ageActivityContexts), signals = [
|
|
123598
|
+
{ id: "contextsWorked", label: EXPERIENCE_LABELS.contextsWorked, value: n(inputs.contextsWorked), xp: n(inputs.contextsWorked) * w.contextsWorked },
|
|
123599
|
+
{ id: "memoryTokens", label: EXPERIENCE_LABELS.memoryTokens, value: n(inputs.memoryTokens), xp: Math.sqrt(n(inputs.memoryTokens)) * w.memoryTokensSqrt },
|
|
123600
|
+
{ id: "skills", label: EXPERIENCE_LABELS.skills, value: n(inputs.skills), xp: n(inputs.skills) * w.skills },
|
|
123601
|
+
{ id: "localTables", label: EXPERIENCE_LABELS.localTables, value: n(inputs.localTables), xp: n(inputs.localTables) * w.localTables },
|
|
123602
|
+
{ id: "localRows", label: EXPERIENCE_LABELS.localRows, value: n(inputs.localRows), xp: Math.sqrt(n(inputs.localRows)) * w.localRowsSqrt },
|
|
123603
|
+
{ id: "filesWritten", label: EXPERIENCE_LABELS.filesWritten, value: n(inputs.filesWritten), xp: n(inputs.filesWritten) * w.filesWritten }
|
|
123604
|
+
];
|
|
123605
|
+
return inputs.agentsSpawned !== null && signals.push({ id: "agentsSpawned", label: EXPERIENCE_LABELS.agentsSpawned, value: n(inputs.agentsSpawned), xp: n(inputs.agentsSpawned) * w.agentsSpawned }), signals.push(
|
|
123606
|
+
{ id: "messages", label: EXPERIENCE_LABELS.messages, value: n(inputs.messages), xp: n(inputs.messages) * w.messages },
|
|
123607
|
+
{ id: "ageDays", label: EXPERIENCE_LABELS.ageDays, value: Math.floor(n(inputs.ageDays)), xp: n(inputs.ageDays) * w.ageDays * activity }
|
|
123608
|
+
), signals;
|
|
123609
|
+
}
|
|
123610
|
+
function ceilCount(n) {
|
|
123611
|
+
if (n < 1e3) return String(n);
|
|
123612
|
+
let k = Math.ceil(n / 100) / 10;
|
|
123613
|
+
return `${k % 1 === 0 ? k.toFixed(0) : k.toFixed(1)}k`;
|
|
123614
|
+
}
|
|
123615
|
+
function scoreExperience(inputs) {
|
|
123616
|
+
let breakdown = experienceSignals(inputs), score = breakdown.reduce((s, b) => s + b.xp, 0), pos = levelPosition(score, EXPERIENCE_CURVE), xp = Math.max(0, pos.nextLevelAt - score), w = EXPERIENCE_WEIGHTS, contexts = Math.ceil(xp / w.contextsWorked), memoryNow = typeof inputs.memoryTokens == "number" && Number.isFinite(inputs.memoryTokens) && inputs.memoryTokens > 0 ? inputs.memoryTokens : 0, memoryXpNow = Math.sqrt(memoryNow) * w.memoryTokensSqrt, memoryTokens = Math.max(0, Math.ceil(((memoryXpNow + xp) / w.memoryTokensSqrt) ** 2 - memoryNow)), skills = Math.ceil(xp / w.skills);
|
|
123617
|
+
return {
|
|
123618
|
+
level: pos.level,
|
|
123619
|
+
progress: pos.progress,
|
|
123620
|
+
score,
|
|
123621
|
+
levelStart: pos.levelStart,
|
|
123622
|
+
nextLevelAt: pos.nextLevelAt,
|
|
123623
|
+
breakdown,
|
|
123624
|
+
nextLevel: {
|
|
123625
|
+
xp,
|
|
123626
|
+
contexts,
|
|
123627
|
+
memoryTokens,
|
|
123628
|
+
skills,
|
|
123629
|
+
hint: `Lv ${pos.level + 1} needs ${Math.ceil(xp)} more XP: about ${plural(contexts, "context")} of work, ${ceilCount(memoryTokens)} memory tokens or ${plural(skills, "skill")}`
|
|
123630
|
+
}
|
|
123631
|
+
};
|
|
123632
|
+
}
|
|
123633
|
+
function scheduleIntervalMs(schedule) {
|
|
123634
|
+
if (schedule) {
|
|
123635
|
+
if (schedule.mode === "interval") return schedule.every_ms > 0 ? schedule.every_ms : void 0;
|
|
123636
|
+
if (schedule.mode === "cron") {
|
|
123637
|
+
let minute = schedule.cron.trim().split(/\s+/)[0] ?? "";
|
|
123638
|
+
if (minute === "*") return 6e4;
|
|
123639
|
+
let step = /^\*\/(\d+)$/.exec(minute);
|
|
123640
|
+
return step ? Number(step[1]) * 6e4 : void 0;
|
|
123641
|
+
}
|
|
123642
|
+
}
|
|
123643
|
+
}
|
|
123644
|
+
function powerInputsFromConfig(config, tables) {
|
|
123645
|
+
let triggers = [];
|
|
123646
|
+
for (let [type, t] of Object.entries(config.triggers ?? {})) {
|
|
123647
|
+
if (type === "on_chat" || !t?.enabled) continue;
|
|
123648
|
+
let targets = Array.isArray(t.targets) ? t.targets.length : 0;
|
|
123649
|
+
targets > 0 && triggers.push({ type, targets });
|
|
123650
|
+
}
|
|
123651
|
+
let mcpServers = (config.mcp?.servers ?? []).map((s) => ({
|
|
123652
|
+
name: s.name,
|
|
123653
|
+
restricted: !!s.restricted,
|
|
123654
|
+
hasCredentials: !!(s.oauth || s.bearer_token_env_var || s.env_keys && s.env_keys.length > 0 || s.env_schema && s.env_schema.length > 0 || s.header_env && s.header_env.length > 0 || s.credential_files && s.credential_files.length > 0)
|
|
123655
|
+
})), adapters = Object.entries(config.adapters ?? {}).filter(([, a]) => a?.enabled).map(([type, a]) => ({ type, restrictedDm: a.policy?.dm === "allowlist" || a.policy?.dm === "none" })), allowedTargets = [...config.compute?.allowed_targets ?? []];
|
|
123656
|
+
return config.compute?.target && !allowedTargets.includes(config.compute.target) && allowedTargets.push(config.compute.target), {
|
|
123657
|
+
tools: (config.tools ?? []).map((t) => ({ name: t.name, enabled: !!t.enabled, restricted: !!t.restricted })),
|
|
123658
|
+
autonomous: !!config.autonomous,
|
|
123659
|
+
autostart: !!config.autostart,
|
|
123660
|
+
messaging: {
|
|
123661
|
+
receive: config.messaging?.receive ?? !1,
|
|
123662
|
+
mode: config.messaging?.mode ?? "proactive",
|
|
123663
|
+
visibility: config.messaging?.visibility ?? "localhost",
|
|
123664
|
+
allowListCount: config.messaging?.allow_list?.length ?? 0
|
|
123665
|
+
},
|
|
123666
|
+
security: {
|
|
123667
|
+
allowUnsigned: config.security?.allow_unsigned ?? !0,
|
|
123668
|
+
requireSignature: !!config.security?.require_signature
|
|
123669
|
+
},
|
|
123670
|
+
serving: {
|
|
123671
|
+
publicEnabled: !!config.serving?.public?.enabled,
|
|
123672
|
+
apiRouteCount: config.serving?.api?.length ?? 0,
|
|
123673
|
+
sharedEnabled: !!config.serving?.shared?.enabled
|
|
123674
|
+
},
|
|
123675
|
+
adapters,
|
|
123676
|
+
wsConnectionCount: (config.ws_connections ?? []).filter((c) => c?.enabled).length,
|
|
123677
|
+
mcpServers,
|
|
123678
|
+
npmPackageCount: config.code_execution?.packages?.length ?? 0,
|
|
123679
|
+
codeNetwork: !!config.code_execution?.network,
|
|
123680
|
+
compute: {
|
|
123681
|
+
enabled: !!config.compute?.enabled,
|
|
123682
|
+
hostAccess: !!config.compute?.host_access,
|
|
123683
|
+
allowedTargets
|
|
123684
|
+
},
|
|
123685
|
+
triggers,
|
|
123686
|
+
sideLoopCount: config.loops?.length ?? 0,
|
|
123687
|
+
credentials: tables.credentials,
|
|
123688
|
+
privateKey: tables.privateKey,
|
|
123689
|
+
timers: tables.timers
|
|
123690
|
+
};
|
|
123691
|
+
}
|
|
123692
|
+
function scoreAgent(power, experience) {
|
|
123693
|
+
return {
|
|
123694
|
+
reach: scoreReach(power),
|
|
123695
|
+
access: scoreAccess(power),
|
|
123696
|
+
autonomy: scoreAutonomy(power),
|
|
123697
|
+
experience: scoreExperience(experience)
|
|
123698
|
+
};
|
|
123699
|
+
}
|
|
123700
|
+
|
|
123701
|
+
// src/shared/utils/agent-activity.ts
|
|
123702
|
+
var ACTIVITY_DAYS = 14;
|
|
123703
|
+
function localDayKeys(now2, days = ACTIVITY_DAYS) {
|
|
123704
|
+
let d = new Date(now2), out = [];
|
|
123705
|
+
for (let i = days - 1; i >= 0; i--)
|
|
123706
|
+
out.push(localDateKey(new Date(d.getFullYear(), d.getMonth(), d.getDate() - i)));
|
|
123707
|
+
return out;
|
|
123708
|
+
}
|
|
123709
|
+
function windowStartMs(now2, days = ACTIVITY_DAYS) {
|
|
123710
|
+
let d = new Date(now2);
|
|
123711
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate() - (days - 1)).getTime();
|
|
123712
|
+
}
|
|
123713
|
+
|
|
123714
|
+
// src/main/services/agent-daily.ts
|
|
123715
|
+
function rowsOf(q, sql, params) {
|
|
123716
|
+
try {
|
|
123717
|
+
return q(sql, params);
|
|
123718
|
+
} catch {
|
|
123719
|
+
return null;
|
|
123720
|
+
}
|
|
123721
|
+
}
|
|
123722
|
+
var num = (v) => typeof v == "number" && Number.isFinite(v) ? v : null, DAY_MS = 1440 * 60 * 1e3, LOOP_COST_RECORDED_SINCE_MS = Date.UTC(2026, 7, 27);
|
|
123723
|
+
function rowCost(model, tokens, createdAt) {
|
|
123724
|
+
if (tokens == null || tokens === "") return { kind: "none" };
|
|
123725
|
+
let usage = tokens;
|
|
123726
|
+
if (typeof tokens == "string")
|
|
123727
|
+
try {
|
|
123728
|
+
usage = JSON.parse(tokens);
|
|
123729
|
+
} catch {
|
|
123730
|
+
return { kind: "unpriced" };
|
|
123731
|
+
}
|
|
123732
|
+
if (!usage || typeof usage != "object" || Array.isArray(usage)) return { kind: "unpriced" };
|
|
123733
|
+
let u = usage, recorded = num(u.cost_usd);
|
|
123734
|
+
if (recorded !== null) return { kind: "priced", usd: recorded };
|
|
123735
|
+
if (createdAt >= LOOP_COST_RECORDED_SINCE_MS || typeof model != "string" || !model) return { kind: "unpriced" };
|
|
123736
|
+
let usd = estimateTokenCostUsd(model, {
|
|
123737
|
+
input: num(u.input) ?? void 0,
|
|
123738
|
+
output: num(u.output) ?? void 0,
|
|
123739
|
+
cache_read: num(u.cache_read) ?? void 0,
|
|
123740
|
+
cache_write: num(u.cache_write) ?? void 0
|
|
123741
|
+
});
|
|
123742
|
+
return usd === void 0 ? { kind: "unpriced" } : { kind: "priced", usd };
|
|
123743
|
+
}
|
|
123744
|
+
function maxLoopSeq(q) {
|
|
123745
|
+
return num(rowsOf(q, "SELECT MAX(seq) AS n FROM adf_loop")?.[0]?.n) ?? 0;
|
|
123746
|
+
}
|
|
123747
|
+
function firstSeqSince(q, since, maxSeq = maxLoopSeq(q)) {
|
|
123748
|
+
let probe = (seq) => {
|
|
123749
|
+
let r = rowsOf(q, "SELECT seq, created_at AS t FROM adf_loop WHERE seq >= ? ORDER BY seq LIMIT 1", [seq])?.[0];
|
|
123750
|
+
return r ? { seq: r.seq, t: num(r.t) ?? 0 } : null;
|
|
123751
|
+
}, lo = 0, hi = maxSeq + 1;
|
|
123752
|
+
for (; lo < hi; ) {
|
|
123753
|
+
let mid = Math.floor((lo + hi) / 2), row = probe(mid);
|
|
123754
|
+
!row || row.seq >= hi || row.t >= since ? hi = mid : lo = row.seq + 1;
|
|
123755
|
+
}
|
|
123756
|
+
return lo;
|
|
123757
|
+
}
|
|
123758
|
+
function startLoopDayScan(q, since) {
|
|
123759
|
+
let startSeq = firstSeqSince(q, since);
|
|
123760
|
+
return { since, startSeq, lastSeq: startSeq - 1, rows: /* @__PURE__ */ new Map() };
|
|
123761
|
+
}
|
|
123762
|
+
function addRows(scan, rows) {
|
|
123763
|
+
for (let r of rows) {
|
|
123764
|
+
let t = num(r.t) ?? 0, cost = rowCost(r.model, r.tokens, t);
|
|
123765
|
+
scan.rows.set(r.seq, cost.kind === "priced" ? { t, usd: cost.usd } : cost.kind === "unpriced" ? { t, unpriced: !0 } : { t });
|
|
123766
|
+
}
|
|
123767
|
+
}
|
|
123768
|
+
function scanLoopRows(q, scan, upTo) {
|
|
123769
|
+
if (upTo <= scan.lastSeq) return scan;
|
|
123770
|
+
let rows = rowsOf(q, "SELECT seq, created_at AS t, model, tokens FROM adf_loop WHERE seq > ? AND seq <= ?", [scan.lastSeq, upTo]) ?? rowsOf(q, "SELECT seq, created_at AS t, NULL AS model, NULL AS tokens FROM adf_loop WHERE seq > ? AND seq <= ?", [scan.lastSeq, upTo]) ?? [];
|
|
123771
|
+
return addRows(scan, rows), scan.lastSeq = upTo, scan;
|
|
123772
|
+
}
|
|
123773
|
+
function seqRangeRows(q, select, from, to) {
|
|
123774
|
+
return rowsOf(q, `SELECT ${select} FROM adf_loop INDEXED BY idx_adf_loop_loop_seq WHERE seq BETWEEN ? AND ?`, [from, to]) ?? rowsOf(q, `SELECT ${select} FROM adf_loop WHERE seq BETWEEN ? AND ?`, [from, to]);
|
|
123775
|
+
}
|
|
123776
|
+
function refreshLoopDayScan(q, since, prior) {
|
|
123777
|
+
let maxSeq = maxLoopSeq(q);
|
|
123778
|
+
if (!prior || prior.since !== since || prior.lastSeq > maxSeq) return scanLoopRows(q, startLoopDayScan(q, since), maxSeq);
|
|
123779
|
+
let scan = prior;
|
|
123780
|
+
if (scan.lastSeq >= scan.startSeq) {
|
|
123781
|
+
let count = num(seqRangeRows(q, "COUNT(*) AS n", scan.startSeq, scan.lastSeq)?.[0]?.n);
|
|
123782
|
+
if (count !== null && count !== scan.rows.size) {
|
|
123783
|
+
let alive = new Set((seqRangeRows(q, "seq", scan.startSeq, scan.lastSeq) ?? []).map((r) => r.seq));
|
|
123784
|
+
for (let seq of scan.rows.keys()) alive.has(seq) || scan.rows.delete(seq);
|
|
123785
|
+
let missing = [...alive].filter((seq) => !scan.rows.has(seq));
|
|
123786
|
+
missing.length > 0 && addRows(scan, rowsOf(q, "SELECT seq, created_at AS t, model, tokens FROM adf_loop WHERE seq IN (SELECT value FROM json_each(?))", [JSON.stringify(missing)]) ?? []);
|
|
123787
|
+
}
|
|
123788
|
+
}
|
|
123789
|
+
return scanLoopRows(q, scan, maxSeq);
|
|
123790
|
+
}
|
|
123791
|
+
var LOOP_AUDIT_WHERE = "(source = 'loop' OR source LIKE 'loop:%')", ARCHIVE_SPREAD_MAX_MS = DAY_MS, loopOfSource = (source) => source === "loop" ? "main" : source.slice(5) || "main";
|
|
123792
|
+
function firstAuditIdSince(q, at) {
|
|
123793
|
+
let bounds = rowsOf(q, "SELECT MIN(id) AS lo, MAX(id) AS hi FROM adf_audit")?.[0], minId = num(bounds?.lo), maxId = num(bounds?.hi);
|
|
123794
|
+
if (minId === null || maxId === null) return null;
|
|
123795
|
+
let lo = minId, hi = maxId + 1;
|
|
123796
|
+
for (; lo < hi; ) {
|
|
123797
|
+
let mid = Math.floor((lo + hi) / 2), row = rowsOf(q, "SELECT id, created_at AS t FROM adf_audit WHERE id >= ? ORDER BY id LIMIT 1", [mid])?.[0];
|
|
123798
|
+
!row || row.id >= hi || (num(row.t) ?? 0) >= at ? hi = mid : lo = row.id + 1;
|
|
123799
|
+
}
|
|
123800
|
+
return lo;
|
|
123801
|
+
}
|
|
123802
|
+
function readArchiveSpans(q, since) {
|
|
123803
|
+
let firstId = firstAuditIdSince(q, since - ARCHIVE_SPREAD_MAX_MS);
|
|
123804
|
+
if (firstId === null) return [];
|
|
123805
|
+
let cols = (seqCols) => `SELECT id, source, ${seqCols}, entry_count, created_at FROM adf_audit WHERE id >= ? AND ${LOOP_AUDIT_WHERE} ORDER BY id`, archives = rowsOf(q, cols("start_seq, end_seq"), [firstId]) ?? rowsOf(q, cols("NULL AS start_seq, NULL AS end_seq"), [firstId]) ?? [], liveAt = (sql, seq) => num(rowsOf(q, sql, [seq])?.[0]?.t), liveInRange = (loop, from, to) => num(rowsOf(q, "SELECT COUNT(*) AS n FROM adf_loop WHERE loop = ? AND seq BETWEEN ? AND ?", [loop, from, to])?.[0]?.n) ?? (loop === "main" ? num(rowsOf(q, "SELECT COUNT(*) AS n FROM adf_loop WHERE seq BETWEEN ? AND ?", [from, to])?.[0]?.n) ?? 0 : 0), spans = [], prevCreated = /* @__PURE__ */ new Map();
|
|
123806
|
+
return archives.forEach((a, i) => {
|
|
123807
|
+
let loop = loopOfSource(a.source), created = num(a.created_at) ?? 0, prev = prevCreated.get(loop);
|
|
123808
|
+
if (prevCreated.set(loop, created), created < since) return;
|
|
123809
|
+
let startSeq = num(a.start_seq), endSeq = num(a.end_seq), hasRange = startSeq !== null && endSeq !== null;
|
|
123810
|
+
if (hasRange && archives.slice(i + 1).some((b) => loopOfSource(b.source) === loop && num(b.start_seq) !== null && num(b.start_seq) <= startSeq && (num(b.end_seq) ?? -1 / 0) >= endSeq)) return;
|
|
123811
|
+
let count = num(a.entry_count) ?? 0;
|
|
123812
|
+
if (hasRange && (count -= liveInRange(loop, startSeq, endSeq)), count <= 0) return;
|
|
123813
|
+
let to = created, after = hasRange ? liveAt("SELECT created_at AS t FROM adf_loop WHERE seq > ? ORDER BY seq LIMIT 1", endSeq) : null;
|
|
123814
|
+
after !== null && after < to && (to = after);
|
|
123815
|
+
let from = to - ARCHIVE_SPREAD_MAX_MS;
|
|
123816
|
+
prev !== void 0 && (from = Math.max(from, prev));
|
|
123817
|
+
let before = hasRange ? liveAt("SELECT created_at AS t FROM adf_loop WHERE seq < ? ORDER BY seq DESC LIMIT 1", startSeq) : null;
|
|
123818
|
+
before !== null && (from = Math.max(from, before)), spans.push({ loop, from: Math.min(from, to), to, count });
|
|
123819
|
+
}), spans;
|
|
123820
|
+
}
|
|
123821
|
+
function spreadSpans(spans, dayStarts) {
|
|
123822
|
+
let out = new Array(dayStarts.length - 1).fill(0);
|
|
123823
|
+
for (let s of spans) {
|
|
123824
|
+
let width = s.to - s.from;
|
|
123825
|
+
for (let i = 0; i < out.length; i++) {
|
|
123826
|
+
let a = dayStarts[i], b = dayStarts[i + 1];
|
|
123827
|
+
if (width <= 0) {
|
|
123828
|
+
s.to >= a && s.to < b && (out[i] += s.count);
|
|
123829
|
+
continue;
|
|
123830
|
+
}
|
|
123831
|
+
let overlap = Math.min(b, s.to) - Math.max(a, s.from);
|
|
123832
|
+
overlap > 0 && (out[i] += s.count * overlap / width);
|
|
123833
|
+
}
|
|
123834
|
+
}
|
|
123835
|
+
return out;
|
|
123836
|
+
}
|
|
123837
|
+
function windowDayStarts(now2, days) {
|
|
123838
|
+
let d = new Date(now2), out = [];
|
|
123839
|
+
for (let i = days - 1; i >= -1; i--) out.push(new Date(d.getFullYear(), d.getMonth(), d.getDate() - i).getTime());
|
|
123840
|
+
return out;
|
|
123841
|
+
}
|
|
123842
|
+
function buildDailyActivity(scan, spans, now2, days) {
|
|
123843
|
+
let keys = localDayKeys(now2, days), starts = windowDayStarts(now2, keys.length), live = keys.map(() => ({ messages: 0, usd: 0, priced: !1, unpriced: !1 }));
|
|
123844
|
+
for (let r of scan.rows.values()) {
|
|
123845
|
+
if (r.t < starts[0] || r.t >= starts[starts.length - 1]) continue;
|
|
123846
|
+
let i = 0;
|
|
123847
|
+
for (; r.t >= starts[i + 1]; ) i++;
|
|
123848
|
+
let day = live[i];
|
|
123849
|
+
day.messages++, r.usd !== void 0 && (day.usd += r.usd, day.priced = !0), r.unpriced && (day.unpriced = !0);
|
|
123850
|
+
}
|
|
123851
|
+
let archived = spreadSpans(spans, starts);
|
|
123852
|
+
return keys.map((date, i) => {
|
|
123853
|
+
let extra = Math.round(archived[i]), d = live[i];
|
|
123854
|
+
return {
|
|
123855
|
+
date,
|
|
123856
|
+
messages: d.messages + extra,
|
|
123857
|
+
...extra > 0 ? { estimated: !0 } : {},
|
|
123858
|
+
...d.priced ? { costUsd: Number(d.usd.toFixed(8)) } : {},
|
|
123859
|
+
...d.unpriced || extra > 0 ? { costPartial: !0 } : {}
|
|
123860
|
+
};
|
|
123861
|
+
});
|
|
123862
|
+
}
|
|
123863
|
+
function readDailyActivity(q, now2, prior) {
|
|
123864
|
+
let since = windowStartMs(now2), scan = refreshLoopDayScan(q, since, prior);
|
|
123865
|
+
return { daily: buildDailyActivity(scan, readArchiveSpans(q, since), now2), scan };
|
|
123866
|
+
}
|
|
123867
|
+
function recentCost(daily, days = 7) {
|
|
123868
|
+
let recent = daily.slice(-days);
|
|
123869
|
+
if (recent.some((d) => d.costUsd !== void 0))
|
|
123870
|
+
return {
|
|
123871
|
+
usd: Number(recent.reduce((s, d) => s + (d.costUsd ?? 0), 0).toFixed(8)),
|
|
123872
|
+
partial: recent.some((d) => d.costPartial === !0)
|
|
123873
|
+
};
|
|
123874
|
+
}
|
|
123875
|
+
|
|
123876
|
+
// src/shared/utils/agent-metrics.ts
|
|
123877
|
+
var isNum = (v) => typeof v == "number" && Number.isFinite(v), isText = (v) => typeof v == "string" && v.trim() !== "";
|
|
123878
|
+
function parseMetric(name21, raw) {
|
|
123879
|
+
let text2 = raw == null ? "" : String(raw), plain = { name: name21, label: name21, value: text2, raw: text2 };
|
|
123880
|
+
if (!text2.trimStart().startsWith("{")) return plain;
|
|
123881
|
+
let o;
|
|
123882
|
+
try {
|
|
123883
|
+
o = JSON.parse(text2);
|
|
123884
|
+
} catch {
|
|
123885
|
+
return plain;
|
|
123886
|
+
}
|
|
123887
|
+
if (!o || typeof o != "object" || Array.isArray(o)) return plain;
|
|
123888
|
+
let r = o;
|
|
123889
|
+
return !isNum(r.value) && typeof r.value != "string" ? plain : {
|
|
123890
|
+
name: name21,
|
|
123891
|
+
label: isText(r.label) ? r.label : name21,
|
|
123892
|
+
value: r.value,
|
|
123893
|
+
...isText(r.unit) ? { unit: r.unit } : {},
|
|
123894
|
+
...isNum(r.min) ? { min: r.min } : {},
|
|
123895
|
+
...isNum(r.max) ? { max: r.max } : {},
|
|
123896
|
+
...isNum(r.target) ? { target: r.target } : {},
|
|
123897
|
+
raw: text2
|
|
123898
|
+
};
|
|
123899
|
+
}
|
|
123900
|
+
|
|
123901
|
+
// src/main/services/agent-vitals.ts
|
|
123902
|
+
var MIND_LOG_SEED_BYTES = Buffer.byteLength(DEFAULT_MIND_LOG_CONTENT);
|
|
123903
|
+
function memoryBytes(path, size) {
|
|
123904
|
+
let bytes = typeof size == "number" && Number.isFinite(size) ? size : 0;
|
|
123905
|
+
return path === "mind/log.md" ? Math.max(0, bytes - MIND_LOG_SEED_BYTES) : bytes;
|
|
123906
|
+
}
|
|
123907
|
+
function overlayLiveStates(meshAgents, live) {
|
|
123908
|
+
let byPath = /* @__PURE__ */ new Map();
|
|
123909
|
+
for (let l of live)
|
|
123910
|
+
byPath.set(l.filePath, { state: l.state, activeLoops: l.activeLoops ?? byPath.get(l.filePath)?.activeLoops });
|
|
123911
|
+
return meshAgents.map((a) => {
|
|
123912
|
+
let l = byPath.get(a.filePath);
|
|
123913
|
+
return l ? l.activeLoops === void 0 ? { ...a, state: l.state } : { ...a, state: l.state, activeLoops: l.activeLoops } : a;
|
|
123914
|
+
});
|
|
123915
|
+
}
|
|
123916
|
+
function parseDidHistory(raw) {
|
|
123917
|
+
if (!raw) return [];
|
|
123918
|
+
try {
|
|
123919
|
+
let parsed = JSON.parse(raw);
|
|
123920
|
+
return Array.isArray(parsed) ? parsed.filter((d) => typeof d == "string" && d) : [];
|
|
123921
|
+
} catch {
|
|
123922
|
+
return [];
|
|
123923
|
+
}
|
|
123924
|
+
}
|
|
123925
|
+
function liveFleetMeta(workspace) {
|
|
123926
|
+
try {
|
|
123927
|
+
let config = workspace.getAgentConfig();
|
|
123928
|
+
return {
|
|
123929
|
+
handle: workspace.getMeta("adf_handle") || config?.handle || null,
|
|
123930
|
+
name: workspace.getMeta("adf_name") || config?.name || null,
|
|
123931
|
+
icon: config?.icon ?? null,
|
|
123932
|
+
model: config?.model?.model_id || null,
|
|
123933
|
+
status: workspace.getMeta("status") ?? null,
|
|
123934
|
+
did: workspace.getMeta("adf_did") || null,
|
|
123935
|
+
didHistory: parseDidHistory(workspace.getMeta("adf_did_history")),
|
|
123936
|
+
agentId: config?.id ?? null,
|
|
123937
|
+
parentDid: workspace.getMeta("adf_parent_did") || null,
|
|
123938
|
+
createdAt: workspace.getMeta("adf_created_at") || config?.metadata?.created_at || null
|
|
123939
|
+
};
|
|
123940
|
+
} catch {
|
|
123941
|
+
return null;
|
|
123942
|
+
}
|
|
123943
|
+
}
|
|
123944
|
+
function safe(q, sql, map, fallback, params) {
|
|
123945
|
+
try {
|
|
123946
|
+
return map(q(sql, params));
|
|
123947
|
+
} catch {
|
|
123948
|
+
return fallback;
|
|
123949
|
+
}
|
|
123950
|
+
}
|
|
123951
|
+
function safeOr(q, sql, map, orElse, params) {
|
|
123952
|
+
try {
|
|
123953
|
+
return map(q(sql, params));
|
|
123954
|
+
} catch {
|
|
123955
|
+
return orElse();
|
|
123956
|
+
}
|
|
123957
|
+
}
|
|
123958
|
+
var firstNumber2 = (rows, col = "n") => {
|
|
123959
|
+
let v = rows[0]?.[col];
|
|
123960
|
+
return typeof v == "number" && Number.isFinite(v) ? v : 0;
|
|
123961
|
+
}, DERIVED_FILES = /* @__PURE__ */ new Set(["skills-registry.json"]), SKILL_FILE = /^skills\/([^/]+)\//, CREATION_GRACE_MS = 1e4;
|
|
123962
|
+
function agentWriteCutoff(createdAt) {
|
|
123963
|
+
let createdMs = createdAt ? Date.parse(createdAt) : NaN;
|
|
123964
|
+
return Number.isFinite(createdMs) ? new Date(createdMs + CREATION_GRACE_MS).toISOString() : "";
|
|
123965
|
+
}
|
|
123966
|
+
function classifyFiles(files, cutoff, registrySkills = []) {
|
|
123967
|
+
let mine = [], agentSkills = /* @__PURE__ */ new Set(), starterSkills = /* @__PURE__ */ new Set();
|
|
123968
|
+
for (let f of files) {
|
|
123969
|
+
if (DERIVED_FILES.has(f.path)) continue;
|
|
123970
|
+
let own = !cutoff || f.updated_at > cutoff, skill = SKILL_FILE.exec(f.path)?.[1];
|
|
123971
|
+
own ? (mine.push(f), skill && agentSkills.add(skill)) : skill && starterSkills.add(skill);
|
|
123972
|
+
}
|
|
123973
|
+
for (let name21 of registrySkills) starterSkills.has(name21) || agentSkills.add(name21);
|
|
123974
|
+
return { mine, agentSkills };
|
|
123975
|
+
}
|
|
123976
|
+
function readRegistrySkills(q) {
|
|
123977
|
+
return safe(
|
|
123978
|
+
q,
|
|
123979
|
+
"SELECT content FROM adf_files WHERE path = 'skills-registry.json'",
|
|
123980
|
+
(rows) => {
|
|
123981
|
+
let c = rows[0]?.content;
|
|
123982
|
+
if (!c) return [];
|
|
123983
|
+
let skills = JSON.parse(Buffer.isBuffer(c) ? c.toString("utf-8") : String(c)).skills;
|
|
123984
|
+
return Array.isArray(skills) ? skills.map((s) => s?.name).filter((n) => typeof n == "string") : skills && typeof skills == "object" ? Object.keys(skills) : [];
|
|
123985
|
+
},
|
|
123986
|
+
[]
|
|
123987
|
+
);
|
|
123988
|
+
}
|
|
123989
|
+
var MAX_TABLES = 50;
|
|
123990
|
+
function listLocalTables(q) {
|
|
123991
|
+
return safe(
|
|
123992
|
+
q,
|
|
123993
|
+
"SELECT name FROM sqlite_master WHERE type = 'table' AND name LIKE 'local\\_%' ESCAPE '\\' ORDER BY name",
|
|
123994
|
+
(rows) => rows.map((r) => r.name).filter((n) => /^local_[A-Za-z0-9_]+$/.test(n)),
|
|
123995
|
+
[]
|
|
123996
|
+
);
|
|
123997
|
+
}
|
|
123998
|
+
var LOOP_AUDIT_WHERE2 = "(source = 'loop' OR source LIKE 'loop:%')", FULL_SNAPSHOT_SHARE = 0.5, BASELINE_KEY = "context_baseline_tokens", loopOfSource2 = (source) => source === "loop" ? "main" : source.slice(5) || "main", clamp01 = (x) => Number.isFinite(x) ? Math.min(1, Math.max(0, x)) : 0;
|
|
123999
|
+
function readSummaryScan(q, prior, upTo = 1 / 0) {
|
|
124000
|
+
let maxSeq = Math.min(upTo, safe(q, "SELECT MAX(seq) AS n FROM adf_loop", (r) => firstNumber2(r), 0)), base = prior && prior.lastSeq <= maxSeq ? prior : null, sql = (loopCol) => `SELECT seq, ${loopCol} AS loop FROM adf_loop WHERE seq > ? AND seq <= ? AND role = 'user' AND content_json LIKE '%[Loop Compacted%'`, params = [base ? base.lastSeq : 0, maxSeq], fresh = safeOr(q, sql("loop"), (r) => r, () => safe(q, sql("'main'"), (r) => r, [], params), params), kept = [];
|
|
124001
|
+
if (base && base.hits.length > 0) {
|
|
124002
|
+
let alive = new Set(safe(
|
|
124003
|
+
q,
|
|
124004
|
+
"SELECT seq FROM adf_loop WHERE seq IN (SELECT value FROM json_each(?))",
|
|
124005
|
+
(r) => r.map((x) => x.seq),
|
|
124006
|
+
[],
|
|
124007
|
+
[JSON.stringify(base.hits.map((h) => h.seq))]
|
|
124008
|
+
));
|
|
124009
|
+
kept = base.hits.filter((h) => alive.has(h.seq));
|
|
124010
|
+
}
|
|
124011
|
+
return { lastSeq: maxSeq, hits: [...kept, ...fresh.map((h) => ({ seq: h.seq, loop: h.loop || "main" }))] };
|
|
124012
|
+
}
|
|
124013
|
+
function readContextsWorked(q, config, summaryScan = readSummaryScan(q)) {
|
|
124014
|
+
let threshold = (loop) => resolveLoopThreshold(config, loop), loops = /* @__PURE__ */ new Set(["main", ...(config.loops ?? []).map((l) => l?.name).filter((n) => typeof n == "string" && !!n)]), live = safeOr(
|
|
124015
|
+
q,
|
|
124016
|
+
"SELECT loop, COUNT(*) AS n FROM adf_loop GROUP BY loop",
|
|
124017
|
+
(r) => r,
|
|
124018
|
+
() => safe(q, "SELECT 'main' AS loop, COUNT(*) AS n FROM adf_loop", (r) => r, [])
|
|
124019
|
+
), liveRows = /* @__PURE__ */ new Map();
|
|
124020
|
+
for (let r of live) {
|
|
124021
|
+
let name21 = r.loop || "main";
|
|
124022
|
+
liveRows.set(name21, (liveRows.get(name21) ?? 0) + r.n), loops.add(name21);
|
|
124023
|
+
}
|
|
124024
|
+
let archived = /* @__PURE__ */ new Map();
|
|
124025
|
+
for (let r of safe(q, `SELECT source, size_bytes AS bytes FROM adf_audit WHERE ${LOOP_AUDIT_WHERE2}`, (rows) => rows, [])) {
|
|
124026
|
+
let name21 = loopOfSource2(r.source);
|
|
124027
|
+
loops.add(name21);
|
|
124028
|
+
let bytes = typeof r.bytes == "number" ? r.bytes : 0;
|
|
124029
|
+
archived.set(name21, (archived.get(name21) ?? 0) + clamp01(bytes / 4 / (threshold(name21) * FULL_SNAPSHOT_SHARE)));
|
|
124030
|
+
}
|
|
124031
|
+
let summaries = /* @__PURE__ */ new Map();
|
|
124032
|
+
for (let h of summaryScan.hits) summaries.set(h.loop, (summaries.get(h.loop) ?? 0) + 1);
|
|
124033
|
+
let baselines = /* @__PURE__ */ new Map();
|
|
124034
|
+
for (let r of safe(q, `SELECT key, value FROM adf_meta WHERE key = '${BASELINE_KEY}' OR key LIKE '${BASELINE_KEY}:%'`, (rows) => rows, []))
|
|
124035
|
+
try {
|
|
124036
|
+
let tokens = JSON.parse(r.value).tokens;
|
|
124037
|
+
typeof tokens == "number" && Number.isFinite(tokens) && baselines.set(r.key === BASELINE_KEY ? "main" : r.key.slice(BASELINE_KEY.length + 1), tokens);
|
|
124038
|
+
} catch {
|
|
124039
|
+
}
|
|
124040
|
+
let total = 0;
|
|
124041
|
+
for (let loop of loops) {
|
|
124042
|
+
if (total += Math.max(archived.get(loop) ?? 0, summaries.get(loop) ?? 0), !liveRows.get(loop)) continue;
|
|
124043
|
+
let tokens = baselines.get(loop);
|
|
124044
|
+
if (tokens === void 0) {
|
|
124045
|
+
let bytesSql = (where) => `SELECT SUM(octet_length(content_json)) AS n FROM adf_loop ${where}`;
|
|
124046
|
+
tokens = (loop === "main" ? safeOr(q, bytesSql("WHERE loop = 'main'"), (r) => firstNumber2(r), () => safe(q, bytesSql(""), (r) => firstNumber2(r), 0)) : safe(q, bytesSql("WHERE loop = ?"), (r) => firstNumber2(r), 0, [loop])) / 4;
|
|
124047
|
+
}
|
|
124048
|
+
total += clamp01(tokens / threshold(loop));
|
|
124049
|
+
}
|
|
124050
|
+
return Math.round(total * 100) / 100;
|
|
124051
|
+
}
|
|
124052
|
+
function readOwnerVerified(q, did) {
|
|
124053
|
+
if (!did) return !1;
|
|
124054
|
+
let rows = safe(q, "SELECT raw_json FROM adf_attestations", (r) => r, []);
|
|
124055
|
+
for (let r of rows) {
|
|
124056
|
+
let att = null;
|
|
124057
|
+
try {
|
|
124058
|
+
att = JSON.parse(r.raw_json);
|
|
124059
|
+
} catch {
|
|
124060
|
+
att = null;
|
|
124061
|
+
}
|
|
124062
|
+
if (att && att.role === "owner" && verifyAttestation(att, { expectedSubject: did })) return !0;
|
|
124063
|
+
}
|
|
124064
|
+
return !1;
|
|
124065
|
+
}
|
|
124066
|
+
function readVitalsCheapPart(q) {
|
|
124067
|
+
let config = safe(
|
|
124068
|
+
q,
|
|
124069
|
+
"SELECT config_json FROM adf_config WHERE id = 1",
|
|
124070
|
+
(rows) => {
|
|
124071
|
+
let raw = rows[0]?.config_json;
|
|
124072
|
+
return raw ? JSON.parse(raw) : {};
|
|
124073
|
+
},
|
|
124074
|
+
{}
|
|
124075
|
+
), metaMap = safe(
|
|
124076
|
+
q,
|
|
124077
|
+
"SELECT key, value FROM adf_meta WHERE key IN ('adf_handle','adf_name','status','adf_did','adf_did_history','adf_parent_did','adf_created_at')",
|
|
124078
|
+
(rows) => new Map(rows.map((r) => [r.key, r.value])),
|
|
124079
|
+
/* @__PURE__ */ new Map()
|
|
124080
|
+
), getMeta = (k) => metaMap.get(k) ?? null, meta = {
|
|
124081
|
+
handle: getMeta("adf_handle") || config.handle || null,
|
|
124082
|
+
name: getMeta("adf_name") || config.name || null,
|
|
124083
|
+
icon: config.icon ?? null,
|
|
124084
|
+
model: config.model?.model_id || null,
|
|
124085
|
+
status: getMeta("status"),
|
|
124086
|
+
did: getMeta("adf_did") || null,
|
|
124087
|
+
didHistory: parseDidHistory(getMeta("adf_did_history")),
|
|
124088
|
+
agentId: config.id ?? null,
|
|
124089
|
+
parentDid: getMeta("adf_parent_did") || null,
|
|
124090
|
+
createdAt: getMeta("adf_created_at") || config.metadata?.created_at || null
|
|
124091
|
+
}, identity = safe(
|
|
124092
|
+
q,
|
|
124093
|
+
"SELECT purpose, encryption_algo FROM adf_identity",
|
|
124094
|
+
(rows) => rows,
|
|
124095
|
+
[]
|
|
124096
|
+
), credentials = { plain: 0, sealed: 0 }, privateKey = "none";
|
|
124097
|
+
for (let r of identity) {
|
|
124098
|
+
let sealed = !!r.encryption_algo && r.encryption_algo !== "plain";
|
|
124099
|
+
if (r.purpose === "crypto:signing:private_key") privateKey = sealed ? "sealed" : "plain";
|
|
124100
|
+
else {
|
|
124101
|
+
if (r.purpose.startsWith("crypto:")) continue;
|
|
124102
|
+
sealed ? credentials.sealed++ : credentials.plain++;
|
|
124103
|
+
}
|
|
124104
|
+
}
|
|
124105
|
+
let timerRows = safeOr(
|
|
124106
|
+
q,
|
|
124107
|
+
"SELECT schedule_json, next_wake_at FROM adf_timers WHERE expired = 0",
|
|
124108
|
+
(rows) => rows,
|
|
124109
|
+
() => safe(q, "SELECT schedule_json, next_wake_at FROM adf_timers", (rows) => rows, [])
|
|
124110
|
+
), fastestIntervalMs, nextWakeAt;
|
|
124111
|
+
for (let t of timerRows) {
|
|
124112
|
+
typeof t.next_wake_at == "number" && (nextWakeAt === void 0 || t.next_wake_at < nextWakeAt) && (nextWakeAt = t.next_wake_at);
|
|
124113
|
+
let schedule = null;
|
|
124114
|
+
try {
|
|
124115
|
+
schedule = JSON.parse(t.schedule_json);
|
|
124116
|
+
} catch {
|
|
124117
|
+
schedule = null;
|
|
124118
|
+
}
|
|
124119
|
+
let every = scheduleIntervalMs(schedule);
|
|
124120
|
+
every !== void 0 && (fastestIntervalMs === void 0 || every < fastestIntervalMs) && (fastestIntervalMs = every);
|
|
124121
|
+
}
|
|
124122
|
+
let messages = Math.max(
|
|
124123
|
+
safe(q, "SELECT seq AS n FROM sqlite_sequence WHERE name = 'adf_loop'", (r) => firstNumber2(r), 0),
|
|
124124
|
+
safe(q, "SELECT MAX(seq) AS n FROM adf_loop", (r) => firstNumber2(r), 0)
|
|
124125
|
+
), metrics = safe(
|
|
124126
|
+
q,
|
|
124127
|
+
"SELECT key, value FROM adf_meta WHERE key LIKE 'metric:%' ORDER BY key LIMIT 20",
|
|
124128
|
+
(rows) => rows.map((r) => parseMetric(r.key.slice(7), r.value)),
|
|
124129
|
+
[]
|
|
124130
|
+
);
|
|
124131
|
+
return {
|
|
124132
|
+
config,
|
|
124133
|
+
meta,
|
|
124134
|
+
power: powerInputsFromConfig(config, {
|
|
124135
|
+
credentials,
|
|
124136
|
+
privateKey,
|
|
124137
|
+
timers: { active: timerRows.length, fastestIntervalMs }
|
|
124138
|
+
}),
|
|
124139
|
+
messages,
|
|
124140
|
+
metrics,
|
|
124141
|
+
nextWakeAt,
|
|
124142
|
+
card: {
|
|
124143
|
+
...config.description?.trim() ? { description: config.description.trim() } : {},
|
|
124144
|
+
public: config.serving?.public?.enabled ?? !1,
|
|
124145
|
+
ownerVerified: readOwnerVerified(q, meta.did)
|
|
124146
|
+
}
|
|
124147
|
+
};
|
|
124148
|
+
}
|
|
124149
|
+
function readVitalsHeavyPart(q, cheap, prior) {
|
|
124150
|
+
let cutoff = agentWriteCutoff(cheap.meta.createdAt), { mine, agentSkills } = classifyFiles(
|
|
124151
|
+
safe(q, "SELECT path, updated_at FROM adf_files", (rows) => rows, []),
|
|
124152
|
+
cutoff,
|
|
124153
|
+
readRegistrySkills(q)
|
|
124154
|
+
), filesWritten = mine.filter((f) => !f.path.startsWith("mind/")).length, mindFiles = safe(q, "SELECT path, size FROM adf_files WHERE path LIKE 'mind/%'", (rows) => rows, []), memoryTokens = Math.round(mindFiles.reduce((n, f) => n + memoryBytes(f.path, f.size), 0) / 4), tables = listLocalTables(q), localRows = 0;
|
|
124155
|
+
for (let t of tables.slice(0, MAX_TABLES)) localRows += safe(q, `SELECT COUNT(*) AS n FROM "${t}"`, (r) => firstNumber2(r), 0);
|
|
124156
|
+
let summaryScan = readSummaryScan(q, prior);
|
|
124157
|
+
return {
|
|
124158
|
+
maturity: {
|
|
124159
|
+
contextsWorked: readContextsWorked(q, cheap.config, summaryScan),
|
|
124160
|
+
filesWritten,
|
|
124161
|
+
memoryTokens,
|
|
124162
|
+
localTables: tables.length,
|
|
124163
|
+
localRows,
|
|
124164
|
+
skills: agentSkills.size
|
|
124165
|
+
},
|
|
124166
|
+
summaryScan
|
|
124167
|
+
};
|
|
124168
|
+
}
|
|
124169
|
+
var WEEK_MS = 10080 * 60 * 1e3, approxTokens = (bytes) => Math.round(bytes / 4), DAY_MS2 = 1440 * 60 * 1e3;
|
|
124170
|
+
function readMemoryStrata(q, now2 = Date.now()) {
|
|
124171
|
+
let since = (days) => new Date(now2 - days * DAY_MS2).toISOString(), week = since(MEMORY_STRATA_DAYS.week), month = since(MEMORY_STRATA_DAYS.month), quarter = since(MEMORY_STRATA_DAYS.quarter), bytes = { older: 0, quarter: 0, month: 0, week: 0 }, rows = safe(q, "SELECT path, size, updated_at FROM adf_files WHERE path LIKE 'mind/%'", (r) => r, []);
|
|
124172
|
+
for (let r of rows) {
|
|
124173
|
+
let at = String(r.updated_at ?? ""), band = at >= week ? "week" : at >= month ? "month" : at >= quarter ? "quarter" : "older";
|
|
124174
|
+
bytes[band] += memoryBytes(r.path, r.size);
|
|
124175
|
+
}
|
|
124176
|
+
return { older: approxTokens(bytes.older), quarter: approxTokens(bytes.quarter), month: approxTokens(bytes.month), week: approxTokens(bytes.week) };
|
|
124177
|
+
}
|
|
124178
|
+
function readContents(q, files, agentSkills, now2 = Date.now()) {
|
|
124179
|
+
let weekAgo = now2 - WEEK_MS, mindFiles = 0, mindBytes = 0, mindRecent = 0, skillBytes = 0;
|
|
124180
|
+
for (let f of files) {
|
|
124181
|
+
let size = typeof f.size == "number" && Number.isFinite(f.size) ? f.size : 0;
|
|
124182
|
+
if (f.path.startsWith("mind/")) {
|
|
124183
|
+
mindFiles++, mindBytes += memoryBytes(f.path, size), Date.parse(f.updated_at) >= weekAgo && mindRecent++;
|
|
124184
|
+
continue;
|
|
124185
|
+
}
|
|
124186
|
+
let skill = SKILL_FILE.exec(f.path)?.[1];
|
|
124187
|
+
skill && agentSkills.has(skill) && (skillBytes += size);
|
|
124188
|
+
}
|
|
124189
|
+
let tables = listLocalTables(q).slice(0, MAX_TABLES), rows = 0;
|
|
124190
|
+
for (let t of tables) rows += safe(q, `SELECT COUNT(*) AS n FROM "${t}"`, (r) => firstNumber2(r), 0);
|
|
124191
|
+
return {
|
|
124192
|
+
mind: { files: mindFiles, tokens: approxTokens(mindBytes), updatedThisWeek: mindRecent, strata: readMemoryStrata(q, now2) },
|
|
124193
|
+
skills: { count: agentSkills.size, tokens: approxTokens(skillBytes) },
|
|
124194
|
+
tables: { count: tables.length, rows }
|
|
124195
|
+
};
|
|
124196
|
+
}
|
|
124197
|
+
function upcomingText(v) {
|
|
124198
|
+
if (!(typeof v != "string" || !v.trim()))
|
|
124199
|
+
return v.length > 1e3 ? `${v.slice(0, 999)}\u2026` : v;
|
|
124200
|
+
}
|
|
124201
|
+
function readUpcoming(q) {
|
|
124202
|
+
let readTimers = (cols, where) => safe(q, `SELECT ${cols} FROM adf_timers ${where} ORDER BY next_wake_at LIMIT 3`, (r) => r, null);
|
|
124203
|
+
return (readTimers("id, next_wake_at, scope, payload, lambda, loop", "WHERE expired = 0") ?? readTimers("id, next_wake_at, scope, payload, lambda, NULL AS loop", "WHERE expired = 0") ?? readTimers("id, next_wake_at, scope, payload, lambda, NULL AS loop", "") ?? []).map((t) => {
|
|
124204
|
+
let scope = "system";
|
|
124205
|
+
try {
|
|
124206
|
+
let parsed = JSON.parse(t.scope ?? "[]");
|
|
124207
|
+
Array.isArray(parsed) && parsed[0] === "agent" && (scope = "agent");
|
|
124208
|
+
} catch {
|
|
124209
|
+
}
|
|
124210
|
+
let text2 = upcomingText(t.payload);
|
|
124211
|
+
return scope === "agent" ? { id: t.id, at: t.next_wake_at, scope, loop: t.loop || "main", ...text2 ? { prompt: text2 } : {} } : { id: t.id, at: t.next_wake_at, scope, ...t.lambda ? { lambda: t.lambda } : {}, ...text2 ? { input: text2 } : {} };
|
|
124212
|
+
});
|
|
124213
|
+
}
|
|
124214
|
+
function readActivityHeavy(q, now2, prior) {
|
|
124215
|
+
let createdAt = safe(
|
|
124216
|
+
q,
|
|
124217
|
+
"SELECT COALESCE((SELECT value FROM adf_meta WHERE key = 'adf_created_at'), (SELECT json_extract(config_json, '$.metadata.created_at') FROM adf_config WHERE id = 1)) AS v",
|
|
124218
|
+
(r) => r[0]?.v ?? null,
|
|
124219
|
+
null
|
|
124220
|
+
), cutoff = agentWriteCutoff(createdAt), files = safe(q, "SELECT path, updated_at, size FROM adf_files", (rows) => rows, []), { agentSkills } = classifyFiles(files, cutoff, readRegistrySkills(q)), { daily, scan } = readDailyActivity(q, now2, prior);
|
|
124221
|
+
return { daily, contents: readContents(q, files, agentSkills, now2), dayScan: scan };
|
|
124222
|
+
}
|
|
124223
|
+
var LIVE_MIN_INTERVAL_MS = 2e3, HEAVY_MIN_AGE_MS = 3e4, SUMMARY_SCAN_CHUNK = 2e3, DAY_SCAN_CHUNK = 2e3, FORCE_MIN_INTERVAL_MS = 2e3, AgentVitalsService = class {
|
|
124224
|
+
constructor(deps) {
|
|
124225
|
+
this.deps = deps;
|
|
124226
|
+
}
|
|
124227
|
+
deps;
|
|
124228
|
+
// Ghost metadata cache, keyed by file path. Two jobs:
|
|
124229
|
+
// 1. Perf — the 5s fleet poll would otherwise open every offline agent's
|
|
124230
|
+
// SQLite each cycle; unchanged mtime serves from memory.
|
|
124231
|
+
// 2. Stability — a peek can fail transiently (SQLITE_BUSY while an agent
|
|
124232
|
+
// is mass-starting and writing its own file). Serving the last good
|
|
124233
|
+
// meta instead of dropping the entry stops agents blinking off the map.
|
|
124234
|
+
fleetMetaCache = /* @__PURE__ */ new Map();
|
|
124235
|
+
// First-observed time of each agent's current status line (for status age)
|
|
124236
|
+
statusSinceMap = /* @__PURE__ */ new Map();
|
|
124237
|
+
/** Last fleet result, for the spawned-children count. */
|
|
124238
|
+
lastFleet = null;
|
|
124239
|
+
lastFleetAt = 0;
|
|
124240
|
+
slowCache = /* @__PURE__ */ new Map();
|
|
124241
|
+
activityCache = /* @__PURE__ */ new Map();
|
|
124242
|
+
/**
|
|
124243
|
+
* Per-row adf_loop scan of the activity window per file, shared by the
|
|
124244
|
+
* vitals (7-day cost) and activity (per-day chart) reads; makes the next
|
|
124245
|
+
* one incremental.
|
|
124246
|
+
*/
|
|
124247
|
+
dayScans = /* @__PURE__ */ new Map();
|
|
124248
|
+
/** In-flight cold day scans, so a vitals and an activity read share one. */
|
|
124249
|
+
dayScanWarming = /* @__PURE__ */ new Map();
|
|
124250
|
+
/** Last compaction-summary scan per file; makes the next one incremental. */
|
|
124251
|
+
summaryScans = /* @__PURE__ */ new Map();
|
|
124252
|
+
workspaceIds = /* @__PURE__ */ new WeakMap();
|
|
124253
|
+
nextWorkspaceId = 1;
|
|
124254
|
+
now() {
|
|
124255
|
+
return this.deps.now ? this.deps.now() : Date.now();
|
|
124256
|
+
}
|
|
124257
|
+
peekFleetMetaCached(filePath) {
|
|
124258
|
+
let mtimeMs;
|
|
124259
|
+
try {
|
|
124260
|
+
mtimeMs = statSync10(filePath).mtimeMs;
|
|
124261
|
+
} catch {
|
|
124262
|
+
return this.fleetMetaCache.delete(filePath), null;
|
|
124263
|
+
}
|
|
124264
|
+
let cached = this.fleetMetaCache.get(filePath);
|
|
124265
|
+
if (cached && cached.mtimeMs === mtimeMs) return cached.meta;
|
|
124266
|
+
let meta = AdfDatabase.peekFleetMeta(filePath);
|
|
124267
|
+
return meta ? (this.fleetMetaCache.set(filePath, { mtimeMs, meta }), meta) : cached?.meta ?? null;
|
|
124268
|
+
}
|
|
124269
|
+
// Fleet map: live mesh agents plus on-disk .adf files in tracked
|
|
124270
|
+
// directories that have no running executor ("ghost" nodes). Works even
|
|
124271
|
+
// with the mesh disabled — every on-disk agent is then a ghost.
|
|
124272
|
+
async getFleetStatus() {
|
|
124273
|
+
let deps = this.deps, running = deps.isMeshRunning(), agents = deps.getLiveMeshAgents().map((a) => {
|
|
124274
|
+
let ctx = deps.getContextGauge(a.filePath);
|
|
124275
|
+
return {
|
|
124276
|
+
...a,
|
|
124277
|
+
online: !0,
|
|
124278
|
+
contextTokens: ctx && ctx.tokens > 0 ? ctx.tokens : void 0,
|
|
124279
|
+
contextThreshold: ctx && ctx.tokens > 0 ? ctx.threshold : void 0,
|
|
124280
|
+
// Standing boundary links — open WS pipes render as dashed channel
|
|
124281
|
+
// edges to the perimeter, distinct from request traffic
|
|
124282
|
+
wsConnections: deps.getWsConnectionCount(a.filePath)
|
|
124283
|
+
};
|
|
124284
|
+
}), trackedDirs2 = deps.getTrackedDirectories(), maxDepth = deps.getMaxScanDepth(), seen = new Set(agents.map((a) => canonicalizePath(a.filePath))), findGhostTrackedDirRoot = (filePath) => {
|
|
124285
|
+
let canonFile = canonicalizePath(filePath), longestMatch, longestLen = -1;
|
|
124286
|
+
for (let dir of trackedDirs2) {
|
|
124287
|
+
let canonDir = canonicalizePath(dir);
|
|
124288
|
+
containsPath(canonDir, canonFile) && canonDir.length > longestLen && (longestMatch = dir, longestLen = canonDir.length);
|
|
124289
|
+
}
|
|
124290
|
+
return longestMatch;
|
|
124291
|
+
}, liveExecStates = /* @__PURE__ */ new Map();
|
|
124292
|
+
for (let s of deps.getLiveExecStates()) liveExecStates.set(canonicalizePath(s.filePath), s.state);
|
|
124293
|
+
let liveWorkspaces = /* @__PURE__ */ new Map();
|
|
124294
|
+
for (let w of deps.getOpenWorkspaces()) liveWorkspaces.set(canonicalizePath(w.filePath), w.workspace);
|
|
124295
|
+
for (let dir of trackedDirs2) {
|
|
124296
|
+
let filePaths = await deps.listAdfFiles(dir, maxDepth);
|
|
124297
|
+
for (let filePath of filePaths) {
|
|
124298
|
+
let canon2 = canonicalizePath(filePath);
|
|
124299
|
+
if (seen.has(canon2)) continue;
|
|
124300
|
+
seen.add(canon2);
|
|
124301
|
+
let openWorkspace = liveWorkspaces.get(canon2), meta = (openWorkspace ? liveFleetMeta(openWorkspace) : null) ?? this.peekFleetMetaCached(filePath);
|
|
124302
|
+
if (!meta) continue;
|
|
124303
|
+
let live = liveExecStates.get(canon2), isLive = live !== void 0 && live !== "off", ctx = isLive ? deps.getContextGauge(filePath) : void 0;
|
|
124304
|
+
agents.push({
|
|
124305
|
+
filePath,
|
|
124306
|
+
handle: meta.handle || deriveHandle(filePath),
|
|
124307
|
+
did: meta.did ?? void 0,
|
|
124308
|
+
agentId: meta.agentId ?? void 0,
|
|
124309
|
+
parentDid: meta.parentDid ?? void 0,
|
|
124310
|
+
didHistory: meta.didHistory.length > 0 ? meta.didHistory : void 0,
|
|
124311
|
+
icon: meta.icon ?? void 0,
|
|
124312
|
+
state: isLive ? live : "off",
|
|
124313
|
+
status: meta.status ?? void 0,
|
|
124314
|
+
model: meta.model ?? void 0,
|
|
124315
|
+
trackedDirRoot: findGhostTrackedDirRoot(filePath),
|
|
124316
|
+
createdAt: meta.createdAt ?? void 0,
|
|
124317
|
+
participating: !1,
|
|
124318
|
+
online: isLive,
|
|
124319
|
+
contextTokens: ctx && ctx.tokens > 0 ? ctx.tokens : void 0,
|
|
124320
|
+
contextThreshold: ctx && ctx.tokens > 0 ? ctx.threshold : void 0
|
|
124321
|
+
});
|
|
124322
|
+
}
|
|
124323
|
+
}
|
|
124324
|
+
let now2 = this.now();
|
|
124325
|
+
for (let a of agents) {
|
|
124326
|
+
if (!a.status) {
|
|
124327
|
+
this.statusSinceMap.delete(a.filePath);
|
|
124328
|
+
continue;
|
|
124329
|
+
}
|
|
124330
|
+
let prev = this.statusSinceMap.get(a.filePath);
|
|
124331
|
+
(!prev || prev.value !== a.status) && this.statusSinceMap.set(a.filePath, { value: a.status, since: now2 }), a.statusSince = this.statusSinceMap.get(a.filePath).since;
|
|
124332
|
+
}
|
|
124333
|
+
return this.lastFleet = agents, this.lastFleetAt = now2, { running, agents };
|
|
124334
|
+
}
|
|
124335
|
+
/**
|
|
124336
|
+
* Redo the fleet scan behind agentsSpawned when it is missing or older than
|
|
124337
|
+
* `maxAgeMs` (always when `force`). Studio's fleet map polls it anyway; a
|
|
124338
|
+
* vitals read with the map closed, or from the daemon, refreshes it here so
|
|
124339
|
+
* the Experience level does not depend on which screen was opened first.
|
|
124340
|
+
*/
|
|
124341
|
+
async ensureFleetScan(maxAgeMs, force = !1) {
|
|
124342
|
+
!force && this.lastFleet && this.now() - this.lastFleetAt <= maxAgeMs || await this.getFleetStatus();
|
|
124343
|
+
}
|
|
124344
|
+
findOpenWorkspace(filePath) {
|
|
124345
|
+
let canon2 = canonicalizePath(filePath), found;
|
|
124346
|
+
for (let w of this.deps.getOpenWorkspaces())
|
|
124347
|
+
canonicalizePath(w.filePath) === canon2 && (found = w.workspace);
|
|
124348
|
+
return found;
|
|
124349
|
+
}
|
|
124350
|
+
workspaceId(ws) {
|
|
124351
|
+
let id = this.workspaceIds.get(ws);
|
|
124352
|
+
return id === void 0 && (id = this.nextWorkspaceId++, this.workspaceIds.set(ws, id)), id;
|
|
124353
|
+
}
|
|
124354
|
+
/** Drop the cached slow part (e.g. after a config change made elsewhere). */
|
|
124355
|
+
invalidate(filePath) {
|
|
124356
|
+
filePath ? (this.slowCache.delete(filePath), this.activityCache.delete(filePath), this.dayScans.delete(filePath), this.summaryScans.delete(filePath)) : (this.slowCache.clear(), this.activityCache.clear(), this.dayScans.clear(), this.summaryScans.clear());
|
|
124357
|
+
}
|
|
124358
|
+
/**
|
|
124359
|
+
* One cached read in two parts against one connection. Live agents: keyed by
|
|
124360
|
+
* the connection's total_changes() (any write — a finished turn, a config
|
|
124361
|
+
* change — bumps it), re-read at most every LIVE_MIN_INTERVAL_MS. Files
|
|
124362
|
+
* nobody has open: keyed by the file's and its WAL's mtime/size, read with
|
|
124363
|
+
* one readonly peek. A new key re-reads `cheap`; `heavy` (the scans) is
|
|
124364
|
+
* reused until it is HEAVY_MIN_AGE_MS old. `force` re-reads `cheap` always
|
|
124365
|
+
* and `heavy` unless it is younger than FORCE_MIN_INTERVAL_MS. `salt` (the
|
|
124366
|
+
* activity read's local day) drops both when it changes.
|
|
124367
|
+
*/
|
|
124368
|
+
async splitRead(cache2, filePath, force, readCheap, readHeavy, salt = "") {
|
|
124369
|
+
await new Promise((resolve15) => setImmediate(resolve15));
|
|
124370
|
+
let ws = this.findOpenWorkspace(filePath), cached = cache2.get(filePath), fresh = cached && cached.salt === salt ? cached : void 0, now2 = this.now(), key;
|
|
124371
|
+
if (ws) {
|
|
124372
|
+
if (!force && fresh?.key.startsWith("live:") && now2 - fresh.at < LIVE_MIN_INTERVAL_MS) return { entry: fresh, live: !0 };
|
|
124373
|
+
let changes = safe(ws.querySQL.bind(ws), "SELECT total_changes() AS n", (r) => firstNumber2(r), -1);
|
|
124374
|
+
key = `live:${this.workspaceId(ws)}:${changes}`;
|
|
124375
|
+
} else {
|
|
124376
|
+
let [main, wal] = await Promise.all([
|
|
124377
|
+
fsp4.stat(filePath),
|
|
124378
|
+
fsp4.stat(`${filePath}-wal`).catch(() => null)
|
|
124379
|
+
]);
|
|
124380
|
+
key = `file:${main.mtimeMs}:${main.size}:${wal?.mtimeMs ?? 0}:${wal?.size ?? 0}`;
|
|
124381
|
+
}
|
|
124382
|
+
if (!force && fresh && fresh.key === key)
|
|
124383
|
+
return ws && (fresh.at = now2), { entry: fresh, live: !!ws };
|
|
124384
|
+
let heavyAge = fresh ? now2 - fresh.heavyAt : 1 / 0, reuseHeavy = fresh !== void 0 && heavyAge < (force ? FORCE_MIN_INTERVAL_MS : HEAVY_MIN_AGE_MS), run2 = (q) => {
|
|
124385
|
+
let cheap = readCheap(q);
|
|
124386
|
+
return { cheap, heavy: reuseHeavy ? fresh.heavy : readHeavy(q, cheap) };
|
|
124387
|
+
};
|
|
124388
|
+
try {
|
|
124389
|
+
let { cheap, heavy } = ws ? run2((sql, params) => ws.querySQL(sql, params)) : AdfDatabase.peek(filePath, (db) => run2((sql, params) => db.prepare(sql).all(...params ?? []))), at = this.now(), entry = { key, salt, at, cheap, heavy, heavyAt: reuseHeavy ? fresh.heavyAt : at };
|
|
124390
|
+
return cache2.set(filePath, entry), { entry, live: !!ws };
|
|
124391
|
+
} catch (err) {
|
|
124392
|
+
if (cached) return { entry: cached, live: !!ws };
|
|
124393
|
+
throw err;
|
|
124394
|
+
}
|
|
124395
|
+
}
|
|
124396
|
+
/**
|
|
124397
|
+
* A live agent's first compaction-summary scan, in SUMMARY_SCAN_CHUNK seq
|
|
124398
|
+
* ranges with the event loop free between them: the LIKE reads every user
|
|
124399
|
+
* row's content, which on a long unbroken loop is tens of milliseconds.
|
|
124400
|
+
* Later scans only read rows above the high-water mark.
|
|
124401
|
+
*/
|
|
124402
|
+
async warmSummaryScan(filePath, ws) {
|
|
124403
|
+
let q = (sql, params) => ws.querySQL(sql, params), maxSeq = safe(q, "SELECT MAX(seq) AS n FROM adf_loop", (r) => firstNumber2(r), 0), scan = { lastSeq: 0, hits: [] };
|
|
124404
|
+
for (; scan.lastSeq < maxSeq; )
|
|
124405
|
+
if (scan = readSummaryScan(q, scan, scan.lastSeq + SUMMARY_SCAN_CHUNK), await new Promise((resolve15) => setImmediate(resolve15)), this.findOpenWorkspace(filePath) !== ws) return;
|
|
124406
|
+
this.summaryScans.has(filePath) || this.summaryScans.set(filePath, scan);
|
|
124407
|
+
}
|
|
124408
|
+
/**
|
|
124409
|
+
* The first day scan of a file for the current window, in DAY_SCAN_CHUNK
|
|
124410
|
+
* seq ranges with the event loop free between them: reading created_at
|
|
124411
|
+
* walks each row's content overflow, about 3 ms per 1 000 rows. A live
|
|
124412
|
+
* agent is read through its workspace; a closed file through one readonly
|
|
124413
|
+
* peek per chunk. Later reads are incremental (refreshLoopDayScan).
|
|
124414
|
+
* Concurrent callers share one warm-up.
|
|
124415
|
+
*/
|
|
124416
|
+
warmDayScan(filePath) {
|
|
124417
|
+
let since = windowStartMs(this.now());
|
|
124418
|
+
if (this.dayScans.get(filePath)?.since === since) return Promise.resolve();
|
|
124419
|
+
let warming = this.dayScanWarming.get(filePath);
|
|
124420
|
+
return warming || (warming = this.runDayScanWarmUp(filePath, since).catch(() => {
|
|
124421
|
+
}).finally(() => this.dayScanWarming.delete(filePath)), this.dayScanWarming.set(filePath, warming)), warming;
|
|
124422
|
+
}
|
|
124423
|
+
async runDayScanWarmUp(filePath, since) {
|
|
124424
|
+
let ws = this.findOpenWorkspace(filePath), run2 = (read) => ws ? read((sql, params) => ws.querySQL(sql, params)) : AdfDatabase.peek(filePath, (db) => read((sql, params) => db.prepare(sql).all(...params ?? []))), scan = run2((q) => startLoopDayScan(q, since)), maxSeq = run2(maxLoopSeq);
|
|
124425
|
+
for (; scan.lastSeq < maxSeq; ) {
|
|
124426
|
+
if (await new Promise((resolve15) => setImmediate(resolve15)), this.findOpenWorkspace(filePath) !== ws) return;
|
|
124427
|
+
let upTo = Math.min(maxSeq, scan.lastSeq + DAY_SCAN_CHUNK);
|
|
124428
|
+
scan = run2((q) => scanLoopRows(q, scan, upTo));
|
|
124429
|
+
}
|
|
124430
|
+
this.dayScans.get(filePath)?.since !== since && this.dayScans.set(filePath, scan);
|
|
124431
|
+
}
|
|
124432
|
+
/** Children in the last fleet scan whose parent reference names this agent. */
|
|
124433
|
+
countSpawned(meta) {
|
|
124434
|
+
if (!this.lastFleet) return null;
|
|
124435
|
+
let ids = /* @__PURE__ */ new Set([...meta.did ? [meta.did] : [], ...meta.didHistory, ...meta.agentId ? [meta.agentId] : []]);
|
|
124436
|
+
return ids.size === 0 ? 0 : this.lastFleet.filter((a) => a.parentDid && ids.has(a.parentDid)).length;
|
|
124437
|
+
}
|
|
124438
|
+
async getAgentVitals(filePath, opts) {
|
|
124439
|
+
let ws = this.findOpenWorkspace(filePath);
|
|
124440
|
+
ws && !this.summaryScans.has(filePath) && await this.warmSummaryScan(filePath, ws), await this.warmDayScan(filePath);
|
|
124441
|
+
let { entry, live } = await this.splitRead(
|
|
124442
|
+
this.slowCache,
|
|
124443
|
+
filePath,
|
|
124444
|
+
!!opts?.force,
|
|
124445
|
+
readVitalsCheapPart,
|
|
124446
|
+
(q, cheap2) => {
|
|
124447
|
+
let heavy2 = readVitalsHeavyPart(q, cheap2, this.summaryScans.get(filePath));
|
|
124448
|
+
this.summaryScans.set(filePath, heavy2.summaryScan);
|
|
124449
|
+
let { daily, scan } = readDailyActivity(q, this.now(), this.dayScans.get(filePath));
|
|
124450
|
+
this.dayScans.set(filePath, scan);
|
|
124451
|
+
let cost7d = recentCost(daily);
|
|
124452
|
+
return cost7d ? { ...heavy2, cost7d } : heavy2;
|
|
124453
|
+
}
|
|
124454
|
+
), { cheap, heavy } = entry, now2 = this.now(), createdMs = cheap.meta.createdAt ? Date.parse(cheap.meta.createdAt) : NaN, ageDays = Number.isFinite(createdMs) ? Math.max(0, (now2 - createdMs) / 864e5) : 0, maturity = {
|
|
124455
|
+
...heavy.maturity,
|
|
124456
|
+
messages: cheap.messages,
|
|
124457
|
+
agentsSpawned: this.countSpawned(cheap.meta),
|
|
124458
|
+
ageDays
|
|
124459
|
+
}, ctx = live ? this.deps.getContextGauge(filePath) : void 0, cost = heavy.cost7d;
|
|
124460
|
+
return {
|
|
124461
|
+
filePath,
|
|
124462
|
+
computedAt: entry.at,
|
|
124463
|
+
live,
|
|
124464
|
+
handle: cheap.meta.handle || deriveHandle(filePath),
|
|
124465
|
+
name: cheap.meta.name ?? void 0,
|
|
124466
|
+
did: cheap.meta.did ?? void 0,
|
|
124467
|
+
agentId: cheap.meta.agentId ?? void 0,
|
|
124468
|
+
model: cheap.meta.model ?? void 0,
|
|
124469
|
+
createdAt: cheap.meta.createdAt ?? void 0,
|
|
124470
|
+
ageDays,
|
|
124471
|
+
...cheap.meta.status?.trim() ? { status: cheap.meta.status.trim() } : {},
|
|
124472
|
+
...cheap.card.description ? { description: cheap.card.description } : {},
|
|
124473
|
+
public: cheap.card.public,
|
|
124474
|
+
ownerVerified: cheap.card.ownerVerified,
|
|
124475
|
+
contextTokens: ctx && ctx.tokens > 0 ? ctx.tokens : void 0,
|
|
124476
|
+
contextThreshold: ctx && ctx.tokens > 0 ? ctx.threshold : void 0,
|
|
124477
|
+
nextWakeAt: cheap.nextWakeAt,
|
|
124478
|
+
cost7dUsd: cost ? cost.usd : void 0,
|
|
124479
|
+
cost7dPartial: cost ? cost.partial : void 0,
|
|
124480
|
+
metrics: cheap.metrics,
|
|
124481
|
+
stats: scoreAgent(cheap.power, maturity),
|
|
124482
|
+
maturity
|
|
124483
|
+
};
|
|
124484
|
+
}
|
|
124485
|
+
/**
|
|
124486
|
+
* The overview's lower sections: next wakes, 14 days of messages and cost
|
|
124487
|
+
* per day (agent-daily.ts, from the file alone), and what the file holds
|
|
124488
|
+
* (mind and skills with approximate tokens, local tables with rows). Cached
|
|
124489
|
+
* like the vitals: wakes are the cheap part, days and contents the heavy one.
|
|
124490
|
+
*/
|
|
124491
|
+
async getAgentActivity(filePath, opts) {
|
|
124492
|
+
let now2 = this.now();
|
|
124493
|
+
await this.warmDayScan(filePath);
|
|
124494
|
+
let { entry, live } = await this.splitRead(
|
|
124495
|
+
this.activityCache,
|
|
124496
|
+
filePath,
|
|
124497
|
+
!!opts?.force,
|
|
124498
|
+
(q) => ({ upcoming: readUpcoming(q) }),
|
|
124499
|
+
(q) => {
|
|
124500
|
+
let { dayScan, ...read } = readActivityHeavy(q, this.now(), this.dayScans.get(filePath));
|
|
124501
|
+
return this.dayScans.set(filePath, dayScan), read;
|
|
124502
|
+
},
|
|
124503
|
+
localDateKey(new Date(now2))
|
|
124504
|
+
);
|
|
124505
|
+
return { filePath, computedAt: entry.at, live, upcoming: entry.cheap.upcoming, ...entry.heavy };
|
|
124506
|
+
}
|
|
124507
|
+
};
|
|
124508
|
+
|
|
124509
|
+
// src/main/runtime/display-state.ts
|
|
124510
|
+
function toDisplayState(executorState) {
|
|
124511
|
+
switch (executorState) {
|
|
124512
|
+
case "thinking":
|
|
124513
|
+
case "tool_use":
|
|
124514
|
+
return "active";
|
|
124515
|
+
case "idle":
|
|
124516
|
+
return "idle";
|
|
124517
|
+
case "awaiting_approval":
|
|
124518
|
+
case "awaiting_ask":
|
|
124519
|
+
case "suspended":
|
|
124520
|
+
return "suspended";
|
|
124521
|
+
case "error":
|
|
124522
|
+
return "error";
|
|
124523
|
+
case "stopped":
|
|
124524
|
+
return "off";
|
|
124525
|
+
// ADF display states (pass-through from sys_set_state target)
|
|
124526
|
+
case "active":
|
|
124527
|
+
case "hibernate":
|
|
124528
|
+
case "off":
|
|
124529
|
+
return executorState;
|
|
124530
|
+
default:
|
|
124531
|
+
return "off";
|
|
124532
|
+
}
|
|
124533
|
+
}
|
|
124534
|
+
|
|
122177
124535
|
// src/main/daemon/tracked-dirs.ts
|
|
122178
|
-
import { existsSync as existsSync21, statSync as
|
|
124536
|
+
import { existsSync as existsSync21, statSync as statSync11 } from "node:fs";
|
|
122179
124537
|
import { basename as basename12, isAbsolute as isAbsolute6 } from "node:path";
|
|
122180
124538
|
var TrackedDirError = class extends Error {
|
|
122181
124539
|
constructor(message, statusCode, details) {
|
|
@@ -122204,7 +124562,7 @@ function sameDir(a, b) {
|
|
|
122204
124562
|
}
|
|
122205
124563
|
function isDirectory(p) {
|
|
122206
124564
|
try {
|
|
122207
|
-
return existsSync21(p) &&
|
|
124565
|
+
return existsSync21(p) && statSync11(p).isDirectory();
|
|
122208
124566
|
} catch {
|
|
122209
124567
|
return !1;
|
|
122210
124568
|
}
|
|
@@ -122226,7 +124584,7 @@ function loadedUnder(runtime2, dir) {
|
|
|
122226
124584
|
var PEEK_CACHE_MAX = 2e3, peekCache = /* @__PURE__ */ new Map();
|
|
122227
124585
|
function statStamp(path) {
|
|
122228
124586
|
try {
|
|
122229
|
-
let st =
|
|
124587
|
+
let st = statSync11(path);
|
|
122230
124588
|
return `${st.mtimeMs}:${st.size}`;
|
|
122231
124589
|
} catch {
|
|
122232
124590
|
return "-";
|
|
@@ -122380,6 +124738,76 @@ async function untrackDir(runtime2, settings2, input, opts = {}, onChanged) {
|
|
|
122380
124738
|
return { removed: match, directories, unloaded };
|
|
122381
124739
|
}
|
|
122382
124740
|
|
|
124741
|
+
// src/main/daemon/vitals-routes.ts
|
|
124742
|
+
var FLEET_SCAN_MAX_AGE_MS = 3e4;
|
|
124743
|
+
function canon(filePath) {
|
|
124744
|
+
try {
|
|
124745
|
+
return canonicalizePath(filePath);
|
|
124746
|
+
} catch {
|
|
124747
|
+
return filePath;
|
|
124748
|
+
}
|
|
124749
|
+
}
|
|
124750
|
+
function createDaemonVitalsDeps(src) {
|
|
124751
|
+
let live = () => src.runtime.listLiveAgents(), liveStates = () => live().map((a) => ({ filePath: a.filePath, state: toDisplayState(a.executorState) }));
|
|
124752
|
+
return {
|
|
124753
|
+
isMeshRunning: () => !!src.mesh?.isEnabled(),
|
|
124754
|
+
getLiveMeshAgents: () => src.mesh?.isEnabled() ? overlayLiveStates(src.mesh.getAgentStatuses(), liveStates()) : [],
|
|
124755
|
+
getTrackedDirectories: () => src.settings ? storedDirs(src.settings) : [],
|
|
124756
|
+
getMaxScanDepth: () => src.settings ? maxDepthOf(src.settings) : 5,
|
|
124757
|
+
listAdfFiles: async (dir, maxDepth) => src.runtime.scanAdfFiles([dir], maxDepth),
|
|
124758
|
+
getContextGauge: (filePath) => {
|
|
124759
|
+
let key = canon(filePath);
|
|
124760
|
+
return live().find((a) => canon(a.filePath) === key)?.getContextGauge();
|
|
124761
|
+
},
|
|
124762
|
+
getWsConnectionCount: (filePath) => src.ws && src.ws.getConnections(filePath).length || void 0,
|
|
124763
|
+
getLiveExecStates: liveStates,
|
|
124764
|
+
getOpenWorkspaces: () => live().map((a) => ({ filePath: a.filePath, workspace: a.workspace }))
|
|
124765
|
+
};
|
|
124766
|
+
}
|
|
124767
|
+
function resolveVitalsFile(id, runtime2, vitals, settings2) {
|
|
124768
|
+
let loaded = runtime2.getAgent(id);
|
|
124769
|
+
if (loaded) return { filePath: loaded.filePath };
|
|
124770
|
+
if (!settings2) return;
|
|
124771
|
+
let files = runtime2.scanAdfFiles(storedDirs(settings2), maxDepthOf(settings2)), byHandle;
|
|
124772
|
+
for (let filePath of files) {
|
|
124773
|
+
let meta = vitals.peekFleetMetaCached(filePath);
|
|
124774
|
+
if (meta) {
|
|
124775
|
+
if (meta.agentId === id) return { filePath };
|
|
124776
|
+
!byHandle && meta.handle === id && (byHandle = filePath);
|
|
124777
|
+
}
|
|
124778
|
+
}
|
|
124779
|
+
return byHandle ? { filePath: byHandle } : void 0;
|
|
124780
|
+
}
|
|
124781
|
+
function registerVitalsRoutes(server, deps) {
|
|
124782
|
+
let target = (request, reply, what) => {
|
|
124783
|
+
let force = request.query.force;
|
|
124784
|
+
if (force !== void 0 && !["1", "0", "true", "false"].includes(force))
|
|
124785
|
+
return reply.code(400).send({ error: "force must be 1, 0, true or false", code: "bad_request" }), null;
|
|
124786
|
+
let found = resolveVitalsFile(request.params.id, deps.runtime, deps.vitals, deps.settings);
|
|
124787
|
+
return found ? found.filePath ? { filePath: found.filePath, forced: force === "1" || force === "true" } : (reply.code(409).send({ error: `Agent has no .adf file; ${what} read from the file.`, code: "conflict" }), null) : (reply.code(404).send({ error: `Unknown agent "${request.params.id}"`, code: "not_found" }), null);
|
|
124788
|
+
};
|
|
124789
|
+
server.get("/agents/:id/vitals", async (request, reply) => {
|
|
124790
|
+
let t = target(request, reply, "vitals are");
|
|
124791
|
+
if (!t) return reply;
|
|
124792
|
+
try {
|
|
124793
|
+
return await deps.vitals.ensureFleetScan(FLEET_SCAN_MAX_AGE_MS, t.forced), await deps.vitals.getAgentVitals(t.filePath, { force: t.forced });
|
|
124794
|
+
} catch (err) {
|
|
124795
|
+
return fail2(reply, err);
|
|
124796
|
+
}
|
|
124797
|
+
}), server.get("/agents/:id/activity", async (request, reply) => {
|
|
124798
|
+
let t = target(request, reply, "activity is");
|
|
124799
|
+
if (!t) return reply;
|
|
124800
|
+
try {
|
|
124801
|
+
return await deps.vitals.getAgentActivity(t.filePath, { force: t.forced });
|
|
124802
|
+
} catch (err) {
|
|
124803
|
+
return fail2(reply, err);
|
|
124804
|
+
}
|
|
124805
|
+
});
|
|
124806
|
+
}
|
|
124807
|
+
function fail2(reply, err) {
|
|
124808
|
+
return reply.code(500).send({ error: err instanceof Error ? err.message : String(err) });
|
|
124809
|
+
}
|
|
124810
|
+
|
|
122383
124811
|
// src/main/daemon/http-api.ts
|
|
122384
124812
|
var AdapterAttachRequestSchema = external_exports.object({
|
|
122385
124813
|
adapterType: external_exports.string(),
|
|
@@ -122469,7 +124897,16 @@ function createDaemonHttpApi(runtime2, opts = {}) {
|
|
|
122469
124897
|
behindProxy: opts.security?.behindProxy ?? behindProxyFromEnv(),
|
|
122470
124898
|
localProof: opts.security?.localProof ?? null
|
|
122471
124899
|
};
|
|
122472
|
-
server.post("/daemon/shutdown", async (request, reply) => requireLocalCaller(request, reply, localAccess, "The daemon can be stopped") ? opts.requestShutdown ? (setTimeout(() => opts.requestShutdown?.(), 50), reply.code(202).send({ accepted: !0, pid: process.pid })) : methodNotAllowed(reply, "Shutdown is not available on this daemon.") : reply), registerIdentityRoutes(server, { identity: opts.identity, agentFactory: opts.agentFactory, localAccess }), registerTemplateRoutes(server, { agentFactory: opts.agentFactory }), registerProviderRoutes(server, { settingsStore: opts.settingsStore, providerKeys: opts.providerKeys }), registerContextRoutes(server, runtime2), server
|
|
124900
|
+
server.post("/daemon/shutdown", async (request, reply) => requireLocalCaller(request, reply, localAccess, "The daemon can be stopped") ? opts.requestShutdown ? (setTimeout(() => opts.requestShutdown?.(), 50), reply.code(202).send({ accepted: !0, pid: process.pid })) : methodNotAllowed(reply, "Shutdown is not available on this daemon.") : reply), registerIdentityRoutes(server, { identity: opts.identity, agentFactory: opts.agentFactory, localAccess }), registerTemplateRoutes(server, { agentFactory: opts.agentFactory }), registerProviderRoutes(server, { settingsStore: opts.settingsStore, providerKeys: opts.providerKeys }), registerContextRoutes(server, runtime2), registerVitalsRoutes(server, {
|
|
124901
|
+
runtime: runtime2,
|
|
124902
|
+
settings: opts.settingsStore,
|
|
124903
|
+
vitals: new AgentVitalsService(createDaemonVitalsDeps({
|
|
124904
|
+
runtime: runtime2,
|
|
124905
|
+
settings: opts.settingsStore,
|
|
124906
|
+
mesh: opts.mesh,
|
|
124907
|
+
ws: opts.wsService
|
|
124908
|
+
}))
|
|
124909
|
+
}), server.get("/events", async (request, reply) => {
|
|
122473
124910
|
if (!opts.eventBus) return unavailable2(reply, "Event bus is not configured.");
|
|
122474
124911
|
let bus = opts.eventBus, lastEventId = single2(request.headers["last-event-id"])?.trim(), sinceText = request.query.since ?? (lastEventId || void 0), since = parseOptionalInteger(sinceText);
|
|
122475
124912
|
if (sinceText !== void 0 && since === void 0)
|
|
@@ -124013,6 +126450,7 @@ var DaemonHost = class {
|
|
|
124013
126450
|
eventBus;
|
|
124014
126451
|
wsService;
|
|
124015
126452
|
networkService;
|
|
126453
|
+
mesh;
|
|
124016
126454
|
mcpPackageService;
|
|
124017
126455
|
mcpPythonPackageService;
|
|
124018
126456
|
adapterPackageService;
|
|
@@ -124029,7 +126467,7 @@ var DaemonHost = class {
|
|
|
124029
126467
|
signalHandlersInstalled = !1;
|
|
124030
126468
|
stopping = null;
|
|
124031
126469
|
constructor(opts) {
|
|
124032
|
-
this.runtime = opts.runtime, this.host = opts.host ?? "127.0.0.1", this.port = opts.port ?? 7385, this.token = opts.token ?? process.env.ADF_DAEMON_TOKEN ?? null, this.allowedHosts = opts.allowedHosts ?? parseAllowedHostsEnv(process.env.ADF_DAEMON_ALLOWED_HOSTS), this.behindProxy = opts.behindProxy, this.localProof = opts.localProof ?? null, this.pidFile = opts.pidFile, this.logger = opts.logger ?? !1, this.shutdownAgentTimeoutMs = opts.shutdownAgentTimeoutMs ?? envShutdownTimeoutMs() ?? DEFAULT_AGENT_UNLOAD_TIMEOUT_MS, this.computeService = opts.computeService, this.settingsStore = opts.settingsStore, this.eventBus = opts.eventBus, this.wsService = opts.wsService, this.networkService = opts.networkService, this.mcpPackageService = opts.mcpPackageService, this.mcpPythonPackageService = opts.mcpPythonPackageService, this.adapterPackageService = opts.adapterPackageService, this.sandboxPackageService = opts.sandboxPackageService, this.identity = opts.identity, this.providerKeys = opts.providerKeys, this.agentFactory = opts.agentFactory, this.requestShutdown = opts.requestShutdown, this.onTrackedDirectoriesChanged = opts.onTrackedDirectoriesChanged, this.onShutdownStart = opts.onShutdownStart ?? [], this.onShutdown = opts.onShutdown ?? [], this.shouldInstallSignalHandlers = opts.installSignalHandlers ?? !0;
|
|
126470
|
+
this.runtime = opts.runtime, this.host = opts.host ?? "127.0.0.1", this.port = opts.port ?? 7385, this.token = opts.token ?? process.env.ADF_DAEMON_TOKEN ?? null, this.allowedHosts = opts.allowedHosts ?? parseAllowedHostsEnv(process.env.ADF_DAEMON_ALLOWED_HOSTS), this.behindProxy = opts.behindProxy, this.localProof = opts.localProof ?? null, this.pidFile = opts.pidFile, this.logger = opts.logger ?? !1, this.shutdownAgentTimeoutMs = opts.shutdownAgentTimeoutMs ?? envShutdownTimeoutMs() ?? DEFAULT_AGENT_UNLOAD_TIMEOUT_MS, this.computeService = opts.computeService, this.settingsStore = opts.settingsStore, this.eventBus = opts.eventBus, this.wsService = opts.wsService, this.networkService = opts.networkService, this.mesh = opts.mesh, this.mcpPackageService = opts.mcpPackageService, this.mcpPythonPackageService = opts.mcpPythonPackageService, this.adapterPackageService = opts.adapterPackageService, this.sandboxPackageService = opts.sandboxPackageService, this.identity = opts.identity, this.providerKeys = opts.providerKeys, this.agentFactory = opts.agentFactory, this.requestShutdown = opts.requestShutdown, this.onTrackedDirectoriesChanged = opts.onTrackedDirectoriesChanged, this.onShutdownStart = opts.onShutdownStart ?? [], this.onShutdown = opts.onShutdown ?? [], this.shouldInstallSignalHandlers = opts.installSignalHandlers ?? !0;
|
|
124033
126471
|
}
|
|
124034
126472
|
async start() {
|
|
124035
126473
|
if (this.server) return { host: this.host, port: this.port };
|
|
@@ -124045,6 +126483,7 @@ var DaemonHost = class {
|
|
|
124045
126483
|
eventBus: this.eventBus,
|
|
124046
126484
|
wsService: this.wsService,
|
|
124047
126485
|
networkService: this.networkService,
|
|
126486
|
+
mesh: this.mesh,
|
|
124048
126487
|
mcpPackageService: this.mcpPackageService,
|
|
124049
126488
|
mcpPythonPackageService: this.mcpPythonPackageService,
|
|
124050
126489
|
adapterPackageService: this.adapterPackageService,
|
|
@@ -124251,7 +126690,7 @@ var DaemonEventBus = class {
|
|
|
124251
126690
|
|
|
124252
126691
|
// src/main/daemon/file-settings-store.ts
|
|
124253
126692
|
import { dirname as dirname17, join as join37 } from "node:path";
|
|
124254
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync17, statSync as
|
|
126693
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync17, statSync as statSync12 } from "node:fs";
|
|
124255
126694
|
|
|
124256
126695
|
// src/shared/constants/compute-defaults.ts
|
|
124257
126696
|
var DEFAULT_COMPUTE_SETTINGS = {
|
|
@@ -124318,16 +126757,23 @@ function createSettingsDefaults() {
|
|
|
124318
126757
|
// the one-time `agentTemplateForChildren` migration has already run.
|
|
124319
126758
|
theme: "light",
|
|
124320
126759
|
// Interface typeface preset + free-text family for 'custom'; see
|
|
124321
|
-
// UI_FONT_STACKS in the renderer's app.store.
|
|
124322
|
-
|
|
126760
|
+
// UI_FONT_STACKS in the renderer's app.store. 'inter-tight' is bundled;
|
|
126761
|
+
// older stores on 'system' move to it once (settings-migrations).
|
|
126762
|
+
uiFont: "inter-tight",
|
|
124323
126763
|
uiFontCustom: "",
|
|
124324
126764
|
// Electron zoom factor for the whole window (1 = 100%).
|
|
124325
126765
|
uiScale: 1,
|
|
126766
|
+
// Small agent avatars: 'orbital' (generated from the DID) or 'emoji'
|
|
126767
|
+
// (config.icon). The home and Overview orbitals ignore it.
|
|
126768
|
+
agentAvatars: "orbital",
|
|
124326
126769
|
globalSystemPrompt: DEFAULT_BASE_PROMPT,
|
|
124327
126770
|
// Dynamic instruction templates share the toolPrompts record (dyn_ keys)
|
|
124328
126771
|
// so they ride the existing settings→executor plumbing.
|
|
124329
126772
|
toolPrompts: { ...DEFAULT_TOOL_PROMPTS, ...DEFAULT_DYNAMIC_PROMPTS },
|
|
124330
126773
|
compactionPrompt: DEFAULT_COMPACTION_PROMPT,
|
|
126774
|
+
// On = a release that changes any shipped prompt overwrites all three
|
|
126775
|
+
// prompt keys above (settings-migrations applyPromptUpdates).
|
|
126776
|
+
autoApplyPromptUpdates: !1,
|
|
124331
126777
|
trackedDirectories: [],
|
|
124332
126778
|
// Empty = built-in default (Documents/adf-agents), resolved on demand.
|
|
124333
126779
|
agentsFolder: "",
|
|
@@ -124335,6 +126781,9 @@ function createSettingsDefaults() {
|
|
|
124335
126781
|
// focused. On by default: an agent blocked on a human the user cannot see
|
|
124336
126782
|
// is exactly the failure this exists to prevent.
|
|
124337
126783
|
nativeNotificationsEnabled: !0,
|
|
126784
|
+
// macOS menu bar icon: running agents, requests waiting on the user, and
|
|
126785
|
+
// today's tokens, reachable with the window closed.
|
|
126786
|
+
menuBarEnabled: !0,
|
|
124338
126787
|
// Owner opt-outs for traffic Studio starts on its own: the background
|
|
124339
126788
|
// update check (GitHub Releases), the MCP / agent registry fetches (GitHub
|
|
124340
126789
|
// raw), and provider connection checks. Off = no request; see docs/NETWORK.md.
|
|
@@ -124372,7 +126821,33 @@ Your private working memory (\`mind.md\`), snapshotted at the start of each sess
|
|
|
124372
126821
|
{{mind.md}}`;
|
|
124373
126822
|
function applySettingsMigrations(data) {
|
|
124374
126823
|
let changedKeys = /* @__PURE__ */ new Set();
|
|
124375
|
-
|
|
126824
|
+
migrateBuiltInAdapters(data) && changedKeys.add("adapters"), migrateComputeDefaults(data) && changedKeys.add("compute"), migrateToolPrompts(data) && changedKeys.add("toolPrompts"), migrateSkillsPromptPlaceholder(data) && changedKeys.add("toolPrompts"), migrateGlobalSystemPromptSoul(data) && changedKeys.add("globalSystemPrompt"), migrateGlobalSystemPromptMind(data) && changedKeys.add("globalSystemPrompt");
|
|
126825
|
+
for (let key of applyPromptUpdates(data)) changedKeys.add(key);
|
|
126826
|
+
for (let key of migrateUiFontBrandDefault(data)) changedKeys.add(key);
|
|
126827
|
+
return { changed: changedKeys.size > 0, changedKeys: [...changedKeys] };
|
|
126828
|
+
}
|
|
126829
|
+
var PROMPT_AUTO_UPDATE_KEY = "autoApplyPromptUpdates", PROMPT_DEFAULTS_APPLIED_KEY = "promptDefaultsApplied";
|
|
126830
|
+
function currentPromptDefaults() {
|
|
126831
|
+
return {
|
|
126832
|
+
globalSystemPrompt: DEFAULT_BASE_PROMPT,
|
|
126833
|
+
compactionPrompt: DEFAULT_COMPACTION_PROMPT,
|
|
126834
|
+
toolPrompts: { ...DEFAULT_TOOL_PROMPTS, ...DEFAULT_DYNAMIC_PROMPTS }
|
|
126835
|
+
};
|
|
126836
|
+
}
|
|
126837
|
+
function promptDefaultsFingerprint() {
|
|
126838
|
+
let text2 = JSON.stringify(currentPromptDefaults()), hash = 2166136261;
|
|
126839
|
+
for (let i = 0; i < text2.length; i++)
|
|
126840
|
+
hash ^= text2.charCodeAt(i), hash = Math.imul(hash, 16777619);
|
|
126841
|
+
return (hash >>> 0).toString(16).padStart(8, "0") + ":" + text2.length;
|
|
126842
|
+
}
|
|
126843
|
+
function applyPromptUpdates(data) {
|
|
126844
|
+
if (data[PROMPT_AUTO_UPDATE_KEY] !== !0) return [];
|
|
126845
|
+
let fingerprint = promptDefaultsFingerprint();
|
|
126846
|
+
return data[PROMPT_DEFAULTS_APPLIED_KEY] === fingerprint ? [] : (Object.assign(data, currentPromptDefaults()), data[PROMPT_DEFAULTS_APPLIED_KEY] = fingerprint, console.log("[Settings] Applied updated default prompts"), ["globalSystemPrompt", "compactionPrompt", "toolPrompts", PROMPT_DEFAULTS_APPLIED_KEY]);
|
|
126847
|
+
}
|
|
126848
|
+
var UI_FONT_BRAND_MIGRATION_KEY = "uiFontBrandDefaultApplied";
|
|
126849
|
+
function migrateUiFontBrandDefault(data) {
|
|
126850
|
+
return data[UI_FONT_BRAND_MIGRATION_KEY] === !0 ? [] : (data[UI_FONT_BRAND_MIGRATION_KEY] = !0, data.uiFont === void 0 || data.uiFont === "system" ? (data.uiFont = "inter-tight", [UI_FONT_BRAND_MIGRATION_KEY, "uiFont"]) : [UI_FONT_BRAND_MIGRATION_KEY]);
|
|
124376
126851
|
}
|
|
124377
126852
|
function mergeSettingsValue(current, key, value) {
|
|
124378
126853
|
return key === "compute" && value && typeof value == "object" && !Array.isArray(value) ? {
|
|
@@ -124445,7 +126920,7 @@ function recordQuarantine(originalPath, quarantinedTo) {
|
|
|
124445
126920
|
}
|
|
124446
126921
|
function fileFingerprint(path) {
|
|
124447
126922
|
try {
|
|
124448
|
-
let s =
|
|
126923
|
+
let s = statSync12(path);
|
|
124449
126924
|
return { mtimeMs: s.mtimeMs, size: s.size };
|
|
124450
126925
|
} catch {
|
|
124451
126926
|
return { mtimeMs: 0, size: 0 };
|
|
@@ -124689,7 +127164,9 @@ setMandatoryReasoningPersister((modelId) => {
|
|
|
124689
127164
|
});
|
|
124690
127165
|
var basePrompt = settings.get("globalSystemPrompt") ?? "", toolPrompts = settings.get("toolPrompts") ?? {}, compactionPrompt = settings.get("compactionPrompt") ?? void 0, trackedDirs = settings.get("trackedDirectories") ?? [], codeSandboxService = new CodeSandboxService();
|
|
124691
127166
|
codeSandboxService.setMaxWorkers(settings.get("sandboxMaxWorkers"));
|
|
124692
|
-
var sandboxPackagesService = new SandboxPackagesService()
|
|
127167
|
+
var sandboxPackagesService = new SandboxPackagesService();
|
|
127168
|
+
codeSandboxService.setUserPackages(sandboxPackagesService.getBasePath(), () => (settings.get("sandboxPackages") ?? []).map((p) => p.name));
|
|
127169
|
+
var sandboxStdlibService = new SandboxStdlibService(), podmanService = new PodmanService();
|
|
124693
127170
|
setManagedBrowserEnsurer((containerName) => podmanService.ensureManagedBrowserUp(containerName));
|
|
124694
127171
|
podmanService.setSettingsAccessor(() => readComputeSettings(settings.get("compute")));
|
|
124695
127172
|
var uvManager = new UvManager(), mcpPackageResolver = new PackageResolver("mcp-servers"), adapterPackageResolver = new PackageResolver("channel-adapters"), uvxPackageResolver = new UvxPackageResolver(uvManager);
|
|
@@ -124705,6 +127182,7 @@ settings.get("meshEnabled") !== !1 && meshManager.enableMesh();
|
|
|
124705
127182
|
var agentRuntimeBuilder = new AgentRuntimeBuilder({
|
|
124706
127183
|
settings,
|
|
124707
127184
|
codeSandboxService,
|
|
127185
|
+
sandboxPackagesService,
|
|
124708
127186
|
podmanService,
|
|
124709
127187
|
credentialEnvelopeLockedHint: daemonEncKey ? `Make the owner identity available (\`adf identity restore\` / \`adf identity unlock\`, or /identity in the TUI), or add this daemon's runtime key (${daemonEncKey.pubKeyPath}) to Studio's trusted daemon keys (trustedDaemonEncKeys) and open the agent in Studio once.` : void 0,
|
|
124710
127188
|
wsConnectionManager,
|
|
@@ -124765,6 +127243,7 @@ var loadedAgentEvents = /* @__PURE__ */ new Map(), agentFactory = new DaemonAgen
|
|
|
124765
127243
|
providerKeys: ownerIdentity.providerKeys,
|
|
124766
127244
|
eventBus,
|
|
124767
127245
|
wsService: wsConnectionManager,
|
|
127246
|
+
mesh: meshManager,
|
|
124768
127247
|
networkService: {
|
|
124769
127248
|
getStatus: () => ({
|
|
124770
127249
|
meshEnabled: meshManager.isEnabled(),
|