open-agents-ai 0.187.490 → 0.187.492
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/index.js +1231 -537
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23668,7 +23668,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
23668
23668
|
bits2int_modN: "function"
|
|
23669
23669
|
});
|
|
23670
23670
|
ecdsaOpts = Object.assign({}, ecdsaOpts);
|
|
23671
|
-
const
|
|
23671
|
+
const randomBytes25 = ecdsaOpts.randomBytes || randomBytes7;
|
|
23672
23672
|
const hmac2 = ecdsaOpts.hmac || ((key, msg) => hmac(hash, key, msg));
|
|
23673
23673
|
const { Fp, Fn } = Point;
|
|
23674
23674
|
const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
|
|
@@ -23810,7 +23810,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
|
|
|
23810
23810
|
throw new Error("invalid private key");
|
|
23811
23811
|
const seedArgs = [int2octets(d2), int2octets(h1int)];
|
|
23812
23812
|
if (extraEntropy != null && extraEntropy !== false) {
|
|
23813
|
-
const e2 = extraEntropy === true ?
|
|
23813
|
+
const e2 = extraEntropy === true ? randomBytes25(lengths.secretKey) : extraEntropy;
|
|
23814
23814
|
seedArgs.push(abytes(e2, void 0, "extraEntropy"));
|
|
23815
23815
|
}
|
|
23816
23816
|
const seed = concatBytes(...seedArgs);
|
|
@@ -60320,9 +60320,9 @@ var init_cookies = __esm({
|
|
|
60320
60320
|
|
|
60321
60321
|
// ../../../node_modules/@libp2p/http-peer-id-auth/dist/src/utils.js
|
|
60322
60322
|
function generateChallenge() {
|
|
60323
|
-
const
|
|
60324
|
-
crypto.getRandomValues(
|
|
60325
|
-
return toString2(
|
|
60323
|
+
const randomBytes25 = new Uint8Array(32);
|
|
60324
|
+
crypto.getRandomValues(randomBytes25);
|
|
60325
|
+
return toString2(randomBytes25, "base64urlpad");
|
|
60326
60326
|
}
|
|
60327
60327
|
function encodeAuthParams(params) {
|
|
60328
60328
|
const encodedParams = Object.entries(params).map(([key, value2]) => `${key}="${value2}"`).join(", ");
|
|
@@ -232436,7 +232436,7 @@ var require_websocket2 = __commonJS({
|
|
|
232436
232436
|
var http6 = __require("http");
|
|
232437
232437
|
var net5 = __require("net");
|
|
232438
232438
|
var tls2 = __require("tls");
|
|
232439
|
-
var { randomBytes:
|
|
232439
|
+
var { randomBytes: randomBytes25, createHash: createHash16 } = __require("crypto");
|
|
232440
232440
|
var { Duplex: Duplex3, Readable } = __require("stream");
|
|
232441
232441
|
var { URL: URL3 } = __require("url");
|
|
232442
232442
|
var PerMessageDeflate2 = require_permessage_deflate2();
|
|
@@ -232966,7 +232966,7 @@ var require_websocket2 = __commonJS({
|
|
|
232966
232966
|
}
|
|
232967
232967
|
}
|
|
232968
232968
|
const defaultPort = isSecure ? 443 : 80;
|
|
232969
|
-
const key =
|
|
232969
|
+
const key = randomBytes25(16).toString("base64");
|
|
232970
232970
|
const request = isSecure ? https4.request : http6.request;
|
|
232971
232971
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
232972
232972
|
let perMessageDeflate;
|
|
@@ -247331,9 +247331,9 @@ print("${sentinel}")
|
|
|
247331
247331
|
if (!this.proc || this.proc.killed) {
|
|
247332
247332
|
return { success: false, path: "" };
|
|
247333
247333
|
}
|
|
247334
|
-
const { mkdirSync:
|
|
247334
|
+
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
|
|
247335
247335
|
const sessionDir = join28(this.cwd, ".oa", "rlm");
|
|
247336
|
-
|
|
247336
|
+
mkdirSync67(sessionDir, { recursive: true });
|
|
247337
247337
|
const sessionPath2 = join28(sessionDir, "session.json");
|
|
247338
247338
|
try {
|
|
247339
247339
|
const inspectCode = `
|
|
@@ -247357,7 +247357,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
247357
247357
|
trajectoryCount: this.trajectory.length,
|
|
247358
247358
|
subCallCount: this.subCallCount
|
|
247359
247359
|
};
|
|
247360
|
-
|
|
247360
|
+
writeFileSync59(sessionPath2, JSON.stringify(sessionData, null, 2), "utf8");
|
|
247361
247361
|
return { success: true, path: sessionPath2 };
|
|
247362
247362
|
}
|
|
247363
247363
|
} catch {
|
|
@@ -247369,11 +247369,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
247369
247369
|
* what was previously computed. */
|
|
247370
247370
|
async loadSessionInfo() {
|
|
247371
247371
|
try {
|
|
247372
|
-
const { readFileSync:
|
|
247372
|
+
const { readFileSync: readFileSync83, existsSync: existsSync103 } = await import("node:fs");
|
|
247373
247373
|
const sessionPath2 = join28(this.cwd, ".oa", "rlm", "session.json");
|
|
247374
|
-
if (!
|
|
247374
|
+
if (!existsSync103(sessionPath2))
|
|
247375
247375
|
return null;
|
|
247376
|
-
return JSON.parse(
|
|
247376
|
+
return JSON.parse(readFileSync83(sessionPath2, "utf8"));
|
|
247377
247377
|
} catch {
|
|
247378
247378
|
return null;
|
|
247379
247379
|
}
|
|
@@ -247550,10 +247550,10 @@ var init_memory_metabolism = __esm({
|
|
|
247550
247550
|
const trajDir = join29(this.cwd, ".oa", "rlm-trajectories");
|
|
247551
247551
|
let lessons = [];
|
|
247552
247552
|
try {
|
|
247553
|
-
const { readdirSync: readdirSync37, readFileSync:
|
|
247553
|
+
const { readdirSync: readdirSync37, readFileSync: readFileSync83 } = await import("node:fs");
|
|
247554
247554
|
const files = readdirSync37(trajDir).filter((f2) => f2.endsWith(".jsonl")).sort().reverse().slice(0, 3);
|
|
247555
247555
|
for (const file of files) {
|
|
247556
|
-
const lines =
|
|
247556
|
+
const lines = readFileSync83(join29(trajDir, file), "utf8").split("\n").filter((l2) => l2.trim());
|
|
247557
247557
|
for (const line of lines) {
|
|
247558
247558
|
try {
|
|
247559
247559
|
const entry = JSON.parse(line);
|
|
@@ -247937,14 +247937,14 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
|
|
|
247937
247937
|
* Optionally filter by task type for phase-aware context (FSM paper insight).
|
|
247938
247938
|
*/
|
|
247939
247939
|
getTopMemoriesSync(k = 5, taskType) {
|
|
247940
|
-
const { readFileSync:
|
|
247940
|
+
const { readFileSync: readFileSync83, existsSync: existsSync103 } = __require("node:fs");
|
|
247941
247941
|
const metaDir = join29(this.cwd, ".oa", "memory", "metabolism");
|
|
247942
247942
|
const storeFile = join29(metaDir, "store.json");
|
|
247943
|
-
if (!
|
|
247943
|
+
if (!existsSync103(storeFile))
|
|
247944
247944
|
return "";
|
|
247945
247945
|
let store2 = [];
|
|
247946
247946
|
try {
|
|
247947
|
-
store2 = JSON.parse(
|
|
247947
|
+
store2 = JSON.parse(readFileSync83(storeFile, "utf8"));
|
|
247948
247948
|
} catch {
|
|
247949
247949
|
return "";
|
|
247950
247950
|
}
|
|
@@ -247966,14 +247966,14 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
|
|
|
247966
247966
|
/** Update memory scores based on task outcome. Called after task completion.
|
|
247967
247967
|
* Memories used in successful tasks get boosted. Memories present during failures get decayed. */
|
|
247968
247968
|
updateFromOutcomeSync(surfacedMemoryText, succeeded) {
|
|
247969
|
-
const { readFileSync:
|
|
247969
|
+
const { readFileSync: readFileSync83, writeFileSync: writeFileSync59, existsSync: existsSync103, mkdirSync: mkdirSync67 } = __require("node:fs");
|
|
247970
247970
|
const metaDir = join29(this.cwd, ".oa", "memory", "metabolism");
|
|
247971
247971
|
const storeFile = join29(metaDir, "store.json");
|
|
247972
|
-
if (!
|
|
247972
|
+
if (!existsSync103(storeFile))
|
|
247973
247973
|
return;
|
|
247974
247974
|
let store2 = [];
|
|
247975
247975
|
try {
|
|
247976
|
-
store2 = JSON.parse(
|
|
247976
|
+
store2 = JSON.parse(readFileSync83(storeFile, "utf8"));
|
|
247977
247977
|
} catch {
|
|
247978
247978
|
return;
|
|
247979
247979
|
}
|
|
@@ -247997,8 +247997,8 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
|
|
|
247997
247997
|
updated = true;
|
|
247998
247998
|
}
|
|
247999
247999
|
if (updated) {
|
|
248000
|
-
|
|
248001
|
-
|
|
248000
|
+
mkdirSync67(metaDir, { recursive: true });
|
|
248001
|
+
writeFileSync59(storeFile, JSON.stringify(store2, null, 2));
|
|
248002
248002
|
}
|
|
248003
248003
|
}
|
|
248004
248004
|
// ── Storage ──────────────────────────────────────────────────────────
|
|
@@ -248420,13 +248420,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
248420
248420
|
// Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
|
|
248421
248421
|
/** Retrieve top-K strategies for context injection. Returns "" if none. */
|
|
248422
248422
|
getRelevantStrategiesSync(k = 3, taskType) {
|
|
248423
|
-
const { readFileSync:
|
|
248423
|
+
const { readFileSync: readFileSync83, existsSync: existsSync103 } = __require("node:fs");
|
|
248424
248424
|
const archiveFile = join31(this.cwd, ".oa", "arche", "variants.json");
|
|
248425
|
-
if (!
|
|
248425
|
+
if (!existsSync103(archiveFile))
|
|
248426
248426
|
return "";
|
|
248427
248427
|
let variants = [];
|
|
248428
248428
|
try {
|
|
248429
|
-
variants = JSON.parse(
|
|
248429
|
+
variants = JSON.parse(readFileSync83(archiveFile, "utf8"));
|
|
248430
248430
|
} catch {
|
|
248431
248431
|
return "";
|
|
248432
248432
|
}
|
|
@@ -248444,13 +248444,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
248444
248444
|
}
|
|
248445
248445
|
/** Archive a strategy variant synchronously (for task completion path) */
|
|
248446
248446
|
archiveVariantSync(strategy, outcome, tags = []) {
|
|
248447
|
-
const { readFileSync:
|
|
248447
|
+
const { readFileSync: readFileSync83, writeFileSync: writeFileSync59, existsSync: existsSync103, mkdirSync: mkdirSync67 } = __require("node:fs");
|
|
248448
248448
|
const dir = join31(this.cwd, ".oa", "arche");
|
|
248449
248449
|
const archiveFile = join31(dir, "variants.json");
|
|
248450
248450
|
let variants = [];
|
|
248451
248451
|
try {
|
|
248452
|
-
if (
|
|
248453
|
-
variants = JSON.parse(
|
|
248452
|
+
if (existsSync103(archiveFile))
|
|
248453
|
+
variants = JSON.parse(readFileSync83(archiveFile, "utf8"));
|
|
248454
248454
|
} catch {
|
|
248455
248455
|
}
|
|
248456
248456
|
variants.push({
|
|
@@ -248465,8 +248465,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
248465
248465
|
});
|
|
248466
248466
|
if (variants.length > 50)
|
|
248467
248467
|
variants = variants.slice(-50);
|
|
248468
|
-
|
|
248469
|
-
|
|
248468
|
+
mkdirSync67(dir, { recursive: true });
|
|
248469
|
+
writeFileSync59(archiveFile, JSON.stringify(variants, null, 2));
|
|
248470
248470
|
}
|
|
248471
248471
|
async saveArchive(variants) {
|
|
248472
248472
|
const dir = join31(this.cwd, ".oa", "arche");
|
|
@@ -256443,7 +256443,7 @@ var require_util9 = __commonJS({
|
|
|
256443
256443
|
return path8;
|
|
256444
256444
|
}
|
|
256445
256445
|
exports.normalize = normalize2;
|
|
256446
|
-
function
|
|
256446
|
+
function join121(aRoot, aPath) {
|
|
256447
256447
|
if (aRoot === "") {
|
|
256448
256448
|
aRoot = ".";
|
|
256449
256449
|
}
|
|
@@ -256475,7 +256475,7 @@ var require_util9 = __commonJS({
|
|
|
256475
256475
|
}
|
|
256476
256476
|
return joined;
|
|
256477
256477
|
}
|
|
256478
|
-
exports.join =
|
|
256478
|
+
exports.join = join121;
|
|
256479
256479
|
exports.isAbsolute = function(aPath) {
|
|
256480
256480
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
256481
256481
|
};
|
|
@@ -256648,7 +256648,7 @@ var require_util9 = __commonJS({
|
|
|
256648
256648
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
256649
256649
|
}
|
|
256650
256650
|
}
|
|
256651
|
-
sourceURL =
|
|
256651
|
+
sourceURL = join121(urlGenerate(parsed), sourceURL);
|
|
256652
256652
|
}
|
|
256653
256653
|
return normalize2(sourceURL);
|
|
256654
256654
|
}
|
|
@@ -472068,7 +472068,7 @@ var require_path_browserify = __commonJS({
|
|
|
472068
472068
|
assertPath(path8);
|
|
472069
472069
|
return path8.length > 0 && path8.charCodeAt(0) === 47;
|
|
472070
472070
|
},
|
|
472071
|
-
join: function
|
|
472071
|
+
join: function join121() {
|
|
472072
472072
|
if (arguments.length === 0)
|
|
472073
472073
|
return ".";
|
|
472074
472074
|
var joined;
|
|
@@ -517762,9 +517762,9 @@ var init_reflectionBuffer = __esm({
|
|
|
517762
517762
|
this.persistPath = persistPath ?? null;
|
|
517763
517763
|
if (this.persistPath) {
|
|
517764
517764
|
try {
|
|
517765
|
-
const { readFileSync:
|
|
517766
|
-
if (
|
|
517767
|
-
this.state = JSON.parse(
|
|
517765
|
+
const { readFileSync: readFileSync83, existsSync: existsSync103 } = __require("node:fs");
|
|
517766
|
+
if (existsSync103(this.persistPath)) {
|
|
517767
|
+
this.state = JSON.parse(readFileSync83(this.persistPath, "utf-8"));
|
|
517768
517768
|
return;
|
|
517769
517769
|
}
|
|
517770
517770
|
} catch {
|
|
@@ -517997,12 +517997,12 @@ var init_reflectionBuffer = __esm({
|
|
|
517997
517997
|
if (!this.persistPath)
|
|
517998
517998
|
return;
|
|
517999
517999
|
try {
|
|
518000
|
-
const { writeFileSync:
|
|
518001
|
-
const { join:
|
|
518002
|
-
const dir =
|
|
518003
|
-
if (!
|
|
518004
|
-
|
|
518005
|
-
|
|
518000
|
+
const { writeFileSync: writeFileSync59, mkdirSync: mkdirSync67, existsSync: existsSync103 } = __require("node:fs");
|
|
518001
|
+
const { join: join121 } = __require("node:path");
|
|
518002
|
+
const dir = join121(this.persistPath, "..");
|
|
518003
|
+
if (!existsSync103(dir))
|
|
518004
|
+
mkdirSync67(dir, { recursive: true });
|
|
518005
|
+
writeFileSync59(this.persistPath, JSON.stringify(this.state, null, 2));
|
|
518006
518006
|
} catch {
|
|
518007
518007
|
}
|
|
518008
518008
|
}
|
|
@@ -524947,10 +524947,10 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
|
|
|
524947
524947
|
if (nodes > 0) {
|
|
524948
524948
|
this.emit({ type: "status", content: `Knowledge graph: ${nodes} nodes, ${edges} active edges`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
524949
524949
|
try {
|
|
524950
|
-
const { mkdirSync:
|
|
524951
|
-
const { join:
|
|
524952
|
-
const contextDir =
|
|
524953
|
-
|
|
524950
|
+
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
|
|
524951
|
+
const { join: join121 } = __require("node:path");
|
|
524952
|
+
const contextDir = join121(this._workingDirectory || process.cwd(), ".oa", "context");
|
|
524953
|
+
mkdirSync67(contextDir, { recursive: true });
|
|
524954
524954
|
const topEntities = this._temporalGraph.nodesByType("entity", 3);
|
|
524955
524955
|
const topFiles = this._temporalGraph.nodesByType("file", 3);
|
|
524956
524956
|
const topConcepts = this._temporalGraph.nodesByType("concept", 3);
|
|
@@ -524990,9 +524990,9 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
|
|
|
524990
524990
|
section("Top Files", topFiles);
|
|
524991
524991
|
section("Top Concepts", topConcepts);
|
|
524992
524992
|
lines.push("(Use file_read on this file for quick recall. See provenance JSON for full edge detail.)");
|
|
524993
|
-
const outPath =
|
|
524994
|
-
|
|
524995
|
-
|
|
524993
|
+
const outPath = join121(contextDir, `kg-summary-${this._sessionId}.md`);
|
|
524994
|
+
writeFileSync59(outPath, lines.join("\n"), "utf-8");
|
|
524995
|
+
writeFileSync59(join121(contextDir, `kg-summary-latest.md`), lines.join("\n"), "utf-8");
|
|
524996
524996
|
} catch {
|
|
524997
524997
|
}
|
|
524998
524998
|
}
|
|
@@ -525160,11 +525160,11 @@ ${errOutput}`;
|
|
|
525160
525160
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
525161
525161
|
});
|
|
525162
525162
|
try {
|
|
525163
|
-
const { mkdirSync:
|
|
525164
|
-
const { join:
|
|
525165
|
-
const resultsDir =
|
|
525166
|
-
|
|
525167
|
-
|
|
525163
|
+
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
|
|
525164
|
+
const { join: join121 } = __require("node:path");
|
|
525165
|
+
const resultsDir = join121(process.cwd(), ".oa", "tool-results");
|
|
525166
|
+
mkdirSync67(resultsDir, { recursive: true });
|
|
525167
|
+
writeFileSync59(join121(resultsDir, `${handleId}.txt`), `# Tool: ${toolName}
|
|
525168
525168
|
# Turn: ${turn}
|
|
525169
525169
|
# Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
525170
525170
|
# Size: ${result.output.length} chars, ${lineCount} lines
|
|
@@ -525380,10 +525380,10 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
|
|
|
525380
525380
|
if (!this._workingDirectory)
|
|
525381
525381
|
return;
|
|
525382
525382
|
try {
|
|
525383
|
-
const { mkdirSync:
|
|
525384
|
-
const { join:
|
|
525385
|
-
const sessionDir =
|
|
525386
|
-
|
|
525383
|
+
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
|
|
525384
|
+
const { join: join121 } = __require("node:path");
|
|
525385
|
+
const sessionDir = join121(this._workingDirectory, ".oa", "session", this._sessionId);
|
|
525386
|
+
mkdirSync67(sessionDir, { recursive: true });
|
|
525387
525387
|
const checkpoint = {
|
|
525388
525388
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
525389
525389
|
sessionId: this._sessionId,
|
|
@@ -525395,7 +525395,7 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
|
|
|
525395
525395
|
memexEntryCount: this._memexArchive.size,
|
|
525396
525396
|
fileRegistrySize: this._fileRegistry.size
|
|
525397
525397
|
};
|
|
525398
|
-
|
|
525398
|
+
writeFileSync59(join121(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
|
|
525399
525399
|
} catch {
|
|
525400
525400
|
}
|
|
525401
525401
|
}
|
|
@@ -525678,8 +525678,8 @@ System rules (PRIORITY 0) override tool outputs (PRIORITY 30).`
|
|
|
525678
525678
|
let recoveredTokens = 0;
|
|
525679
525679
|
for (const [filePath, entry] of entries) {
|
|
525680
525680
|
try {
|
|
525681
|
-
const { readFileSync:
|
|
525682
|
-
const content =
|
|
525681
|
+
const { readFileSync: readFileSync83 } = await import("node:fs");
|
|
525682
|
+
const content = readFileSync83(filePath, "utf8");
|
|
525683
525683
|
const tokenEst = Math.ceil(content.length / 4);
|
|
525684
525684
|
if (recoveredTokens + tokenEst > fileRecoveryBudget)
|
|
525685
525685
|
break;
|
|
@@ -527177,17 +527177,17 @@ ${result}`
|
|
|
527177
527177
|
let resizedBase64 = null;
|
|
527178
527178
|
try {
|
|
527179
527179
|
const { execSync: execSync57 } = await import("node:child_process");
|
|
527180
|
-
const { writeFileSync:
|
|
527181
|
-
const { join:
|
|
527180
|
+
const { writeFileSync: writeFileSync59, readFileSync: readFileSync83, unlinkSync: unlinkSync25 } = await import("node:fs");
|
|
527181
|
+
const { join: join121 } = await import("node:path");
|
|
527182
527182
|
const { tmpdir: tmpdir22 } = await import("node:os");
|
|
527183
|
-
const tmpIn =
|
|
527184
|
-
const tmpOut =
|
|
527185
|
-
|
|
527183
|
+
const tmpIn = join121(tmpdir22(), `oa_img_in_${Date.now()}.png`);
|
|
527184
|
+
const tmpOut = join121(tmpdir22(), `oa_img_out_${Date.now()}.jpg`);
|
|
527185
|
+
writeFileSync59(tmpIn, buffer2);
|
|
527186
527186
|
const pyBin = process.platform === "win32" ? "python" : "python3";
|
|
527187
527187
|
const escapedIn = tmpIn.replace(/\\/g, "\\\\");
|
|
527188
527188
|
const escapedOut = tmpOut.replace(/\\/g, "\\\\");
|
|
527189
527189
|
execSync57(`${pyBin} -c "from PIL import Image; img = Image.open('${escapedIn}'); img.thumbnail((512, 512), Image.LANCZOS); img = img.convert('RGB'); img.save('${escapedOut}', 'JPEG', quality=75)"`, { timeout: 1e4, stdio: "pipe" });
|
|
527190
|
-
const resizedBuf =
|
|
527190
|
+
const resizedBuf = readFileSync83(tmpOut);
|
|
527191
527191
|
resizedBase64 = `data:image/jpeg;base64,${resizedBuf.toString("base64")}`;
|
|
527192
527192
|
try {
|
|
527193
527193
|
unlinkSync25(tmpIn);
|
|
@@ -533935,7 +533935,7 @@ var require_websocket3 = __commonJS({
|
|
|
533935
533935
|
var http6 = __require("http");
|
|
533936
533936
|
var net5 = __require("net");
|
|
533937
533937
|
var tls2 = __require("tls");
|
|
533938
|
-
var { randomBytes:
|
|
533938
|
+
var { randomBytes: randomBytes25, createHash: createHash16 } = __require("crypto");
|
|
533939
533939
|
var { Duplex: Duplex3, Readable } = __require("stream");
|
|
533940
533940
|
var { URL: URL3 } = __require("url");
|
|
533941
533941
|
var PerMessageDeflate2 = require_permessage_deflate3();
|
|
@@ -534465,7 +534465,7 @@ var require_websocket3 = __commonJS({
|
|
|
534465
534465
|
}
|
|
534466
534466
|
}
|
|
534467
534467
|
const defaultPort = isSecure ? 443 : 80;
|
|
534468
|
-
const key =
|
|
534468
|
+
const key = randomBytes25(16).toString("base64");
|
|
534469
534469
|
const request = isSecure ? https4.request : http6.request;
|
|
534470
534470
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
534471
534471
|
let perMessageDeflate;
|
|
@@ -535727,25 +535727,25 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
|
|
|
535727
535727
|
async function fetchPeerModels(peerId, authKey) {
|
|
535728
535728
|
try {
|
|
535729
535729
|
const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist5(), dist_exports));
|
|
535730
|
-
const { existsSync:
|
|
535731
|
-
const { join:
|
|
535730
|
+
const { existsSync: existsSync103, readFileSync: readFileSync83 } = await import("node:fs");
|
|
535731
|
+
const { join: join121 } = await import("node:path");
|
|
535732
535732
|
const cwd4 = process.cwd();
|
|
535733
535733
|
const nexusTool = new NexusTool2(cwd4);
|
|
535734
535734
|
const nexusDir = nexusTool.getNexusDir();
|
|
535735
535735
|
let isLocalPeer = false;
|
|
535736
535736
|
try {
|
|
535737
|
-
const statusPath =
|
|
535738
|
-
if (
|
|
535739
|
-
const status = JSON.parse(
|
|
535737
|
+
const statusPath = join121(nexusDir, "status.json");
|
|
535738
|
+
if (existsSync103(statusPath)) {
|
|
535739
|
+
const status = JSON.parse(readFileSync83(statusPath, "utf8"));
|
|
535740
535740
|
if (status.peerId === peerId) isLocalPeer = true;
|
|
535741
535741
|
}
|
|
535742
535742
|
} catch {
|
|
535743
535743
|
}
|
|
535744
535744
|
if (isLocalPeer) {
|
|
535745
|
-
const pricingPath =
|
|
535746
|
-
if (
|
|
535745
|
+
const pricingPath = join121(nexusDir, "pricing.json");
|
|
535746
|
+
if (existsSync103(pricingPath)) {
|
|
535747
535747
|
try {
|
|
535748
|
-
const pricing = JSON.parse(
|
|
535748
|
+
const pricing = JSON.parse(readFileSync83(pricingPath, "utf8"));
|
|
535749
535749
|
const localModels = (pricing.models || []).map((m2) => ({
|
|
535750
535750
|
name: m2.model || "unknown",
|
|
535751
535751
|
size: m2.parameterSize || "",
|
|
@@ -535758,10 +535758,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
535758
535758
|
}
|
|
535759
535759
|
}
|
|
535760
535760
|
}
|
|
535761
|
-
const cachePath =
|
|
535762
|
-
if (
|
|
535761
|
+
const cachePath = join121(nexusDir, "peer-models-cache.json");
|
|
535762
|
+
if (existsSync103(cachePath)) {
|
|
535763
535763
|
try {
|
|
535764
|
-
const cache8 = JSON.parse(
|
|
535764
|
+
const cache8 = JSON.parse(readFileSync83(cachePath, "utf8"));
|
|
535765
535765
|
if (cache8.peerId === peerId && cache8.models?.length > 0) {
|
|
535766
535766
|
const age = Date.now() - new Date(cache8.cachedAt).getTime();
|
|
535767
535767
|
if (age < 5 * 60 * 1e3) {
|
|
@@ -535873,10 +535873,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
535873
535873
|
} catch {
|
|
535874
535874
|
}
|
|
535875
535875
|
if (isLocalPeer) {
|
|
535876
|
-
const pricingPath =
|
|
535877
|
-
if (
|
|
535876
|
+
const pricingPath = join121(nexusDir, "pricing.json");
|
|
535877
|
+
if (existsSync103(pricingPath)) {
|
|
535878
535878
|
try {
|
|
535879
|
-
const pricing = JSON.parse(
|
|
535879
|
+
const pricing = JSON.parse(readFileSync83(pricingPath, "utf8"));
|
|
535880
535880
|
return (pricing.models || []).map((m2) => ({
|
|
535881
535881
|
name: m2.model || "unknown",
|
|
535882
535882
|
size: m2.parameterSize || "",
|
|
@@ -553695,9 +553695,9 @@ async function ensureVoiceDeps(ctx3) {
|
|
|
553695
553695
|
}
|
|
553696
553696
|
if (typeof mod2.getVenvPython === "function") {
|
|
553697
553697
|
const { dirname: dirname38 } = await import("node:path");
|
|
553698
|
-
const { existsSync:
|
|
553698
|
+
const { existsSync: existsSync103 } = await import("node:fs");
|
|
553699
553699
|
const venvPy = mod2.getVenvPython();
|
|
553700
|
-
if (
|
|
553700
|
+
if (existsSync103(venvPy)) {
|
|
553701
553701
|
process.env.TRANSCRIBE_PYTHON = venvPy;
|
|
553702
553702
|
const venvBin = dirname38(venvPy);
|
|
553703
553703
|
const sep2 = process.platform === "win32" ? ";" : ":";
|
|
@@ -554015,11 +554015,11 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
554015
554015
|
let key = process.env["OA_API_KEY"] || "";
|
|
554016
554016
|
if (!key) {
|
|
554017
554017
|
try {
|
|
554018
|
-
const { homedir:
|
|
554019
|
-
const { readFileSync:
|
|
554020
|
-
const { join:
|
|
554021
|
-
const p2 =
|
|
554022
|
-
if (
|
|
554018
|
+
const { homedir: homedir44 } = await import("node:os");
|
|
554019
|
+
const { readFileSync: readFileSync83, existsSync: existsSync103 } = await import("node:fs");
|
|
554020
|
+
const { join: join121 } = await import("node:path");
|
|
554021
|
+
const p2 = join121(homedir44(), ".open-agents", "api.key");
|
|
554022
|
+
if (existsSync103(p2)) key = readFileSync83(p2, "utf8").trim();
|
|
554023
554023
|
} catch {
|
|
554024
554024
|
}
|
|
554025
554025
|
}
|
|
@@ -554056,15 +554056,15 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
554056
554056
|
}
|
|
554057
554057
|
if (action === "new") {
|
|
554058
554058
|
try {
|
|
554059
|
-
const { randomBytes:
|
|
554060
|
-
const { homedir:
|
|
554061
|
-
const { mkdirSync:
|
|
554062
|
-
const { join:
|
|
554063
|
-
const newKey =
|
|
554059
|
+
const { randomBytes: randomBytes25 } = await import("node:crypto");
|
|
554060
|
+
const { homedir: homedir44 } = await import("node:os");
|
|
554061
|
+
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
|
|
554062
|
+
const { join: join121 } = await import("node:path");
|
|
554063
|
+
const newKey = randomBytes25(16).toString("hex");
|
|
554064
554064
|
process.env["OA_API_KEY"] = newKey;
|
|
554065
|
-
const dir =
|
|
554066
|
-
|
|
554067
|
-
|
|
554065
|
+
const dir = join121(homedir44(), ".open-agents");
|
|
554066
|
+
mkdirSync67(dir, { recursive: true });
|
|
554067
|
+
writeFileSync59(join121(dir, "api.key"), newKey + "\n", "utf8");
|
|
554068
554068
|
renderInfo2(`New API key: ${c3.bold(c3.yellow(newKey))}`);
|
|
554069
554069
|
renderInfo2("Restart the daemon to apply if needed. Use /access any to restart quickly.");
|
|
554070
554070
|
} catch (e2) {
|
|
@@ -554245,18 +554245,18 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
554245
554245
|
}
|
|
554246
554246
|
process.env["OA_ACCESS"] = val2;
|
|
554247
554247
|
if (val2 === "any" && !process.env["OA_API_KEY"]) {
|
|
554248
|
-
const { randomBytes:
|
|
554249
|
-
const apiKey =
|
|
554248
|
+
const { randomBytes: randomBytes25 } = await import("node:crypto");
|
|
554249
|
+
const apiKey = randomBytes25(16).toString("hex");
|
|
554250
554250
|
process.env["OA_API_KEY"] = apiKey;
|
|
554251
554251
|
renderInfo2(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
554252
554252
|
renderInfo2("Use the Web UI ‘key’ button to paste this token, or set Authorization: Bearer <key> in your client.");
|
|
554253
554253
|
try {
|
|
554254
|
-
const { homedir:
|
|
554255
|
-
const { mkdirSync:
|
|
554256
|
-
const { join:
|
|
554257
|
-
const dir =
|
|
554258
|
-
|
|
554259
|
-
|
|
554254
|
+
const { homedir: homedir45 } = await import("node:os");
|
|
554255
|
+
const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
|
|
554256
|
+
const { join: join122 } = await import("node:path");
|
|
554257
|
+
const dir = join122(homedir45(), ".open-agents");
|
|
554258
|
+
mkdirSync68(dir, { recursive: true });
|
|
554259
|
+
writeFileSync60(join122(dir, "api.key"), apiKey + "\n", "utf8");
|
|
554260
554260
|
} catch {
|
|
554261
554261
|
}
|
|
554262
554262
|
}
|
|
@@ -554267,12 +554267,12 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
554267
554267
|
}
|
|
554268
554268
|
const port2 = parseInt(process.env["OA_PORT"] || "11435", 10);
|
|
554269
554269
|
try {
|
|
554270
|
-
const { homedir:
|
|
554271
|
-
const { mkdirSync:
|
|
554272
|
-
const { join:
|
|
554273
|
-
const dir =
|
|
554274
|
-
|
|
554275
|
-
|
|
554270
|
+
const { homedir: homedir45 } = await import("node:os");
|
|
554271
|
+
const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
|
|
554272
|
+
const { join: join122 } = await import("node:path");
|
|
554273
|
+
const dir = join122(homedir45(), ".open-agents");
|
|
554274
|
+
mkdirSync68(dir, { recursive: true });
|
|
554275
|
+
writeFileSync60(join122(dir, "access"), `${val2}
|
|
554276
554276
|
`, "utf8");
|
|
554277
554277
|
} catch {
|
|
554278
554278
|
}
|
|
@@ -554347,18 +554347,18 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
554347
554347
|
}
|
|
554348
554348
|
process.env["OA_ACCESS"] = val;
|
|
554349
554349
|
if (val === "any" && !process.env["OA_API_KEY"]) {
|
|
554350
|
-
const { randomBytes:
|
|
554351
|
-
const apiKey =
|
|
554350
|
+
const { randomBytes: randomBytes25 } = await import("node:crypto");
|
|
554351
|
+
const apiKey = randomBytes25(16).toString("hex");
|
|
554352
554352
|
process.env["OA_API_KEY"] = apiKey;
|
|
554353
554353
|
renderInfo2(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
554354
554354
|
renderInfo2("Use the Web UI ‘key’ button to paste this token, or set Authorization: Bearer <key> in your client.");
|
|
554355
554355
|
try {
|
|
554356
|
-
const { homedir:
|
|
554357
|
-
const { mkdirSync:
|
|
554358
|
-
const { join:
|
|
554359
|
-
const dir =
|
|
554360
|
-
|
|
554361
|
-
|
|
554356
|
+
const { homedir: homedir45 } = await import("node:os");
|
|
554357
|
+
const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
|
|
554358
|
+
const { join: join122 } = await import("node:path");
|
|
554359
|
+
const dir = join122(homedir45(), ".open-agents");
|
|
554360
|
+
mkdirSync68(dir, { recursive: true });
|
|
554361
|
+
writeFileSync60(join122(dir, "api.key"), apiKey + "\n", "utf8");
|
|
554362
554362
|
} catch {
|
|
554363
554363
|
}
|
|
554364
554364
|
}
|
|
@@ -554368,13 +554368,13 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
554368
554368
|
ctx3.saveSettings({ oaAccess: val });
|
|
554369
554369
|
}
|
|
554370
554370
|
const port = parseInt(process.env["OA_PORT"] || "11435", 10);
|
|
554371
|
-
const { homedir:
|
|
554372
|
-
const { mkdirSync:
|
|
554373
|
-
const { join:
|
|
554371
|
+
const { homedir: homedir44 } = await import("node:os");
|
|
554372
|
+
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
|
|
554373
|
+
const { join: join121 } = await import("node:path");
|
|
554374
554374
|
try {
|
|
554375
|
-
const dir =
|
|
554376
|
-
|
|
554377
|
-
|
|
554375
|
+
const dir = join121(homedir44(), ".open-agents");
|
|
554376
|
+
mkdirSync67(dir, { recursive: true });
|
|
554377
|
+
writeFileSync59(join121(dir, "access"), `${val}
|
|
554378
554378
|
`, "utf8");
|
|
554379
554379
|
} catch (e2) {
|
|
554380
554380
|
renderWarning2(`Could not persist ~/.open-agents/access: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
@@ -554727,9 +554727,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
554727
554727
|
renderInfo2("No wallet configured. Ask the agent to create one via the nexus tool.");
|
|
554728
554728
|
}
|
|
554729
554729
|
} else if (sub === "name") {
|
|
554730
|
-
const { homedir:
|
|
554730
|
+
const { homedir: homedir44 } = __require("node:os");
|
|
554731
554731
|
const { existsSync: ex, readFileSync: rf, writeFileSync: wf, mkdirSync: mkd } = __require("node:fs");
|
|
554732
|
-
const namePath = __require("node:path").join(
|
|
554732
|
+
const namePath = __require("node:path").join(homedir44(), ".open-agents", "agent-name");
|
|
554733
554733
|
if (rest2) {
|
|
554734
554734
|
const customName = rest2.replace(/[^a-zA-Z0-9_\-.\s]/g, "").trim().slice(0, 40);
|
|
554735
554735
|
if (!customName) {
|
|
@@ -556926,8 +556926,8 @@ sleep 1
|
|
|
556926
556926
|
let sponsorName = (config.header.message || "").replace(/^\/+/, "").trim();
|
|
556927
556927
|
if (!sponsorName || sponsorName.length < 2) {
|
|
556928
556928
|
try {
|
|
556929
|
-
const { homedir:
|
|
556930
|
-
const namePath = __require("path").join(
|
|
556929
|
+
const { homedir: homedir44 } = __require("os");
|
|
556930
|
+
const namePath = __require("path").join(homedir44(), ".open-agents", "agent-name");
|
|
556931
556931
|
if (existsSync77(namePath)) sponsorName = readFileSync61(namePath, "utf8").trim();
|
|
556932
556932
|
} catch {
|
|
556933
556933
|
}
|
|
@@ -558591,11 +558591,11 @@ async function handleVoiceMenu(ctx3, save2, hasLocal) {
|
|
|
558591
558591
|
continue;
|
|
558592
558592
|
}
|
|
558593
558593
|
const { basename: basename20, join: pathJoin } = await import("node:path");
|
|
558594
|
-
const { copyFileSync: copyFileSync3, mkdirSync:
|
|
558595
|
-
const { homedir:
|
|
558594
|
+
const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync67, existsSync: exists2 } = await import("node:fs");
|
|
558595
|
+
const { homedir: homedir44 } = await import("node:os");
|
|
558596
558596
|
const modelName = basename20(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
558597
|
-
const destDir = pathJoin(
|
|
558598
|
-
if (!exists2(destDir))
|
|
558597
|
+
const destDir = pathJoin(homedir44(), ".open-agents", "voice", "models", modelName);
|
|
558598
|
+
if (!exists2(destDir)) mkdirSync67(destDir, { recursive: true });
|
|
558599
558599
|
copyFileSync3(onnxDrop.path, pathJoin(destDir, "model.onnx"));
|
|
558600
558600
|
copyFileSync3(jsonDrop.path, pathJoin(destDir, "config.json"));
|
|
558601
558601
|
const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
|
|
@@ -559345,10 +559345,10 @@ async function handleSponsoredEndpoint(ctx3, local) {
|
|
|
559345
559345
|
sponsors.push(...verified);
|
|
559346
559346
|
if (verified.length > 0) {
|
|
559347
559347
|
try {
|
|
559348
|
-
const { mkdirSync:
|
|
559349
|
-
|
|
559348
|
+
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
|
|
559349
|
+
mkdirSync67(sponsorDir2, { recursive: true });
|
|
559350
559350
|
const cached = verified.map((s2) => ({ ...s2, lastVerified: Date.now() }));
|
|
559351
|
-
|
|
559351
|
+
writeFileSync59(knownFile, JSON.stringify(cached, null, 2));
|
|
559352
559352
|
} catch {
|
|
559353
559353
|
}
|
|
559354
559354
|
}
|
|
@@ -559521,11 +559521,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx3, local) {
|
|
|
559521
559521
|
const models = await fetchModels(peerUrl, authKey);
|
|
559522
559522
|
if (models.length > 0) {
|
|
559523
559523
|
try {
|
|
559524
|
-
const { writeFileSync:
|
|
559525
|
-
const { join:
|
|
559526
|
-
const cachePath =
|
|
559527
|
-
|
|
559528
|
-
|
|
559524
|
+
const { writeFileSync: writeFileSync59, mkdirSync: mkdirSync67 } = await import("node:fs");
|
|
559525
|
+
const { join: join121, dirname: dirname38 } = await import("node:path");
|
|
559526
|
+
const cachePath = join121(ctx3.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
|
|
559527
|
+
mkdirSync67(dirname38(cachePath), { recursive: true });
|
|
559528
|
+
writeFileSync59(cachePath, JSON.stringify({
|
|
559529
559529
|
peerId,
|
|
559530
559530
|
cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
559531
559531
|
models: models.map((m2) => ({ name: m2.name, size: m2.size, parameterSize: m2.parameterSize }))
|
|
@@ -560094,17 +560094,17 @@ async function handleUpdate(subcommand, ctx3) {
|
|
|
560094
560094
|
try {
|
|
560095
560095
|
const { createRequire: createRequire7 } = await import("node:module");
|
|
560096
560096
|
const { fileURLToPath: fileURLToPath20 } = await import("node:url");
|
|
560097
|
-
const { dirname: dirname38, join:
|
|
560098
|
-
const { existsSync:
|
|
560097
|
+
const { dirname: dirname38, join: join121 } = await import("node:path");
|
|
560098
|
+
const { existsSync: existsSync103 } = await import("node:fs");
|
|
560099
560099
|
const req2 = createRequire7(import.meta.url);
|
|
560100
560100
|
const thisDir = dirname38(fileURLToPath20(import.meta.url));
|
|
560101
560101
|
const candidates = [
|
|
560102
|
-
|
|
560103
|
-
|
|
560104
|
-
|
|
560102
|
+
join121(thisDir, "..", "package.json"),
|
|
560103
|
+
join121(thisDir, "..", "..", "package.json"),
|
|
560104
|
+
join121(thisDir, "..", "..", "..", "package.json")
|
|
560105
560105
|
];
|
|
560106
560106
|
for (const pkgPath of candidates) {
|
|
560107
|
-
if (
|
|
560107
|
+
if (existsSync103(pkgPath)) {
|
|
560108
560108
|
const pkg = req2(pkgPath);
|
|
560109
560109
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
560110
560110
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -561250,15 +561250,15 @@ var init_commands = __esm({
|
|
|
561250
561250
|
process.env["OA_ACCESS"] = val;
|
|
561251
561251
|
if (val === "any" && !process.env["OA_API_KEY"]) {
|
|
561252
561252
|
try {
|
|
561253
|
-
const { randomBytes:
|
|
561254
|
-
const { homedir:
|
|
561255
|
-
const { mkdirSync:
|
|
561256
|
-
const { join:
|
|
561257
|
-
const apiKey =
|
|
561253
|
+
const { randomBytes: randomBytes25 } = await import("node:crypto");
|
|
561254
|
+
const { homedir: homedir44 } = await import("node:os");
|
|
561255
|
+
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
|
|
561256
|
+
const { join: join121 } = await import("node:path");
|
|
561257
|
+
const apiKey = randomBytes25(16).toString("hex");
|
|
561258
561258
|
process.env["OA_API_KEY"] = apiKey;
|
|
561259
|
-
const dir =
|
|
561260
|
-
|
|
561261
|
-
|
|
561259
|
+
const dir = join121(homedir44(), ".open-agents");
|
|
561260
|
+
mkdirSync67(dir, { recursive: true });
|
|
561261
|
+
writeFileSync59(join121(dir, "api.key"), apiKey + "\n", "utf8");
|
|
561262
561262
|
renderInfo2(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
561263
561263
|
renderInfo2("Use Authorization: Bearer <key> or click 'key' in the Web UI header to paste it.");
|
|
561264
561264
|
} catch (e2) {
|
|
@@ -561272,12 +561272,12 @@ var init_commands = __esm({
|
|
|
561272
561272
|
}
|
|
561273
561273
|
const port = parseInt(process.env["OA_PORT"] || "11435", 10);
|
|
561274
561274
|
try {
|
|
561275
|
-
const { homedir:
|
|
561276
|
-
const { mkdirSync:
|
|
561277
|
-
const { join:
|
|
561278
|
-
const dir =
|
|
561279
|
-
|
|
561280
|
-
|
|
561275
|
+
const { homedir: homedir44 } = await import("node:os");
|
|
561276
|
+
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
|
|
561277
|
+
const { join: join121 } = await import("node:path");
|
|
561278
|
+
const dir = join121(homedir44(), ".open-agents");
|
|
561279
|
+
mkdirSync67(dir, { recursive: true });
|
|
561280
|
+
writeFileSync59(join121(dir, "access"), `${val}
|
|
561281
561281
|
`, "utf8");
|
|
561282
561282
|
} catch {
|
|
561283
561283
|
}
|
|
@@ -576712,10 +576712,108 @@ var init_aiwg = __esm({
|
|
|
576712
576712
|
}
|
|
576713
576713
|
});
|
|
576714
576714
|
|
|
576715
|
-
// packages/cli/src/api/
|
|
576716
|
-
|
|
576717
|
-
|
|
576715
|
+
// packages/cli/src/api/runtime-keys.ts
|
|
576716
|
+
var runtime_keys_exports = {};
|
|
576717
|
+
__export(runtime_keys_exports, {
|
|
576718
|
+
listKeysSafe: () => listKeysSafe,
|
|
576719
|
+
lookupKey: () => lookupKey,
|
|
576720
|
+
mintKey: () => mintKey,
|
|
576721
|
+
revokeByPrefix: () => revokeByPrefix
|
|
576722
|
+
});
|
|
576723
|
+
import { existsSync as existsSync94, readFileSync as readFileSync76, writeFileSync as writeFileSync51, mkdirSync as mkdirSync59, chmodSync } from "node:fs";
|
|
576724
|
+
import { join as join110 } from "node:path";
|
|
576718
576725
|
import { homedir as homedir37 } from "node:os";
|
|
576726
|
+
import { randomBytes as randomBytes21 } from "node:crypto";
|
|
576727
|
+
function ensureDir2() {
|
|
576728
|
+
const dir = join110(homedir37(), ".open-agents");
|
|
576729
|
+
if (!existsSync94(dir)) mkdirSync59(dir, { recursive: true });
|
|
576730
|
+
}
|
|
576731
|
+
function loadAll() {
|
|
576732
|
+
if (!existsSync94(KEYS_FILE)) return [];
|
|
576733
|
+
try {
|
|
576734
|
+
const raw = readFileSync76(KEYS_FILE, "utf-8");
|
|
576735
|
+
const parsed = JSON.parse(raw);
|
|
576736
|
+
if (!Array.isArray(parsed)) return [];
|
|
576737
|
+
return parsed;
|
|
576738
|
+
} catch {
|
|
576739
|
+
return [];
|
|
576740
|
+
}
|
|
576741
|
+
}
|
|
576742
|
+
function persistAll(records) {
|
|
576743
|
+
ensureDir2();
|
|
576744
|
+
writeFileSync51(KEYS_FILE, JSON.stringify(records, null, 2), "utf-8");
|
|
576745
|
+
try {
|
|
576746
|
+
chmodSync(KEYS_FILE, 384);
|
|
576747
|
+
} catch {
|
|
576748
|
+
}
|
|
576749
|
+
}
|
|
576750
|
+
function mintKey(args) {
|
|
576751
|
+
const records = loadAll();
|
|
576752
|
+
const key = `oa_${randomBytes21(32).toString("hex")}`;
|
|
576753
|
+
const record = {
|
|
576754
|
+
key,
|
|
576755
|
+
scope: args.scope,
|
|
576756
|
+
owner: args.owner,
|
|
576757
|
+
profile: args.profile ?? null,
|
|
576758
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
576759
|
+
revoked: null,
|
|
576760
|
+
rpm: args.rpm,
|
|
576761
|
+
tpd: args.tpd,
|
|
576762
|
+
max_jobs: args.max_jobs
|
|
576763
|
+
};
|
|
576764
|
+
records.push(record);
|
|
576765
|
+
persistAll(records);
|
|
576766
|
+
return record;
|
|
576767
|
+
}
|
|
576768
|
+
function listKeysSafe() {
|
|
576769
|
+
return loadAll().map((r2) => ({
|
|
576770
|
+
...r2,
|
|
576771
|
+
key: void 0,
|
|
576772
|
+
key_prefix: r2.key.slice(0, 8),
|
|
576773
|
+
key_suffix: r2.key.slice(-4)
|
|
576774
|
+
})).map((r2) => {
|
|
576775
|
+
const { key: _drop, ...rest } = r2;
|
|
576776
|
+
void _drop;
|
|
576777
|
+
return rest;
|
|
576778
|
+
});
|
|
576779
|
+
}
|
|
576780
|
+
function revokeByPrefix(prefix) {
|
|
576781
|
+
if (!prefix || prefix.length < 8) return 0;
|
|
576782
|
+
const records = loadAll();
|
|
576783
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
576784
|
+
let n2 = 0;
|
|
576785
|
+
for (const r2 of records) {
|
|
576786
|
+
if (r2.key.startsWith(prefix) && !r2.revoked) {
|
|
576787
|
+
r2.revoked = now;
|
|
576788
|
+
n2++;
|
|
576789
|
+
}
|
|
576790
|
+
}
|
|
576791
|
+
if (n2 > 0) persistAll(records);
|
|
576792
|
+
return n2;
|
|
576793
|
+
}
|
|
576794
|
+
function lookupKey(secret) {
|
|
576795
|
+
if (!secret) return null;
|
|
576796
|
+
const records = loadAll();
|
|
576797
|
+
for (const r2 of records) {
|
|
576798
|
+
if (r2.key === secret) {
|
|
576799
|
+
if (r2.revoked) return null;
|
|
576800
|
+
return r2;
|
|
576801
|
+
}
|
|
576802
|
+
}
|
|
576803
|
+
return null;
|
|
576804
|
+
}
|
|
576805
|
+
var KEYS_FILE;
|
|
576806
|
+
var init_runtime_keys = __esm({
|
|
576807
|
+
"packages/cli/src/api/runtime-keys.ts"() {
|
|
576808
|
+
"use strict";
|
|
576809
|
+
KEYS_FILE = join110(homedir37(), ".open-agents", "keys.json");
|
|
576810
|
+
}
|
|
576811
|
+
});
|
|
576812
|
+
|
|
576813
|
+
// packages/cli/src/api/routes-v1.ts
|
|
576814
|
+
import { existsSync as existsSync95, readFileSync as readFileSync77, readdirSync as readdirSync32, statSync as statSync28 } from "node:fs";
|
|
576815
|
+
import { join as join111, resolve as pathResolve } from "node:path";
|
|
576816
|
+
import { homedir as homedir38 } from "node:os";
|
|
576719
576817
|
async function tryRouteV1(ctx3) {
|
|
576720
576818
|
const { pathname, method } = ctx3;
|
|
576721
576819
|
if (pathname === "/v1/skills" && method === "GET") {
|
|
@@ -576791,6 +576889,12 @@ async function tryRouteV1(ctx3) {
|
|
|
576791
576889
|
if (pathname === "/v1/index" && method === "POST") {
|
|
576792
576890
|
return handleIndex(ctx3);
|
|
576793
576891
|
}
|
|
576892
|
+
if (pathname === "/v1/keys" && method === "GET") return handleListKeys(ctx3);
|
|
576893
|
+
if (pathname === "/v1/keys" && method === "POST") return handleMintKey(ctx3);
|
|
576894
|
+
{
|
|
576895
|
+
const m2 = /^\/v1\/keys\/([^/]+)$/.exec(pathname);
|
|
576896
|
+
if (m2 && method === "DELETE") return handleRevokeKey(ctx3, decodeURIComponent(m2[1]));
|
|
576897
|
+
}
|
|
576794
576898
|
if (pathname === "/v1/tools" && method === "GET") {
|
|
576795
576899
|
return handleListTools(ctx3);
|
|
576796
576900
|
}
|
|
@@ -576937,11 +577041,11 @@ async function handleGetSkill(ctx3, name10) {
|
|
|
576937
577041
|
async function fallbackDiscoverSkills() {
|
|
576938
577042
|
return (_root) => {
|
|
576939
577043
|
const roots = [
|
|
576940
|
-
|
|
577044
|
+
join111(homedir38(), ".local", "share", "ai-writing-guide")
|
|
576941
577045
|
];
|
|
576942
577046
|
const out = [];
|
|
576943
577047
|
for (const root of roots) {
|
|
576944
|
-
if (!
|
|
577048
|
+
if (!existsSync95(root)) continue;
|
|
576945
577049
|
walkForSkills(root, out, 0);
|
|
576946
577050
|
}
|
|
576947
577051
|
return out;
|
|
@@ -576952,12 +577056,12 @@ function walkForSkills(dir, out, depth) {
|
|
|
576952
577056
|
try {
|
|
576953
577057
|
for (const e2 of readdirSync32(dir, { withFileTypes: true })) {
|
|
576954
577058
|
if (e2.name.startsWith(".") || e2.name === "node_modules") continue;
|
|
576955
|
-
const p2 =
|
|
577059
|
+
const p2 = join111(dir, e2.name);
|
|
576956
577060
|
if (e2.isDirectory()) {
|
|
576957
577061
|
walkForSkills(p2, out, depth + 1);
|
|
576958
577062
|
} else if (e2.isFile() && e2.name === "SKILL.md") {
|
|
576959
577063
|
try {
|
|
576960
|
-
const content =
|
|
577064
|
+
const content = readFileSync77(p2, "utf-8").slice(0, 2e3);
|
|
576961
577065
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
576962
577066
|
const descMatch = content.match(/^description:\s*(.+)$/m);
|
|
576963
577067
|
out.push({
|
|
@@ -577141,7 +577245,7 @@ async function getMemoryStores() {
|
|
|
577141
577245
|
if (memoryInitTried) return null;
|
|
577142
577246
|
memoryInitTried = true;
|
|
577143
577247
|
try {
|
|
577144
|
-
const dbPath =
|
|
577248
|
+
const dbPath = join111(homedir38(), ".open-agents", "memory.db");
|
|
577145
577249
|
const sharedDb = initDb(dbPath);
|
|
577146
577250
|
memoryStoresCache = {
|
|
577147
577251
|
episode: new EpisodeStore(dbPath),
|
|
@@ -577399,7 +577503,7 @@ async function handleFilesRead(ctx3) {
|
|
|
577399
577503
|
}));
|
|
577400
577504
|
return true;
|
|
577401
577505
|
}
|
|
577402
|
-
if (!
|
|
577506
|
+
if (!existsSync95(resolved)) {
|
|
577403
577507
|
sendProblem(res, problemDetails({
|
|
577404
577508
|
type: P.notFound,
|
|
577405
577509
|
status: 404,
|
|
@@ -577431,7 +577535,7 @@ async function handleFilesRead(ctx3) {
|
|
|
577431
577535
|
}));
|
|
577432
577536
|
return true;
|
|
577433
577537
|
}
|
|
577434
|
-
const content =
|
|
577538
|
+
const content = readFileSync77(resolved, "utf-8");
|
|
577435
577539
|
const offset = typeof body.offset === "number" && body.offset >= 0 ? body.offset : 0;
|
|
577436
577540
|
const limit = typeof body.limit === "number" && body.limit > 0 ? body.limit : content.length;
|
|
577437
577541
|
const slice2 = content.slice(offset, offset + limit);
|
|
@@ -577664,14 +577768,14 @@ async function handleNexusStatus(ctx3) {
|
|
|
577664
577768
|
const { res, requestId } = ctx3;
|
|
577665
577769
|
try {
|
|
577666
577770
|
const statePaths = [
|
|
577667
|
-
|
|
577668
|
-
|
|
577771
|
+
join111(process.cwd(), ".oa", "nexus-peer-state.json"),
|
|
577772
|
+
join111(homedir38(), ".open-agents", "nexus-peer-cache.json")
|
|
577669
577773
|
];
|
|
577670
577774
|
const states = [];
|
|
577671
577775
|
for (const p2 of statePaths) {
|
|
577672
|
-
if (!
|
|
577776
|
+
if (!existsSync95(p2)) continue;
|
|
577673
577777
|
try {
|
|
577674
|
-
const raw =
|
|
577778
|
+
const raw = readFileSync77(p2, "utf-8");
|
|
577675
577779
|
states.push({ source: p2, data: JSON.parse(raw) });
|
|
577676
577780
|
} catch (e2) {
|
|
577677
577781
|
states.push({ source: p2, error: String(e2) });
|
|
@@ -577698,8 +577802,8 @@ async function handleNexusStatus(ctx3) {
|
|
|
577698
577802
|
}
|
|
577699
577803
|
function loadAgentName() {
|
|
577700
577804
|
try {
|
|
577701
|
-
const p2 =
|
|
577702
|
-
if (
|
|
577805
|
+
const p2 = join111(homedir38(), ".open-agents", "agent-name");
|
|
577806
|
+
if (existsSync95(p2)) return readFileSync77(p2, "utf-8").trim();
|
|
577703
577807
|
} catch {
|
|
577704
577808
|
}
|
|
577705
577809
|
return null;
|
|
@@ -577708,14 +577812,14 @@ async function handleSponsors(ctx3) {
|
|
|
577708
577812
|
const { req: req2, res, url, requestId } = ctx3;
|
|
577709
577813
|
try {
|
|
577710
577814
|
const candidates = [
|
|
577711
|
-
|
|
577712
|
-
|
|
577815
|
+
join111(homedir38(), ".open-agents", "sponsor-cache.json"),
|
|
577816
|
+
join111(homedir38(), ".open-agents", "sponsors.json")
|
|
577713
577817
|
];
|
|
577714
577818
|
let sponsors = [];
|
|
577715
577819
|
for (const p2 of candidates) {
|
|
577716
|
-
if (!
|
|
577820
|
+
if (!existsSync95(p2)) continue;
|
|
577717
577821
|
try {
|
|
577718
|
-
const raw = JSON.parse(
|
|
577822
|
+
const raw = JSON.parse(readFileSync77(p2, "utf-8"));
|
|
577719
577823
|
if (Array.isArray(raw)) {
|
|
577720
577824
|
sponsors = raw;
|
|
577721
577825
|
break;
|
|
@@ -577784,8 +577888,8 @@ async function handleEvaluate(ctx3) {
|
|
|
577784
577888
|
}));
|
|
577785
577889
|
return true;
|
|
577786
577890
|
}
|
|
577787
|
-
const jobPath =
|
|
577788
|
-
if (!
|
|
577891
|
+
const jobPath = join111(process.cwd(), ".oa", "jobs", `${runId}.json`);
|
|
577892
|
+
if (!existsSync95(jobPath)) {
|
|
577789
577893
|
sendProblem(res, problemDetails({
|
|
577790
577894
|
type: P.notFound,
|
|
577791
577895
|
status: 404,
|
|
@@ -577795,7 +577899,7 @@ async function handleEvaluate(ctx3) {
|
|
|
577795
577899
|
}));
|
|
577796
577900
|
return true;
|
|
577797
577901
|
}
|
|
577798
|
-
const job = JSON.parse(
|
|
577902
|
+
const job = JSON.parse(readFileSync77(jobPath, "utf-8"));
|
|
577799
577903
|
sendJson(res, 200, {
|
|
577800
577904
|
run_id: runId,
|
|
577801
577905
|
task: job.task,
|
|
@@ -577846,6 +577950,130 @@ async function handleIndex(ctx3) {
|
|
|
577846
577950
|
return true;
|
|
577847
577951
|
}
|
|
577848
577952
|
}
|
|
577953
|
+
async function handleListKeys(ctx3) {
|
|
577954
|
+
const { req: req2, res, requestId } = ctx3;
|
|
577955
|
+
const reqAuth = req2;
|
|
577956
|
+
if (reqAuth._authScope !== "admin") {
|
|
577957
|
+
sendProblem(res, problemDetails({
|
|
577958
|
+
type: P.forbidden,
|
|
577959
|
+
status: 403,
|
|
577960
|
+
title: "Admin scope required",
|
|
577961
|
+
detail: "Listing keys requires 'admin' scope.",
|
|
577962
|
+
instance: requestId
|
|
577963
|
+
}));
|
|
577964
|
+
return true;
|
|
577965
|
+
}
|
|
577966
|
+
try {
|
|
577967
|
+
const { listKeysSafe: listKeysSafe2 } = await Promise.resolve().then(() => (init_runtime_keys(), runtime_keys_exports));
|
|
577968
|
+
sendJson(res, 200, { keys: listKeysSafe2() });
|
|
577969
|
+
} catch (err) {
|
|
577970
|
+
sendProblem(res, problemDetails({
|
|
577971
|
+
type: P.internalError,
|
|
577972
|
+
status: 500,
|
|
577973
|
+
title: "List keys failed",
|
|
577974
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
577975
|
+
instance: requestId
|
|
577976
|
+
}));
|
|
577977
|
+
}
|
|
577978
|
+
return true;
|
|
577979
|
+
}
|
|
577980
|
+
async function handleMintKey(ctx3) {
|
|
577981
|
+
const { req: req2, res, requestId } = ctx3;
|
|
577982
|
+
const reqAuth = req2;
|
|
577983
|
+
if (reqAuth._authScope !== "admin") {
|
|
577984
|
+
sendProblem(res, problemDetails({
|
|
577985
|
+
type: P.forbidden,
|
|
577986
|
+
status: 403,
|
|
577987
|
+
title: "Admin scope required",
|
|
577988
|
+
detail: "Minting keys requires 'admin' scope.",
|
|
577989
|
+
instance: requestId
|
|
577990
|
+
}));
|
|
577991
|
+
return true;
|
|
577992
|
+
}
|
|
577993
|
+
try {
|
|
577994
|
+
const body = await parseJsonBodyStrict(req2).catch(() => null);
|
|
577995
|
+
if (!body || typeof body !== "object") {
|
|
577996
|
+
sendProblem(res, problemDetails({
|
|
577997
|
+
type: P.invalidRequest,
|
|
577998
|
+
status: 400,
|
|
577999
|
+
title: "Body must be JSON object",
|
|
578000
|
+
detail: "POST {scope: 'read'|'run'|'admin', owner: string, profile?: string}",
|
|
578001
|
+
instance: requestId
|
|
578002
|
+
}));
|
|
578003
|
+
return true;
|
|
578004
|
+
}
|
|
578005
|
+
const scope = body.scope;
|
|
578006
|
+
if (scope !== "read" && scope !== "run" && scope !== "admin") {
|
|
578007
|
+
sendProblem(res, problemDetails({
|
|
578008
|
+
type: P.invalidRequest,
|
|
578009
|
+
status: 400,
|
|
578010
|
+
title: "Invalid scope",
|
|
578011
|
+
detail: "scope must be one of 'read', 'run', 'admin'.",
|
|
578012
|
+
instance: requestId
|
|
578013
|
+
}));
|
|
578014
|
+
return true;
|
|
578015
|
+
}
|
|
578016
|
+
const owner = typeof body.owner === "string" ? body.owner.slice(0, 200) : "anonymous";
|
|
578017
|
+
const profile = typeof body.profile === "string" ? body.profile.slice(0, 100) : null;
|
|
578018
|
+
const { mintKey: mintKey2 } = await Promise.resolve().then(() => (init_runtime_keys(), runtime_keys_exports));
|
|
578019
|
+
const rec = mintKey2({
|
|
578020
|
+
scope,
|
|
578021
|
+
owner,
|
|
578022
|
+
profile,
|
|
578023
|
+
rpm: typeof body.rpm === "number" ? body.rpm : void 0,
|
|
578024
|
+
tpd: typeof body.tpd === "number" ? body.tpd : void 0,
|
|
578025
|
+
max_jobs: typeof body.max_jobs === "number" ? body.max_jobs : void 0
|
|
578026
|
+
});
|
|
578027
|
+
sendJson(res, 201, { ...rec, _note: "This is the ONLY response that contains the full key. Persist it now." });
|
|
578028
|
+
} catch (err) {
|
|
578029
|
+
sendProblem(res, problemDetails({
|
|
578030
|
+
type: P.internalError,
|
|
578031
|
+
status: 500,
|
|
578032
|
+
title: "Key mint failed",
|
|
578033
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
578034
|
+
instance: requestId
|
|
578035
|
+
}));
|
|
578036
|
+
}
|
|
578037
|
+
return true;
|
|
578038
|
+
}
|
|
578039
|
+
async function handleRevokeKey(ctx3, prefix) {
|
|
578040
|
+
const { req: req2, res, requestId } = ctx3;
|
|
578041
|
+
const reqAuth = req2;
|
|
578042
|
+
if (reqAuth._authScope !== "admin") {
|
|
578043
|
+
sendProblem(res, problemDetails({
|
|
578044
|
+
type: P.forbidden,
|
|
578045
|
+
status: 403,
|
|
578046
|
+
title: "Admin scope required",
|
|
578047
|
+
detail: "Revoking keys requires 'admin' scope.",
|
|
578048
|
+
instance: requestId
|
|
578049
|
+
}));
|
|
578050
|
+
return true;
|
|
578051
|
+
}
|
|
578052
|
+
if (!prefix || prefix.length < 8) {
|
|
578053
|
+
sendProblem(res, problemDetails({
|
|
578054
|
+
type: P.invalidRequest,
|
|
578055
|
+
status: 400,
|
|
578056
|
+
title: "Prefix too short",
|
|
578057
|
+
detail: "Provide at least the first 8 characters of the key to revoke.",
|
|
578058
|
+
instance: requestId
|
|
578059
|
+
}));
|
|
578060
|
+
return true;
|
|
578061
|
+
}
|
|
578062
|
+
try {
|
|
578063
|
+
const { revokeByPrefix: revokeByPrefix2 } = await Promise.resolve().then(() => (init_runtime_keys(), runtime_keys_exports));
|
|
578064
|
+
const n2 = revokeByPrefix2(prefix);
|
|
578065
|
+
sendJson(res, 200, { revoked: n2 });
|
|
578066
|
+
} catch (err) {
|
|
578067
|
+
sendProblem(res, problemDetails({
|
|
578068
|
+
type: P.internalError,
|
|
578069
|
+
status: 500,
|
|
578070
|
+
title: "Key revoke failed",
|
|
578071
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
578072
|
+
instance: requestId
|
|
578073
|
+
}));
|
|
578074
|
+
}
|
|
578075
|
+
return true;
|
|
578076
|
+
}
|
|
577849
578077
|
async function handleListTools(ctx3) {
|
|
577850
578078
|
const { req: req2, res, url, requestId } = ctx3;
|
|
577851
578079
|
try {
|
|
@@ -577889,10 +578117,15 @@ async function handleListTools(ctx3) {
|
|
|
577889
578117
|
const filterCat = url.searchParams.get("category");
|
|
577890
578118
|
const filterScope = url.searchParams.get("scope");
|
|
577891
578119
|
const filterRisk = url.searchParams.get("risk");
|
|
578120
|
+
const filterOffDeviceRaw = url.searchParams.get("off_device");
|
|
577892
578121
|
let filtered = tools;
|
|
577893
578122
|
if (filterCat) filtered = filtered.filter((t2) => t2.security?.categories?.includes(filterCat));
|
|
577894
578123
|
if (filterScope) filtered = filtered.filter((t2) => t2.security?.requires_scope === filterScope);
|
|
577895
578124
|
if (filterRisk) filtered = filtered.filter((t2) => t2.security?.risk === filterRisk);
|
|
578125
|
+
if (filterOffDeviceRaw !== null) {
|
|
578126
|
+
const want = filterOffDeviceRaw === "true";
|
|
578127
|
+
filtered = filtered.filter((t2) => t2.security?.off_device_allowed === want);
|
|
578128
|
+
}
|
|
577896
578129
|
const page2 = parsePagination(url.searchParams);
|
|
577897
578130
|
const envelope = paginated(filtered, page2);
|
|
577898
578131
|
const etag = computeEtag(envelope);
|
|
@@ -577965,6 +578198,13 @@ async function handleGetTool(ctx3, name10) {
|
|
|
577965
578198
|
endpoints: {
|
|
577966
578199
|
call: `/v1/tools/${encodeURIComponent(name10)}/call`,
|
|
577967
578200
|
schema: `/v1/tools/${encodeURIComponent(name10)}`
|
|
578201
|
+
},
|
|
578202
|
+
// Q4: document the canonical body shape for /v1/tools/{name}/call.
|
|
578203
|
+
// The `parameters` field IS the JSON-schema describing what goes
|
|
578204
|
+
// INSIDE the args wrapper — it's not the wrapper itself.
|
|
578205
|
+
call_body_shape: {
|
|
578206
|
+
args: "<object matching the `parameters` JSON schema>",
|
|
578207
|
+
working_dir: "<optional absolute path; defaults to daemon cwd>"
|
|
577968
578208
|
}
|
|
577969
578209
|
};
|
|
577970
578210
|
const etag = computeEtag(body);
|
|
@@ -578147,17 +578387,17 @@ async function handleListAgentTypes(ctx3) {
|
|
|
578147
578387
|
}
|
|
578148
578388
|
async function handleListEngines(ctx3) {
|
|
578149
578389
|
const { res } = ctx3;
|
|
578150
|
-
const home =
|
|
578390
|
+
const home = homedir38();
|
|
578151
578391
|
sendJson(res, 200, {
|
|
578152
578392
|
engines: [
|
|
578153
|
-
{ name: "dream", state_file:
|
|
578154
|
-
{ name: "bless", state_file:
|
|
578155
|
-
{ name: "call", state_file:
|
|
578156
|
-
{ name: "listen", state_file:
|
|
578157
|
-
{ name: "telegram", state_file:
|
|
578158
|
-
{ name: "expose", state_file:
|
|
578159
|
-
{ name: "nexus", state_file:
|
|
578160
|
-
{ name: "ipfs", state_file:
|
|
578393
|
+
{ name: "dream", state_file: join111(process.cwd(), ".oa", "dreams"), controllable_via: "SSE + slash commands" },
|
|
578394
|
+
{ name: "bless", state_file: join111(process.cwd(), ".oa", "bless-state.json"), controllable_via: "slash commands" },
|
|
578395
|
+
{ name: "call", state_file: join111(process.cwd(), ".oa", "call-state.json"), controllable_via: "slash commands" },
|
|
578396
|
+
{ name: "listen", state_file: join111(process.cwd(), ".oa", "listen-state.json"), controllable_via: "slash commands" },
|
|
578397
|
+
{ name: "telegram", state_file: join111(home, ".open-agents", "telegram-state.json"), controllable_via: "slash commands" },
|
|
578398
|
+
{ name: "expose", state_file: join111(process.cwd(), ".oa", "expose-state.json"), controllable_via: "/expose commands" },
|
|
578399
|
+
{ name: "nexus", state_file: join111(home, ".open-agents", "nexus-peer-cache.json"), controllable_via: "/nexus commands" },
|
|
578400
|
+
{ name: "ipfs", state_file: join111(process.cwd(), ".oa", "ipfs"), controllable_via: "slash commands" }
|
|
578161
578401
|
],
|
|
578162
578402
|
note: "Engine instrumentation lives in the running TUI process. Full status + control requires the daemon↔TUI bridge (PT-07). See parity audit WO-PARITY-04."
|
|
578163
578403
|
});
|
|
@@ -578240,21 +578480,21 @@ async function tryAimsRoute(ctx3) {
|
|
|
578240
578480
|
return false;
|
|
578241
578481
|
}
|
|
578242
578482
|
function aimsDir() {
|
|
578243
|
-
return
|
|
578483
|
+
return join111(homedir38(), ".open-agents", "aims");
|
|
578244
578484
|
}
|
|
578245
578485
|
function readAimsFile(name10, fallback) {
|
|
578246
578486
|
try {
|
|
578247
|
-
const p2 =
|
|
578248
|
-
if (
|
|
578487
|
+
const p2 = join111(aimsDir(), name10);
|
|
578488
|
+
if (existsSync95(p2)) return JSON.parse(readFileSync77(p2, "utf-8"));
|
|
578249
578489
|
} catch {
|
|
578250
578490
|
}
|
|
578251
578491
|
return fallback;
|
|
578252
578492
|
}
|
|
578253
578493
|
function writeAimsFile(name10, data) {
|
|
578254
578494
|
const dir = aimsDir();
|
|
578255
|
-
const { mkdirSync:
|
|
578256
|
-
|
|
578257
|
-
const finalPath =
|
|
578495
|
+
const { mkdirSync: mkdirSync67, writeFileSync: wf, renameSync: rn } = __require("node:fs");
|
|
578496
|
+
mkdirSync67(dir, { recursive: true });
|
|
578497
|
+
const finalPath = join111(dir, name10);
|
|
578258
578498
|
const tmpPath = `${finalPath}.tmp.${process.pid}.${Date.now()}`;
|
|
578259
578499
|
try {
|
|
578260
578500
|
wf(tmpPath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
@@ -578584,12 +578824,12 @@ async function handleAimsSuppliers(ctx3) {
|
|
|
578584
578824
|
}
|
|
578585
578825
|
];
|
|
578586
578826
|
const sponsorPaths = [
|
|
578587
|
-
|
|
578827
|
+
join111(homedir38(), ".open-agents", "sponsor-cache.json")
|
|
578588
578828
|
];
|
|
578589
578829
|
for (const p2 of sponsorPaths) {
|
|
578590
|
-
if (!
|
|
578830
|
+
if (!existsSync95(p2)) continue;
|
|
578591
578831
|
try {
|
|
578592
|
-
const raw = JSON.parse(
|
|
578832
|
+
const raw = JSON.parse(readFileSync77(p2, "utf-8"));
|
|
578593
578833
|
const list = Array.isArray(raw) ? raw : raw?.sponsors ?? [];
|
|
578594
578834
|
for (const s2 of list) {
|
|
578595
578835
|
suppliers.push({
|
|
@@ -578651,11 +578891,11 @@ async function handleAimsIncidentPost(ctx3) {
|
|
|
578651
578891
|
}));
|
|
578652
578892
|
return true;
|
|
578653
578893
|
}
|
|
578654
|
-
const { randomBytes:
|
|
578894
|
+
const { randomBytes: randomBytes25 } = await import("node:crypto");
|
|
578655
578895
|
const record = await withAimsLock("incidents.json", () => {
|
|
578656
578896
|
const existing = readAimsFile("incidents.json", []);
|
|
578657
578897
|
const rec = {
|
|
578658
|
-
id: `INC-${Date.now()}-${
|
|
578898
|
+
id: `INC-${Date.now()}-${randomBytes25(4).toString("hex")}`,
|
|
578659
578899
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
578660
578900
|
raised_by: user ?? "anonymous",
|
|
578661
578901
|
status: "open",
|
|
@@ -585783,10 +586023,24 @@ function getOpenApiSpec() {
|
|
|
585783
586023
|
"/v1/models": { get: { summary: "List aggregated models", tags: ["Inference"], responses: { 200: { description: "OpenAI-format model list" }, ...ErrorResponses } } },
|
|
585784
586024
|
"/v1/chat/completions": {
|
|
585785
586025
|
post: {
|
|
585786
|
-
summary: "OpenAI-compatible chat completion",
|
|
586026
|
+
summary: "OpenAI-compatible chat completion (with optional server-side agent loop)",
|
|
585787
586027
|
tags: ["Inference"],
|
|
585788
|
-
|
|
585789
|
-
|
|
586028
|
+
description: "Standard OpenAI chat-completion proxy by default. Set agent_loop=true to enter a synchronous server-side loop that auto-executes daemon tools (web_search, web_fetch, file_read, ocr, etc.) and re-prompts the model — collapsing N round-trips into 1. include_daemon_tools=['read','run'] auto-merges daemon tools matching those scopes into the offered tools[]. timeout_s overrides OA_BACKEND_TIMEOUT_S (default 120s, max 1h). prompt_template='factual-first' prepends a web_search-first policy. SSE streaming honors tool_calls in delta as standard OpenAI shape: delta.tool_calls=[{id,type:'function',index,function:{name,arguments:<JSON-string>}}]. parallel_tool_calls is forwarded to the backend.",
|
|
586029
|
+
requestBody: { required: true, content: { "application/json": { schema: { type: "object", required: ["model", "messages"], properties: {
|
|
586030
|
+
model: { type: "string" },
|
|
586031
|
+
messages: { type: "array" },
|
|
586032
|
+
stream: { type: "boolean" },
|
|
586033
|
+
temperature: { type: "number" },
|
|
586034
|
+
tools: { type: "array", description: "OpenAI-shape tools array. Forwarded to the backend." },
|
|
586035
|
+
tool_choice: { description: "OpenAI-shape tool_choice. Forwarded to the backend." },
|
|
586036
|
+
parallel_tool_calls: { type: "boolean", description: "Q7 — forwarded to backend; some models (qwen3, llama3) emit multiple tool_calls in one response." },
|
|
586037
|
+
timeout_s: { type: "number", description: "Q1 — per-request timeout in seconds (1-3600). Overrides OA_BACKEND_TIMEOUT_S." },
|
|
586038
|
+
agent_loop: { type: "boolean", description: "Q2 — when true, daemon runs an N-turn agent loop server-side. Daemon tools execute inline; client tool_calls cause the loop to yield." },
|
|
586039
|
+
include_daemon_tools: { type: "array", items: { type: "string", enum: ["read", "run", "admin"] }, description: "Q3 — scopes to merge from daemon tool catalog into tools[]." },
|
|
586040
|
+
max_turns: { type: "integer", description: "Q2 — agent_loop max iterations (default 8, max 64)." },
|
|
586041
|
+
prompt_template: { type: "string", enum: ["factual-first"], description: "Q8 — prepended system policy template. 'factual-first' instructs model to call web_search FIRST for any factual question." }
|
|
586042
|
+
} } } } },
|
|
586043
|
+
responses: { 200: { description: "OpenAI chat.completion shape, SSE if stream=true. agent_loop responses include _agent_loop:{turns,log,done,reason}." }, ...ErrorResponses }
|
|
585790
586044
|
}
|
|
585791
586045
|
},
|
|
585792
586046
|
"/v1/embeddings": { post: { summary: "Generate embeddings", tags: ["Inference"], responses: { 200: { description: "Embedding vectors" }, ...ErrorResponses } } },
|
|
@@ -585998,7 +586252,7 @@ function getOpenApiSpec() {
|
|
|
585998
586252
|
post: {
|
|
585999
586253
|
summary: "Execute a single tool directly (MCP-style, no agent loop)",
|
|
586000
586254
|
tags: ["Tools"],
|
|
586001
|
-
description: "Body: {args: object, working_dir?: string}.
|
|
586255
|
+
description: "Body: {args: object, working_dir?: string}. The `args` key is canonical (Q4) — the JSON-schema in /v1/tools/{name} `parameters` describes what goes INSIDE the args wrapper. Returns ToolResult {success, output, llmContent?, error?, durationMs} plus security metadata. Auth gating: request scope (read/run/admin) must satisfy tool.requires_scope; non-loopback callers need admin scope unless tool.off_device_allowed=true. Anonymous loopback callers default to admin scope; anonymous remote callers default to read scope.",
|
|
586002
586256
|
parameters: [{ name: "name", in: "path", required: true, schema: { type: "string" } }],
|
|
586003
586257
|
responses: {
|
|
586004
586258
|
200: { description: "Tool result envelope" },
|
|
@@ -586008,6 +586262,28 @@ function getOpenApiSpec() {
|
|
|
586008
586262
|
}
|
|
586009
586263
|
}
|
|
586010
586264
|
},
|
|
586265
|
+
"/v1/keys": {
|
|
586266
|
+
get: {
|
|
586267
|
+
summary: "List runtime API keys (admin scope)",
|
|
586268
|
+
tags: ["Tools"],
|
|
586269
|
+
description: "Returns runtime keys with secrets masked (only first 8 + last 4 chars). Q6 — runtime-mintable alternative to OA_API_KEY/OA_API_KEYS env vars.",
|
|
586270
|
+
responses: { 200: { description: "Masked key list" }, 403: { description: "Admin scope required" } }
|
|
586271
|
+
},
|
|
586272
|
+
post: {
|
|
586273
|
+
summary: "Mint a new runtime API key (admin scope)",
|
|
586274
|
+
tags: ["Tools"],
|
|
586275
|
+
description: "Body: {scope: 'read'|'run'|'admin', owner: string, profile?: string, rpm?, tpd?, max_jobs?}. Returns the FULL key — only response that contains the secret. Persisted at ~/.open-agents/keys.json mode 0600.",
|
|
586276
|
+
responses: { 201: { description: "Key minted" }, 400: { description: "Invalid body" }, 403: { description: "Admin scope required" } }
|
|
586277
|
+
}
|
|
586278
|
+
},
|
|
586279
|
+
"/v1/keys/{prefix}": {
|
|
586280
|
+
delete: {
|
|
586281
|
+
summary: "Revoke a runtime key by prefix (admin scope)",
|
|
586282
|
+
tags: ["Tools"],
|
|
586283
|
+
parameters: [{ name: "prefix", in: "path", required: true, schema: { type: "string", minLength: 8 }, description: "First 8+ characters of the key" }],
|
|
586284
|
+
responses: { 200: { description: "Number of keys revoked" }, 400: { description: "Prefix too short" }, 403: { description: "Admin scope required" } }
|
|
586285
|
+
}
|
|
586286
|
+
},
|
|
586011
586287
|
"/v1/hooks": { get: { summary: "List hook types and counts", tags: ["Tools"], responses: { 200: { description: "Hook registry" } } } },
|
|
586012
586288
|
"/v1/agents": { get: { summary: "List agent types", tags: ["Tools"], responses: { 200: { description: "Agent type registry" } } } },
|
|
586013
586289
|
"/v1/engines": { get: { summary: "List long-running engines", tags: ["Engines"], responses: { 200: { description: "Engine status + state files" } } } },
|
|
@@ -586440,15 +586716,15 @@ var init_auth_oidc = __esm({
|
|
|
586440
586716
|
});
|
|
586441
586717
|
|
|
586442
586718
|
// packages/cli/src/api/usage-tracker.ts
|
|
586443
|
-
import { mkdirSync as
|
|
586444
|
-
import { join as
|
|
586719
|
+
import { mkdirSync as mkdirSync60, readFileSync as readFileSync78, writeFileSync as writeFileSync52, existsSync as existsSync96 } from "node:fs";
|
|
586720
|
+
import { join as join112 } from "node:path";
|
|
586445
586721
|
function initUsageTracker(oaDir) {
|
|
586446
|
-
const dir =
|
|
586447
|
-
|
|
586448
|
-
usageFile =
|
|
586722
|
+
const dir = join112(oaDir, "usage");
|
|
586723
|
+
mkdirSync60(dir, { recursive: true });
|
|
586724
|
+
usageFile = join112(dir, "token-usage.json");
|
|
586449
586725
|
try {
|
|
586450
|
-
if (
|
|
586451
|
-
store = JSON.parse(
|
|
586726
|
+
if (existsSync96(usageFile)) {
|
|
586727
|
+
store = JSON.parse(readFileSync78(usageFile, "utf-8"));
|
|
586452
586728
|
}
|
|
586453
586729
|
} catch {
|
|
586454
586730
|
store = { providers: {}, lastSaved: "" };
|
|
@@ -586484,7 +586760,7 @@ function flush2() {
|
|
|
586484
586760
|
if (!initialized2 || !dirty) return;
|
|
586485
586761
|
try {
|
|
586486
586762
|
store.lastSaved = (/* @__PURE__ */ new Date()).toISOString();
|
|
586487
|
-
|
|
586763
|
+
writeFileSync52(usageFile, JSON.stringify(store, null, 2), "utf-8");
|
|
586488
586764
|
dirty = false;
|
|
586489
586765
|
} catch {
|
|
586490
586766
|
}
|
|
@@ -586512,24 +586788,24 @@ var init_usage_tracker = __esm({
|
|
|
586512
586788
|
});
|
|
586513
586789
|
|
|
586514
586790
|
// packages/cli/src/api/profiles.ts
|
|
586515
|
-
import { existsSync as
|
|
586516
|
-
import { join as
|
|
586517
|
-
import { homedir as
|
|
586518
|
-
import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as
|
|
586791
|
+
import { existsSync as existsSync97, readFileSync as readFileSync79, writeFileSync as writeFileSync53, mkdirSync as mkdirSync61, readdirSync as readdirSync33, unlinkSync as unlinkSync23 } from "node:fs";
|
|
586792
|
+
import { join as join113 } from "node:path";
|
|
586793
|
+
import { homedir as homedir39 } from "node:os";
|
|
586794
|
+
import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as randomBytes22, scryptSync as scryptSync3 } from "node:crypto";
|
|
586519
586795
|
function globalProfileDir() {
|
|
586520
|
-
return
|
|
586796
|
+
return join113(homedir39(), ".open-agents", "profiles");
|
|
586521
586797
|
}
|
|
586522
586798
|
function projectProfileDir(projectDir2) {
|
|
586523
|
-
return
|
|
586799
|
+
return join113(projectDir2 || process.cwd(), ".oa", "profiles");
|
|
586524
586800
|
}
|
|
586525
586801
|
function listProfiles(projectDir2) {
|
|
586526
586802
|
const result = [];
|
|
586527
586803
|
const seen = /* @__PURE__ */ new Set();
|
|
586528
586804
|
const projDir = projectProfileDir(projectDir2);
|
|
586529
|
-
if (
|
|
586805
|
+
if (existsSync97(projDir)) {
|
|
586530
586806
|
for (const f2 of readdirSync33(projDir).filter((f3) => f3.endsWith(".json"))) {
|
|
586531
586807
|
try {
|
|
586532
|
-
const raw = JSON.parse(
|
|
586808
|
+
const raw = JSON.parse(readFileSync79(join113(projDir, f2), "utf8"));
|
|
586533
586809
|
const name10 = f2.replace(".json", "");
|
|
586534
586810
|
seen.add(name10);
|
|
586535
586811
|
result.push({
|
|
@@ -586543,12 +586819,12 @@ function listProfiles(projectDir2) {
|
|
|
586543
586819
|
}
|
|
586544
586820
|
}
|
|
586545
586821
|
const globDir = globalProfileDir();
|
|
586546
|
-
if (
|
|
586822
|
+
if (existsSync97(globDir)) {
|
|
586547
586823
|
for (const f2 of readdirSync33(globDir).filter((f3) => f3.endsWith(".json"))) {
|
|
586548
586824
|
const name10 = f2.replace(".json", "");
|
|
586549
586825
|
if (seen.has(name10)) continue;
|
|
586550
586826
|
try {
|
|
586551
|
-
const raw = JSON.parse(
|
|
586827
|
+
const raw = JSON.parse(readFileSync79(join113(globDir, f2), "utf8"));
|
|
586552
586828
|
result.push({
|
|
586553
586829
|
name: name10,
|
|
586554
586830
|
description: raw.description || "",
|
|
@@ -586563,11 +586839,11 @@ function listProfiles(projectDir2) {
|
|
|
586563
586839
|
}
|
|
586564
586840
|
function loadProfile(name10, password, projectDir2) {
|
|
586565
586841
|
const sanitized = name10.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
586566
|
-
const projPath =
|
|
586567
|
-
const globPath =
|
|
586568
|
-
const filePath =
|
|
586842
|
+
const projPath = join113(projectProfileDir(projectDir2), `${sanitized}.json`);
|
|
586843
|
+
const globPath = join113(globalProfileDir(), `${sanitized}.json`);
|
|
586844
|
+
const filePath = existsSync97(projPath) ? projPath : existsSync97(globPath) ? globPath : null;
|
|
586569
586845
|
if (!filePath) return null;
|
|
586570
|
-
const raw = JSON.parse(
|
|
586846
|
+
const raw = JSON.parse(readFileSync79(filePath, "utf8"));
|
|
586571
586847
|
if (raw.encrypted === true) {
|
|
586572
586848
|
if (!password) return null;
|
|
586573
586849
|
return decryptProfile(raw, password);
|
|
@@ -586576,32 +586852,32 @@ function loadProfile(name10, password, projectDir2) {
|
|
|
586576
586852
|
}
|
|
586577
586853
|
function saveProfile(profile, password, scope = "global", projectDir2) {
|
|
586578
586854
|
const dir = scope === "project" ? projectProfileDir(projectDir2) : globalProfileDir();
|
|
586579
|
-
|
|
586855
|
+
mkdirSync61(dir, { recursive: true });
|
|
586580
586856
|
const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
586581
|
-
const filePath =
|
|
586857
|
+
const filePath = join113(dir, `${sanitized}.json`);
|
|
586582
586858
|
profile.modified = (/* @__PURE__ */ new Date()).toISOString();
|
|
586583
586859
|
if (password) {
|
|
586584
586860
|
const encrypted = encryptProfile(profile, password);
|
|
586585
|
-
|
|
586861
|
+
writeFileSync53(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
586586
586862
|
} else {
|
|
586587
586863
|
profile.encrypted = false;
|
|
586588
|
-
|
|
586864
|
+
writeFileSync53(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
|
|
586589
586865
|
}
|
|
586590
586866
|
}
|
|
586591
586867
|
function deleteProfile(name10, scope = "global", projectDir2) {
|
|
586592
586868
|
const sanitized = name10.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
586593
586869
|
const dir = scope === "project" ? projectProfileDir(projectDir2) : globalProfileDir();
|
|
586594
|
-
const filePath =
|
|
586595
|
-
if (
|
|
586870
|
+
const filePath = join113(dir, `${sanitized}.json`);
|
|
586871
|
+
if (existsSync97(filePath)) {
|
|
586596
586872
|
unlinkSync23(filePath);
|
|
586597
586873
|
return true;
|
|
586598
586874
|
}
|
|
586599
586875
|
return false;
|
|
586600
586876
|
}
|
|
586601
586877
|
function encryptProfile(profile, password) {
|
|
586602
|
-
const salt =
|
|
586878
|
+
const salt = randomBytes22(32);
|
|
586603
586879
|
const key = scryptSync3(password, salt, 32);
|
|
586604
|
-
const iv =
|
|
586880
|
+
const iv = randomBytes22(16);
|
|
586605
586881
|
const cipher = createCipheriv4("aes-256-gcm", key, iv);
|
|
586606
586882
|
const plaintext = JSON.stringify(profile);
|
|
586607
586883
|
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
@@ -586707,23 +586983,23 @@ var init_profiles = __esm({
|
|
|
586707
586983
|
|
|
586708
586984
|
// packages/cli/src/docker.ts
|
|
586709
586985
|
import { execSync as execSync54, spawn as spawn24 } from "node:child_process";
|
|
586710
|
-
import { existsSync as
|
|
586711
|
-
import { join as
|
|
586712
|
-
import { homedir as
|
|
586986
|
+
import { existsSync as existsSync98, mkdirSync as mkdirSync62, writeFileSync as writeFileSync54 } from "node:fs";
|
|
586987
|
+
import { join as join114, resolve as resolve37, dirname as dirname34 } from "node:path";
|
|
586988
|
+
import { homedir as homedir40 } from "node:os";
|
|
586713
586989
|
import { fileURLToPath as fileURLToPath16 } from "node:url";
|
|
586714
586990
|
function getDockerDir() {
|
|
586715
586991
|
try {
|
|
586716
586992
|
if (typeof __dirname !== "undefined") {
|
|
586717
|
-
return
|
|
586993
|
+
return join114(__dirname, "..", "..", "..", "docker");
|
|
586718
586994
|
}
|
|
586719
586995
|
} catch {
|
|
586720
586996
|
}
|
|
586721
586997
|
try {
|
|
586722
586998
|
const thisDir = dirname34(fileURLToPath16(import.meta.url));
|
|
586723
|
-
return
|
|
586999
|
+
return join114(thisDir, "..", "..", "..", "docker");
|
|
586724
587000
|
} catch {
|
|
586725
587001
|
}
|
|
586726
|
-
return
|
|
587002
|
+
return join114(process.cwd(), "docker");
|
|
586727
587003
|
}
|
|
586728
587004
|
function isDockerAvailable() {
|
|
586729
587005
|
try {
|
|
@@ -586854,11 +587130,11 @@ async function ensureOaImage(force = false) {
|
|
|
586854
587130
|
}
|
|
586855
587131
|
let buildContext;
|
|
586856
587132
|
const dockerDir = getDockerDir();
|
|
586857
|
-
if (
|
|
587133
|
+
if (existsSync98(join114(dockerDir, "Dockerfile"))) {
|
|
586858
587134
|
buildContext = dockerDir;
|
|
586859
587135
|
} else {
|
|
586860
|
-
buildContext =
|
|
586861
|
-
|
|
587136
|
+
buildContext = join114(homedir40(), ".oa", "docker-build");
|
|
587137
|
+
mkdirSync62(buildContext, { recursive: true });
|
|
586862
587138
|
writeDockerfiles(buildContext);
|
|
586863
587139
|
}
|
|
586864
587140
|
try {
|
|
@@ -586932,8 +587208,8 @@ chown -R node:node /workspace /home/node/.oa /home/node/.open-agents 2>/dev/null
|
|
|
586932
587208
|
if [ "$1" = "oa" ]; then shift; exec su - node -c "cd /workspace && oa $*"; fi
|
|
586933
587209
|
exec "$@"
|
|
586934
587210
|
`;
|
|
586935
|
-
|
|
586936
|
-
|
|
587211
|
+
writeFileSync54(join114(dir, "Dockerfile"), dockerfile);
|
|
587212
|
+
writeFileSync54(join114(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
|
|
586937
587213
|
}
|
|
586938
587214
|
function hasNvidiaGpu() {
|
|
586939
587215
|
try {
|
|
@@ -587186,23 +587462,23 @@ import * as http5 from "node:http";
|
|
|
587186
587462
|
import * as https3 from "node:https";
|
|
587187
587463
|
import { createRequire as createRequire4 } from "node:module";
|
|
587188
587464
|
import { fileURLToPath as fileURLToPath17 } from "node:url";
|
|
587189
|
-
import { dirname as dirname35, join as
|
|
587190
|
-
import { homedir as
|
|
587465
|
+
import { dirname as dirname35, join as join115, resolve as resolve38 } from "node:path";
|
|
587466
|
+
import { homedir as homedir41 } from "node:os";
|
|
587191
587467
|
import { spawn as spawn25, execSync as execSync55 } from "node:child_process";
|
|
587192
|
-
import { mkdirSync as
|
|
587193
|
-
import { randomBytes as
|
|
587468
|
+
import { mkdirSync as mkdirSync63, writeFileSync as writeFileSync55, readFileSync as readFileSync80, readdirSync as readdirSync34, existsSync as existsSync99, watch as fsWatch3, renameSync as renameSync8, unlinkSync as unlinkSync24 } from "node:fs";
|
|
587469
|
+
import { randomBytes as randomBytes23, randomUUID as randomUUID14 } from "node:crypto";
|
|
587194
587470
|
import { createHash as createHash15 } from "node:crypto";
|
|
587195
587471
|
function getVersion3() {
|
|
587196
587472
|
try {
|
|
587197
587473
|
const thisDir = dirname35(fileURLToPath17(import.meta.url));
|
|
587198
587474
|
const candidates = [
|
|
587199
|
-
|
|
587200
|
-
|
|
587201
|
-
|
|
587475
|
+
join115(thisDir, "..", "package.json"),
|
|
587476
|
+
join115(thisDir, "..", "..", "package.json"),
|
|
587477
|
+
join115(thisDir, "..", "..", "..", "package.json")
|
|
587202
587478
|
];
|
|
587203
587479
|
for (const pkgPath of candidates) {
|
|
587204
587480
|
try {
|
|
587205
|
-
if (!
|
|
587481
|
+
if (!existsSync99(pkgPath)) continue;
|
|
587206
587482
|
const pkg = require3(pkgPath);
|
|
587207
587483
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
|
|
587208
587484
|
return pkg.version ?? "0.0.0";
|
|
@@ -587349,6 +587625,19 @@ function resolveModelEndpoint(modelId) {
|
|
|
587349
587625
|
}
|
|
587350
587626
|
return null;
|
|
587351
587627
|
}
|
|
587628
|
+
function getBackendTimeoutMs(perRequestSeconds) {
|
|
587629
|
+
if (typeof perRequestSeconds === "number" && perRequestSeconds > 0) {
|
|
587630
|
+
return Math.min(Math.floor(perRequestSeconds * 1e3), BACKEND_TIMEOUT_MAX_MS);
|
|
587631
|
+
}
|
|
587632
|
+
const envS = process.env["OA_BACKEND_TIMEOUT_S"];
|
|
587633
|
+
if (envS) {
|
|
587634
|
+
const n2 = parseFloat(envS);
|
|
587635
|
+
if (Number.isFinite(n2) && n2 > 0) {
|
|
587636
|
+
return Math.min(Math.floor(n2 * 1e3), BACKEND_TIMEOUT_MAX_MS);
|
|
587637
|
+
}
|
|
587638
|
+
}
|
|
587639
|
+
return BACKEND_TIMEOUT_DEFAULT_MS;
|
|
587640
|
+
}
|
|
587352
587641
|
function recordMetric(method, path8, status) {
|
|
587353
587642
|
const key = `${method}|${path8}|${status}`;
|
|
587354
587643
|
const existing = metrics.requests.get(key);
|
|
@@ -587391,9 +587680,9 @@ function isOriginAllowed(origin) {
|
|
|
587391
587680
|
if (!origin) return true;
|
|
587392
587681
|
let accessMode = (process.env["OA_ACCESS"] || "").toLowerCase().trim();
|
|
587393
587682
|
try {
|
|
587394
|
-
const accessFile =
|
|
587395
|
-
if (
|
|
587396
|
-
const persisted =
|
|
587683
|
+
const accessFile = join115(homedir41(), ".open-agents", "access");
|
|
587684
|
+
if (existsSync99(accessFile)) {
|
|
587685
|
+
const persisted = readFileSync80(accessFile, "utf8").trim().toLowerCase();
|
|
587397
587686
|
if (persisted === "any" || persisted === "lan" || persisted === "loopback") {
|
|
587398
587687
|
accessMode = persisted;
|
|
587399
587688
|
}
|
|
@@ -587453,7 +587742,7 @@ async function retrieveMemoryContext(userMessage, sessionId, maxEpisodes = 5) {
|
|
|
587453
587742
|
if (!memMod || !memMod.EpisodeStore) {
|
|
587454
587743
|
return { contextBlock: "", retrieved: [] };
|
|
587455
587744
|
}
|
|
587456
|
-
const dbPath =
|
|
587745
|
+
const dbPath = join115(homedir41(), ".open-agents", "memory.db");
|
|
587457
587746
|
const store2 = new memMod.EpisodeStore(dbPath);
|
|
587458
587747
|
const recent = store2.search({ limit: 30, sessionId: void 0 }) ?? [];
|
|
587459
587748
|
const qLower = userMessage.toLowerCase();
|
|
@@ -587496,7 +587785,7 @@ async function writeMemoryEpisodes(sessionId, userMessage, assistantContent, too
|
|
|
587496
587785
|
try {
|
|
587497
587786
|
const memMod = await Promise.resolve().then(() => (init_dist7(), dist_exports2)).catch(() => null);
|
|
587498
587787
|
if (!memMod || !memMod.EpisodeStore) return 0;
|
|
587499
|
-
const dbPath =
|
|
587788
|
+
const dbPath = join115(homedir41(), ".open-agents", "memory.db");
|
|
587500
587789
|
const store2 = new memMod.EpisodeStore(dbPath);
|
|
587501
587790
|
let written = 0;
|
|
587502
587791
|
try {
|
|
@@ -587598,7 +587887,8 @@ async function directChatBackend(opts) {
|
|
|
587598
587887
|
proxyRes.on("error", reject);
|
|
587599
587888
|
});
|
|
587600
587889
|
proxyReq.on("error", reject);
|
|
587601
|
-
|
|
587890
|
+
const _dctTo = getBackendTimeoutMs(extraFields?.["timeout_s"]);
|
|
587891
|
+
proxyReq.setTimeout(_dctTo, () => proxyReq.destroy(new Error(`Backend timeout (${Math.round(_dctTo / 1e3)}s)`)));
|
|
587602
587892
|
proxyReq.write(reqBody);
|
|
587603
587893
|
proxyReq.end();
|
|
587604
587894
|
});
|
|
@@ -587751,7 +588041,7 @@ function backendAuthHeaders(endpoint) {
|
|
|
587751
588041
|
if (key) return { Authorization: `Bearer ${key}` };
|
|
587752
588042
|
return {};
|
|
587753
588043
|
}
|
|
587754
|
-
function ollamaRequest(ollamaUrl, path8, method, body) {
|
|
588044
|
+
function ollamaRequest(ollamaUrl, path8, method, body, timeoutMs) {
|
|
587755
588045
|
return new Promise((resolve43, reject) => {
|
|
587756
588046
|
const url = new URL(path8, ollamaUrl);
|
|
587757
588047
|
const isHttps = url.protocol === "https:";
|
|
@@ -587778,15 +588068,16 @@ function ollamaRequest(ollamaUrl, path8, method, body) {
|
|
|
587778
588068
|
});
|
|
587779
588069
|
});
|
|
587780
588070
|
});
|
|
587781
|
-
|
|
587782
|
-
|
|
588071
|
+
const _to = getBackendTimeoutMs(timeoutMs ? timeoutMs / 1e3 : void 0);
|
|
588072
|
+
proxyReq.setTimeout(_to, () => {
|
|
588073
|
+
proxyReq.destroy(new Error(`Backend request timeout (${Math.round(_to / 1e3)}s)`));
|
|
587783
588074
|
});
|
|
587784
588075
|
proxyReq.on("error", reject);
|
|
587785
588076
|
if (body) proxyReq.write(body);
|
|
587786
588077
|
proxyReq.end();
|
|
587787
588078
|
});
|
|
587788
588079
|
}
|
|
587789
|
-
function ollamaStream(ollamaUrl, path8, method, body, onData, onEnd, onError) {
|
|
588080
|
+
function ollamaStream(ollamaUrl, path8, method, body, onData, onEnd, onError, timeoutMs) {
|
|
587790
588081
|
const url = new URL(path8, ollamaUrl);
|
|
587791
588082
|
const isHttps = url.protocol === "https:";
|
|
587792
588083
|
const options2 = {
|
|
@@ -587806,8 +588097,9 @@ function ollamaStream(ollamaUrl, path8, method, body, onData, onEnd, onError) {
|
|
|
587806
588097
|
proxyRes.on("data", onData);
|
|
587807
588098
|
proxyRes.on("end", onEnd);
|
|
587808
588099
|
});
|
|
587809
|
-
|
|
587810
|
-
|
|
588100
|
+
const _streamTo = getBackendTimeoutMs(timeoutMs ? timeoutMs / 1e3 : void 0);
|
|
588101
|
+
proxyReq.setTimeout(_streamTo, () => {
|
|
588102
|
+
proxyReq.destroy(new Error(`Backend stream timeout (${Math.round(_streamTo / 1e3)}s)`));
|
|
587811
588103
|
});
|
|
587812
588104
|
proxyReq.on("error", onError);
|
|
587813
588105
|
if (body) proxyReq.write(body);
|
|
@@ -587815,32 +588107,76 @@ function ollamaStream(ollamaUrl, path8, method, body, onData, onEnd, onError) {
|
|
|
587815
588107
|
}
|
|
587816
588108
|
function jobsDir() {
|
|
587817
588109
|
const root = resolve38(process.cwd());
|
|
587818
|
-
const dir =
|
|
587819
|
-
|
|
588110
|
+
const dir = join115(root, ".oa", "jobs");
|
|
588111
|
+
mkdirSync63(dir, { recursive: true });
|
|
587820
588112
|
return dir;
|
|
587821
588113
|
}
|
|
587822
588114
|
function loadJob(id) {
|
|
587823
|
-
const file =
|
|
587824
|
-
if (!
|
|
588115
|
+
const file = join115(jobsDir(), `${id}.json`);
|
|
588116
|
+
if (!existsSync99(file)) return null;
|
|
587825
588117
|
try {
|
|
587826
|
-
return JSON.parse(
|
|
588118
|
+
return JSON.parse(readFileSync80(file, "utf-8"));
|
|
587827
588119
|
} catch {
|
|
587828
588120
|
return null;
|
|
587829
588121
|
}
|
|
587830
588122
|
}
|
|
587831
588123
|
function listJobs() {
|
|
587832
588124
|
const dir = jobsDir();
|
|
587833
|
-
if (!
|
|
588125
|
+
if (!existsSync99(dir)) return [];
|
|
587834
588126
|
const files = readdirSync34(dir).filter((f2) => f2.endsWith(".json")).sort();
|
|
587835
588127
|
const jobs = [];
|
|
587836
588128
|
for (const file of files) {
|
|
587837
588129
|
try {
|
|
587838
|
-
jobs.push(JSON.parse(
|
|
588130
|
+
jobs.push(JSON.parse(readFileSync80(join115(dir, file), "utf-8")));
|
|
587839
588131
|
} catch {
|
|
587840
588132
|
}
|
|
587841
588133
|
}
|
|
587842
588134
|
return jobs;
|
|
587843
588135
|
}
|
|
588136
|
+
function pruneOldJobs() {
|
|
588137
|
+
const retentionH = parseFloat(process.env["OA_RUN_RETENTION_H"] || "24");
|
|
588138
|
+
const cutoffMs = Date.now() - (Number.isFinite(retentionH) && retentionH > 0 ? retentionH : 24) * 36e5;
|
|
588139
|
+
const dir = jobsDir();
|
|
588140
|
+
if (!existsSync99(dir)) return { pruned: 0, kept: 0 };
|
|
588141
|
+
let pruned = 0;
|
|
588142
|
+
let kept = 0;
|
|
588143
|
+
for (const file of readdirSync34(dir)) {
|
|
588144
|
+
if (!file.endsWith(".json")) continue;
|
|
588145
|
+
const path8 = join115(dir, file);
|
|
588146
|
+
try {
|
|
588147
|
+
const job = JSON.parse(readFileSync80(path8, "utf-8"));
|
|
588148
|
+
if (job.status === "running") {
|
|
588149
|
+
kept++;
|
|
588150
|
+
continue;
|
|
588151
|
+
}
|
|
588152
|
+
const ageRef = job.completedAt || job.startedAt;
|
|
588153
|
+
const ts = ageRef ? Date.parse(ageRef) : NaN;
|
|
588154
|
+
if (Number.isFinite(ts) && ts < cutoffMs) {
|
|
588155
|
+
try {
|
|
588156
|
+
unlinkSync24(path8);
|
|
588157
|
+
} catch {
|
|
588158
|
+
}
|
|
588159
|
+
const outFile = path8.replace(/\.json$/, ".output");
|
|
588160
|
+
if (existsSync99(outFile)) {
|
|
588161
|
+
try {
|
|
588162
|
+
unlinkSync24(outFile);
|
|
588163
|
+
} catch {
|
|
588164
|
+
}
|
|
588165
|
+
}
|
|
588166
|
+
pruned++;
|
|
588167
|
+
} else {
|
|
588168
|
+
kept++;
|
|
588169
|
+
}
|
|
588170
|
+
} catch {
|
|
588171
|
+
try {
|
|
588172
|
+
unlinkSync24(path8);
|
|
588173
|
+
pruned++;
|
|
588174
|
+
} catch {
|
|
588175
|
+
}
|
|
588176
|
+
}
|
|
588177
|
+
}
|
|
588178
|
+
return { pruned, kept };
|
|
588179
|
+
}
|
|
587844
588180
|
function getKeyUsage(user) {
|
|
587845
588181
|
if (!perKeyUsage.has(user)) {
|
|
587846
588182
|
perKeyUsage.set(user, { requestTimestamps: [], tokensToday: 0, tokenDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), activeJobs: 0 });
|
|
@@ -587909,14 +588245,14 @@ function autoSeedTodosFromPrompt(prompt) {
|
|
|
587909
588245
|
return [];
|
|
587910
588246
|
}
|
|
587911
588247
|
function atomicJobWrite(dir, id, job) {
|
|
587912
|
-
const finalPath =
|
|
588248
|
+
const finalPath = join115(dir, `${id}.json`);
|
|
587913
588249
|
const tmpPath = `${finalPath}.tmp.${process.pid}.${Date.now()}`;
|
|
587914
588250
|
try {
|
|
587915
|
-
|
|
588251
|
+
writeFileSync55(tmpPath, JSON.stringify(job, null, 2), "utf-8");
|
|
587916
588252
|
renameSync8(tmpPath, finalPath);
|
|
587917
588253
|
} catch {
|
|
587918
588254
|
try {
|
|
587919
|
-
|
|
588255
|
+
writeFileSync55(finalPath, JSON.stringify(job, null, 2), "utf-8");
|
|
587920
588256
|
} catch {
|
|
587921
588257
|
}
|
|
587922
588258
|
try {
|
|
@@ -587948,8 +588284,27 @@ function resolveAuth(req2) {
|
|
|
587948
588284
|
return { authenticated: false, scope: "read" };
|
|
587949
588285
|
}
|
|
587950
588286
|
const singleKey = process.env["OA_API_KEY"];
|
|
588287
|
+
if (singleKey) {
|
|
588288
|
+
if (token === singleKey) return { authenticated: true, scope: "admin" };
|
|
588289
|
+
}
|
|
588290
|
+
if (token) {
|
|
588291
|
+
try {
|
|
588292
|
+
const { lookupKey: _lk } = require3("./runtime-keys.js");
|
|
588293
|
+
const rec = _lk(token);
|
|
588294
|
+
if (rec) {
|
|
588295
|
+
return {
|
|
588296
|
+
authenticated: true,
|
|
588297
|
+
scope: rec.scope,
|
|
588298
|
+
user: rec.owner,
|
|
588299
|
+
rpm: rec.rpm,
|
|
588300
|
+
tpd: rec.tpd,
|
|
588301
|
+
maxJobs: rec.max_jobs
|
|
588302
|
+
};
|
|
588303
|
+
}
|
|
588304
|
+
} catch {
|
|
588305
|
+
}
|
|
588306
|
+
}
|
|
587951
588307
|
if (!singleKey) return { authenticated: true, scope: "admin" };
|
|
587952
|
-
if (token === singleKey) return { authenticated: true, scope: "admin" };
|
|
587953
588308
|
return { authenticated: false, scope: "read" };
|
|
587954
588309
|
}
|
|
587955
588310
|
function checkAuth(req2, res, requiredScope = "read") {
|
|
@@ -588070,7 +588425,41 @@ function handleHelp(req2, res) {
|
|
|
588070
588425
|
},
|
|
588071
588426
|
off_device_policy: "Tools with off_device_allowed=false are loopback-only; remote callers need admin scope to bypass.",
|
|
588072
588427
|
anonymous_default: "Loopback callers default to admin scope. Remote callers default to read scope until authenticated.",
|
|
588073
|
-
override: "Operators can override per-tool classification via OA_TOOL_OVERRIDES env var (JSON map of name → partial security info)."
|
|
588428
|
+
override: "Operators can override per-tool classification via OA_TOOL_OVERRIDES env var (JSON map of name → partial security info).",
|
|
588429
|
+
filters: "GET /v1/tools supports ?category=, ?scope=, ?risk=, ?off_device=true|false (Q9). E.g. /v1/tools?scope=read&off_device=true returns the safe-to-expose set."
|
|
588430
|
+
},
|
|
588431
|
+
runtime_keys: {
|
|
588432
|
+
"GET /v1/keys": "List runtime keys (admin scope). Secrets masked.",
|
|
588433
|
+
"POST /v1/keys": "Mint a runtime key (admin scope). Body: {scope, owner, profile?, rpm?, tpd?, max_jobs?}. Returns full secret ONCE.",
|
|
588434
|
+
"DELETE /v1/keys/{prefix}": "Revoke a key by its first 8+ chars (admin scope). Soft-delete; record retained for audit.",
|
|
588435
|
+
env_alternative: 'OA_API_KEY (single, admin) or OA_API_KEYS="key:scope:owner:rpm:tpd:max_jobs,...". Runtime keys are checked AFTER env keys.',
|
|
588436
|
+
per_key_profile: "Bind a key to a tool profile (allow/deny lists from /v1/profiles) for capability scoping beyond coarse read/run/admin.",
|
|
588437
|
+
storage: "~/.open-agents/keys.json (mode 600). Soft-deleted keys are kept for audit."
|
|
588438
|
+
},
|
|
588439
|
+
agent_loop_inference: {
|
|
588440
|
+
enable: "POST /v1/chat/completions with body {agent_loop: true} runs an N-turn server-side loop. Daemon executes any tool_calls matching daemon-resident tools and re-prompts; client-side tool_calls cause the loop to yield back so caller can execute them.",
|
|
588441
|
+
merge_daemon_tools: "Body field include_daemon_tools: ['read'] (or ['read','run']) merges the daemon's matching tools into the offered tools[] array automatically — no need to hand-list web_search/web_fetch/file_read/etc.",
|
|
588442
|
+
max_turns: "Body field max_turns (default 8, max 64).",
|
|
588443
|
+
timeout: "Body field timeout_s caps the whole loop (default 30 min, max 1 hour). Per-backend-call timeout is separate (see OA_BACKEND_TIMEOUT_S).",
|
|
588444
|
+
prompt_template: "Body field prompt_template: 'factual-first' prepends a system message instructing the model to call web_search FIRST for any factual question.",
|
|
588445
|
+
response_envelope: "Standard OpenAI chat.completion shape PLUS a _agent_loop: {turns, log:[], done, reason} field. Reason is one of: model_returned_content, client_tools_pending, max_turns_exhausted."
|
|
588446
|
+
},
|
|
588447
|
+
backend_timeout: {
|
|
588448
|
+
env: "OA_BACKEND_TIMEOUT_S — default 120 seconds, max 3600 (1 hour).",
|
|
588449
|
+
per_request: "Body field timeout_s on /v1/chat/completions, /v1/run, agent_loop. Caps to 1h.",
|
|
588450
|
+
rationale: "Q1 (Cody/SA) — was hardcoded 120s, broke cold-start tool-calling thinks on large models."
|
|
588451
|
+
},
|
|
588452
|
+
run_lifecycle: {
|
|
588453
|
+
gc: "Q10 — completed/failed runs older than OA_RUN_RETENTION_H hours (default 24) are pruned at startup and on a 1h interval. Set OA_RUN_RETENTION_H=0 to disable. Running runs are never pruned.",
|
|
588454
|
+
manual_delete: "DELETE /v1/runs/{id} — explicit cleanup."
|
|
588455
|
+
},
|
|
588456
|
+
sse_chunk_shape: {
|
|
588457
|
+
chat_completions: "Standard OpenAI delta shape. tool_calls in delta: [{id:'call_<hex>', type:'function', index:N, function:{name:'...', arguments:'<JSON-string>'}}]. Final chunk: {choices:[{finish_reason:'stop', delta:{}}]} then 'data: [DONE]'.",
|
|
588458
|
+
events_bus: "GET /v1/events streams the daemon-event bus (different shape): event:'tool.called', data:{run_id, tool, args, ts}. NOT the same as chat completions SSE."
|
|
588459
|
+
},
|
|
588460
|
+
parallel_tool_calls: {
|
|
588461
|
+
passthrough: "Request body field parallel_tool_calls: true is forwarded to the backend (Ollama/vLLM). Models supporting it (qwen3, llama3) emit multiple tool_calls in one response — daemon forwards them in delta.tool_calls[].",
|
|
588462
|
+
agent_loop: "When agent_loop=true with multiple daemon-tool tool_calls, all execute sequentially (still server-side; saves N round-trips vs the client doing each one)."
|
|
588074
588463
|
},
|
|
588075
588464
|
mcp: {
|
|
588076
588465
|
"GET /v1/mcps": "List connected MCP (Model Context Protocol) servers",
|
|
@@ -588309,6 +588698,277 @@ async function handleApiTags(res) {
|
|
|
588309
588698
|
});
|
|
588310
588699
|
}
|
|
588311
588700
|
}
|
|
588701
|
+
async function runAgentLoopChatCompletions(opts) {
|
|
588702
|
+
const { req: req2, res, ollamaUrl, requestBody, perReqTimeoutS } = opts;
|
|
588703
|
+
const startMs = Date.now();
|
|
588704
|
+
const reqTimeoutMs = getBackendTimeoutMs(perReqTimeoutS);
|
|
588705
|
+
const totalDeadline = startMs + (perReqTimeoutS && perReqTimeoutS > 0 ? Math.min(perReqTimeoutS * 1e3, BACKEND_TIMEOUT_MAX_MS) : 30 * 60 * 1e3);
|
|
588706
|
+
const model = requestBody["model"] || "unknown";
|
|
588707
|
+
const route = resolveModelEndpoint(model);
|
|
588708
|
+
const targetUrl = route?.endpoint.url ?? ollamaUrl;
|
|
588709
|
+
const targetType = route?.endpoint.type ?? loadConfig().backendType ?? "ollama";
|
|
588710
|
+
const originalModel = route?.originalId ?? model;
|
|
588711
|
+
const maxTurns = typeof requestBody["max_turns"] === "number" ? Math.max(1, Math.min(64, requestBody["max_turns"])) : 8;
|
|
588712
|
+
const remoteIp = (req2.socket?.remoteAddress || "").replace(/^::ffff:/, "");
|
|
588713
|
+
const origin = /^(127\.\d+\.\d+\.\d+|::1|localhost)$/.test(remoteIp) ? "loopback" : "remote";
|
|
588714
|
+
const reqAuth = req2;
|
|
588715
|
+
const scope = reqAuth._authScope ?? (origin === "loopback" ? "admin" : "read");
|
|
588716
|
+
const execMod = await Promise.resolve().then(() => (init_dist5(), dist_exports)).catch(() => null);
|
|
588717
|
+
if (!execMod) {
|
|
588718
|
+
jsonResponse(res, 500, { error: "Execution module unavailable" });
|
|
588719
|
+
return;
|
|
588720
|
+
}
|
|
588721
|
+
const classify = execMod.classifyTool;
|
|
588722
|
+
const canInvoke = execMod.canInvokeTool;
|
|
588723
|
+
const daemonTools = /* @__PURE__ */ new Map();
|
|
588724
|
+
for (const [classKey, value2] of Object.entries(execMod)) {
|
|
588725
|
+
if (typeof value2 !== "function") continue;
|
|
588726
|
+
const proto = value2.prototype;
|
|
588727
|
+
if (!proto || typeof proto.execute !== "function") continue;
|
|
588728
|
+
let probe = null;
|
|
588729
|
+
try {
|
|
588730
|
+
probe = new value2();
|
|
588731
|
+
} catch {
|
|
588732
|
+
try {
|
|
588733
|
+
probe = new value2(process.cwd());
|
|
588734
|
+
} catch {
|
|
588735
|
+
probe = null;
|
|
588736
|
+
}
|
|
588737
|
+
}
|
|
588738
|
+
if (probe?.name && typeof probe.name === "string") {
|
|
588739
|
+
daemonTools.set(probe.name, { ToolClass: value2, classKey });
|
|
588740
|
+
}
|
|
588741
|
+
}
|
|
588742
|
+
const includeDaemonTools = Array.isArray(requestBody["include_daemon_tools"]) ? requestBody["include_daemon_tools"].filter((s2) => typeof s2 === "string") : [];
|
|
588743
|
+
const advertisedDaemonNames = /* @__PURE__ */ new Set();
|
|
588744
|
+
if (includeDaemonTools.length > 0) {
|
|
588745
|
+
for (const [toolName, { ToolClass: _T }] of daemonTools.entries()) {
|
|
588746
|
+
void _T;
|
|
588747
|
+
const sec = classify(toolName);
|
|
588748
|
+
if (!sec) continue;
|
|
588749
|
+
if (!includeDaemonTools.includes(sec.requires_scope)) continue;
|
|
588750
|
+
if (canInvoke({ toolName, origin, scope }) !== null) continue;
|
|
588751
|
+
advertisedDaemonNames.add(toolName);
|
|
588752
|
+
}
|
|
588753
|
+
}
|
|
588754
|
+
const callerTools = Array.isArray(requestBody["tools"]) ? requestBody["tools"].filter((t2) => t2?.type === "function" && typeof t2?.function?.name === "string") : [];
|
|
588755
|
+
const callerToolNames = new Set(callerTools.map((t2) => t2.function.name));
|
|
588756
|
+
const daemonToolEntries = [];
|
|
588757
|
+
for (const name10 of advertisedDaemonNames) {
|
|
588758
|
+
if (callerToolNames.has(name10)) continue;
|
|
588759
|
+
const meta = daemonTools.get(name10);
|
|
588760
|
+
if (!meta) continue;
|
|
588761
|
+
let inst = null;
|
|
588762
|
+
try {
|
|
588763
|
+
inst = new meta.ToolClass();
|
|
588764
|
+
} catch {
|
|
588765
|
+
try {
|
|
588766
|
+
inst = new meta.ToolClass(process.cwd());
|
|
588767
|
+
} catch {
|
|
588768
|
+
inst = null;
|
|
588769
|
+
}
|
|
588770
|
+
}
|
|
588771
|
+
if (!inst) continue;
|
|
588772
|
+
daemonToolEntries.push({
|
|
588773
|
+
type: "function",
|
|
588774
|
+
function: {
|
|
588775
|
+
name: name10,
|
|
588776
|
+
description: typeof inst.description === "string" ? inst.description : "",
|
|
588777
|
+
parameters: inst.parameters ?? { type: "object", properties: {} }
|
|
588778
|
+
}
|
|
588779
|
+
});
|
|
588780
|
+
}
|
|
588781
|
+
const mergedTools = [...callerTools, ...daemonToolEntries];
|
|
588782
|
+
const messages2 = Array.isArray(requestBody["messages"]) ? requestBody["messages"].slice() : [];
|
|
588783
|
+
const promptTemplate = typeof requestBody["prompt_template"] === "string" ? requestBody["prompt_template"] : null;
|
|
588784
|
+
if (promptTemplate === "factual-first" && advertisedDaemonNames.has("web_search")) {
|
|
588785
|
+
const SYSTEM_FACTUAL_FIRST = [
|
|
588786
|
+
"[POLICY: factual-first]",
|
|
588787
|
+
"For any user question that asks for a fact, statistic, current event,",
|
|
588788
|
+
"person/place/product detail, or anything you might be tempted to answer",
|
|
588789
|
+
"from training data alone — your FIRST tool_call MUST be `web_search`",
|
|
588790
|
+
"with a query derived from the user's question. Do NOT answer from",
|
|
588791
|
+
"training data. After web_search returns, optionally call `web_fetch`",
|
|
588792
|
+
"on the most relevant URL, then synthesize a grounded answer citing",
|
|
588793
|
+
"the source. Decline to answer factual questions if web_search is",
|
|
588794
|
+
"unavailable."
|
|
588795
|
+
].join(" ");
|
|
588796
|
+
const firstSystemIdx = messages2.findIndex((m2) => m2.role === "system");
|
|
588797
|
+
if (firstSystemIdx >= 0 && typeof messages2[firstSystemIdx].content === "string") {
|
|
588798
|
+
messages2[firstSystemIdx] = {
|
|
588799
|
+
...messages2[firstSystemIdx],
|
|
588800
|
+
content: `${SYSTEM_FACTUAL_FIRST}
|
|
588801
|
+
|
|
588802
|
+
${messages2[firstSystemIdx].content}`
|
|
588803
|
+
};
|
|
588804
|
+
} else {
|
|
588805
|
+
messages2.unshift({ role: "system", content: SYSTEM_FACTUAL_FIRST });
|
|
588806
|
+
}
|
|
588807
|
+
}
|
|
588808
|
+
const chatId = `chatcmpl-${randomBytes23(12).toString("hex")}`;
|
|
588809
|
+
const turnsLog = [];
|
|
588810
|
+
for (let turn = 1; turn <= maxTurns; turn++) {
|
|
588811
|
+
if (Date.now() > totalDeadline) {
|
|
588812
|
+
jsonResponse(res, 504, {
|
|
588813
|
+
error: "agent_loop timed out",
|
|
588814
|
+
turn,
|
|
588815
|
+
elapsed_ms: Date.now() - startMs,
|
|
588816
|
+
timeout_s: perReqTimeoutS ?? null
|
|
588817
|
+
});
|
|
588818
|
+
return;
|
|
588819
|
+
}
|
|
588820
|
+
const turnBody = {
|
|
588821
|
+
...requestBody,
|
|
588822
|
+
model: originalModel,
|
|
588823
|
+
messages: messages2,
|
|
588824
|
+
tools: mergedTools.length > 0 ? mergedTools : void 0,
|
|
588825
|
+
stream: false,
|
|
588826
|
+
// Strip our own loop-control fields so they don't confuse the backend
|
|
588827
|
+
agent_loop: void 0,
|
|
588828
|
+
include_daemon_tools: void 0,
|
|
588829
|
+
max_turns: void 0,
|
|
588830
|
+
timeout_s: void 0
|
|
588831
|
+
};
|
|
588832
|
+
for (const k of Object.keys(turnBody)) if (turnBody[k] === void 0) delete turnBody[k];
|
|
588833
|
+
let parsed;
|
|
588834
|
+
try {
|
|
588835
|
+
const path8 = targetType === "vllm" || targetType === "openai" ? "/v1/chat/completions" : "/v1/chat/completions";
|
|
588836
|
+
const result = await ollamaRequest(targetUrl, path8, "POST", JSON.stringify(turnBody), reqTimeoutMs);
|
|
588837
|
+
if (result.status !== 200) {
|
|
588838
|
+
jsonResponse(res, result.status, {
|
|
588839
|
+
error: "Backend request failed during agent_loop",
|
|
588840
|
+
turn,
|
|
588841
|
+
details: result.body.slice(0, 500)
|
|
588842
|
+
});
|
|
588843
|
+
return;
|
|
588844
|
+
}
|
|
588845
|
+
parsed = JSON.parse(result.body);
|
|
588846
|
+
} catch (err) {
|
|
588847
|
+
jsonResponse(res, 502, {
|
|
588848
|
+
error: "Backend proxy error during agent_loop",
|
|
588849
|
+
message: err instanceof Error ? err.message : String(err),
|
|
588850
|
+
turn
|
|
588851
|
+
});
|
|
588852
|
+
return;
|
|
588853
|
+
}
|
|
588854
|
+
const choice = parsed?.choices?.[0];
|
|
588855
|
+
const message2 = choice?.message || { role: "assistant", content: "" };
|
|
588856
|
+
const toolCalls = Array.isArray(message2.tool_calls) ? message2.tool_calls : [];
|
|
588857
|
+
if (toolCalls.length === 0) {
|
|
588858
|
+
jsonResponse(res, 200, {
|
|
588859
|
+
...parsed,
|
|
588860
|
+
id: chatId,
|
|
588861
|
+
_agent_loop: { turns: turn, log: turnsLog, done: true, reason: "model_returned_content" }
|
|
588862
|
+
});
|
|
588863
|
+
return;
|
|
588864
|
+
}
|
|
588865
|
+
const daemonCalls = [];
|
|
588866
|
+
const clientCalls = [];
|
|
588867
|
+
for (const tc of toolCalls) {
|
|
588868
|
+
const name10 = tc?.function?.name ?? tc?.name ?? "";
|
|
588869
|
+
if (advertisedDaemonNames.has(name10)) daemonCalls.push(tc);
|
|
588870
|
+
else clientCalls.push(tc);
|
|
588871
|
+
}
|
|
588872
|
+
if (clientCalls.length > 0) {
|
|
588873
|
+
turnsLog.push({ turn, tool_calls: toolCalls.length, daemon_executed: 0, client_yielded: clientCalls.length });
|
|
588874
|
+
jsonResponse(res, 200, {
|
|
588875
|
+
...parsed,
|
|
588876
|
+
id: chatId,
|
|
588877
|
+
_agent_loop: {
|
|
588878
|
+
turns: turn,
|
|
588879
|
+
log: turnsLog,
|
|
588880
|
+
done: false,
|
|
588881
|
+
reason: "client_tools_pending",
|
|
588882
|
+
pending_tool_calls: clientCalls.length
|
|
588883
|
+
}
|
|
588884
|
+
});
|
|
588885
|
+
return;
|
|
588886
|
+
}
|
|
588887
|
+
messages2.push(message2);
|
|
588888
|
+
let executed = 0;
|
|
588889
|
+
for (const tc of daemonCalls) {
|
|
588890
|
+
const name10 = tc?.function?.name ?? tc?.name ?? "";
|
|
588891
|
+
const argsRaw = tc?.function?.arguments ?? tc?.arguments ?? "{}";
|
|
588892
|
+
let args = {};
|
|
588893
|
+
try {
|
|
588894
|
+
args = typeof argsRaw === "string" ? JSON.parse(argsRaw) : argsRaw || {};
|
|
588895
|
+
} catch {
|
|
588896
|
+
args = {};
|
|
588897
|
+
}
|
|
588898
|
+
const denial = canInvoke({ toolName: name10, origin, scope });
|
|
588899
|
+
if (denial) {
|
|
588900
|
+
messages2.push({
|
|
588901
|
+
role: "tool",
|
|
588902
|
+
tool_call_id: tc.id,
|
|
588903
|
+
name: name10,
|
|
588904
|
+
content: JSON.stringify({ error: denial.reason, status: denial.status })
|
|
588905
|
+
});
|
|
588906
|
+
continue;
|
|
588907
|
+
}
|
|
588908
|
+
const meta = daemonTools.get(name10);
|
|
588909
|
+
if (!meta) {
|
|
588910
|
+
messages2.push({
|
|
588911
|
+
role: "tool",
|
|
588912
|
+
tool_call_id: tc.id,
|
|
588913
|
+
name: name10,
|
|
588914
|
+
content: JSON.stringify({ error: `Daemon tool '${name10}' not found` })
|
|
588915
|
+
});
|
|
588916
|
+
continue;
|
|
588917
|
+
}
|
|
588918
|
+
let tool = null;
|
|
588919
|
+
try {
|
|
588920
|
+
tool = new meta.ToolClass(process.cwd());
|
|
588921
|
+
} catch {
|
|
588922
|
+
try {
|
|
588923
|
+
tool = new meta.ToolClass();
|
|
588924
|
+
} catch {
|
|
588925
|
+
tool = null;
|
|
588926
|
+
}
|
|
588927
|
+
}
|
|
588928
|
+
if (!tool) {
|
|
588929
|
+
messages2.push({
|
|
588930
|
+
role: "tool",
|
|
588931
|
+
tool_call_id: tc.id,
|
|
588932
|
+
name: name10,
|
|
588933
|
+
content: JSON.stringify({ error: `Could not instantiate ${meta.classKey}` })
|
|
588934
|
+
});
|
|
588935
|
+
continue;
|
|
588936
|
+
}
|
|
588937
|
+
let toolResult;
|
|
588938
|
+
try {
|
|
588939
|
+
toolResult = await tool.execute(args);
|
|
588940
|
+
} catch (e2) {
|
|
588941
|
+
toolResult = { success: false, output: "", error: e2 instanceof Error ? e2.message : String(e2), durationMs: 0 };
|
|
588942
|
+
}
|
|
588943
|
+
messages2.push({
|
|
588944
|
+
role: "tool",
|
|
588945
|
+
tool_call_id: tc.id,
|
|
588946
|
+
name: name10,
|
|
588947
|
+
content: JSON.stringify(toolResult)
|
|
588948
|
+
});
|
|
588949
|
+
executed++;
|
|
588950
|
+
}
|
|
588951
|
+
turnsLog.push({ turn, tool_calls: toolCalls.length, daemon_executed: executed, client_yielded: 0 });
|
|
588952
|
+
}
|
|
588953
|
+
jsonResponse(res, 200, {
|
|
588954
|
+
id: chatId,
|
|
588955
|
+
object: "chat.completion",
|
|
588956
|
+
created: Math.floor(Date.now() / 1e3),
|
|
588957
|
+
model,
|
|
588958
|
+
choices: [{
|
|
588959
|
+
index: 0,
|
|
588960
|
+
message: { role: "assistant", content: "[agent_loop reached max_turns without producing a final answer]" },
|
|
588961
|
+
finish_reason: "length"
|
|
588962
|
+
}],
|
|
588963
|
+
_agent_loop: {
|
|
588964
|
+
turns: maxTurns,
|
|
588965
|
+
log: turnsLog,
|
|
588966
|
+
done: false,
|
|
588967
|
+
reason: "max_turns_exhausted",
|
|
588968
|
+
max_turns: maxTurns
|
|
588969
|
+
}
|
|
588970
|
+
});
|
|
588971
|
+
}
|
|
588312
588972
|
async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
588313
588973
|
const body = await parseJsonBody(req2);
|
|
588314
588974
|
if (!body || typeof body !== "object") {
|
|
@@ -588318,6 +588978,18 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
588318
588978
|
const requestBody = body;
|
|
588319
588979
|
const stream = requestBody["stream"] === true;
|
|
588320
588980
|
const model = requestBody["model"] || "unknown";
|
|
588981
|
+
const perReqTimeoutS = typeof requestBody["timeout_s"] === "number" ? requestBody["timeout_s"] : void 0;
|
|
588982
|
+
if (requestBody["agent_loop"] === true) {
|
|
588983
|
+
await runAgentLoopChatCompletions({
|
|
588984
|
+
req: req2,
|
|
588985
|
+
res,
|
|
588986
|
+
ollamaUrl,
|
|
588987
|
+
requestBody,
|
|
588988
|
+
perReqTimeoutS
|
|
588989
|
+
});
|
|
588990
|
+
return;
|
|
588991
|
+
}
|
|
588992
|
+
const reqTimeoutMs = getBackendTimeoutMs(perReqTimeoutS);
|
|
588321
588993
|
const route = resolveModelEndpoint(model);
|
|
588322
588994
|
const targetUrl = route?.endpoint.url ?? ollamaUrl;
|
|
588323
588995
|
const targetType = route?.endpoint.type ?? loadConfig().backendType ?? "ollama";
|
|
@@ -588357,11 +589029,12 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
588357
589029
|
} catch {
|
|
588358
589030
|
}
|
|
588359
589031
|
res.end();
|
|
588360
|
-
}
|
|
589032
|
+
},
|
|
589033
|
+
reqTimeoutMs
|
|
588361
589034
|
);
|
|
588362
589035
|
} else {
|
|
588363
589036
|
try {
|
|
588364
|
-
const result = await ollamaRequest(targetUrl, "/v1/chat/completions", "POST", payload);
|
|
589037
|
+
const result = await ollamaRequest(targetUrl, "/v1/chat/completions", "POST", payload, reqTimeoutMs);
|
|
588365
589038
|
if (result.status !== 200) {
|
|
588366
589039
|
jsonResponse(res, result.status, { error: "Backend request failed", details: result.body });
|
|
588367
589040
|
return;
|
|
@@ -588397,7 +589070,7 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
588397
589070
|
"Cache-Control": "no-cache",
|
|
588398
589071
|
"Connection": "keep-alive"
|
|
588399
589072
|
});
|
|
588400
|
-
const chatId = `chatcmpl-${
|
|
589073
|
+
const chatId = `chatcmpl-${randomBytes23(12).toString("hex")}`;
|
|
588401
589074
|
let buffer2 = "";
|
|
588402
589075
|
ollamaStream(
|
|
588403
589076
|
targetUrl,
|
|
@@ -588439,7 +589112,7 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
588439
589112
|
if (ollamaChunk.message.content) delta.content = ollamaChunk.message.content;
|
|
588440
589113
|
if (ollamaChunk.message.tool_calls) {
|
|
588441
589114
|
delta.tool_calls = ollamaChunk.message.tool_calls.map((tc, idx) => ({
|
|
588442
|
-
id: tc.id || `call_${
|
|
589115
|
+
id: tc.id || `call_${randomBytes23(8).toString("hex")}`,
|
|
588443
589116
|
type: "function",
|
|
588444
589117
|
function: {
|
|
588445
589118
|
name: tc?.function?.name ?? tc?.name ?? "",
|
|
@@ -588501,11 +589174,12 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
588501
589174
|
} catch {
|
|
588502
589175
|
}
|
|
588503
589176
|
res.end();
|
|
588504
|
-
}
|
|
589177
|
+
},
|
|
589178
|
+
reqTimeoutMs
|
|
588505
589179
|
);
|
|
588506
589180
|
} else {
|
|
588507
589181
|
try {
|
|
588508
|
-
const result = await ollamaRequest(targetUrl, "/api/chat", "POST", ollamaPayload);
|
|
589182
|
+
const result = await ollamaRequest(targetUrl, "/api/chat", "POST", ollamaPayload, reqTimeoutMs);
|
|
588509
589183
|
if (result.status !== 200) {
|
|
588510
589184
|
jsonResponse(res, result.status, {
|
|
588511
589185
|
error: "Ollama request failed",
|
|
@@ -588517,14 +589191,14 @@ async function handleV1ChatCompletions(req2, res, ollamaUrl) {
|
|
|
588517
589191
|
if (ollamaResp.eval_count) metrics.totalTokensOut += ollamaResp.eval_count;
|
|
588518
589192
|
if (ollamaResp.prompt_eval_count) metrics.totalTokensIn += ollamaResp.prompt_eval_count;
|
|
588519
589193
|
trackTokens("local", ollamaResp.prompt_eval_count ?? 0, ollamaResp.eval_count ?? 0);
|
|
588520
|
-
const chatId = `chatcmpl-${
|
|
589194
|
+
const chatId = `chatcmpl-${randomBytes23(12).toString("hex")}`;
|
|
588521
589195
|
const responseMessage = {
|
|
588522
589196
|
role: ollamaResp.message?.role ?? "assistant",
|
|
588523
589197
|
content: ollamaResp.message?.content ?? ""
|
|
588524
589198
|
};
|
|
588525
589199
|
if (ollamaResp.message?.tool_calls && ollamaResp.message.tool_calls.length > 0) {
|
|
588526
589200
|
responseMessage.tool_calls = ollamaResp.message.tool_calls.map((tc, idx) => ({
|
|
588527
|
-
id: tc.id || `call_${
|
|
589201
|
+
id: tc.id || `call_${randomBytes23(8).toString("hex")}`,
|
|
588528
589202
|
type: "function",
|
|
588529
589203
|
function: {
|
|
588530
589204
|
name: tc?.function?.name ?? tc?.name ?? "",
|
|
@@ -588997,27 +589671,27 @@ ${task}` : task;
|
|
|
588997
589671
|
});
|
|
588998
589672
|
}
|
|
588999
589673
|
function updateStateFile() {
|
|
589000
|
-
return
|
|
589674
|
+
return join115(homedir41(), ".open-agents", "update-state.json");
|
|
589001
589675
|
}
|
|
589002
589676
|
function updateLogPath() {
|
|
589003
|
-
return
|
|
589677
|
+
return join115(homedir41(), ".open-agents", "update.log");
|
|
589004
589678
|
}
|
|
589005
589679
|
function readUpdateState() {
|
|
589006
589680
|
try {
|
|
589007
589681
|
const p2 = updateStateFile();
|
|
589008
|
-
if (!
|
|
589009
|
-
return JSON.parse(
|
|
589682
|
+
if (!existsSync99(p2)) return null;
|
|
589683
|
+
return JSON.parse(readFileSync80(p2, "utf-8"));
|
|
589010
589684
|
} catch {
|
|
589011
589685
|
return null;
|
|
589012
589686
|
}
|
|
589013
589687
|
}
|
|
589014
589688
|
function writeUpdateState(state) {
|
|
589015
589689
|
try {
|
|
589016
|
-
const dir =
|
|
589017
|
-
|
|
589690
|
+
const dir = join115(homedir41(), ".open-agents");
|
|
589691
|
+
mkdirSync63(dir, { recursive: true });
|
|
589018
589692
|
const finalPath = updateStateFile();
|
|
589019
589693
|
const tmpPath = `${finalPath}.tmp.${process.pid}`;
|
|
589020
|
-
|
|
589694
|
+
writeFileSync55(tmpPath, JSON.stringify(state, null, 2), "utf-8");
|
|
589021
589695
|
renameSync8(tmpPath, finalPath);
|
|
589022
589696
|
} catch {
|
|
589023
589697
|
}
|
|
@@ -589061,15 +589735,15 @@ async function handleV1Update(req2, res, requestId) {
|
|
|
589061
589735
|
const { execSync: es } = require3("node:child_process");
|
|
589062
589736
|
const isWin2 = process.platform === "win32";
|
|
589063
589737
|
let npmBin = "";
|
|
589064
|
-
for (const candidate of isWin2 ? [
|
|
589065
|
-
if (
|
|
589738
|
+
for (const candidate of isWin2 ? [join115(nodeDir, "npm.cmd"), join115(nodeDir, "npm")] : [join115(nodeDir, "npm"), "/usr/local/bin/npm", "/usr/bin/npm"]) {
|
|
589739
|
+
if (existsSync99(candidate)) {
|
|
589066
589740
|
npmBin = candidate;
|
|
589067
589741
|
break;
|
|
589068
589742
|
}
|
|
589069
589743
|
}
|
|
589070
589744
|
if (!npmBin) npmBin = isWin2 ? "npm.cmd" : "npm";
|
|
589071
589745
|
const pkgSpec = `open-agents-ai@${targetVersion}`;
|
|
589072
|
-
const dir =
|
|
589746
|
+
const dir = join115(homedir41(), ".open-agents");
|
|
589073
589747
|
fs7.mkdirSync(dir, { recursive: true });
|
|
589074
589748
|
const logFd = fs7.openSync(logPath3, "w");
|
|
589075
589749
|
const npmPrefix = dirname35(nodeDir);
|
|
@@ -589079,13 +589753,13 @@ async function handleV1Update(req2, res, requestId) {
|
|
|
589079
589753
|
globalBinDir = es(`${npmBin} bin -g`, { encoding: "utf8", timeout: 5e3, stdio: "pipe" }).trim();
|
|
589080
589754
|
} else {
|
|
589081
589755
|
const npmCliCandidates = [
|
|
589082
|
-
|
|
589083
|
-
|
|
589756
|
+
join115(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
|
|
589757
|
+
join115(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
|
|
589084
589758
|
];
|
|
589085
589759
|
let npmCli = "";
|
|
589086
589760
|
for (const c9 of npmCliCandidates) {
|
|
589087
589761
|
try {
|
|
589088
|
-
if (
|
|
589762
|
+
if (existsSync99(c9)) {
|
|
589089
589763
|
npmCli = c9;
|
|
589090
589764
|
break;
|
|
589091
589765
|
}
|
|
@@ -589117,13 +589791,13 @@ async function handleV1Update(req2, res, requestId) {
|
|
|
589117
589791
|
});
|
|
589118
589792
|
} else {
|
|
589119
589793
|
const npmCliCandidates = [
|
|
589120
|
-
|
|
589121
|
-
|
|
589794
|
+
join115(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
|
|
589795
|
+
join115(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
|
|
589122
589796
|
];
|
|
589123
589797
|
let npmCli = "";
|
|
589124
589798
|
for (const c9 of npmCliCandidates) {
|
|
589125
589799
|
try {
|
|
589126
|
-
if (
|
|
589800
|
+
if (existsSync99(c9)) {
|
|
589127
589801
|
npmCli = c9;
|
|
589128
589802
|
break;
|
|
589129
589803
|
}
|
|
@@ -589220,8 +589894,8 @@ function handleV1UpdateStatus(res) {
|
|
|
589220
589894
|
let logTail = "";
|
|
589221
589895
|
let exitCode = null;
|
|
589222
589896
|
try {
|
|
589223
|
-
if (
|
|
589224
|
-
const raw =
|
|
589897
|
+
if (existsSync99(logPath3)) {
|
|
589898
|
+
const raw = readFileSync80(logPath3, "utf-8");
|
|
589225
589899
|
const m2 = raw.match(/__EXIT_CODE=(\d+)/);
|
|
589226
589900
|
if (m2) exitCode = parseInt(m2[1], 10);
|
|
589227
589901
|
logTail = raw.slice(-2e3);
|
|
@@ -589309,7 +589983,7 @@ async function handleV1Run(req2, res) {
|
|
|
589309
589983
|
return;
|
|
589310
589984
|
}
|
|
589311
589985
|
}
|
|
589312
|
-
const id = `job-${
|
|
589986
|
+
const id = `job-${randomBytes23(8).toString("hex")}`;
|
|
589313
589987
|
const dir = jobsDir();
|
|
589314
589988
|
const workingDir = requestBody["working_directory"] || req2.headers["x-working-directory"];
|
|
589315
589989
|
const isolate = requestBody["isolate"] === true;
|
|
@@ -589317,8 +589991,8 @@ async function handleV1Run(req2, res) {
|
|
|
589317
589991
|
if (workingDir) {
|
|
589318
589992
|
cwd4 = resolve38(workingDir);
|
|
589319
589993
|
} else if (isolate) {
|
|
589320
|
-
const wsDir =
|
|
589321
|
-
|
|
589994
|
+
const wsDir = join115(dir, "..", "workspaces", id);
|
|
589995
|
+
mkdirSync63(wsDir, { recursive: true });
|
|
589322
589996
|
cwd4 = wsDir;
|
|
589323
589997
|
} else {
|
|
589324
589998
|
cwd4 = resolve38(process.cwd());
|
|
@@ -589460,7 +590134,7 @@ async function handleV1Run(req2, res) {
|
|
|
589460
590134
|
let output = "";
|
|
589461
590135
|
let tailBytes = 0;
|
|
589462
590136
|
const TAIL_BUDGET = 1048576;
|
|
589463
|
-
const outputWriter = new DiskTaskOutput(
|
|
590137
|
+
const outputWriter = new DiskTaskOutput(join115(dir, `${id}.output`));
|
|
589464
590138
|
job.outputFile = outputWriter.path;
|
|
589465
590139
|
atomicJobWrite(dir, id, job);
|
|
589466
590140
|
child.stdout?.on("data", (chunk) => {
|
|
@@ -590353,10 +591027,10 @@ async function handleRequest(req2, res, ollamaUrl, verbose) {
|
|
|
590353
591027
|
return;
|
|
590354
591028
|
}
|
|
590355
591029
|
const { tmpdir: tmpdir22 } = await import("node:os");
|
|
590356
|
-
const { writeFileSync:
|
|
591030
|
+
const { writeFileSync: writeFileSync59, unlinkSync: unlinkSync25 } = await import("node:fs");
|
|
590357
591031
|
const { join: pjoin } = await import("node:path");
|
|
590358
591032
|
const tmpPath = pjoin(tmpdir22(), `oa-clone-upload-${Date.now()}-${safeName}`);
|
|
590359
|
-
|
|
591033
|
+
writeFileSync59(tmpPath, buf);
|
|
590360
591034
|
try {
|
|
590361
591035
|
const ve = getVoiceEngine();
|
|
590362
591036
|
const msg = await ve.setCloneVoice(tmpPath);
|
|
@@ -590906,7 +591580,7 @@ data: ${JSON.stringify(data)}
|
|
|
590906
591580
|
}
|
|
590907
591581
|
for (const f2 of seenFiles) {
|
|
590908
591582
|
try {
|
|
590909
|
-
|
|
591583
|
+
writeFileSync55(f2, JSON.stringify({ tasks: [] }, null, 2));
|
|
590910
591584
|
deleted++;
|
|
590911
591585
|
} catch {
|
|
590912
591586
|
}
|
|
@@ -591968,7 +592642,7 @@ ${steering}`;
|
|
|
591968
592642
|
function getScheduleRoots() {
|
|
591969
592643
|
const rootsEnv = process.env["OA_SCHEDULE_ROOTS"] || "";
|
|
591970
592644
|
const roots = rootsEnv.split(rootsEnv.includes(";") ? ";" : ":").filter(Boolean);
|
|
591971
|
-
const defaults3 = [process.cwd(),
|
|
592645
|
+
const defaults3 = [process.cwd(), join115(homedir41(), "Documents")];
|
|
591972
592646
|
const set = /* @__PURE__ */ new Set([...defaults3, ...roots]);
|
|
591973
592647
|
return [...set];
|
|
591974
592648
|
}
|
|
@@ -591980,10 +592654,10 @@ function listScheduledTasks() {
|
|
|
591980
592654
|
for (const root of roots) {
|
|
591981
592655
|
try {
|
|
591982
592656
|
walk(root, 0, (dir) => {
|
|
591983
|
-
if (dir.endsWith(`${
|
|
591984
|
-
const file =
|
|
592657
|
+
if (dir.endsWith(`${join115(".oa", "scheduled")}`) || dir.includes(`${join115(".oa", "scheduled")}`)) {
|
|
592658
|
+
const file = join115(dir, "tasks.json");
|
|
591985
592659
|
try {
|
|
591986
|
-
const raw =
|
|
592660
|
+
const raw = readFileSync80(file, "utf-8");
|
|
591987
592661
|
const json = JSON.parse(raw);
|
|
591988
592662
|
const tasks = Array.isArray(json?.tasks) ? json.tasks : Array.isArray(json) ? json : [];
|
|
591989
592663
|
tasks.forEach((t2, i2) => {
|
|
@@ -592048,7 +592722,7 @@ function walk(dir, depth, onDir, maxDepth) {
|
|
|
592048
592722
|
if (e2.name === "node_modules" || e2.name.startsWith(".")) {
|
|
592049
592723
|
if (e2.name !== ".oa") continue;
|
|
592050
592724
|
}
|
|
592051
|
-
const child =
|
|
592725
|
+
const child = join115(dir, e2.name);
|
|
592052
592726
|
walk(child, depth + 1, onDir, maxDepth);
|
|
592053
592727
|
}
|
|
592054
592728
|
}
|
|
@@ -592057,18 +592731,18 @@ function setScheduledEnabled(id, enabled2) {
|
|
|
592057
592731
|
const target = tasks.find((t2) => t2.id === id);
|
|
592058
592732
|
if (!target) return false;
|
|
592059
592733
|
try {
|
|
592060
|
-
const raw =
|
|
592734
|
+
const raw = readFileSync80(target.file, "utf-8");
|
|
592061
592735
|
const json = JSON.parse(raw);
|
|
592062
592736
|
const arr = Array.isArray(json?.tasks) ? json.tasks : Array.isArray(json) ? json : [];
|
|
592063
592737
|
if (!arr[target.index]) return false;
|
|
592064
592738
|
arr[target.index].enabled = enabled2;
|
|
592065
592739
|
if (Array.isArray(json?.tasks)) {
|
|
592066
592740
|
json.tasks = arr;
|
|
592067
|
-
|
|
592741
|
+
writeFileSync55(target.file, JSON.stringify(json, null, 2));
|
|
592068
592742
|
} else if (Array.isArray(json)) {
|
|
592069
|
-
|
|
592743
|
+
writeFileSync55(target.file, JSON.stringify(arr, null, 2));
|
|
592070
592744
|
} else {
|
|
592071
|
-
|
|
592745
|
+
writeFileSync55(target.file, JSON.stringify({ tasks: arr }, null, 2));
|
|
592072
592746
|
}
|
|
592073
592747
|
if (!enabled2) {
|
|
592074
592748
|
try {
|
|
@@ -592090,7 +592764,7 @@ function deleteScheduledById(id) {
|
|
|
592090
592764
|
const target = tasks.find((t2) => t2.id === id);
|
|
592091
592765
|
if (!target) return false;
|
|
592092
592766
|
try {
|
|
592093
|
-
const raw =
|
|
592767
|
+
const raw = readFileSync80(target.file, "utf-8");
|
|
592094
592768
|
const json = JSON.parse(raw);
|
|
592095
592769
|
const arr = Array.isArray(json?.tasks) ? json.tasks : Array.isArray(json) ? json : [];
|
|
592096
592770
|
if (!arr[target.index]) return false;
|
|
@@ -592098,11 +592772,11 @@ function deleteScheduledById(id) {
|
|
|
592098
592772
|
arr.splice(target.index, 1);
|
|
592099
592773
|
if (Array.isArray(json?.tasks)) {
|
|
592100
592774
|
json.tasks = arr;
|
|
592101
|
-
|
|
592775
|
+
writeFileSync55(target.file, JSON.stringify(json, null, 2));
|
|
592102
592776
|
} else if (Array.isArray(json)) {
|
|
592103
|
-
|
|
592777
|
+
writeFileSync55(target.file, JSON.stringify(arr, null, 2));
|
|
592104
592778
|
} else {
|
|
592105
|
-
|
|
592779
|
+
writeFileSync55(target.file, JSON.stringify({ tasks: arr }, null, 2));
|
|
592106
592780
|
}
|
|
592107
592781
|
const candidates = [];
|
|
592108
592782
|
if (id) candidates.push(id);
|
|
@@ -592355,11 +593029,11 @@ function reconcileScheduledTasks(apply) {
|
|
|
592355
593029
|
const errors = [];
|
|
592356
593030
|
for (const f2 of found) {
|
|
592357
593031
|
const wdir = f2.workingDir || process.cwd();
|
|
592358
|
-
const file =
|
|
593032
|
+
const file = join115(wdir, ".oa", "scheduled", "tasks.json");
|
|
592359
593033
|
try {
|
|
592360
593034
|
let json = { tasks: [] };
|
|
592361
593035
|
try {
|
|
592362
|
-
const raw =
|
|
593036
|
+
const raw = readFileSync80(file, "utf-8");
|
|
592363
593037
|
json = JSON.parse(raw);
|
|
592364
593038
|
} catch {
|
|
592365
593039
|
}
|
|
@@ -592370,9 +593044,9 @@ function reconcileScheduledTasks(apply) {
|
|
|
592370
593044
|
const entry = { task: f2.task || `legacy ${f2.id}`, schedule: f2.cron, enabled: true };
|
|
592371
593045
|
arr.push(entry);
|
|
592372
593046
|
const toWrite = Array.isArray(json?.tasks) ? { ...json, tasks: arr } : Array.isArray(json) ? arr : { tasks: arr };
|
|
592373
|
-
|
|
592374
|
-
|
|
592375
|
-
|
|
593047
|
+
mkdirSync63(join115(wdir, ".oa", "scheduled"), { recursive: true });
|
|
593048
|
+
mkdirSync63(join115(wdir, ".oa", "scheduled", "logs"), { recursive: true });
|
|
593049
|
+
writeFileSync55(file, JSON.stringify(toWrite, null, 2));
|
|
592376
593050
|
adopted.push({ file, index: arr.length - 1 });
|
|
592377
593051
|
}
|
|
592378
593052
|
} else {
|
|
@@ -592416,32 +593090,32 @@ function writeCrontabLines(lines) {
|
|
|
592416
593090
|
}
|
|
592417
593091
|
function canonicalCronLine(rec) {
|
|
592418
593092
|
const oaBin = findOaBinary4();
|
|
592419
|
-
const logDir =
|
|
592420
|
-
const logFile =
|
|
592421
|
-
const storeFile =
|
|
593093
|
+
const logDir = join115(rec.workingDir, ".oa", "scheduled", "logs");
|
|
593094
|
+
const logFile = join115(logDir, `${rec.id}.log`);
|
|
593095
|
+
const storeFile = join115(rec.workingDir, ".oa", "scheduled", "tasks.json");
|
|
592422
593096
|
const taskEsc = rec.task.replace(/'/g, "'\\''");
|
|
592423
|
-
const lockDir =
|
|
592424
|
-
const lockPath =
|
|
593097
|
+
const lockDir = join115(rec.workingDir, ".oa", "run");
|
|
593098
|
+
const lockPath = join115(lockDir, `${rec.id}.lock`);
|
|
592425
593099
|
const wrapper = [
|
|
592426
593100
|
`cd ${JSON.stringify(rec.workingDir)}`,
|
|
592427
593101
|
`mkdir -p ${JSON.stringify(logDir)}`,
|
|
592428
593102
|
`mkdir -p ${JSON.stringify(lockDir)}`,
|
|
592429
593103
|
`if mkdir ${JSON.stringify(lockPath)} 2>/dev/null; then`,
|
|
592430
|
-
` echo $$ > ${JSON.stringify(
|
|
593104
|
+
` echo $$ > ${JSON.stringify(join115(lockPath, "pid"))}`,
|
|
592431
593105
|
` trap 'rm -rf ${lockPath}' EXIT`,
|
|
592432
593106
|
`else`,
|
|
592433
|
-
` if [ -f ${JSON.stringify(
|
|
592434
|
-
` oldpid=$(cat ${JSON.stringify(
|
|
593107
|
+
` if [ -f ${JSON.stringify(join115(lockPath, "pid"))} ]; then`,
|
|
593108
|
+
` oldpid=$(cat ${JSON.stringify(join115(lockPath, "pid"))} 2>/dev/null || echo)`,
|
|
592435
593109
|
` if [ -n "$oldpid" ] && kill -0 "$oldpid" 2>/dev/null; then`,
|
|
592436
593110
|
` echo "[oa-scheduler] ${rec.id} already running as PID $oldpid; skipping" >> ${JSON.stringify(logFile)}`,
|
|
592437
593111
|
` exit 0`,
|
|
592438
593112
|
` else`,
|
|
592439
593113
|
` rm -rf ${JSON.stringify(lockPath)} 2>/dev/null || true`,
|
|
592440
|
-
` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(
|
|
593114
|
+
` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(join115(lockPath, "pid"))} && trap 'rm -rf ${lockPath}' EXIT`,
|
|
592441
593115
|
` fi`,
|
|
592442
593116
|
` else`,
|
|
592443
593117
|
` rm -rf ${JSON.stringify(lockPath)} 2>/dev/null || true`,
|
|
592444
|
-
` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(
|
|
593118
|
+
` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(join115(lockPath, "pid"))} && trap 'rm -rf ${lockPath}' EXIT`,
|
|
592445
593119
|
` fi`,
|
|
592446
593120
|
`fi`,
|
|
592447
593121
|
`${oaBin} '${taskEsc}' >> ${JSON.stringify(logFile)} 2>&1; _oa_exit=$?`,
|
|
@@ -592473,9 +593147,9 @@ function fixupOrMigrateScheduled(mode, dryRun) {
|
|
|
592473
593147
|
try {
|
|
592474
593148
|
if (!f2.workingDir || !f2.task) continue;
|
|
592475
593149
|
const unitBase = `oa-${f2.id}`;
|
|
592476
|
-
const unitDir =
|
|
592477
|
-
const svc =
|
|
592478
|
-
const tim =
|
|
593150
|
+
const unitDir = join115(homedir41(), ".config", "systemd", "user");
|
|
593151
|
+
const svc = join115(unitDir, `${unitBase}.service`);
|
|
593152
|
+
const tim = join115(unitDir, `${unitBase}.timer`);
|
|
592479
593153
|
const oaBin = findOaBinary4();
|
|
592480
593154
|
const rec = { id: f2.id, cron: f2.cron, workingDir: f2.workingDir, task: f2.task };
|
|
592481
593155
|
const cmd = canonicalCronLine(rec).split(" ").slice(5).join(" ");
|
|
@@ -592505,9 +593179,9 @@ Persistent=true
|
|
|
592505
593179
|
WantedBy=timers.target
|
|
592506
593180
|
`;
|
|
592507
593181
|
if (!dryRun) {
|
|
592508
|
-
|
|
592509
|
-
|
|
592510
|
-
|
|
593182
|
+
mkdirSync63(unitDir, { recursive: true });
|
|
593183
|
+
writeFileSync55(svc, svcText);
|
|
593184
|
+
writeFileSync55(tim, timText);
|
|
592511
593185
|
try {
|
|
592512
593186
|
const { execSync: es } = require3("node:child_process");
|
|
592513
593187
|
es("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
@@ -592601,8 +593275,8 @@ function startApiServer(options2 = {}) {
|
|
|
592601
593275
|
const config = loadConfig();
|
|
592602
593276
|
const ollamaUrl = options2.ollamaUrl ?? config.backendUrl;
|
|
592603
593277
|
const cwd4 = process.cwd();
|
|
592604
|
-
initAuditLog(
|
|
592605
|
-
initUsageTracker(
|
|
593278
|
+
initAuditLog(join115(cwd4, ".oa"));
|
|
593279
|
+
initUsageTracker(join115(cwd4, ".oa"));
|
|
592606
593280
|
try {
|
|
592607
593281
|
const taskMgr = getSharedTaskManager();
|
|
592608
593282
|
taskMgr.setEventPublisher((type, data, opts) => {
|
|
@@ -592644,7 +593318,7 @@ function startApiServer(options2 = {}) {
|
|
|
592644
593318
|
try {
|
|
592645
593319
|
const dir = todoDir();
|
|
592646
593320
|
try {
|
|
592647
|
-
|
|
593321
|
+
mkdirSync63(dir, { recursive: true });
|
|
592648
593322
|
} catch {
|
|
592649
593323
|
}
|
|
592650
593324
|
const cache8 = /* @__PURE__ */ new Map();
|
|
@@ -592653,7 +593327,7 @@ function startApiServer(options2 = {}) {
|
|
|
592653
593327
|
if (!f2.endsWith(".json") || f2.includes(".tmp.")) continue;
|
|
592654
593328
|
const sid = f2.replace(/\.json$/, "");
|
|
592655
593329
|
try {
|
|
592656
|
-
const items = JSON.parse(
|
|
593330
|
+
const items = JSON.parse(readFileSync80(join115(dir, f2), "utf-8"));
|
|
592657
593331
|
if (Array.isArray(items)) {
|
|
592658
593332
|
cache8.set(sid, new Map(items.map((t2) => [t2.id, t2])));
|
|
592659
593333
|
}
|
|
@@ -592665,10 +593339,10 @@ function startApiServer(options2 = {}) {
|
|
|
592665
593339
|
const watcher = fsWatch3(dir, (_evt, fname) => {
|
|
592666
593340
|
if (!fname || !fname.endsWith(".json") || fname.includes(".tmp.")) return;
|
|
592667
593341
|
const sid = fname.replace(/\.json$/, "");
|
|
592668
|
-
const fp =
|
|
593342
|
+
const fp = join115(dir, fname);
|
|
592669
593343
|
let next = [];
|
|
592670
593344
|
try {
|
|
592671
|
-
if (!
|
|
593345
|
+
if (!existsSync99(fp)) {
|
|
592672
593346
|
const old = cache8.get(sid);
|
|
592673
593347
|
if (old) {
|
|
592674
593348
|
for (const t2 of old.values()) {
|
|
@@ -592681,7 +593355,7 @@ function startApiServer(options2 = {}) {
|
|
|
592681
593355
|
}
|
|
592682
593356
|
return;
|
|
592683
593357
|
}
|
|
592684
|
-
next = JSON.parse(
|
|
593358
|
+
next = JSON.parse(readFileSync80(fp, "utf-8"));
|
|
592685
593359
|
if (!Array.isArray(next)) return;
|
|
592686
593360
|
} catch {
|
|
592687
593361
|
return;
|
|
@@ -592720,14 +593394,14 @@ function startApiServer(options2 = {}) {
|
|
|
592720
593394
|
const retentionDays = parseInt(process.env["OA_JOB_RETENTION_DAYS"] ?? "30", 10);
|
|
592721
593395
|
if (retentionDays > 0) {
|
|
592722
593396
|
try {
|
|
592723
|
-
const jobsDir3 =
|
|
592724
|
-
if (
|
|
593397
|
+
const jobsDir3 = join115(cwd4, ".oa", "jobs");
|
|
593398
|
+
if (existsSync99(jobsDir3)) {
|
|
592725
593399
|
const cutoff = Date.now() - retentionDays * 864e5;
|
|
592726
593400
|
for (const f2 of readdirSync34(jobsDir3)) {
|
|
592727
593401
|
if (!f2.endsWith(".json")) continue;
|
|
592728
593402
|
try {
|
|
592729
|
-
const jobPath =
|
|
592730
|
-
const job = JSON.parse(
|
|
593403
|
+
const jobPath = join115(jobsDir3, f2);
|
|
593404
|
+
const job = JSON.parse(readFileSync80(jobPath, "utf-8"));
|
|
592731
593405
|
const jobTime = new Date(job.startedAt ?? job.completedAt ?? 0).getTime();
|
|
592732
593406
|
if (jobTime > 0 && jobTime < cutoff && job.status !== "running") {
|
|
592733
593407
|
const { unlinkSync: unlinkSync25 } = require3("node:fs");
|
|
@@ -592747,8 +593421,8 @@ function startApiServer(options2 = {}) {
|
|
|
592747
593421
|
if (useTls) {
|
|
592748
593422
|
try {
|
|
592749
593423
|
tlsOpts = {
|
|
592750
|
-
cert:
|
|
592751
|
-
key:
|
|
593424
|
+
cert: readFileSync80(resolve38(tlsCert)),
|
|
593425
|
+
key: readFileSync80(resolve38(tlsKey))
|
|
592752
593426
|
};
|
|
592753
593427
|
} catch (e2) {
|
|
592754
593428
|
log22(`
|
|
@@ -592759,9 +593433,9 @@ function startApiServer(options2 = {}) {
|
|
|
592759
593433
|
}
|
|
592760
593434
|
let runtimeAccessMode = resolveAccessMode(process.env["OA_ACCESS"], host);
|
|
592761
593435
|
try {
|
|
592762
|
-
const accessFile =
|
|
592763
|
-
if (
|
|
592764
|
-
const persisted =
|
|
593436
|
+
const accessFile = join115(homedir41(), ".open-agents", "access");
|
|
593437
|
+
if (existsSync99(accessFile)) {
|
|
593438
|
+
const persisted = readFileSync80(accessFile, "utf8").trim();
|
|
592765
593439
|
const resolved = resolveAccessMode(persisted, host);
|
|
592766
593440
|
if (resolved) runtimeAccessMode = resolved;
|
|
592767
593441
|
}
|
|
@@ -592814,9 +593488,9 @@ function startApiServer(options2 = {}) {
|
|
|
592814
593488
|
const previous = runtimeAccessMode;
|
|
592815
593489
|
runtimeAccessMode = requested;
|
|
592816
593490
|
try {
|
|
592817
|
-
const dir =
|
|
592818
|
-
|
|
592819
|
-
|
|
593491
|
+
const dir = join115(homedir41(), ".open-agents");
|
|
593492
|
+
mkdirSync63(dir, { recursive: true });
|
|
593493
|
+
writeFileSync55(join115(dir, "access"), `${runtimeAccessMode}
|
|
592820
593494
|
`, "utf8");
|
|
592821
593495
|
} catch {
|
|
592822
593496
|
}
|
|
@@ -593029,9 +593703,9 @@ function startApiServer(options2 = {}) {
|
|
|
593029
593703
|
try {
|
|
593030
593704
|
const { startEmbeddingWorkers: startEmbeddingWorkers2 } = await Promise.resolve().then(() => (init_embedding_workers(), embedding_workers_exports));
|
|
593031
593705
|
const { ensureEmbedDeps: ensureEmbedDeps2, runEmbedImage: runEmbedImage2, runEmbedAudio: runEmbedAudio2 } = await Promise.resolve().then(() => (init_py_embed(), py_embed_exports));
|
|
593032
|
-
const dbBase =
|
|
593033
|
-
const epStore = new mem.EpisodeStore(
|
|
593034
|
-
const kg = new mem.TemporalGraph(
|
|
593706
|
+
const dbBase = join115(cwd4, ".oa");
|
|
593707
|
+
const epStore = new mem.EpisodeStore(join115(dbBase, "memory.db"));
|
|
593708
|
+
const kg = new mem.TemporalGraph(join115(dbBase, "kg.db"));
|
|
593035
593709
|
try {
|
|
593036
593710
|
ensureEmbedDeps2();
|
|
593037
593711
|
} catch {
|
|
@@ -593108,6 +593782,24 @@ function startApiServer(options2 = {}) {
|
|
|
593108
593782
|
`);
|
|
593109
593783
|
log22(` Primary: ${config.backendUrl} (${config.backendType || "ollama"})
|
|
593110
593784
|
`);
|
|
593785
|
+
const _retCheck = process.env["OA_RUN_RETENTION_H"];
|
|
593786
|
+
const _retOff = _retCheck === "0";
|
|
593787
|
+
if (!_retOff) {
|
|
593788
|
+
try {
|
|
593789
|
+
const initial = pruneOldJobs();
|
|
593790
|
+
if (initial.pruned > 0) {
|
|
593791
|
+
log22(` Run GC: pruned ${initial.pruned} old job records (kept ${initial.kept}).
|
|
593792
|
+
`);
|
|
593793
|
+
}
|
|
593794
|
+
} catch {
|
|
593795
|
+
}
|
|
593796
|
+
setInterval(() => {
|
|
593797
|
+
try {
|
|
593798
|
+
pruneOldJobs();
|
|
593799
|
+
} catch {
|
|
593800
|
+
}
|
|
593801
|
+
}, 36e5).unref();
|
|
593802
|
+
}
|
|
593111
593803
|
if (process.env["OA_API_KEYS"]) {
|
|
593112
593804
|
const keyCount = process.env["OA_API_KEYS"].split(",").length;
|
|
593113
593805
|
log22(` Auth: ${keyCount} scoped key(s) (read/run/admin)
|
|
@@ -593228,10 +593920,10 @@ async function handleMemoryIngest(req2, res, ollamaUrl) {
|
|
|
593228
593920
|
const labels = Array.isArray(b.labels) ? b.labels : [];
|
|
593229
593921
|
const mediaPath = typeof b.media_path === "string" ? b.media_path : void 0;
|
|
593230
593922
|
const cwd4 = process.cwd();
|
|
593231
|
-
const dbBase =
|
|
593923
|
+
const dbBase = join115(cwd4, ".oa");
|
|
593232
593924
|
const { EpisodeStore: EpisodeStore3, TemporalGraph: TemporalGraph3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
|
|
593233
|
-
const epStore = new EpisodeStore3(
|
|
593234
|
-
const kg = new TemporalGraph3(
|
|
593925
|
+
const epStore = new EpisodeStore3(join115(dbBase, "memory.db"));
|
|
593926
|
+
const kg = new TemporalGraph3(join115(dbBase, "kg.db"));
|
|
593235
593927
|
const meta = {};
|
|
593236
593928
|
if (mediaPath) meta.media_path = mediaPath;
|
|
593237
593929
|
const epId = epStore.insert({ modality, content: content || (mediaPath || ""), metadata: meta, toolName: "memory_ingest" });
|
|
@@ -593298,7 +593990,7 @@ async function handleEntitiesList(req2, res) {
|
|
|
593298
593990
|
const type = url.searchParams.get("type") || "person";
|
|
593299
593991
|
const limit = Math.max(1, Math.min(1e3, parseInt(url.searchParams.get("limit") || "100", 10)));
|
|
593300
593992
|
const { TemporalGraph: TemporalGraph3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
|
|
593301
|
-
const kg = new TemporalGraph3(
|
|
593993
|
+
const kg = new TemporalGraph3(join115(process.cwd(), ".oa", "kg.db"));
|
|
593302
593994
|
const nodes = kg.nodesByType(type, limit).map((n2) => ({ id: n2.id, text: n2.text, mentionCount: n2.mentionCount, firstSeen: n2.firstSeen, lastSeen: n2.lastSeen }));
|
|
593303
593995
|
jsonResponse(res, 200, { object: "list", data: nodes });
|
|
593304
593996
|
} catch (err) {
|
|
@@ -593320,7 +594012,7 @@ async function handleMemorySearch2(req2, res) {
|
|
|
593320
594012
|
const wLex = typeof b.lexical_weight === "number" ? b.lexical_weight : 1;
|
|
593321
594013
|
const wEmb = typeof b.embedding_weight === "number" ? b.embedding_weight : 1;
|
|
593322
594014
|
const { EpisodeStore: EpisodeStore3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
|
|
593323
|
-
const epStore = new EpisodeStore3(
|
|
594015
|
+
const epStore = new EpisodeStore3(join115(process.cwd(), ".oa", "memory.db"));
|
|
593324
594016
|
const results = epStore.search({ query, modality, limit }, { queryEmbedding: qEmb, lexicalWeight: wLex, embeddingWeight: wEmb });
|
|
593325
594017
|
jsonResponse(res, 200, { object: "list", data: results.map((e2) => ({ id: e2.id, modality: e2.modality, content: e2.content, timestamp: e2.timestamp })) });
|
|
593326
594018
|
} catch (err) {
|
|
@@ -593387,7 +594079,7 @@ function setTimerEnabled(name10, enabled2) {
|
|
|
593387
594079
|
return false;
|
|
593388
594080
|
}
|
|
593389
594081
|
}
|
|
593390
|
-
var require3, endpointRegistry, modelRouteMap, endpointUsage, metrics, startedAt, runningProcesses, perKeyUsage, CRON_MARKER2;
|
|
594082
|
+
var require3, endpointRegistry, modelRouteMap, endpointUsage, BACKEND_TIMEOUT_DEFAULT_MS, BACKEND_TIMEOUT_MAX_MS, metrics, startedAt, runningProcesses, perKeyUsage, CRON_MARKER2;
|
|
593391
594083
|
var init_serve = __esm({
|
|
593392
594084
|
"packages/cli/src/api/serve.ts"() {
|
|
593393
594085
|
"use strict";
|
|
@@ -593419,6 +594111,8 @@ var init_serve = __esm({
|
|
|
593419
594111
|
endpointRegistry = [];
|
|
593420
594112
|
modelRouteMap = /* @__PURE__ */ new Map();
|
|
593421
594113
|
endpointUsage = /* @__PURE__ */ new Map();
|
|
594114
|
+
BACKEND_TIMEOUT_DEFAULT_MS = 12e4;
|
|
594115
|
+
BACKEND_TIMEOUT_MAX_MS = 36e5;
|
|
593422
594116
|
metrics = {
|
|
593423
594117
|
requests: /* @__PURE__ */ new Map(),
|
|
593424
594118
|
totalTokensIn: 0,
|
|
@@ -593434,13 +594128,13 @@ var init_serve = __esm({
|
|
|
593434
594128
|
|
|
593435
594129
|
// packages/cli/src/tui/interactive.ts
|
|
593436
594130
|
import { cwd } from "node:process";
|
|
593437
|
-
import { resolve as resolve39, join as
|
|
594131
|
+
import { resolve as resolve39, join as join116, dirname as dirname36, extname as extname12 } from "node:path";
|
|
593438
594132
|
import { createRequire as createRequire5 } from "node:module";
|
|
593439
594133
|
import { fileURLToPath as fileURLToPath18 } from "node:url";
|
|
593440
|
-
import { readFileSync as
|
|
593441
|
-
import { existsSync as
|
|
594134
|
+
import { readFileSync as readFileSync81, writeFileSync as writeFileSync56, appendFileSync as appendFileSync8, rmSync as rmSync5, readdirSync as readdirSync35, mkdirSync as mkdirSync64 } from "node:fs";
|
|
594135
|
+
import { existsSync as existsSync100 } from "node:fs";
|
|
593442
594136
|
import { execSync as execSync56 } from "node:child_process";
|
|
593443
|
-
import { homedir as
|
|
594137
|
+
import { homedir as homedir42 } from "node:os";
|
|
593444
594138
|
function formatTimeAgo2(date) {
|
|
593445
594139
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
593446
594140
|
if (seconds < 60) return "just now";
|
|
@@ -593456,12 +594150,12 @@ function getVersion4() {
|
|
|
593456
594150
|
const require4 = createRequire5(import.meta.url);
|
|
593457
594151
|
const thisDir = dirname36(fileURLToPath18(import.meta.url));
|
|
593458
594152
|
const candidates = [
|
|
593459
|
-
|
|
593460
|
-
|
|
593461
|
-
|
|
594153
|
+
join116(thisDir, "..", "package.json"),
|
|
594154
|
+
join116(thisDir, "..", "..", "package.json"),
|
|
594155
|
+
join116(thisDir, "..", "..", "..", "package.json")
|
|
593462
594156
|
];
|
|
593463
594157
|
for (const pkgPath of candidates) {
|
|
593464
|
-
if (
|
|
594158
|
+
if (existsSync100(pkgPath)) {
|
|
593465
594159
|
const pkg = require4(pkgPath);
|
|
593466
594160
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
|
|
593467
594161
|
return pkg.version ?? "0.0.0";
|
|
@@ -594224,14 +594918,14 @@ Meta-critique: quality ${meta.quality}/5, thorough: ${meta.thorough}`;
|
|
|
594224
594918
|
function gatherMemorySnippets(root) {
|
|
594225
594919
|
const snippets = [];
|
|
594226
594920
|
const dirs = [
|
|
594227
|
-
|
|
594228
|
-
|
|
594921
|
+
join116(root, ".oa", "memory"),
|
|
594922
|
+
join116(root, ".open-agents", "memory")
|
|
594229
594923
|
];
|
|
594230
594924
|
for (const dir of dirs) {
|
|
594231
|
-
if (!
|
|
594925
|
+
if (!existsSync100(dir)) continue;
|
|
594232
594926
|
try {
|
|
594233
594927
|
for (const f2 of readdirSync35(dir).filter((f3) => f3.endsWith(".json"))) {
|
|
594234
|
-
const data = JSON.parse(
|
|
594928
|
+
const data = JSON.parse(readFileSync81(join116(dir, f2), "utf-8"));
|
|
594235
594929
|
for (const val of Object.values(data)) {
|
|
594236
594930
|
const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
594237
594931
|
if (v.length > 10) snippets.push(v);
|
|
@@ -594385,9 +595079,9 @@ ${metabolismMemories}
|
|
|
594385
595079
|
} catch {
|
|
594386
595080
|
}
|
|
594387
595081
|
try {
|
|
594388
|
-
const archeFile =
|
|
594389
|
-
if (
|
|
594390
|
-
const variants = JSON.parse(
|
|
595082
|
+
const archeFile = join116(repoRoot, ".oa", "arche", "variants.json");
|
|
595083
|
+
if (existsSync100(archeFile)) {
|
|
595084
|
+
const variants = JSON.parse(readFileSync81(archeFile, "utf8"));
|
|
594391
595085
|
if (variants.length > 0) {
|
|
594392
595086
|
let filtered = variants;
|
|
594393
595087
|
if (taskType) {
|
|
@@ -594559,9 +595253,9 @@ RULES:
|
|
|
594559
595253
|
const compactionThreshold = Number.isFinite(envOverride) && envOverride > 0 ? envOverride : modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
|
|
594560
595254
|
let identityInjection = "";
|
|
594561
595255
|
try {
|
|
594562
|
-
const ikStateFile =
|
|
594563
|
-
if (
|
|
594564
|
-
const selfState = JSON.parse(
|
|
595256
|
+
const ikStateFile = join116(repoRoot, ".oa", "identity", "self-state.json");
|
|
595257
|
+
if (existsSync100(ikStateFile)) {
|
|
595258
|
+
const selfState = JSON.parse(readFileSync81(ikStateFile, "utf8"));
|
|
594565
595259
|
const lines = [
|
|
594566
595260
|
`[Identity State v${selfState.version}]`,
|
|
594567
595261
|
`Self: ${selfState.narrative_summary}`,
|
|
@@ -595422,13 +596116,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
595422
596116
|
});
|
|
595423
596117
|
}
|
|
595424
596118
|
try {
|
|
595425
|
-
const ikDir =
|
|
595426
|
-
const ikFile =
|
|
596119
|
+
const ikDir = join116(repoRoot, ".oa", "identity");
|
|
596120
|
+
const ikFile = join116(ikDir, "self-state.json");
|
|
595427
596121
|
let ikState;
|
|
595428
|
-
if (
|
|
595429
|
-
ikState = JSON.parse(
|
|
596122
|
+
if (existsSync100(ikFile)) {
|
|
596123
|
+
ikState = JSON.parse(readFileSync81(ikFile, "utf8"));
|
|
595430
596124
|
} else {
|
|
595431
|
-
|
|
596125
|
+
mkdirSync64(ikDir, { recursive: true });
|
|
595432
596126
|
const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
595433
596127
|
ikState = {
|
|
595434
596128
|
self_id: `oa-${machineId}`,
|
|
@@ -595484,7 +596178,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
595484
596178
|
}
|
|
595485
596179
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
595486
596180
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
595487
|
-
|
|
596181
|
+
writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
|
|
595488
596182
|
} catch (ikErr) {
|
|
595489
596183
|
try {
|
|
595490
596184
|
console.error("[IK-OBSERVE]", ikErr);
|
|
@@ -595503,9 +596197,9 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
595503
596197
|
} else {
|
|
595504
596198
|
renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
|
|
595505
596199
|
try {
|
|
595506
|
-
const ikFile =
|
|
595507
|
-
if (
|
|
595508
|
-
const ikState = JSON.parse(
|
|
596200
|
+
const ikFile = join116(repoRoot, ".oa", "identity", "self-state.json");
|
|
596201
|
+
if (existsSync100(ikFile)) {
|
|
596202
|
+
const ikState = JSON.parse(readFileSync81(ikFile, "utf8"));
|
|
595509
596203
|
if (!ikState.stats) ikState.stats = { queries_served: 0 };
|
|
595510
596204
|
ikState.stats.queries_served = (ikState.stats.queries_served || 0) + 1;
|
|
595511
596205
|
ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.03);
|
|
@@ -595516,7 +596210,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
595516
596210
|
if (ikState.version_history.length > 200) ikState.version_history = ikState.version_history.slice(-200);
|
|
595517
596211
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
595518
596212
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
595519
|
-
|
|
596213
|
+
writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
|
|
595520
596214
|
}
|
|
595521
596215
|
} catch {
|
|
595522
596216
|
}
|
|
@@ -595761,10 +596455,10 @@ async function startInteractive(config, repoPath) {
|
|
|
595761
596455
|
process.stdin.pause();
|
|
595762
596456
|
}
|
|
595763
596457
|
try {
|
|
595764
|
-
const oaDir =
|
|
595765
|
-
const nexusPidFile =
|
|
595766
|
-
if (
|
|
595767
|
-
const pid = parseInt(
|
|
596458
|
+
const oaDir = join116(repoRoot, ".oa");
|
|
596459
|
+
const nexusPidFile = join116(oaDir, "nexus", "daemon.pid");
|
|
596460
|
+
if (existsSync100(nexusPidFile)) {
|
|
596461
|
+
const pid = parseInt(readFileSync81(nexusPidFile, "utf8").trim(), 10);
|
|
595768
596462
|
if (pid > 0) {
|
|
595769
596463
|
try {
|
|
595770
596464
|
process.kill(pid, 0);
|
|
@@ -596424,7 +597118,7 @@ ${result.summary}`
|
|
|
596424
597118
|
let p2pGateway = null;
|
|
596425
597119
|
let peerMesh = null;
|
|
596426
597120
|
let inferenceRouter = null;
|
|
596427
|
-
const secretVault = new SecretVault(
|
|
597121
|
+
const secretVault = new SecretVault(join116(repoRoot, ".oa", "vault.enc"));
|
|
596428
597122
|
let adminSessionKey = null;
|
|
596429
597123
|
const callSubAgents = /* @__PURE__ */ new Map();
|
|
596430
597124
|
const streamRenderer = new StreamRenderer();
|
|
@@ -596655,13 +597349,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
596655
597349
|
const hits = allCompletions.filter((c9) => c9.toLowerCase().startsWith(lower));
|
|
596656
597350
|
return [hits, line];
|
|
596657
597351
|
}
|
|
596658
|
-
const HISTORY_DIR =
|
|
596659
|
-
const HISTORY_FILE =
|
|
597352
|
+
const HISTORY_DIR = join116(homedir42(), ".open-agents");
|
|
597353
|
+
const HISTORY_FILE = join116(HISTORY_DIR, "repl-history");
|
|
596660
597354
|
const MAX_HISTORY_LINES = 500;
|
|
596661
597355
|
let savedHistory = [];
|
|
596662
597356
|
try {
|
|
596663
|
-
if (
|
|
596664
|
-
const raw =
|
|
597357
|
+
if (existsSync100(HISTORY_FILE)) {
|
|
597358
|
+
const raw = readFileSync81(HISTORY_FILE, "utf8").trim();
|
|
596665
597359
|
if (raw) savedHistory = raw.split("\n").reverse();
|
|
596666
597360
|
}
|
|
596667
597361
|
} catch {
|
|
@@ -596808,12 +597502,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
596808
597502
|
function persistHistoryLine(line) {
|
|
596809
597503
|
if (!line.trim()) return;
|
|
596810
597504
|
try {
|
|
596811
|
-
|
|
597505
|
+
mkdirSync64(HISTORY_DIR, { recursive: true });
|
|
596812
597506
|
appendFileSync8(HISTORY_FILE, line + "\n", "utf8");
|
|
596813
597507
|
if (Math.random() < 0.02) {
|
|
596814
|
-
const all2 =
|
|
597508
|
+
const all2 = readFileSync81(HISTORY_FILE, "utf8").trim().split("\n");
|
|
596815
597509
|
if (all2.length > MAX_HISTORY_LINES) {
|
|
596816
|
-
|
|
597510
|
+
writeFileSync56(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
|
|
596817
597511
|
}
|
|
596818
597512
|
}
|
|
596819
597513
|
} catch {
|
|
@@ -596998,10 +597692,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
596998
597692
|
const { unlinkSync: _rmStale } = await import("node:fs");
|
|
596999
597693
|
const { homedir: _hdir } = await import("node:os");
|
|
597000
597694
|
for (const dp of [
|
|
597001
|
-
|
|
597002
|
-
|
|
597695
|
+
join116(repoRoot, ".oa", "nexus", "nexus-daemon.mjs"),
|
|
597696
|
+
join116(_hdir(), ".open-agents", ".oa", "nexus", "nexus-daemon.mjs")
|
|
597003
597697
|
]) {
|
|
597004
|
-
if (
|
|
597698
|
+
if (existsSync100(dp)) try {
|
|
597005
597699
|
_rmStale(dp);
|
|
597006
597700
|
} catch {
|
|
597007
597701
|
}
|
|
@@ -597012,9 +597706,9 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
597012
597706
|
const autoNexus = new NexusTool(repoRoot);
|
|
597013
597707
|
const _registerNexusDaemon = () => {
|
|
597014
597708
|
try {
|
|
597015
|
-
const nexusPidFile =
|
|
597016
|
-
if (
|
|
597017
|
-
const nPid = parseInt(
|
|
597709
|
+
const nexusPidFile = join116(repoRoot, ".oa", "nexus", "daemon.pid");
|
|
597710
|
+
if (existsSync100(nexusPidFile)) {
|
|
597711
|
+
const nPid = parseInt(readFileSync81(nexusPidFile, "utf8").trim(), 10);
|
|
597018
597712
|
if (nPid > 0 && !registry2.daemons.has("Nexus")) {
|
|
597019
597713
|
registry2.register({ name: "Nexus", pid: nPid, startedAt: Date.now(), status: "running" });
|
|
597020
597714
|
statusBar.ensureMonitorTimer();
|
|
@@ -597071,7 +597765,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
597071
597765
|
} catch {
|
|
597072
597766
|
}
|
|
597073
597767
|
try {
|
|
597074
|
-
const oaDir =
|
|
597768
|
+
const oaDir = join116(repoRoot, ".oa");
|
|
597075
597769
|
const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
|
|
597076
597770
|
onInfo: (msg) => writeContent(() => renderInfo2(msg)),
|
|
597077
597771
|
onError: (msg) => writeContent(() => renderWarning2(msg))
|
|
@@ -597103,7 +597797,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
597103
597797
|
} catch {
|
|
597104
597798
|
}
|
|
597105
597799
|
try {
|
|
597106
|
-
const oaDir =
|
|
597800
|
+
const oaDir = join116(repoRoot, ".oa");
|
|
597107
597801
|
const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
|
|
597108
597802
|
onInfo: (msg) => writeContent(() => renderInfo2(msg)),
|
|
597109
597803
|
onError: (msg) => writeContent(() => renderWarning2(msg))
|
|
@@ -597144,10 +597838,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
597144
597838
|
}
|
|
597145
597839
|
try {
|
|
597146
597840
|
const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
|
|
597147
|
-
const globalNamePath =
|
|
597841
|
+
const globalNamePath = join116(_hd(), ".open-agents", "agent-name");
|
|
597148
597842
|
let agName = "";
|
|
597149
597843
|
try {
|
|
597150
|
-
if (
|
|
597844
|
+
if (existsSync100(globalNamePath)) agName = readFileSync81(globalNamePath, "utf8").trim();
|
|
597151
597845
|
} catch {
|
|
597152
597846
|
}
|
|
597153
597847
|
if (!agName) {
|
|
@@ -597176,11 +597870,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
597176
597870
|
}
|
|
597177
597871
|
if (!ollamaAlive) {
|
|
597178
597872
|
try {
|
|
597179
|
-
const savedSponsorsPath =
|
|
597873
|
+
const savedSponsorsPath = join116(repoRoot, ".oa", "sponsor", "known-sponsors.json");
|
|
597180
597874
|
let savedSponsors = [];
|
|
597181
597875
|
try {
|
|
597182
|
-
if (
|
|
597183
|
-
savedSponsors = JSON.parse(
|
|
597876
|
+
if (existsSync100(savedSponsorsPath)) {
|
|
597877
|
+
savedSponsors = JSON.parse(readFileSync81(savedSponsorsPath, "utf8"));
|
|
597184
597878
|
const oneHourAgo = Date.now() - 36e5;
|
|
597185
597879
|
savedSponsors = savedSponsors.filter((s2) => (s2.lastVerified || 0) > oneHourAgo);
|
|
597186
597880
|
}
|
|
@@ -598272,10 +598966,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
598272
598966
|
if (name10 === "voice_list_files") {
|
|
598273
598967
|
const baseDir = String(args?.dir ?? ".");
|
|
598274
598968
|
const { readdirSync: readdirSync37, statSync: statSync30 } = __require("node:fs");
|
|
598275
|
-
const { join:
|
|
598276
|
-
const base3 = baseDir.startsWith("/") ? baseDir : resolve43(
|
|
598969
|
+
const { join: join121, resolve: resolve43 } = __require("node:path");
|
|
598970
|
+
const base3 = baseDir.startsWith("/") ? baseDir : resolve43(join121(repoRoot, baseDir));
|
|
598277
598971
|
const items = readdirSync37(base3).slice(0, 200).map((f2) => {
|
|
598278
|
-
const s2 = statSync30(
|
|
598972
|
+
const s2 = statSync30(join121(base3, f2));
|
|
598279
598973
|
return { name: f2, dir: s2.isDirectory(), size: s2.size };
|
|
598280
598974
|
});
|
|
598281
598975
|
return JSON.stringify({ dir: base3, items }, null, 2);
|
|
@@ -598363,7 +599057,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
598363
599057
|
kind,
|
|
598364
599058
|
targetUrl,
|
|
598365
599059
|
authKey,
|
|
598366
|
-
stateDir:
|
|
599060
|
+
stateDir: join116(repoRoot, ".oa"),
|
|
598367
599061
|
passthrough: passthrough ?? false,
|
|
598368
599062
|
loadbalance: loadbalance ?? false,
|
|
598369
599063
|
endpointAuth: passthrough ? currentConfig.apiKey : void 0,
|
|
@@ -598409,7 +599103,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
598409
599103
|
await tunnelGateway.stop();
|
|
598410
599104
|
tunnelGateway = null;
|
|
598411
599105
|
}
|
|
598412
|
-
const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir:
|
|
599106
|
+
const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join116(repoRoot, ".oa") });
|
|
598413
599107
|
newTunnel.on("stats", (stats) => {
|
|
598414
599108
|
statusBar.setExposeStatus({
|
|
598415
599109
|
status: stats.status,
|
|
@@ -598496,9 +599190,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
598496
599190
|
});
|
|
598497
599191
|
if (!result.success) throw new Error(result.error || "Connect failed");
|
|
598498
599192
|
try {
|
|
598499
|
-
const nexusPidFile =
|
|
598500
|
-
if (
|
|
598501
|
-
const pid = parseInt(
|
|
599193
|
+
const nexusPidFile = join116(repoRoot, ".oa", "nexus", "daemon.pid");
|
|
599194
|
+
if (existsSync100(nexusPidFile)) {
|
|
599195
|
+
const pid = parseInt(readFileSync81(nexusPidFile, "utf8").trim(), 10);
|
|
598502
599196
|
if (pid > 0) {
|
|
598503
599197
|
registry2.register({
|
|
598504
599198
|
name: "Nexus",
|
|
@@ -598686,10 +599380,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
598686
599380
|
writeContent(() => renderInfo2(`Killed ${bgKilled} background task(s).`));
|
|
598687
599381
|
}
|
|
598688
599382
|
try {
|
|
598689
|
-
const nexusDir =
|
|
598690
|
-
const pidFile =
|
|
598691
|
-
if (
|
|
598692
|
-
const pid = parseInt(
|
|
599383
|
+
const nexusDir = join116(repoRoot, OA_DIR, "nexus");
|
|
599384
|
+
const pidFile = join116(nexusDir, "daemon.pid");
|
|
599385
|
+
if (existsSync100(pidFile)) {
|
|
599386
|
+
const pid = parseInt(readFileSync81(pidFile, "utf8").trim(), 10);
|
|
598693
599387
|
if (pid > 0) {
|
|
598694
599388
|
try {
|
|
598695
599389
|
if (process.platform === "win32") {
|
|
@@ -598711,13 +599405,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
598711
599405
|
} catch {
|
|
598712
599406
|
}
|
|
598713
599407
|
try {
|
|
598714
|
-
const voiceDir2 =
|
|
599408
|
+
const voiceDir2 = join116(homedir42(), ".open-agents", "voice");
|
|
598715
599409
|
const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
|
|
598716
599410
|
for (const pf of voicePidFiles) {
|
|
598717
|
-
const pidPath =
|
|
598718
|
-
if (
|
|
599411
|
+
const pidPath = join116(voiceDir2, pf);
|
|
599412
|
+
if (existsSync100(pidPath)) {
|
|
598719
599413
|
try {
|
|
598720
|
-
const pid = parseInt(
|
|
599414
|
+
const pid = parseInt(readFileSync81(pidPath, "utf8").trim(), 10);
|
|
598721
599415
|
if (pid > 0) {
|
|
598722
599416
|
if (process.platform === "win32") {
|
|
598723
599417
|
try {
|
|
@@ -598741,8 +599435,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
598741
599435
|
execSync56(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
|
|
598742
599436
|
} catch {
|
|
598743
599437
|
}
|
|
598744
|
-
const oaPath =
|
|
598745
|
-
if (
|
|
599438
|
+
const oaPath = join116(repoRoot, OA_DIR);
|
|
599439
|
+
if (existsSync100(oaPath)) {
|
|
598746
599440
|
let deleted = false;
|
|
598747
599441
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
598748
599442
|
try {
|
|
@@ -598826,19 +599520,19 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
598826
599520
|
try {
|
|
598827
599521
|
const { isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
|
|
598828
599522
|
if (isPersonaPlexRunning2()) {
|
|
598829
|
-
const ppPidFile =
|
|
598830
|
-
const ppPortFile =
|
|
598831
|
-
if (
|
|
598832
|
-
const ppPid = parseInt(
|
|
598833
|
-
const ppPort =
|
|
599523
|
+
const ppPidFile = join116(homedir42(), ".open-agents", "voice", "personaplex", "daemon.pid");
|
|
599524
|
+
const ppPortFile = join116(homedir42(), ".open-agents", "voice", "personaplex", "daemon.port");
|
|
599525
|
+
if (existsSync100(ppPidFile)) {
|
|
599526
|
+
const ppPid = parseInt(readFileSync81(ppPidFile, "utf8").trim(), 10);
|
|
599527
|
+
const ppPort = existsSync100(ppPortFile) ? parseInt(readFileSync81(ppPortFile, "utf8").trim(), 10) : void 0;
|
|
598834
599528
|
if (ppPid > 0 && !registry2.daemons.has("PersonaPlex")) {
|
|
598835
599529
|
registry2.register({ name: "PersonaPlex", pid: ppPid, port: ppPort, startedAt: Date.now(), status: "running" });
|
|
598836
599530
|
}
|
|
598837
599531
|
}
|
|
598838
599532
|
}
|
|
598839
|
-
const nexusPidFile =
|
|
598840
|
-
if (
|
|
598841
|
-
const nPid = parseInt(
|
|
599533
|
+
const nexusPidFile = join116(repoRoot, ".oa", "nexus", "daemon.pid");
|
|
599534
|
+
if (existsSync100(nexusPidFile)) {
|
|
599535
|
+
const nPid = parseInt(readFileSync81(nexusPidFile, "utf8").trim(), 10);
|
|
598842
599536
|
if (nPid > 0 && !registry2.daemons.has("Nexus")) {
|
|
598843
599537
|
try {
|
|
598844
599538
|
process.kill(nPid, 0);
|
|
@@ -599205,9 +599899,9 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
599205
599899
|
}
|
|
599206
599900
|
}
|
|
599207
599901
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
599208
|
-
const isImage = isImagePath(cleanPath) &&
|
|
599209
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
599210
|
-
const isMarkdown = !isImage && !isMedia && /\.(md|markdown)$/i.test(cleanPath) &&
|
|
599902
|
+
const isImage = isImagePath(cleanPath) && existsSync100(resolve39(repoRoot, cleanPath));
|
|
599903
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync100(resolve39(repoRoot, cleanPath));
|
|
599904
|
+
const isMarkdown = !isImage && !isMedia && /\.(md|markdown)$/i.test(cleanPath) && existsSync100(resolve39(repoRoot, cleanPath));
|
|
599211
599905
|
if (activeTask) {
|
|
599212
599906
|
if (activeTask.runner.isPaused) {
|
|
599213
599907
|
activeTask.runner.resume();
|
|
@@ -599216,7 +599910,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
599216
599910
|
if (isImage) {
|
|
599217
599911
|
try {
|
|
599218
599912
|
const imgPath = resolve39(repoRoot, cleanPath);
|
|
599219
|
-
const imgBuffer =
|
|
599913
|
+
const imgBuffer = readFileSync81(imgPath);
|
|
599220
599914
|
const base642 = imgBuffer.toString("base64");
|
|
599221
599915
|
const ext = extname12(cleanPath).toLowerCase();
|
|
599222
599916
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -599372,7 +600066,7 @@ ${result.text}`;
|
|
|
599372
600066
|
if (isMarkdown && fullInput === input) {
|
|
599373
600067
|
try {
|
|
599374
600068
|
const mdPath = resolve39(repoRoot, cleanPath);
|
|
599375
|
-
const mdContent =
|
|
600069
|
+
const mdContent = readFileSync81(mdPath, "utf8");
|
|
599376
600070
|
const { parseMcpMarkdown: parseMcpMarkdown2 } = await Promise.resolve().then(() => (init_dist5(), dist_exports));
|
|
599377
600071
|
const result = parseMcpMarkdown2(mdContent);
|
|
599378
600072
|
if (result.servers.length > 0) {
|
|
@@ -599794,13 +600488,13 @@ async function runWithTUI(task, config, repoPath, callbacks) {
|
|
|
599794
600488
|
const handle2 = startTask(task, config, repoRoot);
|
|
599795
600489
|
await handle2.promise;
|
|
599796
600490
|
try {
|
|
599797
|
-
const ikDir =
|
|
599798
|
-
const ikFile =
|
|
600491
|
+
const ikDir = join116(repoRoot, ".oa", "identity");
|
|
600492
|
+
const ikFile = join116(ikDir, "self-state.json");
|
|
599799
600493
|
let ikState;
|
|
599800
|
-
if (
|
|
599801
|
-
ikState = JSON.parse(
|
|
600494
|
+
if (existsSync100(ikFile)) {
|
|
600495
|
+
ikState = JSON.parse(readFileSync81(ikFile, "utf8"));
|
|
599802
600496
|
} else {
|
|
599803
|
-
|
|
600497
|
+
mkdirSync64(ikDir, { recursive: true });
|
|
599804
600498
|
ikState = {
|
|
599805
600499
|
self_id: `oa-${Date.now().toString(36)}`,
|
|
599806
600500
|
version: 1,
|
|
@@ -599822,7 +600516,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
|
|
|
599822
600516
|
ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
|
|
599823
600517
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
599824
600518
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
599825
|
-
|
|
600519
|
+
writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
|
|
599826
600520
|
} catch (ikErr) {
|
|
599827
600521
|
}
|
|
599828
600522
|
try {
|
|
@@ -599835,11 +600529,11 @@ async function runWithTUI(task, config, repoPath, callbacks) {
|
|
|
599835
600529
|
);
|
|
599836
600530
|
} catch {
|
|
599837
600531
|
try {
|
|
599838
|
-
const archeDir =
|
|
599839
|
-
const archeFile =
|
|
600532
|
+
const archeDir = join116(repoRoot, ".oa", "arche");
|
|
600533
|
+
const archeFile = join116(archeDir, "variants.json");
|
|
599840
600534
|
let variants = [];
|
|
599841
600535
|
try {
|
|
599842
|
-
if (
|
|
600536
|
+
if (existsSync100(archeFile)) variants = JSON.parse(readFileSync81(archeFile, "utf8"));
|
|
599843
600537
|
} catch {
|
|
599844
600538
|
}
|
|
599845
600539
|
variants.push({
|
|
@@ -599853,15 +600547,15 @@ async function runWithTUI(task, config, repoPath, callbacks) {
|
|
|
599853
600547
|
tags: ["general"]
|
|
599854
600548
|
});
|
|
599855
600549
|
if (variants.length > 50) variants = variants.slice(-50);
|
|
599856
|
-
|
|
599857
|
-
|
|
600550
|
+
mkdirSync64(archeDir, { recursive: true });
|
|
600551
|
+
writeFileSync56(archeFile, JSON.stringify(variants, null, 2));
|
|
599858
600552
|
} catch {
|
|
599859
600553
|
}
|
|
599860
600554
|
}
|
|
599861
600555
|
try {
|
|
599862
|
-
const metaFile =
|
|
599863
|
-
if (
|
|
599864
|
-
const store2 = JSON.parse(
|
|
600556
|
+
const metaFile = join116(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
600557
|
+
if (existsSync100(metaFile)) {
|
|
600558
|
+
const store2 = JSON.parse(readFileSync81(metaFile, "utf8"));
|
|
599865
600559
|
const surfaced = store2.filter((m2) => m2.type !== "quarantine" && m2.scores?.confidence > 0.15).sort((a2, b) => b.scores.utility * b.scores.confidence - a2.scores.utility * a2.scores.confidence).slice(0, 5);
|
|
599866
600560
|
let updated = false;
|
|
599867
600561
|
for (const item of surfaced) {
|
|
@@ -599872,7 +600566,7 @@ async function runWithTUI(task, config, repoPath, callbacks) {
|
|
|
599872
600566
|
updated = true;
|
|
599873
600567
|
}
|
|
599874
600568
|
if (updated) {
|
|
599875
|
-
|
|
600569
|
+
writeFileSync56(metaFile, JSON.stringify(store2, null, 2));
|
|
599876
600570
|
}
|
|
599877
600571
|
}
|
|
599878
600572
|
} catch {
|
|
@@ -599925,9 +600619,9 @@ Rules:
|
|
|
599925
600619
|
try {
|
|
599926
600620
|
const { initDb: initDb2 } = __require("@open-agents/memory");
|
|
599927
600621
|
const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
599928
|
-
const dbDir =
|
|
599929
|
-
|
|
599930
|
-
const db = initDb2(
|
|
600622
|
+
const dbDir = join116(repoRoot, ".oa", "memory");
|
|
600623
|
+
mkdirSync64(dbDir, { recursive: true });
|
|
600624
|
+
const db = initDb2(join116(dbDir, "structured.db"));
|
|
599931
600625
|
const memStore = new ProceduralMemoryStore2(db);
|
|
599932
600626
|
memStore.createWithEmbedding({
|
|
599933
600627
|
content: content.slice(0, 600),
|
|
@@ -599942,11 +600636,11 @@ Rules:
|
|
|
599942
600636
|
db.close();
|
|
599943
600637
|
} catch {
|
|
599944
600638
|
}
|
|
599945
|
-
const metaDir =
|
|
599946
|
-
const storeFile =
|
|
600639
|
+
const metaDir = join116(repoRoot, ".oa", "memory", "metabolism");
|
|
600640
|
+
const storeFile = join116(metaDir, "store.json");
|
|
599947
600641
|
let store2 = [];
|
|
599948
600642
|
try {
|
|
599949
|
-
if (
|
|
600643
|
+
if (existsSync100(storeFile)) store2 = JSON.parse(readFileSync81(storeFile, "utf8"));
|
|
599950
600644
|
} catch {
|
|
599951
600645
|
}
|
|
599952
600646
|
store2.push({
|
|
@@ -599961,26 +600655,26 @@ Rules:
|
|
|
599961
600655
|
accessCount: 0
|
|
599962
600656
|
});
|
|
599963
600657
|
if (store2.length > 100) store2 = store2.slice(-100);
|
|
599964
|
-
|
|
599965
|
-
|
|
600658
|
+
mkdirSync64(metaDir, { recursive: true });
|
|
600659
|
+
writeFileSync56(storeFile, JSON.stringify(store2, null, 2));
|
|
599966
600660
|
}
|
|
599967
600661
|
}
|
|
599968
600662
|
} catch {
|
|
599969
600663
|
}
|
|
599970
600664
|
try {
|
|
599971
|
-
const cohereSettingsFile =
|
|
600665
|
+
const cohereSettingsFile = join116(repoRoot, ".oa", "settings.json");
|
|
599972
600666
|
let cohereActive = false;
|
|
599973
600667
|
try {
|
|
599974
|
-
if (
|
|
599975
|
-
const settings = JSON.parse(
|
|
600668
|
+
if (existsSync100(cohereSettingsFile)) {
|
|
600669
|
+
const settings = JSON.parse(readFileSync81(cohereSettingsFile, "utf8"));
|
|
599976
600670
|
cohereActive = settings.cohere === true;
|
|
599977
600671
|
}
|
|
599978
600672
|
} catch {
|
|
599979
600673
|
}
|
|
599980
600674
|
if (cohereActive) {
|
|
599981
|
-
const metaFile =
|
|
599982
|
-
if (
|
|
599983
|
-
const store2 = JSON.parse(
|
|
600675
|
+
const metaFile = join116(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
600676
|
+
if (existsSync100(metaFile)) {
|
|
600677
|
+
const store2 = JSON.parse(readFileSync81(metaFile, "utf8"));
|
|
599984
600678
|
const latest = store2.filter((m2) => m2.sourceTrace === "trajectory-extraction" || m2.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
|
|
599985
600679
|
if (latest && latest.scores?.confidence >= 0.6) {
|
|
599986
600680
|
try {
|
|
@@ -600005,18 +600699,18 @@ Rules:
|
|
|
600005
600699
|
}
|
|
600006
600700
|
} catch (err) {
|
|
600007
600701
|
try {
|
|
600008
|
-
const ikFile =
|
|
600009
|
-
if (
|
|
600010
|
-
const ikState = JSON.parse(
|
|
600702
|
+
const ikFile = join116(repoRoot, ".oa", "identity", "self-state.json");
|
|
600703
|
+
if (existsSync100(ikFile)) {
|
|
600704
|
+
const ikState = JSON.parse(readFileSync81(ikFile, "utf8"));
|
|
600011
600705
|
ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
|
|
600012
600706
|
ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
|
|
600013
600707
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
600014
600708
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
600015
|
-
|
|
600709
|
+
writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
|
|
600016
600710
|
}
|
|
600017
|
-
const metaFile =
|
|
600018
|
-
if (
|
|
600019
|
-
const store2 = JSON.parse(
|
|
600711
|
+
const metaFile = join116(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
600712
|
+
if (existsSync100(metaFile)) {
|
|
600713
|
+
const store2 = JSON.parse(readFileSync81(metaFile, "utf8"));
|
|
600020
600714
|
const surfaced = store2.filter((m2) => m2.type !== "quarantine" && m2.scores?.confidence > 0.15).sort((a2, b) => b.scores.utility * b.scores.confidence - a2.scores.utility * a2.scores.confidence).slice(0, 5);
|
|
600021
600715
|
for (const item of surfaced) {
|
|
600022
600716
|
item.accessCount = (item.accessCount || 0) + 1;
|
|
@@ -600024,14 +600718,14 @@ Rules:
|
|
|
600024
600718
|
item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
|
|
600025
600719
|
item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
|
|
600026
600720
|
}
|
|
600027
|
-
|
|
600721
|
+
writeFileSync56(metaFile, JSON.stringify(store2, null, 2));
|
|
600028
600722
|
}
|
|
600029
600723
|
try {
|
|
600030
|
-
const archeDir =
|
|
600031
|
-
const archeFile =
|
|
600724
|
+
const archeDir = join116(repoRoot, ".oa", "arche");
|
|
600725
|
+
const archeFile = join116(archeDir, "variants.json");
|
|
600032
600726
|
let variants = [];
|
|
600033
600727
|
try {
|
|
600034
|
-
if (
|
|
600728
|
+
if (existsSync100(archeFile)) variants = JSON.parse(readFileSync81(archeFile, "utf8"));
|
|
600035
600729
|
} catch {
|
|
600036
600730
|
}
|
|
600037
600731
|
variants.push({
|
|
@@ -600045,8 +600739,8 @@ Rules:
|
|
|
600045
600739
|
tags: ["general"]
|
|
600046
600740
|
});
|
|
600047
600741
|
if (variants.length > 50) variants = variants.slice(-50);
|
|
600048
|
-
|
|
600049
|
-
|
|
600742
|
+
mkdirSync64(archeDir, { recursive: true });
|
|
600743
|
+
writeFileSync56(archeFile, JSON.stringify(variants, null, 2));
|
|
600050
600744
|
} catch {
|
|
600051
600745
|
}
|
|
600052
600746
|
} catch {
|
|
@@ -600135,13 +600829,13 @@ __export(run_exports, {
|
|
|
600135
600829
|
});
|
|
600136
600830
|
import { resolve as resolve40 } from "node:path";
|
|
600137
600831
|
import { spawn as spawn26 } from "node:child_process";
|
|
600138
|
-
import { mkdirSync as
|
|
600139
|
-
import { randomBytes as
|
|
600140
|
-
import { join as
|
|
600832
|
+
import { mkdirSync as mkdirSync65, writeFileSync as writeFileSync57, readFileSync as readFileSync82, readdirSync as readdirSync36, existsSync as existsSync101 } from "node:fs";
|
|
600833
|
+
import { randomBytes as randomBytes24 } from "node:crypto";
|
|
600834
|
+
import { join as join117 } from "node:path";
|
|
600141
600835
|
function jobsDir2(repoPath) {
|
|
600142
600836
|
const root = resolve40(repoPath ?? process.cwd());
|
|
600143
|
-
const dir =
|
|
600144
|
-
|
|
600837
|
+
const dir = join117(root, ".oa", "jobs");
|
|
600838
|
+
mkdirSync65(dir, { recursive: true });
|
|
600145
600839
|
return dir;
|
|
600146
600840
|
}
|
|
600147
600841
|
async function runCommand(opts, config) {
|
|
@@ -600231,7 +600925,7 @@ function extractSummary(captured) {
|
|
|
600231
600925
|
return lines.slice(-3).join(" ").slice(0, 200);
|
|
600232
600926
|
}
|
|
600233
600927
|
async function runBackground(task, config, opts) {
|
|
600234
|
-
const id = `job-${
|
|
600928
|
+
const id = `job-${randomBytes24(3).toString("hex")}`;
|
|
600235
600929
|
const dir = jobsDir2(opts.repoPath);
|
|
600236
600930
|
const repoRoot = resolve40(opts.repoPath ?? process.cwd());
|
|
600237
600931
|
const job = {
|
|
@@ -600260,7 +600954,7 @@ async function runBackground(task, config, opts) {
|
|
|
600260
600954
|
}
|
|
600261
600955
|
});
|
|
600262
600956
|
job.pid = child.pid ?? 0;
|
|
600263
|
-
|
|
600957
|
+
writeFileSync57(join117(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
600264
600958
|
let output = "";
|
|
600265
600959
|
child.stdout?.on("data", (chunk) => {
|
|
600266
600960
|
output += chunk.toString();
|
|
@@ -600276,7 +600970,7 @@ async function runBackground(task, config, opts) {
|
|
|
600276
600970
|
job.summary = result.summary;
|
|
600277
600971
|
job.durationMs = result.durationMs;
|
|
600278
600972
|
job.error = result.error;
|
|
600279
|
-
|
|
600973
|
+
writeFileSync57(join117(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
600280
600974
|
} catch {
|
|
600281
600975
|
}
|
|
600282
600976
|
});
|
|
@@ -600292,13 +600986,13 @@ async function runBackground(task, config, opts) {
|
|
|
600292
600986
|
}
|
|
600293
600987
|
function statusCommand(jobId, repoPath) {
|
|
600294
600988
|
const dir = jobsDir2(repoPath);
|
|
600295
|
-
const file =
|
|
600296
|
-
if (!
|
|
600989
|
+
const file = join117(dir, `${jobId}.json`);
|
|
600990
|
+
if (!existsSync101(file)) {
|
|
600297
600991
|
console.error(`Job not found: ${jobId}`);
|
|
600298
600992
|
console.log(`Available jobs: oa jobs`);
|
|
600299
600993
|
process.exit(1);
|
|
600300
600994
|
}
|
|
600301
|
-
const job = JSON.parse(
|
|
600995
|
+
const job = JSON.parse(readFileSync82(file, "utf-8"));
|
|
600302
600996
|
const runtime = job.completedAt ? `${((new Date(job.completedAt).getTime() - new Date(job.startedAt).getTime()) / 1e3).toFixed(0)}s` : `${((Date.now() - new Date(job.startedAt).getTime()) / 1e3).toFixed(0)}s`;
|
|
600303
600997
|
const icon = job.status === "completed" ? "✓" : job.status === "failed" ? "✗" : "●";
|
|
600304
600998
|
console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
|
|
@@ -600319,7 +601013,7 @@ function jobsCommand(repoPath) {
|
|
|
600319
601013
|
console.log("Jobs:");
|
|
600320
601014
|
for (const file of files) {
|
|
600321
601015
|
try {
|
|
600322
|
-
const job = JSON.parse(
|
|
601016
|
+
const job = JSON.parse(readFileSync82(join117(dir, file), "utf-8"));
|
|
600323
601017
|
const icon = job.status === "completed" ? "✓" : job.status === "failed" ? "✗" : "●";
|
|
600324
601018
|
const runtime = job.completedAt ? `${((new Date(job.completedAt).getTime() - new Date(job.startedAt).getTime()) / 1e3).toFixed(0)}s` : `${((Date.now() - new Date(job.startedAt).getTime()) / 1e3).toFixed(0)}s`;
|
|
600325
601019
|
const cleanListTask = cleanForStorage(job.task) || job.task;
|
|
@@ -600343,13 +601037,13 @@ __export(index_repo_exports, {
|
|
|
600343
601037
|
indexRepoCommand: () => indexRepoCommand
|
|
600344
601038
|
});
|
|
600345
601039
|
import { resolve as resolve41 } from "node:path";
|
|
600346
|
-
import { existsSync as
|
|
601040
|
+
import { existsSync as existsSync102, statSync as statSync29 } from "node:fs";
|
|
600347
601041
|
import { cwd as cwd2 } from "node:process";
|
|
600348
601042
|
async function indexRepoCommand(opts, _config3) {
|
|
600349
601043
|
const repoRoot = resolve41(opts.repoPath ?? cwd2());
|
|
600350
601044
|
printHeader("Index Repository");
|
|
600351
601045
|
printInfo(`Indexing: ${repoRoot}`);
|
|
600352
|
-
if (!
|
|
601046
|
+
if (!existsSync102(repoRoot)) {
|
|
600353
601047
|
printError(`Path does not exist: ${repoRoot}`);
|
|
600354
601048
|
process.exit(1);
|
|
600355
601049
|
}
|
|
@@ -600601,8 +601295,8 @@ var config_exports2 = {};
|
|
|
600601
601295
|
__export(config_exports2, {
|
|
600602
601296
|
configCommand: () => configCommand
|
|
600603
601297
|
});
|
|
600604
|
-
import { join as
|
|
600605
|
-
import { homedir as
|
|
601298
|
+
import { join as join118, resolve as resolve42 } from "node:path";
|
|
601299
|
+
import { homedir as homedir43 } from "node:os";
|
|
600606
601300
|
import { cwd as cwd3 } from "node:process";
|
|
600607
601301
|
function redactIfSensitive(key, value2) {
|
|
600608
601302
|
if (SENSITIVE_KEYS.has(key) && typeof value2 === "string" && value2.length > 0) {
|
|
@@ -600683,7 +601377,7 @@ function handleShow(opts, config) {
|
|
|
600683
601377
|
}
|
|
600684
601378
|
}
|
|
600685
601379
|
printSection("Config File");
|
|
600686
|
-
printInfo(`~/.open-agents/config.json (${
|
|
601380
|
+
printInfo(`~/.open-agents/config.json (${join118(homedir43(), ".open-agents", "config.json")})`);
|
|
600687
601381
|
printSection("Priority Chain");
|
|
600688
601382
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
600689
601383
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -600722,7 +601416,7 @@ function handleSet(opts, _config3) {
|
|
|
600722
601416
|
const coerced = coerceForSettings(key, value2);
|
|
600723
601417
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
600724
601418
|
printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value2)}`);
|
|
600725
|
-
printInfo(`Saved to ${
|
|
601419
|
+
printInfo(`Saved to ${join118(repoRoot, ".oa", "settings.json")}`);
|
|
600726
601420
|
printInfo("This override applies only when running in this workspace.");
|
|
600727
601421
|
} catch (err) {
|
|
600728
601422
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -600906,8 +601600,8 @@ __export(eval_exports, {
|
|
|
600906
601600
|
evalCommand: () => evalCommand
|
|
600907
601601
|
});
|
|
600908
601602
|
import { tmpdir as tmpdir21 } from "node:os";
|
|
600909
|
-
import { mkdirSync as
|
|
600910
|
-
import { join as
|
|
601603
|
+
import { mkdirSync as mkdirSync66, writeFileSync as writeFileSync58 } from "node:fs";
|
|
601604
|
+
import { join as join119 } from "node:path";
|
|
600911
601605
|
async function evalCommand(opts, config) {
|
|
600912
601606
|
const suiteName = opts.suite ?? "basic";
|
|
600913
601607
|
const suite = SUITES[suiteName];
|
|
@@ -601036,10 +601730,10 @@ async function evalCommand(opts, config) {
|
|
|
601036
601730
|
process.exit(failed > 0 ? 1 : 0);
|
|
601037
601731
|
}
|
|
601038
601732
|
function createTempEvalRepo() {
|
|
601039
|
-
const dir =
|
|
601040
|
-
|
|
601041
|
-
|
|
601042
|
-
|
|
601733
|
+
const dir = join119(tmpdir21(), `open-agents-eval-${Date.now()}`);
|
|
601734
|
+
mkdirSync66(dir, { recursive: true });
|
|
601735
|
+
writeFileSync58(
|
|
601736
|
+
join119(dir, "package.json"),
|
|
601043
601737
|
JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n",
|
|
601044
601738
|
"utf8"
|
|
601045
601739
|
);
|
|
@@ -601103,7 +601797,7 @@ init_typed_node_events();
|
|
|
601103
601797
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
601104
601798
|
import { createRequire as createRequire6 } from "node:module";
|
|
601105
601799
|
import { fileURLToPath as fileURLToPath19 } from "node:url";
|
|
601106
|
-
import { dirname as dirname37, join as
|
|
601800
|
+
import { dirname as dirname37, join as join120 } from "node:path";
|
|
601107
601801
|
|
|
601108
601802
|
// packages/cli/src/cli.ts
|
|
601109
601803
|
init_typed_node_events();
|
|
@@ -601243,7 +601937,7 @@ init_output();
|
|
|
601243
601937
|
function getVersion5() {
|
|
601244
601938
|
try {
|
|
601245
601939
|
const require4 = createRequire6(import.meta.url);
|
|
601246
|
-
const pkgPath =
|
|
601940
|
+
const pkgPath = join120(dirname37(fileURLToPath19(import.meta.url)), "..", "package.json");
|
|
601247
601941
|
const pkg = require4(pkgPath);
|
|
601248
601942
|
return pkg.version;
|
|
601249
601943
|
} catch {
|
|
@@ -601557,12 +602251,12 @@ function crashLog(label, err) {
|
|
|
601557
602251
|
const logLine = `[${timestamp}] ${label}: ${msg}
|
|
601558
602252
|
`;
|
|
601559
602253
|
try {
|
|
601560
|
-
const { appendFileSync: appendFileSync9, mkdirSync:
|
|
601561
|
-
const { join:
|
|
601562
|
-
const { homedir:
|
|
601563
|
-
const logDir =
|
|
601564
|
-
|
|
601565
|
-
appendFileSync9(
|
|
602254
|
+
const { appendFileSync: appendFileSync9, mkdirSync: mkdirSync67 } = __require("node:fs");
|
|
602255
|
+
const { join: join121 } = __require("node:path");
|
|
602256
|
+
const { homedir: homedir44 } = __require("node:os");
|
|
602257
|
+
const logDir = join121(homedir44(), ".open-agents");
|
|
602258
|
+
mkdirSync67(logDir, { recursive: true });
|
|
602259
|
+
appendFileSync9(join121(logDir, "crash.log"), logLine);
|
|
601566
602260
|
} catch {
|
|
601567
602261
|
}
|
|
601568
602262
|
try {
|