open-agents-ai 0.187.534 → 0.187.535
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 +1258 -451
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7783,11 +7783,41 @@ async function handleCmd(cmd) {
|
|
|
7783
7783
|
const capability = args.capability || 'text-generation';
|
|
7784
7784
|
const input = args.input || {};
|
|
7785
7785
|
if (!peerId) { writeResp(id, { ok: false, output: 'target_peer is required' }); return; }
|
|
7786
|
-
|
|
7786
|
+
// Streaming mode: when stream_file is supplied, tee invoke events
|
|
7787
|
+
// to the file as JSONL so the caller can tail them in real time.
|
|
7788
|
+
const icStreamFile = typeof args.stream_file === 'string' ? args.stream_file : '';
|
|
7789
|
+
const icUseStream = !!icStreamFile;
|
|
7790
|
+
dlog('invoke_capability: peer=' + peerId.slice(0, 20) + ' cap=' + capability + (icUseStream ? ' [stream]' : ''));
|
|
7787
7791
|
try {
|
|
7788
|
-
// Race libp2p + NATS in parallel — whichever route works first wins
|
|
7789
7792
|
const INVOKE_TIMEOUT = 300_000;
|
|
7790
7793
|
const invokeInput = typeof input === 'string' ? { prompt: input } : input;
|
|
7794
|
+
if (icUseStream) {
|
|
7795
|
+
// Stream-mode: get an AsyncGenerator and tee each event to the file.
|
|
7796
|
+
var icStreamGen;
|
|
7797
|
+
try {
|
|
7798
|
+
icStreamGen = await nexus.invokeCapability(peerId, capability, invokeInput, { stream: true, maxDurationMs: 240000 });
|
|
7799
|
+
} catch (invokeStartErr) {
|
|
7800
|
+
writeResp(id, { ok: false, output: 'Invoke start failed: ' + (invokeStartErr.message || invokeStartErr) });
|
|
7801
|
+
break;
|
|
7802
|
+
}
|
|
7803
|
+
// Signal the caller that streaming has begun.
|
|
7804
|
+
writeResp(id, { ok: true, output: JSON.stringify({ streaming: true, stream_file: icStreamFile }) });
|
|
7805
|
+
try {
|
|
7806
|
+
for await (var icEvt of icStreamGen) {
|
|
7807
|
+
appendFileSync(icStreamFile, JSON.stringify({ type: 'event', event: icEvt.event || '', seq: icEvt.seq || 0, data: icEvt.data }) + '
|
|
7808
|
+
');
|
|
7809
|
+
}
|
|
7810
|
+
appendFileSync(icStreamFile, JSON.stringify({ type: 'done' }) + '
|
|
7811
|
+
');
|
|
7812
|
+
dlog('invoke_capability: stream complete');
|
|
7813
|
+
} catch (icStreamErr) {
|
|
7814
|
+
appendFileSync(icStreamFile, JSON.stringify({ type: 'error', error: String(icStreamErr.message || icStreamErr) }) + '
|
|
7815
|
+
');
|
|
7816
|
+
dlog('invoke_capability: stream error: ' + (icStreamErr.message || icStreamErr));
|
|
7817
|
+
}
|
|
7818
|
+
break;
|
|
7819
|
+
}
|
|
7820
|
+
// Non-stream mode: race libp2p + NATS in parallel.
|
|
7791
7821
|
const invokePromise = nexus.invokeCapability(peerId, capability, invokeInput, { stream: false, maxDurationMs: 240000 });
|
|
7792
7822
|
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('invoke_capability timed out after ' + (INVOKE_TIMEOUT / 1000) + 's')), INVOKE_TIMEOUT));
|
|
7793
7823
|
|
|
@@ -9427,6 +9457,119 @@ process.on('unhandledRejection', (reason) => {
|
|
|
9427
9457
|
}
|
|
9428
9458
|
connected = true;
|
|
9429
9459
|
|
|
9460
|
+
// http_tunnel capability — proxies HTTP requests from remote peers
|
|
9461
|
+
// to the local OA API daemon. Auth is delegated to the API key store
|
|
9462
|
+
// (remote sends share key in Authorization header). SSE streams are
|
|
9463
|
+
// forwarded chunk-by-chunk over libp2p invoke. The local API port is
|
|
9464
|
+
// read from nexusDir/api-port.json which oa serve writes on startup.
|
|
9465
|
+
if (typeof nexus.registerCapability === 'function') {
|
|
9466
|
+
var nodePathMod = require('node:path');
|
|
9467
|
+
var apiPortHintPath = nodePathMod.join(nexusDir, 'api-port.json');
|
|
9468
|
+
nexus.registerCapability('http_tunnel', async (request, stream) => {
|
|
9469
|
+
var htClosed = false;
|
|
9470
|
+
async function htWrite(msg) {
|
|
9471
|
+
if (htClosed) return;
|
|
9472
|
+
try { await stream.write(msg); } catch { htClosed = true; }
|
|
9473
|
+
}
|
|
9474
|
+
var htChunks = [];
|
|
9475
|
+
var htInputDone = false;
|
|
9476
|
+
stream.onData(function(msg) {
|
|
9477
|
+
if (msg.type === 'invoke.chunk') {
|
|
9478
|
+
htChunks.push(typeof msg.data === 'string' ? msg.data : JSON.stringify(msg.data));
|
|
9479
|
+
}
|
|
9480
|
+
if (msg.type === 'invoke.done' || msg.type === 'invoke.end') htInputDone = true;
|
|
9481
|
+
});
|
|
9482
|
+
await htWrite({ type: 'invoke.accept', version: 1, requestId: request.requestId, accepted: true });
|
|
9483
|
+
var htWait = 0;
|
|
9484
|
+
while (!htInputDone && htWait < 5000) {
|
|
9485
|
+
await new Promise(function(r) { setTimeout(r, 20); });
|
|
9486
|
+
htWait += 20;
|
|
9487
|
+
}
|
|
9488
|
+
var htReq;
|
|
9489
|
+
try {
|
|
9490
|
+
htReq = JSON.parse(htChunks.join(''));
|
|
9491
|
+
} catch (parseErr) {
|
|
9492
|
+
await htWrite({ type: 'invoke.event', version: 1, requestId: request.requestId, seq: 0, event: 'http.error', data: 'Bad request JSON: ' + (parseErr.message || parseErr) });
|
|
9493
|
+
await htWrite({ type: 'invoke.done', version: 1, requestId: request.requestId, usage: { inputBytes: 0, outputBytes: 0 } });
|
|
9494
|
+
try { stream.close(); } catch {}
|
|
9495
|
+
return;
|
|
9496
|
+
}
|
|
9497
|
+
// Resolve API endpoint from sibling api-port.json
|
|
9498
|
+
var htApiHost = '127.0.0.1';
|
|
9499
|
+
var htApiPort = 11435;
|
|
9500
|
+
var htApiScheme = 'http';
|
|
9501
|
+
try {
|
|
9502
|
+
if (existsSync(apiPortHintPath)) {
|
|
9503
|
+
var apiCfg = JSON.parse(readFileSync(apiPortHintPath, 'utf-8'));
|
|
9504
|
+
if (typeof apiCfg.port === 'number' && apiCfg.port > 0) htApiPort = apiCfg.port;
|
|
9505
|
+
if (typeof apiCfg.scheme === 'string') htApiScheme = apiCfg.scheme;
|
|
9506
|
+
if (typeof apiCfg.host === 'string' && apiCfg.host) htApiHost = apiCfg.host;
|
|
9507
|
+
} else {
|
|
9508
|
+
dlog('http_tunnel: api-port.json missing — using defaults 127.0.0.1:11435');
|
|
9509
|
+
}
|
|
9510
|
+
} catch (cfgErr) {
|
|
9511
|
+
dlog('http_tunnel: api-port.json parse failed: ' + (cfgErr.message || cfgErr));
|
|
9512
|
+
}
|
|
9513
|
+
var htPath = typeof htReq.path === 'string' ? htReq.path : '/';
|
|
9514
|
+
if (!htPath.startsWith('/')) htPath = '/' + htPath;
|
|
9515
|
+
var htUrl = htApiScheme + '://' + htApiHost + ':' + htApiPort + htPath;
|
|
9516
|
+
var htMethod = (htReq.method || 'GET').toUpperCase();
|
|
9517
|
+
var htHeaders = (htReq.headers && typeof htReq.headers === 'object') ? Object.assign({}, htReq.headers) : {};
|
|
9518
|
+
// Inject auth — share key from req.key overrides any incoming auth
|
|
9519
|
+
if (typeof htReq.key === 'string' && htReq.key) {
|
|
9520
|
+
htHeaders['authorization'] = 'Bearer ' + htReq.key;
|
|
9521
|
+
}
|
|
9522
|
+
// Strip hop-by-hop headers that don't translate
|
|
9523
|
+
delete htHeaders['host'];
|
|
9524
|
+
delete htHeaders['connection'];
|
|
9525
|
+
delete htHeaders['content-length'];
|
|
9526
|
+
var htBodyInit;
|
|
9527
|
+
if (htMethod !== 'GET' && htMethod !== 'HEAD' && htReq.body !== undefined && htReq.body !== null) {
|
|
9528
|
+
if (typeof htReq.body === 'string') htBodyInit = htReq.body;
|
|
9529
|
+
else htBodyInit = JSON.stringify(htReq.body);
|
|
9530
|
+
if (!htHeaders['content-type']) htHeaders['content-type'] = 'application/json';
|
|
9531
|
+
}
|
|
9532
|
+
dlog('http_tunnel: ' + htMethod + ' ' + htPath + ' from ' + (request.from || '?').slice(0, 16));
|
|
9533
|
+
try {
|
|
9534
|
+
var htResp = await fetch(htUrl, {
|
|
9535
|
+
method: htMethod, headers: htHeaders, body: htBodyInit,
|
|
9536
|
+
});
|
|
9537
|
+
var htRespHeaders = {};
|
|
9538
|
+
htResp.headers.forEach(function(v, k) { htRespHeaders[k] = v; });
|
|
9539
|
+
var htCT = (htRespHeaders['content-type'] || '').toLowerCase();
|
|
9540
|
+
var htIsStream = htCT.includes('text/event-stream') || htCT.includes('application/x-ndjson');
|
|
9541
|
+
await htWrite({
|
|
9542
|
+
type: 'invoke.event', version: 1, requestId: request.requestId, seq: 0,
|
|
9543
|
+
event: 'http.head',
|
|
9544
|
+
data: JSON.stringify({ status: htResp.status, headers: htRespHeaders, streaming: htIsStream }),
|
|
9545
|
+
});
|
|
9546
|
+
var htSeq = 1;
|
|
9547
|
+
if (htIsStream && htResp.body) {
|
|
9548
|
+
var htReader = htResp.body.getReader();
|
|
9549
|
+
var htDecoder = new TextDecoder();
|
|
9550
|
+
while (true) {
|
|
9551
|
+
var htChunk = await htReader.read();
|
|
9552
|
+
if (htChunk.done) break;
|
|
9553
|
+
var htText = htDecoder.decode(htChunk.value, { stream: true });
|
|
9554
|
+
if (htText) {
|
|
9555
|
+
await htWrite({ type: 'invoke.event', version: 1, requestId: request.requestId, seq: htSeq++, event: 'http.chunk', data: htText });
|
|
9556
|
+
}
|
|
9557
|
+
}
|
|
9558
|
+
} else {
|
|
9559
|
+
var htBodyText = await htResp.text();
|
|
9560
|
+
await htWrite({ type: 'invoke.event', version: 1, requestId: request.requestId, seq: htSeq++, event: 'http.body', data: htBodyText });
|
|
9561
|
+
}
|
|
9562
|
+
await htWrite({ type: 'invoke.done', version: 1, requestId: request.requestId, usage: { inputBytes: 0, outputBytes: 0 } });
|
|
9563
|
+
} catch (htErr) {
|
|
9564
|
+
dlog('http_tunnel: fetch failed: ' + (htErr.message || htErr));
|
|
9565
|
+
await htWrite({ type: 'invoke.event', version: 1, requestId: request.requestId, seq: 0, event: 'http.error', data: String(htErr.message || htErr) });
|
|
9566
|
+
await htWrite({ type: 'invoke.done', version: 1, requestId: request.requestId, usage: { inputBytes: 0, outputBytes: 0 } });
|
|
9567
|
+
}
|
|
9568
|
+
try { stream.close(); } catch {}
|
|
9569
|
+
});
|
|
9570
|
+
dlog('http_tunnel capability registered (api hint: ' + apiPortHintPath + ')');
|
|
9571
|
+
}
|
|
9572
|
+
|
|
9430
9573
|
// Monkey-patch node.dialProtocol AND node.dial to convert string multiaddrs
|
|
9431
9574
|
// to proper Multiaddr objects. libp2p v3 transports call .getComponents()
|
|
9432
9575
|
// on multiaddr objects, which fails on plain strings. open-agents-nexus
|
|
@@ -247683,11 +247826,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
247683
247826
|
* what was previously computed. */
|
|
247684
247827
|
async loadSessionInfo() {
|
|
247685
247828
|
try {
|
|
247686
|
-
const { readFileSync:
|
|
247829
|
+
const { readFileSync: readFileSync89, existsSync: existsSync110 } = await import("node:fs");
|
|
247687
247830
|
const sessionPath2 = join28(this.cwd, ".oa", "rlm", "session.json");
|
|
247688
|
-
if (!
|
|
247831
|
+
if (!existsSync110(sessionPath2))
|
|
247689
247832
|
return null;
|
|
247690
|
-
return JSON.parse(
|
|
247833
|
+
return JSON.parse(readFileSync89(sessionPath2, "utf8"));
|
|
247691
247834
|
} catch {
|
|
247692
247835
|
return null;
|
|
247693
247836
|
}
|
|
@@ -247864,10 +248007,10 @@ var init_memory_metabolism = __esm({
|
|
|
247864
248007
|
const trajDir = join29(this.cwd, ".oa", "rlm-trajectories");
|
|
247865
248008
|
let lessons = [];
|
|
247866
248009
|
try {
|
|
247867
|
-
const { readdirSync: readdirSync39, readFileSync:
|
|
248010
|
+
const { readdirSync: readdirSync39, readFileSync: readFileSync89 } = await import("node:fs");
|
|
247868
248011
|
const files = readdirSync39(trajDir).filter((f2) => f2.endsWith(".jsonl")).sort().reverse().slice(0, 3);
|
|
247869
248012
|
for (const file of files) {
|
|
247870
|
-
const lines =
|
|
248013
|
+
const lines = readFileSync89(join29(trajDir, file), "utf8").split("\n").filter((l2) => l2.trim());
|
|
247871
248014
|
for (const line of lines) {
|
|
247872
248015
|
try {
|
|
247873
248016
|
const entry = JSON.parse(line);
|
|
@@ -248251,14 +248394,14 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
|
|
|
248251
248394
|
* Optionally filter by task type for phase-aware context (FSM paper insight).
|
|
248252
248395
|
*/
|
|
248253
248396
|
getTopMemoriesSync(k = 5, taskType) {
|
|
248254
|
-
const { readFileSync:
|
|
248397
|
+
const { readFileSync: readFileSync89, existsSync: existsSync110 } = __require("node:fs");
|
|
248255
248398
|
const metaDir = join29(this.cwd, ".oa", "memory", "metabolism");
|
|
248256
248399
|
const storeFile = join29(metaDir, "store.json");
|
|
248257
|
-
if (!
|
|
248400
|
+
if (!existsSync110(storeFile))
|
|
248258
248401
|
return "";
|
|
248259
248402
|
let store2 = [];
|
|
248260
248403
|
try {
|
|
248261
|
-
store2 = JSON.parse(
|
|
248404
|
+
store2 = JSON.parse(readFileSync89(storeFile, "utf8"));
|
|
248262
248405
|
} catch {
|
|
248263
248406
|
return "";
|
|
248264
248407
|
}
|
|
@@ -248280,14 +248423,14 @@ ${issues.map((i2) => ` - ${i2}`).join("\n")}` : " No issues found."),
|
|
|
248280
248423
|
/** Update memory scores based on task outcome. Called after task completion.
|
|
248281
248424
|
* Memories used in successful tasks get boosted. Memories present during failures get decayed. */
|
|
248282
248425
|
updateFromOutcomeSync(surfacedMemoryText, succeeded) {
|
|
248283
|
-
const { readFileSync:
|
|
248426
|
+
const { readFileSync: readFileSync89, writeFileSync: writeFileSync59, existsSync: existsSync110, mkdirSync: mkdirSync67 } = __require("node:fs");
|
|
248284
248427
|
const metaDir = join29(this.cwd, ".oa", "memory", "metabolism");
|
|
248285
248428
|
const storeFile = join29(metaDir, "store.json");
|
|
248286
|
-
if (!
|
|
248429
|
+
if (!existsSync110(storeFile))
|
|
248287
248430
|
return;
|
|
248288
248431
|
let store2 = [];
|
|
248289
248432
|
try {
|
|
248290
|
-
store2 = JSON.parse(
|
|
248433
|
+
store2 = JSON.parse(readFileSync89(storeFile, "utf8"));
|
|
248291
248434
|
} catch {
|
|
248292
248435
|
return;
|
|
248293
248436
|
}
|
|
@@ -248734,13 +248877,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
248734
248877
|
// Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
|
|
248735
248878
|
/** Retrieve top-K strategies for context injection. Returns "" if none. */
|
|
248736
248879
|
getRelevantStrategiesSync(k = 3, taskType) {
|
|
248737
|
-
const { readFileSync:
|
|
248880
|
+
const { readFileSync: readFileSync89, existsSync: existsSync110 } = __require("node:fs");
|
|
248738
248881
|
const archiveFile = join31(this.cwd, ".oa", "arche", "variants.json");
|
|
248739
|
-
if (!
|
|
248882
|
+
if (!existsSync110(archiveFile))
|
|
248740
248883
|
return "";
|
|
248741
248884
|
let variants = [];
|
|
248742
248885
|
try {
|
|
248743
|
-
variants = JSON.parse(
|
|
248886
|
+
variants = JSON.parse(readFileSync89(archiveFile, "utf8"));
|
|
248744
248887
|
} catch {
|
|
248745
248888
|
return "";
|
|
248746
248889
|
}
|
|
@@ -248758,13 +248901,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
248758
248901
|
}
|
|
248759
248902
|
/** Archive a strategy variant synchronously (for task completion path) */
|
|
248760
248903
|
archiveVariantSync(strategy, outcome, tags = []) {
|
|
248761
|
-
const { readFileSync:
|
|
248904
|
+
const { readFileSync: readFileSync89, writeFileSync: writeFileSync59, existsSync: existsSync110, mkdirSync: mkdirSync67 } = __require("node:fs");
|
|
248762
248905
|
const dir = join31(this.cwd, ".oa", "arche");
|
|
248763
248906
|
const archiveFile = join31(dir, "variants.json");
|
|
248764
248907
|
let variants = [];
|
|
248765
248908
|
try {
|
|
248766
|
-
if (
|
|
248767
|
-
variants = JSON.parse(
|
|
248909
|
+
if (existsSync110(archiveFile))
|
|
248910
|
+
variants = JSON.parse(readFileSync89(archiveFile, "utf8"));
|
|
248768
248911
|
} catch {
|
|
248769
248912
|
}
|
|
248770
248913
|
variants.push({
|
|
@@ -257044,7 +257187,7 @@ var require_util9 = __commonJS({
|
|
|
257044
257187
|
return path8;
|
|
257045
257188
|
}
|
|
257046
257189
|
exports.normalize = normalize2;
|
|
257047
|
-
function
|
|
257190
|
+
function join128(aRoot, aPath) {
|
|
257048
257191
|
if (aRoot === "") {
|
|
257049
257192
|
aRoot = ".";
|
|
257050
257193
|
}
|
|
@@ -257076,7 +257219,7 @@ var require_util9 = __commonJS({
|
|
|
257076
257219
|
}
|
|
257077
257220
|
return joined;
|
|
257078
257221
|
}
|
|
257079
|
-
exports.join =
|
|
257222
|
+
exports.join = join128;
|
|
257080
257223
|
exports.isAbsolute = function(aPath) {
|
|
257081
257224
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
257082
257225
|
};
|
|
@@ -257249,7 +257392,7 @@ var require_util9 = __commonJS({
|
|
|
257249
257392
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
257250
257393
|
}
|
|
257251
257394
|
}
|
|
257252
|
-
sourceURL =
|
|
257395
|
+
sourceURL = join128(urlGenerate(parsed), sourceURL);
|
|
257253
257396
|
}
|
|
257254
257397
|
return normalize2(sourceURL);
|
|
257255
257398
|
}
|
|
@@ -472669,7 +472812,7 @@ var require_path_browserify = __commonJS({
|
|
|
472669
472812
|
assertPath(path8);
|
|
472670
472813
|
return path8.length > 0 && path8.charCodeAt(0) === 47;
|
|
472671
472814
|
},
|
|
472672
|
-
join: function
|
|
472815
|
+
join: function join128() {
|
|
472673
472816
|
if (arguments.length === 0)
|
|
472674
472817
|
return ".";
|
|
472675
472818
|
var joined;
|
|
@@ -522783,9 +522926,9 @@ var init_reflectionBuffer = __esm({
|
|
|
522783
522926
|
this.persistPath = persistPath ?? null;
|
|
522784
522927
|
if (this.persistPath) {
|
|
522785
522928
|
try {
|
|
522786
|
-
const { readFileSync:
|
|
522787
|
-
if (
|
|
522788
|
-
this.state = JSON.parse(
|
|
522929
|
+
const { readFileSync: readFileSync89, existsSync: existsSync110 } = __require("node:fs");
|
|
522930
|
+
if (existsSync110(this.persistPath)) {
|
|
522931
|
+
this.state = JSON.parse(readFileSync89(this.persistPath, "utf-8"));
|
|
522789
522932
|
return;
|
|
522790
522933
|
}
|
|
522791
522934
|
} catch {
|
|
@@ -523018,10 +523161,10 @@ var init_reflectionBuffer = __esm({
|
|
|
523018
523161
|
if (!this.persistPath)
|
|
523019
523162
|
return;
|
|
523020
523163
|
try {
|
|
523021
|
-
const { writeFileSync: writeFileSync59, mkdirSync: mkdirSync67, existsSync:
|
|
523022
|
-
const { join:
|
|
523023
|
-
const dir =
|
|
523024
|
-
if (!
|
|
523164
|
+
const { writeFileSync: writeFileSync59, mkdirSync: mkdirSync67, existsSync: existsSync110 } = __require("node:fs");
|
|
523165
|
+
const { join: join128 } = __require("node:path");
|
|
523166
|
+
const dir = join128(this.persistPath, "..");
|
|
523167
|
+
if (!existsSync110(dir))
|
|
523025
523168
|
mkdirSync67(dir, { recursive: true });
|
|
523026
523169
|
writeFileSync59(this.persistPath, JSON.stringify(this.state, null, 2));
|
|
523027
523170
|
} catch {
|
|
@@ -533564,8 +533707,8 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
|
|
|
533564
533707
|
this.emit({ type: "status", content: `Knowledge graph: ${nodes} nodes, ${edges} active edges`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
533565
533708
|
try {
|
|
533566
533709
|
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
|
|
533567
|
-
const { join:
|
|
533568
|
-
const contextDir =
|
|
533710
|
+
const { join: join128 } = __require("node:path");
|
|
533711
|
+
const contextDir = join128(this._workingDirectory || process.cwd(), ".oa", "context");
|
|
533569
533712
|
mkdirSync67(contextDir, { recursive: true });
|
|
533570
533713
|
const topEntities = this._temporalGraph.nodesByType("entity", 3);
|
|
533571
533714
|
const topFiles = this._temporalGraph.nodesByType("file", 3);
|
|
@@ -533606,9 +533749,9 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
|
|
|
533606
533749
|
section("Top Files", topFiles);
|
|
533607
533750
|
section("Top Concepts", topConcepts);
|
|
533608
533751
|
lines.push("(Use file_read on this file for quick recall. See provenance JSON for full edge detail.)");
|
|
533609
|
-
const outPath =
|
|
533752
|
+
const outPath = join128(contextDir, `kg-summary-${this._sessionId}.md`);
|
|
533610
533753
|
writeFileSync59(outPath, lines.join("\n"), "utf-8");
|
|
533611
|
-
writeFileSync59(
|
|
533754
|
+
writeFileSync59(join128(contextDir, `kg-summary-latest.md`), lines.join("\n"), "utf-8");
|
|
533612
533755
|
} catch {
|
|
533613
533756
|
}
|
|
533614
533757
|
}
|
|
@@ -533777,10 +533920,10 @@ ${errOutput}`;
|
|
|
533777
533920
|
});
|
|
533778
533921
|
try {
|
|
533779
533922
|
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
|
|
533780
|
-
const { join:
|
|
533781
|
-
const resultsDir =
|
|
533923
|
+
const { join: join128 } = __require("node:path");
|
|
533924
|
+
const resultsDir = join128(process.cwd(), ".oa", "tool-results");
|
|
533782
533925
|
mkdirSync67(resultsDir, { recursive: true });
|
|
533783
|
-
writeFileSync59(
|
|
533926
|
+
writeFileSync59(join128(resultsDir, `${handleId}.txt`), `# Tool: ${toolName}
|
|
533784
533927
|
# Turn: ${turn}
|
|
533785
533928
|
# Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
533786
533929
|
# Size: ${result.output.length} chars, ${lineCount} lines
|
|
@@ -533997,8 +534140,8 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
|
|
|
533997
534140
|
return;
|
|
533998
534141
|
try {
|
|
533999
534142
|
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = __require("node:fs");
|
|
534000
|
-
const { join:
|
|
534001
|
-
const sessionDir =
|
|
534143
|
+
const { join: join128 } = __require("node:path");
|
|
534144
|
+
const sessionDir = join128(this._workingDirectory, ".oa", "session", this._sessionId);
|
|
534002
534145
|
mkdirSync67(sessionDir, { recursive: true });
|
|
534003
534146
|
const checkpoint = {
|
|
534004
534147
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -534011,7 +534154,7 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
|
|
|
534011
534154
|
memexEntryCount: this._memexArchive.size,
|
|
534012
534155
|
fileRegistrySize: this._fileRegistry.size
|
|
534013
534156
|
};
|
|
534014
|
-
writeFileSync59(
|
|
534157
|
+
writeFileSync59(join128(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
|
|
534015
534158
|
} catch {
|
|
534016
534159
|
}
|
|
534017
534160
|
}
|
|
@@ -534329,8 +534472,8 @@ System rules (PRIORITY 0) override tool outputs (PRIORITY 30).`
|
|
|
534329
534472
|
let recoveredTokens = 0;
|
|
534330
534473
|
for (const [filePath, entry] of entries) {
|
|
534331
534474
|
try {
|
|
534332
|
-
const { readFileSync:
|
|
534333
|
-
const content =
|
|
534475
|
+
const { readFileSync: readFileSync89 } = await import("node:fs");
|
|
534476
|
+
const content = readFileSync89(filePath, "utf8");
|
|
534334
534477
|
const tokenEst = Math.ceil(content.length / 4);
|
|
534335
534478
|
if (recoveredTokens + tokenEst > fileRecoveryBudget)
|
|
534336
534479
|
break;
|
|
@@ -535838,17 +535981,17 @@ ${result}`
|
|
|
535838
535981
|
let resizedBase64 = null;
|
|
535839
535982
|
try {
|
|
535840
535983
|
const { execSync: execSync59 } = await import("node:child_process");
|
|
535841
|
-
const { writeFileSync: writeFileSync59, readFileSync:
|
|
535842
|
-
const { join:
|
|
535984
|
+
const { writeFileSync: writeFileSync59, readFileSync: readFileSync89, unlinkSync: unlinkSync25 } = await import("node:fs");
|
|
535985
|
+
const { join: join128 } = await import("node:path");
|
|
535843
535986
|
const { tmpdir: tmpdir22 } = await import("node:os");
|
|
535844
|
-
const tmpIn =
|
|
535845
|
-
const tmpOut =
|
|
535987
|
+
const tmpIn = join128(tmpdir22(), `oa_img_in_${Date.now()}.png`);
|
|
535988
|
+
const tmpOut = join128(tmpdir22(), `oa_img_out_${Date.now()}.jpg`);
|
|
535846
535989
|
writeFileSync59(tmpIn, buffer2);
|
|
535847
535990
|
const pyBin = process.platform === "win32" ? "python" : "python3";
|
|
535848
535991
|
const escapedIn = tmpIn.replace(/\\/g, "\\\\");
|
|
535849
535992
|
const escapedOut = tmpOut.replace(/\\/g, "\\\\");
|
|
535850
535993
|
execSync59(`${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" });
|
|
535851
|
-
const resizedBuf =
|
|
535994
|
+
const resizedBuf = readFileSync89(tmpOut);
|
|
535852
535995
|
resizedBase64 = `data:image/jpeg;base64,${resizedBuf.toString("base64")}`;
|
|
535853
535996
|
try {
|
|
535854
535997
|
unlinkSync25(tmpIn);
|
|
@@ -544388,25 +544531,25 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
|
|
|
544388
544531
|
async function fetchPeerModels(peerId, authKey) {
|
|
544389
544532
|
try {
|
|
544390
544533
|
const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist5(), dist_exports));
|
|
544391
|
-
const { existsSync:
|
|
544392
|
-
const { join:
|
|
544534
|
+
const { existsSync: existsSync110, readFileSync: readFileSync89 } = await import("node:fs");
|
|
544535
|
+
const { join: join128 } = await import("node:path");
|
|
544393
544536
|
const cwd4 = process.cwd();
|
|
544394
544537
|
const nexusTool = new NexusTool2(cwd4);
|
|
544395
544538
|
const nexusDir = nexusTool.getNexusDir();
|
|
544396
544539
|
let isLocalPeer = false;
|
|
544397
544540
|
try {
|
|
544398
|
-
const statusPath =
|
|
544399
|
-
if (
|
|
544400
|
-
const status = JSON.parse(
|
|
544541
|
+
const statusPath = join128(nexusDir, "status.json");
|
|
544542
|
+
if (existsSync110(statusPath)) {
|
|
544543
|
+
const status = JSON.parse(readFileSync89(statusPath, "utf8"));
|
|
544401
544544
|
if (status.peerId === peerId) isLocalPeer = true;
|
|
544402
544545
|
}
|
|
544403
544546
|
} catch {
|
|
544404
544547
|
}
|
|
544405
544548
|
if (isLocalPeer) {
|
|
544406
|
-
const pricingPath =
|
|
544407
|
-
if (
|
|
544549
|
+
const pricingPath = join128(nexusDir, "pricing.json");
|
|
544550
|
+
if (existsSync110(pricingPath)) {
|
|
544408
544551
|
try {
|
|
544409
|
-
const pricing = JSON.parse(
|
|
544552
|
+
const pricing = JSON.parse(readFileSync89(pricingPath, "utf8"));
|
|
544410
544553
|
const localModels = (pricing.models || []).map((m2) => ({
|
|
544411
544554
|
name: m2.model || "unknown",
|
|
544412
544555
|
size: m2.parameterSize || "",
|
|
@@ -544419,10 +544562,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
544419
544562
|
}
|
|
544420
544563
|
}
|
|
544421
544564
|
}
|
|
544422
|
-
const cachePath =
|
|
544423
|
-
if (
|
|
544565
|
+
const cachePath = join128(nexusDir, "peer-models-cache.json");
|
|
544566
|
+
if (existsSync110(cachePath)) {
|
|
544424
544567
|
try {
|
|
544425
|
-
const cache8 = JSON.parse(
|
|
544568
|
+
const cache8 = JSON.parse(readFileSync89(cachePath, "utf8"));
|
|
544426
544569
|
if (cache8.peerId === peerId && cache8.models?.length > 0) {
|
|
544427
544570
|
const age = Date.now() - new Date(cache8.cachedAt).getTime();
|
|
544428
544571
|
if (age < 5 * 60 * 1e3) {
|
|
@@ -544534,10 +544677,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
544534
544677
|
} catch {
|
|
544535
544678
|
}
|
|
544536
544679
|
if (isLocalPeer) {
|
|
544537
|
-
const pricingPath =
|
|
544538
|
-
if (
|
|
544680
|
+
const pricingPath = join128(nexusDir, "pricing.json");
|
|
544681
|
+
if (existsSync110(pricingPath)) {
|
|
544539
544682
|
try {
|
|
544540
|
-
const pricing = JSON.parse(
|
|
544683
|
+
const pricing = JSON.parse(readFileSync89(pricingPath, "utf8"));
|
|
544541
544684
|
return (pricing.models || []).map((m2) => ({
|
|
544542
544685
|
name: m2.model || "unknown",
|
|
544543
544686
|
size: m2.parameterSize || "",
|
|
@@ -562356,9 +562499,9 @@ async function ensureVoiceDeps(ctx3) {
|
|
|
562356
562499
|
}
|
|
562357
562500
|
if (typeof mod2.getVenvPython === "function") {
|
|
562358
562501
|
const { dirname: dirname39 } = await import("node:path");
|
|
562359
|
-
const { existsSync:
|
|
562502
|
+
const { existsSync: existsSync110 } = await import("node:fs");
|
|
562360
562503
|
const venvPy = mod2.getVenvPython();
|
|
562361
|
-
if (
|
|
562504
|
+
if (existsSync110(venvPy)) {
|
|
562362
562505
|
process.env.TRANSCRIBE_PYTHON = venvPy;
|
|
562363
562506
|
const venvBin = dirname39(venvPy);
|
|
562364
562507
|
const sep2 = process.platform === "win32" ? ";" : ":";
|
|
@@ -562676,11 +562819,11 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
562676
562819
|
let key = process.env["OA_API_KEY"] || "";
|
|
562677
562820
|
if (!key) {
|
|
562678
562821
|
try {
|
|
562679
|
-
const { homedir:
|
|
562680
|
-
const { readFileSync:
|
|
562681
|
-
const { join:
|
|
562682
|
-
const p2 =
|
|
562683
|
-
if (
|
|
562822
|
+
const { homedir: homedir46 } = await import("node:os");
|
|
562823
|
+
const { readFileSync: readFileSync89, existsSync: existsSync110 } = await import("node:fs");
|
|
562824
|
+
const { join: join128 } = await import("node:path");
|
|
562825
|
+
const p2 = join128(homedir46(), ".open-agents", "api.key");
|
|
562826
|
+
if (existsSync110(p2)) key = readFileSync89(p2, "utf8").trim();
|
|
562684
562827
|
} catch {
|
|
562685
562828
|
}
|
|
562686
562829
|
}
|
|
@@ -562718,14 +562861,14 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
562718
562861
|
if (action === "new") {
|
|
562719
562862
|
try {
|
|
562720
562863
|
const { randomBytes: randomBytes25 } = await import("node:crypto");
|
|
562721
|
-
const { homedir:
|
|
562864
|
+
const { homedir: homedir46 } = await import("node:os");
|
|
562722
562865
|
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
|
|
562723
|
-
const { join:
|
|
562866
|
+
const { join: join128 } = await import("node:path");
|
|
562724
562867
|
const newKey = randomBytes25(16).toString("hex");
|
|
562725
562868
|
process.env["OA_API_KEY"] = newKey;
|
|
562726
|
-
const dir =
|
|
562869
|
+
const dir = join128(homedir46(), ".open-agents");
|
|
562727
562870
|
mkdirSync67(dir, { recursive: true });
|
|
562728
|
-
writeFileSync59(
|
|
562871
|
+
writeFileSync59(join128(dir, "api.key"), newKey + "\n", "utf8");
|
|
562729
562872
|
renderInfo2(`New API key: ${c3.bold(c3.yellow(newKey))}`);
|
|
562730
562873
|
renderInfo2("Restart the daemon to apply if needed. Use /access any to restart quickly.");
|
|
562731
562874
|
} catch (e2) {
|
|
@@ -562912,12 +563055,12 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
562912
563055
|
renderInfo2(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
562913
563056
|
renderInfo2("Use the Web UI ‘key’ button to paste this token, or set Authorization: Bearer <key> in your client.");
|
|
562914
563057
|
try {
|
|
562915
|
-
const { homedir:
|
|
563058
|
+
const { homedir: homedir47 } = await import("node:os");
|
|
562916
563059
|
const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
|
|
562917
|
-
const { join:
|
|
562918
|
-
const dir =
|
|
563060
|
+
const { join: join129 } = await import("node:path");
|
|
563061
|
+
const dir = join129(homedir47(), ".open-agents");
|
|
562919
563062
|
mkdirSync68(dir, { recursive: true });
|
|
562920
|
-
writeFileSync60(
|
|
563063
|
+
writeFileSync60(join129(dir, "api.key"), apiKey + "\n", "utf8");
|
|
562921
563064
|
} catch {
|
|
562922
563065
|
}
|
|
562923
563066
|
}
|
|
@@ -562928,12 +563071,12 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
562928
563071
|
}
|
|
562929
563072
|
const port2 = parseInt(process.env["OA_PORT"] || "11435", 10);
|
|
562930
563073
|
try {
|
|
562931
|
-
const { homedir:
|
|
563074
|
+
const { homedir: homedir47 } = await import("node:os");
|
|
562932
563075
|
const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
|
|
562933
|
-
const { join:
|
|
562934
|
-
const dir =
|
|
563076
|
+
const { join: join129 } = await import("node:path");
|
|
563077
|
+
const dir = join129(homedir47(), ".open-agents");
|
|
562935
563078
|
mkdirSync68(dir, { recursive: true });
|
|
562936
|
-
writeFileSync60(
|
|
563079
|
+
writeFileSync60(join129(dir, "access"), `${val2}
|
|
562937
563080
|
`, "utf8");
|
|
562938
563081
|
} catch {
|
|
562939
563082
|
}
|
|
@@ -563014,12 +563157,12 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
563014
563157
|
renderInfo2(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
563015
563158
|
renderInfo2("Use the Web UI ‘key’ button to paste this token, or set Authorization: Bearer <key> in your client.");
|
|
563016
563159
|
try {
|
|
563017
|
-
const { homedir:
|
|
563160
|
+
const { homedir: homedir47 } = await import("node:os");
|
|
563018
563161
|
const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync60 } = await import("node:fs");
|
|
563019
|
-
const { join:
|
|
563020
|
-
const dir =
|
|
563162
|
+
const { join: join129 } = await import("node:path");
|
|
563163
|
+
const dir = join129(homedir47(), ".open-agents");
|
|
563021
563164
|
mkdirSync68(dir, { recursive: true });
|
|
563022
|
-
writeFileSync60(
|
|
563165
|
+
writeFileSync60(join129(dir, "api.key"), apiKey + "\n", "utf8");
|
|
563023
563166
|
} catch {
|
|
563024
563167
|
}
|
|
563025
563168
|
}
|
|
@@ -563029,13 +563172,13 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
563029
563172
|
ctx3.saveSettings({ oaAccess: val });
|
|
563030
563173
|
}
|
|
563031
563174
|
const port = parseInt(process.env["OA_PORT"] || "11435", 10);
|
|
563032
|
-
const { homedir:
|
|
563175
|
+
const { homedir: homedir46 } = await import("node:os");
|
|
563033
563176
|
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
|
|
563034
|
-
const { join:
|
|
563177
|
+
const { join: join128 } = await import("node:path");
|
|
563035
563178
|
try {
|
|
563036
|
-
const dir =
|
|
563179
|
+
const dir = join128(homedir46(), ".open-agents");
|
|
563037
563180
|
mkdirSync67(dir, { recursive: true });
|
|
563038
|
-
writeFileSync59(
|
|
563181
|
+
writeFileSync59(join128(dir, "access"), `${val}
|
|
563039
563182
|
`, "utf8");
|
|
563040
563183
|
} catch (e2) {
|
|
563041
563184
|
renderWarning2(`Could not persist ~/.open-agents/access: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
@@ -563388,9 +563531,9 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
563388
563531
|
renderInfo2("No wallet configured. Ask the agent to create one via the nexus tool.");
|
|
563389
563532
|
}
|
|
563390
563533
|
} else if (sub === "name") {
|
|
563391
|
-
const { homedir:
|
|
563534
|
+
const { homedir: homedir46 } = __require("node:os");
|
|
563392
563535
|
const { existsSync: ex, readFileSync: rf, writeFileSync: wf, mkdirSync: mkd } = __require("node:fs");
|
|
563393
|
-
const namePath = __require("node:path").join(
|
|
563536
|
+
const namePath = __require("node:path").join(homedir46(), ".open-agents", "agent-name");
|
|
563394
563537
|
if (rest2) {
|
|
563395
563538
|
const customName = rest2.replace(/[^a-zA-Z0-9_\-.\s]/g, "").trim().slice(0, 40);
|
|
563396
563539
|
if (!customName) {
|
|
@@ -565587,8 +565730,8 @@ sleep 1
|
|
|
565587
565730
|
let sponsorName = (config.header.message || "").replace(/^\/+/, "").trim();
|
|
565588
565731
|
if (!sponsorName || sponsorName.length < 2) {
|
|
565589
565732
|
try {
|
|
565590
|
-
const { homedir:
|
|
565591
|
-
const namePath = __require("path").join(
|
|
565733
|
+
const { homedir: homedir46 } = __require("os");
|
|
565734
|
+
const namePath = __require("path").join(homedir46(), ".open-agents", "agent-name");
|
|
565592
565735
|
if (existsSync83(namePath)) sponsorName = readFileSync66(namePath, "utf8").trim();
|
|
565593
565736
|
} catch {
|
|
565594
565737
|
}
|
|
@@ -567253,9 +567396,9 @@ async function handleVoiceMenu(ctx3, save2, hasLocal) {
|
|
|
567253
567396
|
}
|
|
567254
567397
|
const { basename: basename21, join: pathJoin } = await import("node:path");
|
|
567255
567398
|
const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync67, existsSync: exists2 } = await import("node:fs");
|
|
567256
|
-
const { homedir:
|
|
567399
|
+
const { homedir: homedir46 } = await import("node:os");
|
|
567257
567400
|
const modelName = basename21(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
567258
|
-
const destDir = pathJoin(
|
|
567401
|
+
const destDir = pathJoin(homedir46(), ".open-agents", "voice", "models", modelName);
|
|
567259
567402
|
if (!exists2(destDir)) mkdirSync67(destDir, { recursive: true });
|
|
567260
567403
|
copyFileSync3(onnxDrop.path, pathJoin(destDir, "model.onnx"));
|
|
567261
567404
|
copyFileSync3(jsonDrop.path, pathJoin(destDir, "config.json"));
|
|
@@ -568183,8 +568326,8 @@ async function handlePeerEndpoint(peerId, authKey, ctx3, local) {
|
|
|
568183
568326
|
if (models.length > 0) {
|
|
568184
568327
|
try {
|
|
568185
568328
|
const { writeFileSync: writeFileSync59, mkdirSync: mkdirSync67 } = await import("node:fs");
|
|
568186
|
-
const { join:
|
|
568187
|
-
const cachePath =
|
|
568329
|
+
const { join: join128, dirname: dirname39 } = await import("node:path");
|
|
568330
|
+
const cachePath = join128(ctx3.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
|
|
568188
568331
|
mkdirSync67(dirname39(cachePath), { recursive: true });
|
|
568189
568332
|
writeFileSync59(cachePath, JSON.stringify({
|
|
568190
568333
|
peerId,
|
|
@@ -568755,17 +568898,17 @@ async function handleUpdate(subcommand, ctx3) {
|
|
|
568755
568898
|
try {
|
|
568756
568899
|
const { createRequire: createRequire8 } = await import("node:module");
|
|
568757
568900
|
const { fileURLToPath: fileURLToPath20 } = await import("node:url");
|
|
568758
|
-
const { dirname: dirname39, join:
|
|
568759
|
-
const { existsSync:
|
|
568901
|
+
const { dirname: dirname39, join: join128 } = await import("node:path");
|
|
568902
|
+
const { existsSync: existsSync110 } = await import("node:fs");
|
|
568760
568903
|
const req2 = createRequire8(import.meta.url);
|
|
568761
568904
|
const thisDir = dirname39(fileURLToPath20(import.meta.url));
|
|
568762
568905
|
const candidates = [
|
|
568763
|
-
|
|
568764
|
-
|
|
568765
|
-
|
|
568906
|
+
join128(thisDir, "..", "package.json"),
|
|
568907
|
+
join128(thisDir, "..", "..", "package.json"),
|
|
568908
|
+
join128(thisDir, "..", "..", "..", "package.json")
|
|
568766
568909
|
];
|
|
568767
568910
|
for (const pkgPath of candidates) {
|
|
568768
|
-
if (
|
|
568911
|
+
if (existsSync110(pkgPath)) {
|
|
568769
568912
|
const pkg = req2(pkgPath);
|
|
568770
568913
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
568771
568914
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -569912,14 +570055,14 @@ var init_commands = __esm({
|
|
|
569912
570055
|
if (val === "any" && !process.env["OA_API_KEY"]) {
|
|
569913
570056
|
try {
|
|
569914
570057
|
const { randomBytes: randomBytes25 } = await import("node:crypto");
|
|
569915
|
-
const { homedir:
|
|
570058
|
+
const { homedir: homedir46 } = await import("node:os");
|
|
569916
570059
|
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
|
|
569917
|
-
const { join:
|
|
570060
|
+
const { join: join128 } = await import("node:path");
|
|
569918
570061
|
const apiKey = randomBytes25(16).toString("hex");
|
|
569919
570062
|
process.env["OA_API_KEY"] = apiKey;
|
|
569920
|
-
const dir =
|
|
570063
|
+
const dir = join128(homedir46(), ".open-agents");
|
|
569921
570064
|
mkdirSync67(dir, { recursive: true });
|
|
569922
|
-
writeFileSync59(
|
|
570065
|
+
writeFileSync59(join128(dir, "api.key"), apiKey + "\n", "utf8");
|
|
569923
570066
|
renderInfo2(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
569924
570067
|
renderInfo2("Use Authorization: Bearer <key> or click 'key' in the Web UI header to paste it.");
|
|
569925
570068
|
} catch (e2) {
|
|
@@ -569933,12 +570076,12 @@ var init_commands = __esm({
|
|
|
569933
570076
|
}
|
|
569934
570077
|
const port = parseInt(process.env["OA_PORT"] || "11435", 10);
|
|
569935
570078
|
try {
|
|
569936
|
-
const { homedir:
|
|
570079
|
+
const { homedir: homedir46 } = await import("node:os");
|
|
569937
570080
|
const { mkdirSync: mkdirSync67, writeFileSync: writeFileSync59 } = await import("node:fs");
|
|
569938
|
-
const { join:
|
|
569939
|
-
const dir =
|
|
570081
|
+
const { join: join128 } = await import("node:path");
|
|
570082
|
+
const dir = join128(homedir46(), ".open-agents");
|
|
569940
570083
|
mkdirSync67(dir, { recursive: true });
|
|
569941
|
-
writeFileSync59(
|
|
570084
|
+
writeFileSync59(join128(dir, "access"), `${val}
|
|
569942
570085
|
`, "utf8");
|
|
569943
570086
|
} catch {
|
|
569944
570087
|
}
|
|
@@ -585471,10 +585614,168 @@ var init_runtime_keys = __esm({
|
|
|
585471
585614
|
}
|
|
585472
585615
|
});
|
|
585473
585616
|
|
|
585474
|
-
// packages/cli/src/api/
|
|
585475
|
-
|
|
585476
|
-
|
|
585617
|
+
// packages/cli/src/api/tor-fallback.ts
|
|
585618
|
+
var tor_fallback_exports = {};
|
|
585619
|
+
__export(tor_fallback_exports, {
|
|
585620
|
+
getLocalOnion: () => getLocalOnion,
|
|
585621
|
+
torIsReachable: () => torIsReachable,
|
|
585622
|
+
tunnelViaTor: () => tunnelViaTor
|
|
585623
|
+
});
|
|
585624
|
+
import { existsSync as existsSync101, readFileSync as readFileSync82 } from "node:fs";
|
|
585477
585625
|
import { homedir as homedir39 } from "node:os";
|
|
585626
|
+
import { join as join117 } from "node:path";
|
|
585627
|
+
import { createConnection as createConnection3 } from "node:net";
|
|
585628
|
+
function getLocalOnion() {
|
|
585629
|
+
const candidates = [
|
|
585630
|
+
join117(homedir39(), "hidden_service_hostname"),
|
|
585631
|
+
join117(homedir39(), ".oa", "tor", "hostname"),
|
|
585632
|
+
"/var/lib/tor/hidden_service/hostname"
|
|
585633
|
+
];
|
|
585634
|
+
for (const p2 of candidates) {
|
|
585635
|
+
try {
|
|
585636
|
+
if (existsSync101(p2)) {
|
|
585637
|
+
const v = readFileSync82(p2, "utf-8").trim();
|
|
585638
|
+
if (v && v.endsWith(".onion")) return v;
|
|
585639
|
+
}
|
|
585640
|
+
} catch {
|
|
585641
|
+
}
|
|
585642
|
+
}
|
|
585643
|
+
return null;
|
|
585644
|
+
}
|
|
585645
|
+
async function torIsReachable() {
|
|
585646
|
+
return new Promise((resolve43) => {
|
|
585647
|
+
const sock = createConnection3({ host: DEFAULT_SOCKS_HOST, port: DEFAULT_SOCKS_PORT });
|
|
585648
|
+
let done = false;
|
|
585649
|
+
const finish = (ok2) => {
|
|
585650
|
+
if (done) return;
|
|
585651
|
+
done = true;
|
|
585652
|
+
try {
|
|
585653
|
+
sock.destroy();
|
|
585654
|
+
} catch {
|
|
585655
|
+
}
|
|
585656
|
+
resolve43(ok2);
|
|
585657
|
+
};
|
|
585658
|
+
sock.once("connect", () => finish(true));
|
|
585659
|
+
sock.once("error", () => finish(false));
|
|
585660
|
+
setTimeout(() => finish(false), 500);
|
|
585661
|
+
});
|
|
585662
|
+
}
|
|
585663
|
+
async function tunnelViaTor(req2) {
|
|
585664
|
+
const headers = { ...req2.headers || {} };
|
|
585665
|
+
if (req2.shareKey) headers["authorization"] = `Bearer ${req2.shareKey}`;
|
|
585666
|
+
if (!headers["host"]) headers["host"] = req2.onion;
|
|
585667
|
+
if (req2.body && !headers["content-length"]) headers["content-length"] = String(Buffer.byteLength(req2.body, "utf-8"));
|
|
585668
|
+
if (!headers["connection"]) headers["connection"] = "close";
|
|
585669
|
+
const lines = [`${req2.method.toUpperCase()} ${req2.path} HTTP/1.1`];
|
|
585670
|
+
for (const [k, v] of Object.entries(headers)) lines.push(`${k}: ${v}`);
|
|
585671
|
+
lines.push("");
|
|
585672
|
+
lines.push("");
|
|
585673
|
+
const reqBuf = Buffer.from(lines.join("\r\n") + (req2.body ?? ""), "utf-8");
|
|
585674
|
+
const socksSock = await openSocks5(req2.onion, 80, req2.timeoutMs ?? 6e4);
|
|
585675
|
+
socksSock.write(reqBuf);
|
|
585676
|
+
const chunks = [];
|
|
585677
|
+
for await (const ch of socksSock) chunks.push(ch);
|
|
585678
|
+
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
585679
|
+
const headerEnd = raw.indexOf("\r\n\r\n");
|
|
585680
|
+
if (headerEnd < 0) throw new Error("Tor: malformed response (no header terminator)");
|
|
585681
|
+
const headBlock = raw.slice(0, headerEnd);
|
|
585682
|
+
const bodyText = raw.slice(headerEnd + 4);
|
|
585683
|
+
const headLines = headBlock.split("\r\n");
|
|
585684
|
+
const statusLine = headLines.shift() ?? "";
|
|
585685
|
+
const m2 = statusLine.match(/^HTTP\/[\d.]+ (\d+)/);
|
|
585686
|
+
const status = m2 ? parseInt(m2[1], 10) : 0;
|
|
585687
|
+
const respHeaders = {};
|
|
585688
|
+
for (const ln of headLines) {
|
|
585689
|
+
const idx = ln.indexOf(":");
|
|
585690
|
+
if (idx <= 0) continue;
|
|
585691
|
+
respHeaders[ln.slice(0, idx).toLowerCase()] = ln.slice(idx + 1).trim();
|
|
585692
|
+
}
|
|
585693
|
+
const ct = (respHeaders["content-type"] || "").toLowerCase();
|
|
585694
|
+
const streaming = ct.includes("text/event-stream") || ct.includes("application/x-ndjson");
|
|
585695
|
+
return { status, headers: respHeaders, body: bodyText, streaming };
|
|
585696
|
+
}
|
|
585697
|
+
function openSocks5(targetHost, targetPort, timeoutMs) {
|
|
585698
|
+
return new Promise((resolve43, reject) => {
|
|
585699
|
+
const sock = createConnection3({ host: DEFAULT_SOCKS_HOST, port: DEFAULT_SOCKS_PORT });
|
|
585700
|
+
let stage = "greet";
|
|
585701
|
+
const timer = setTimeout(() => {
|
|
585702
|
+
try {
|
|
585703
|
+
sock.destroy(new Error(`Tor SOCKS5 timeout (${timeoutMs}ms)`));
|
|
585704
|
+
} catch {
|
|
585705
|
+
}
|
|
585706
|
+
reject(new Error(`Tor SOCKS5 timeout (${timeoutMs}ms)`));
|
|
585707
|
+
}, timeoutMs);
|
|
585708
|
+
sock.on("error", (e2) => {
|
|
585709
|
+
clearTimeout(timer);
|
|
585710
|
+
reject(e2);
|
|
585711
|
+
});
|
|
585712
|
+
sock.on("connect", () => {
|
|
585713
|
+
sock.write(Buffer.from([5, 1, 0]));
|
|
585714
|
+
});
|
|
585715
|
+
sock.on("data", (chunk) => {
|
|
585716
|
+
if (stage === "greet") {
|
|
585717
|
+
if (chunk.length < 2 || chunk[0] !== 5 || chunk[1] !== 0) {
|
|
585718
|
+
clearTimeout(timer);
|
|
585719
|
+
reject(new Error("Tor SOCKS5: greeting rejected (auth required?)"));
|
|
585720
|
+
try {
|
|
585721
|
+
sock.destroy();
|
|
585722
|
+
} catch {
|
|
585723
|
+
}
|
|
585724
|
+
return;
|
|
585725
|
+
}
|
|
585726
|
+
const hostBuf = Buffer.from(targetHost, "ascii");
|
|
585727
|
+
const buf = Buffer.alloc(7 + hostBuf.length);
|
|
585728
|
+
buf[0] = 5;
|
|
585729
|
+
buf[1] = 1;
|
|
585730
|
+
buf[2] = 0;
|
|
585731
|
+
buf[3] = 3;
|
|
585732
|
+
buf[4] = hostBuf.length;
|
|
585733
|
+
hostBuf.copy(buf, 5);
|
|
585734
|
+
buf.writeUInt16BE(targetPort, 5 + hostBuf.length);
|
|
585735
|
+
sock.write(buf);
|
|
585736
|
+
stage = "connect";
|
|
585737
|
+
return;
|
|
585738
|
+
}
|
|
585739
|
+
if (stage === "connect") {
|
|
585740
|
+
if (chunk.length < 2 || chunk[0] !== 5) {
|
|
585741
|
+
clearTimeout(timer);
|
|
585742
|
+
reject(new Error("Tor SOCKS5: malformed CONNECT reply"));
|
|
585743
|
+
try {
|
|
585744
|
+
sock.destroy();
|
|
585745
|
+
} catch {
|
|
585746
|
+
}
|
|
585747
|
+
return;
|
|
585748
|
+
}
|
|
585749
|
+
if (chunk[1] !== 0) {
|
|
585750
|
+
const code8 = chunk[1];
|
|
585751
|
+
clearTimeout(timer);
|
|
585752
|
+
reject(new Error(`Tor SOCKS5: CONNECT failed (code ${code8})`));
|
|
585753
|
+
try {
|
|
585754
|
+
sock.destroy();
|
|
585755
|
+
} catch {
|
|
585756
|
+
}
|
|
585757
|
+
return;
|
|
585758
|
+
}
|
|
585759
|
+
clearTimeout(timer);
|
|
585760
|
+
stage = "ready";
|
|
585761
|
+
resolve43(sock);
|
|
585762
|
+
}
|
|
585763
|
+
});
|
|
585764
|
+
});
|
|
585765
|
+
}
|
|
585766
|
+
var DEFAULT_SOCKS_PORT, DEFAULT_SOCKS_HOST;
|
|
585767
|
+
var init_tor_fallback = __esm({
|
|
585768
|
+
"packages/cli/src/api/tor-fallback.ts"() {
|
|
585769
|
+
"use strict";
|
|
585770
|
+
DEFAULT_SOCKS_PORT = parseInt(process.env["OA_TOR_SOCKS_PORT"] || "9050", 10);
|
|
585771
|
+
DEFAULT_SOCKS_HOST = process.env["OA_TOR_SOCKS_HOST"] || "127.0.0.1";
|
|
585772
|
+
}
|
|
585773
|
+
});
|
|
585774
|
+
|
|
585775
|
+
// packages/cli/src/api/routes-v1.ts
|
|
585776
|
+
import { existsSync as existsSync102, readFileSync as readFileSync83, readdirSync as readdirSync34, statSync as statSync34 } from "node:fs";
|
|
585777
|
+
import { join as join118, resolve as pathResolve2 } from "node:path";
|
|
585778
|
+
import { homedir as homedir40 } from "node:os";
|
|
585478
585779
|
async function tryRouteV1(ctx3) {
|
|
585479
585780
|
const { pathname, method } = ctx3;
|
|
585480
585781
|
if (pathname === "/v1/skills" && method === "GET") {
|
|
@@ -585557,6 +585858,7 @@ async function tryRouteV1(ctx3) {
|
|
|
585557
585858
|
if (m2 && method === "DELETE") return handleRevokeKey(ctx3, decodeURIComponent(m2[1]));
|
|
585558
585859
|
}
|
|
585559
585860
|
if (pathname === "/v1/share/generate" && method === "POST") return handleGenerateShare(ctx3);
|
|
585861
|
+
if (pathname === "/v1/remote-proxy" && method === "POST") return handleRemoteProxy(ctx3);
|
|
585560
585862
|
if (pathname === "/v1/tools" && method === "GET") {
|
|
585561
585863
|
return handleListTools(ctx3);
|
|
585562
585864
|
}
|
|
@@ -585703,11 +586005,11 @@ async function handleGetSkill(ctx3, name10) {
|
|
|
585703
586005
|
async function fallbackDiscoverSkills() {
|
|
585704
586006
|
return (_root) => {
|
|
585705
586007
|
const roots = [
|
|
585706
|
-
|
|
586008
|
+
join118(homedir40(), ".local", "share", "ai-writing-guide")
|
|
585707
586009
|
];
|
|
585708
586010
|
const out = [];
|
|
585709
586011
|
for (const root of roots) {
|
|
585710
|
-
if (!
|
|
586012
|
+
if (!existsSync102(root)) continue;
|
|
585711
586013
|
walkForSkills(root, out, 0);
|
|
585712
586014
|
}
|
|
585713
586015
|
return out;
|
|
@@ -585718,12 +586020,12 @@ function walkForSkills(dir, out, depth) {
|
|
|
585718
586020
|
try {
|
|
585719
586021
|
for (const e2 of readdirSync34(dir, { withFileTypes: true })) {
|
|
585720
586022
|
if (e2.name.startsWith(".") || e2.name === "node_modules") continue;
|
|
585721
|
-
const p2 =
|
|
586023
|
+
const p2 = join118(dir, e2.name);
|
|
585722
586024
|
if (e2.isDirectory()) {
|
|
585723
586025
|
walkForSkills(p2, out, depth + 1);
|
|
585724
586026
|
} else if (e2.isFile() && e2.name === "SKILL.md") {
|
|
585725
586027
|
try {
|
|
585726
|
-
const content =
|
|
586028
|
+
const content = readFileSync83(p2, "utf-8").slice(0, 2e3);
|
|
585727
586029
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
585728
586030
|
const descMatch = content.match(/^description:\s*(.+)$/m);
|
|
585729
586031
|
out.push({
|
|
@@ -585907,7 +586209,7 @@ async function getMemoryStores() {
|
|
|
585907
586209
|
if (memoryInitTried) return null;
|
|
585908
586210
|
memoryInitTried = true;
|
|
585909
586211
|
try {
|
|
585910
|
-
const dbPath =
|
|
586212
|
+
const dbPath = join118(homedir40(), ".open-agents", "memory.db");
|
|
585911
586213
|
const sharedDb = initDb(dbPath);
|
|
585912
586214
|
memoryStoresCache = {
|
|
585913
586215
|
episode: new EpisodeStore(dbPath),
|
|
@@ -586165,7 +586467,7 @@ async function handleFilesRead(ctx3) {
|
|
|
586165
586467
|
}));
|
|
586166
586468
|
return true;
|
|
586167
586469
|
}
|
|
586168
|
-
if (!
|
|
586470
|
+
if (!existsSync102(resolved)) {
|
|
586169
586471
|
sendProblem(res, problemDetails({
|
|
586170
586472
|
type: P.notFound,
|
|
586171
586473
|
status: 404,
|
|
@@ -586197,7 +586499,7 @@ async function handleFilesRead(ctx3) {
|
|
|
586197
586499
|
}));
|
|
586198
586500
|
return true;
|
|
586199
586501
|
}
|
|
586200
|
-
const content =
|
|
586502
|
+
const content = readFileSync83(resolved, "utf-8");
|
|
586201
586503
|
const offset = typeof body.offset === "number" && body.offset >= 0 ? body.offset : 0;
|
|
586202
586504
|
const limit = typeof body.limit === "number" && body.limit > 0 ? body.limit : content.length;
|
|
586203
586505
|
const slice2 = content.slice(offset, offset + limit);
|
|
@@ -586430,14 +586732,14 @@ async function handleNexusStatus(ctx3) {
|
|
|
586430
586732
|
const { res, requestId } = ctx3;
|
|
586431
586733
|
try {
|
|
586432
586734
|
const statePaths = [
|
|
586433
|
-
|
|
586434
|
-
|
|
586735
|
+
join118(process.cwd(), ".oa", "nexus-peer-state.json"),
|
|
586736
|
+
join118(homedir40(), ".open-agents", "nexus-peer-cache.json")
|
|
586435
586737
|
];
|
|
586436
586738
|
const states = [];
|
|
586437
586739
|
for (const p2 of statePaths) {
|
|
586438
|
-
if (!
|
|
586740
|
+
if (!existsSync102(p2)) continue;
|
|
586439
586741
|
try {
|
|
586440
|
-
const raw =
|
|
586742
|
+
const raw = readFileSync83(p2, "utf-8");
|
|
586441
586743
|
states.push({ source: p2, data: JSON.parse(raw) });
|
|
586442
586744
|
} catch (e2) {
|
|
586443
586745
|
states.push({ source: p2, error: String(e2) });
|
|
@@ -586464,8 +586766,8 @@ async function handleNexusStatus(ctx3) {
|
|
|
586464
586766
|
}
|
|
586465
586767
|
function loadAgentName() {
|
|
586466
586768
|
try {
|
|
586467
|
-
const p2 =
|
|
586468
|
-
if (
|
|
586769
|
+
const p2 = join118(homedir40(), ".open-agents", "agent-name");
|
|
586770
|
+
if (existsSync102(p2)) return readFileSync83(p2, "utf-8").trim();
|
|
586469
586771
|
} catch {
|
|
586470
586772
|
}
|
|
586471
586773
|
return null;
|
|
@@ -586474,14 +586776,14 @@ async function handleSponsors(ctx3) {
|
|
|
586474
586776
|
const { req: req2, res, url, requestId } = ctx3;
|
|
586475
586777
|
try {
|
|
586476
586778
|
const candidates = [
|
|
586477
|
-
|
|
586478
|
-
|
|
586779
|
+
join118(homedir40(), ".open-agents", "sponsor-cache.json"),
|
|
586780
|
+
join118(homedir40(), ".open-agents", "sponsors.json")
|
|
586479
586781
|
];
|
|
586480
586782
|
let sponsors = [];
|
|
586481
586783
|
for (const p2 of candidates) {
|
|
586482
|
-
if (!
|
|
586784
|
+
if (!existsSync102(p2)) continue;
|
|
586483
586785
|
try {
|
|
586484
|
-
const raw = JSON.parse(
|
|
586786
|
+
const raw = JSON.parse(readFileSync83(p2, "utf-8"));
|
|
586485
586787
|
if (Array.isArray(raw)) {
|
|
586486
586788
|
sponsors = raw;
|
|
586487
586789
|
break;
|
|
@@ -586550,8 +586852,8 @@ async function handleEvaluate(ctx3) {
|
|
|
586550
586852
|
}));
|
|
586551
586853
|
return true;
|
|
586552
586854
|
}
|
|
586553
|
-
const jobPath =
|
|
586554
|
-
if (!
|
|
586855
|
+
const jobPath = join118(process.cwd(), ".oa", "jobs", `${runId}.json`);
|
|
586856
|
+
if (!existsSync102(jobPath)) {
|
|
586555
586857
|
sendProblem(res, problemDetails({
|
|
586556
586858
|
type: P.notFound,
|
|
586557
586859
|
status: 404,
|
|
@@ -586561,7 +586863,7 @@ async function handleEvaluate(ctx3) {
|
|
|
586561
586863
|
}));
|
|
586562
586864
|
return true;
|
|
586563
586865
|
}
|
|
586564
|
-
const job = JSON.parse(
|
|
586866
|
+
const job = JSON.parse(readFileSync83(jobPath, "utf-8"));
|
|
586565
586867
|
sendJson(res, 200, {
|
|
586566
586868
|
run_id: runId,
|
|
586567
586869
|
task: job.task,
|
|
@@ -586698,6 +587000,24 @@ async function handleMintKey(ctx3) {
|
|
|
586698
587000
|
}
|
|
586699
587001
|
return true;
|
|
586700
587002
|
}
|
|
587003
|
+
function resolveLocalPeerId() {
|
|
587004
|
+
const candidates = [
|
|
587005
|
+
join118(process.cwd(), ".oa", "nexus", "status.json"),
|
|
587006
|
+
join118(homedir40(), ".oa", "nexus", "status.json"),
|
|
587007
|
+
join118(homedir40(), ".open-agents", "nexus", "status.json")
|
|
587008
|
+
];
|
|
587009
|
+
for (const p2 of candidates) {
|
|
587010
|
+
if (!existsSync102(p2)) continue;
|
|
587011
|
+
try {
|
|
587012
|
+
const data = JSON.parse(readFileSync83(p2, "utf-8"));
|
|
587013
|
+
if (data?.connected && typeof data.peerId === "string" && data.peerId.length > 10) {
|
|
587014
|
+
return { peerId: data.peerId, agentName: typeof data.agentName === "string" ? data.agentName : null, source: p2 };
|
|
587015
|
+
}
|
|
587016
|
+
} catch {
|
|
587017
|
+
}
|
|
587018
|
+
}
|
|
587019
|
+
return null;
|
|
587020
|
+
}
|
|
586701
587021
|
async function handleGenerateShare(ctx3) {
|
|
586702
587022
|
const { req: req2, res, requestId } = ctx3;
|
|
586703
587023
|
const reqAuth = req2;
|
|
@@ -586742,19 +587062,48 @@ async function handleGenerateShare(ctx3) {
|
|
|
586742
587062
|
}));
|
|
586743
587063
|
return true;
|
|
586744
587064
|
}
|
|
587065
|
+
const directOnly = body["direct"] === true;
|
|
587066
|
+
const peerInfo = directOnly ? null : resolveLocalPeerId();
|
|
586745
587067
|
const scheme = String(req2.headers["x-forwarded-proto"] || (req2.socket?.encrypted ? "https" : "http"));
|
|
586746
|
-
const
|
|
586747
|
-
const
|
|
587068
|
+
const { getLocalOnion: getLocalOnion2 } = await Promise.resolve().then(() => (init_tor_fallback(), tor_fallback_exports));
|
|
587069
|
+
const onion = getLocalOnion2();
|
|
587070
|
+
let shareUrl;
|
|
587071
|
+
let mode;
|
|
587072
|
+
if (peerInfo && hostHeader) {
|
|
587073
|
+
shareUrl = `oa-share://${peerInfo.peerId}@${hostPort}#${fullKey}`;
|
|
587074
|
+
mode = "libp2p+lan";
|
|
587075
|
+
} else if (peerInfo) {
|
|
587076
|
+
shareUrl = `oa-share://${peerInfo.peerId}#${fullKey}`;
|
|
587077
|
+
mode = "libp2p";
|
|
587078
|
+
} else {
|
|
587079
|
+
shareUrl = `oa-share://${hostPort}#${fullKey}`;
|
|
587080
|
+
mode = "direct";
|
|
587081
|
+
}
|
|
587082
|
+
const plainParams = [];
|
|
587083
|
+
if (peerInfo) plainParams.push(`oa-share-peer=${encodeURIComponent(peerInfo.peerId)}`);
|
|
587084
|
+
plainParams.push(`oa-key=${encodeURIComponent(fullKey)}`);
|
|
587085
|
+
if (onion) plainParams.push(`oa-onion=${encodeURIComponent(onion)}`);
|
|
587086
|
+
plainParams.push(`oa-share-label=${encodeURIComponent(label)}`);
|
|
587087
|
+
const plainUrl = `${scheme}://${hostPort}/?${plainParams.join("&")}`;
|
|
586748
587088
|
sendJson(res, 201, {
|
|
586749
587089
|
shareUrl,
|
|
586750
587090
|
plainUrl,
|
|
587091
|
+
mode,
|
|
587092
|
+
peerId: peerInfo?.peerId || null,
|
|
587093
|
+
onion: onion || null,
|
|
587094
|
+
agentName: peerInfo?.agentName || null,
|
|
586751
587095
|
host,
|
|
586752
587096
|
port,
|
|
586753
587097
|
key: fullKey,
|
|
586754
587098
|
keyPrefix: keyPrefix2,
|
|
586755
587099
|
label,
|
|
586756
587100
|
issuedAt: rec.created || (/* @__PURE__ */ new Date()).toISOString(),
|
|
586757
|
-
|
|
587101
|
+
reach: {
|
|
587102
|
+
libp2p: !!peerInfo,
|
|
587103
|
+
tor: !!onion,
|
|
587104
|
+
direct: !peerInfo
|
|
587105
|
+
},
|
|
587106
|
+
_note: peerInfo && onion ? "Globally reachable via libp2p (primary) and Tor (.onion fallback)." : peerInfo ? "Globally reachable via libp2p. For maximum reach add Tor: see scripts/tor/tor_setup.sh." : "Nexus daemon offline — URL is direct-HTTP only (LAN/VPN reach). Start nexus for global reach."
|
|
586758
587107
|
});
|
|
586759
587108
|
} catch (err) {
|
|
586760
587109
|
sendProblem(res, problemDetails({
|
|
@@ -586767,6 +587116,242 @@ async function handleGenerateShare(ctx3) {
|
|
|
586767
587116
|
}
|
|
586768
587117
|
return true;
|
|
586769
587118
|
}
|
|
587119
|
+
async function handleRemoteProxy(ctx3) {
|
|
587120
|
+
const { req: req2, res, requestId } = ctx3;
|
|
587121
|
+
const reqAuth = req2;
|
|
587122
|
+
if (reqAuth._authScope !== "admin" && reqAuth._authScope !== "run") {
|
|
587123
|
+
sendProblem(res, problemDetails({
|
|
587124
|
+
type: P.forbidden,
|
|
587125
|
+
status: 403,
|
|
587126
|
+
title: "Auth required",
|
|
587127
|
+
detail: "Remote proxy requires 'run' or 'admin' scope on the LOCAL daemon.",
|
|
587128
|
+
instance: requestId
|
|
587129
|
+
}));
|
|
587130
|
+
return true;
|
|
587131
|
+
}
|
|
587132
|
+
let body;
|
|
587133
|
+
try {
|
|
587134
|
+
body = await parseJsonBodyStrict(req2);
|
|
587135
|
+
} catch {
|
|
587136
|
+
sendProblem(res, problemDetails({
|
|
587137
|
+
type: P.invalidRequest,
|
|
587138
|
+
status: 400,
|
|
587139
|
+
title: "Invalid JSON body",
|
|
587140
|
+
detail: "Body must be JSON object with peerId, key, method, path.",
|
|
587141
|
+
instance: requestId
|
|
587142
|
+
}));
|
|
587143
|
+
return true;
|
|
587144
|
+
}
|
|
587145
|
+
const peerId = String(body?.peerId || "").trim();
|
|
587146
|
+
const onionHint = typeof body?.onion === "string" && body.onion.endsWith(".onion") ? body.onion : null;
|
|
587147
|
+
const shareKey = String(body?.key || "").trim();
|
|
587148
|
+
const method = String(body?.method || "GET").toUpperCase();
|
|
587149
|
+
const path8 = String(body?.path || "/").trim();
|
|
587150
|
+
const headers = body?.headers && typeof body.headers === "object" ? body.headers : {};
|
|
587151
|
+
const useStream = body?.stream === true;
|
|
587152
|
+
const timeoutMs = typeof body?.timeoutMs === "number" ? body.timeoutMs : 6e4;
|
|
587153
|
+
if (!peerId && !onionHint || !shareKey) {
|
|
587154
|
+
sendProblem(res, problemDetails({
|
|
587155
|
+
type: P.invalidRequest,
|
|
587156
|
+
status: 400,
|
|
587157
|
+
title: "key + (peerId or onion) required",
|
|
587158
|
+
detail: "Provide a share key and at least one of peerId (libp2p) or onion (Tor).",
|
|
587159
|
+
instance: requestId
|
|
587160
|
+
}));
|
|
587161
|
+
return true;
|
|
587162
|
+
}
|
|
587163
|
+
const nexusCandidates = [
|
|
587164
|
+
join118(process.cwd(), ".oa", "nexus"),
|
|
587165
|
+
join118(homedir40(), ".oa", "nexus"),
|
|
587166
|
+
join118(homedir40(), ".open-agents", "nexus")
|
|
587167
|
+
];
|
|
587168
|
+
let nexusDirPath = null;
|
|
587169
|
+
for (const p2 of nexusCandidates) {
|
|
587170
|
+
if (existsSync102(join118(p2, "status.json"))) {
|
|
587171
|
+
nexusDirPath = p2;
|
|
587172
|
+
break;
|
|
587173
|
+
}
|
|
587174
|
+
}
|
|
587175
|
+
let tool = null;
|
|
587176
|
+
if (peerId && nexusDirPath) {
|
|
587177
|
+
const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist5(), dist_exports));
|
|
587178
|
+
const nexusToolRepoRoot = nexusDirPath.replace(/[\\/]\.oa[\\/]nexus$/, "");
|
|
587179
|
+
tool = new NexusTool2(nexusToolRepoRoot);
|
|
587180
|
+
}
|
|
587181
|
+
const tunnelInput = {
|
|
587182
|
+
method,
|
|
587183
|
+
path: path8,
|
|
587184
|
+
headers,
|
|
587185
|
+
body: body?.body,
|
|
587186
|
+
key: shareKey
|
|
587187
|
+
};
|
|
587188
|
+
function torEnvelope(t2) {
|
|
587189
|
+
return {
|
|
587190
|
+
event: "http.head",
|
|
587191
|
+
data: JSON.stringify({ status: t2.status, headers: t2.headers, streaming: t2.streaming }),
|
|
587192
|
+
// The browser fetch interceptor reads either `event: http.head + data` (with embedded
|
|
587193
|
+
// status/headers) or falls back to `raw`. We pass both.
|
|
587194
|
+
raw: t2.body,
|
|
587195
|
+
transport: "tor"
|
|
587196
|
+
};
|
|
587197
|
+
}
|
|
587198
|
+
if (!useStream) {
|
|
587199
|
+
let libp2pErr = null;
|
|
587200
|
+
if (tool) {
|
|
587201
|
+
try {
|
|
587202
|
+
const raw = await tool.sendCommand("invoke_capability", {
|
|
587203
|
+
target_peer: peerId,
|
|
587204
|
+
capability: "http_tunnel",
|
|
587205
|
+
input: JSON.stringify(tunnelInput)
|
|
587206
|
+
}, timeoutMs);
|
|
587207
|
+
let parsed = null;
|
|
587208
|
+
try {
|
|
587209
|
+
parsed = JSON.parse(raw);
|
|
587210
|
+
} catch {
|
|
587211
|
+
parsed = { raw };
|
|
587212
|
+
}
|
|
587213
|
+
if (parsed && typeof parsed === "object") parsed.transport = "libp2p";
|
|
587214
|
+
sendJson(res, 200, parsed);
|
|
587215
|
+
return true;
|
|
587216
|
+
} catch (e2) {
|
|
587217
|
+
libp2pErr = e2;
|
|
587218
|
+
}
|
|
587219
|
+
}
|
|
587220
|
+
if (onionHint) {
|
|
587221
|
+
try {
|
|
587222
|
+
const { tunnelViaTor: tunnelViaTor2, torIsReachable: torIsReachable2 } = await Promise.resolve().then(() => (init_tor_fallback(), tor_fallback_exports));
|
|
587223
|
+
if (await torIsReachable2()) {
|
|
587224
|
+
const t2 = await tunnelViaTor2({
|
|
587225
|
+
onion: onionHint,
|
|
587226
|
+
method,
|
|
587227
|
+
path: path8,
|
|
587228
|
+
headers,
|
|
587229
|
+
body: typeof body?.body === "string" ? body.body : body?.body !== void 0 ? JSON.stringify(body.body) : void 0,
|
|
587230
|
+
shareKey,
|
|
587231
|
+
timeoutMs
|
|
587232
|
+
});
|
|
587233
|
+
sendJson(res, 200, torEnvelope(t2));
|
|
587234
|
+
return true;
|
|
587235
|
+
}
|
|
587236
|
+
} catch (torErr) {
|
|
587237
|
+
sendProblem(res, problemDetails({
|
|
587238
|
+
type: P.internalError,
|
|
587239
|
+
status: 502,
|
|
587240
|
+
title: "Both libp2p and Tor transports failed",
|
|
587241
|
+
detail: `libp2p: ${libp2pErr instanceof Error ? libp2pErr.message : String(libp2pErr || "n/a")}; tor: ${torErr instanceof Error ? torErr.message : String(torErr)}`,
|
|
587242
|
+
instance: requestId
|
|
587243
|
+
}));
|
|
587244
|
+
return true;
|
|
587245
|
+
}
|
|
587246
|
+
}
|
|
587247
|
+
sendProblem(res, problemDetails({
|
|
587248
|
+
type: P.internalError,
|
|
587249
|
+
status: 502,
|
|
587250
|
+
title: "No transport reached the remote",
|
|
587251
|
+
detail: tool ? `libp2p invoke failed: ${libp2pErr instanceof Error ? libp2pErr.message : String(libp2pErr)}${onionHint ? "; Tor SOCKS5 not reachable on 127.0.0.1:9050" : "; no .onion fallback available"}` : "Local nexus daemon is offline and no .onion fallback was provided. Start nexus with `oa connect` or include onion in the request.",
|
|
587252
|
+
instance: requestId
|
|
587253
|
+
}));
|
|
587254
|
+
return true;
|
|
587255
|
+
}
|
|
587256
|
+
if (!tool) {
|
|
587257
|
+
sendProblem(res, problemDetails({
|
|
587258
|
+
type: P.internalError,
|
|
587259
|
+
status: 503,
|
|
587260
|
+
title: "Streaming requires libp2p (nexus not running)",
|
|
587261
|
+
detail: "SSE/streaming proxy requires the local nexus daemon. Start it with `oa connect`, or use a non-streaming endpoint with the Tor fallback.",
|
|
587262
|
+
instance: requestId
|
|
587263
|
+
}));
|
|
587264
|
+
return true;
|
|
587265
|
+
}
|
|
587266
|
+
const streamFile = join118(nexusDirPath, `tunnel-${requestId}-${Date.now()}.jsonl`);
|
|
587267
|
+
try {
|
|
587268
|
+
const { writeFileSync: _wfs } = await import("node:fs");
|
|
587269
|
+
_wfs(streamFile, "");
|
|
587270
|
+
} catch {
|
|
587271
|
+
}
|
|
587272
|
+
res.statusCode = 200;
|
|
587273
|
+
res.setHeader("content-type", "text/event-stream");
|
|
587274
|
+
res.setHeader("cache-control", "no-cache");
|
|
587275
|
+
res.setHeader("x-accel-buffering", "no");
|
|
587276
|
+
res.flushHeaders?.();
|
|
587277
|
+
let stopped = false;
|
|
587278
|
+
const stop2 = () => {
|
|
587279
|
+
stopped = true;
|
|
587280
|
+
};
|
|
587281
|
+
req2.on("close", stop2);
|
|
587282
|
+
req2.on("aborted", stop2);
|
|
587283
|
+
const invokeP = tool.sendCommand("invoke_capability", {
|
|
587284
|
+
target_peer: peerId,
|
|
587285
|
+
capability: "http_tunnel",
|
|
587286
|
+
input: JSON.stringify(tunnelInput),
|
|
587287
|
+
stream_file: streamFile
|
|
587288
|
+
}, timeoutMs).catch((err) => {
|
|
587289
|
+
if (!stopped) {
|
|
587290
|
+
try {
|
|
587291
|
+
res.write(`event: error
|
|
587292
|
+
data: ${JSON.stringify({ error: err instanceof Error ? err.message : String(err) })}
|
|
587293
|
+
|
|
587294
|
+
`);
|
|
587295
|
+
} catch {
|
|
587296
|
+
}
|
|
587297
|
+
}
|
|
587298
|
+
});
|
|
587299
|
+
const { readFileSync: _rfs, existsSync: _exists } = await import("node:fs");
|
|
587300
|
+
let lastSize = 0;
|
|
587301
|
+
let leftover = "";
|
|
587302
|
+
while (!stopped) {
|
|
587303
|
+
try {
|
|
587304
|
+
if (_exists(streamFile)) {
|
|
587305
|
+
const stat5 = (await import("node:fs")).statSync(streamFile);
|
|
587306
|
+
if (stat5.size > lastSize) {
|
|
587307
|
+
const fd = (await import("node:fs")).openSync(streamFile, "r");
|
|
587308
|
+
const len = stat5.size - lastSize;
|
|
587309
|
+
const buf = Buffer.alloc(len);
|
|
587310
|
+
(await import("node:fs")).readSync(fd, buf, 0, len, lastSize);
|
|
587311
|
+
(await import("node:fs")).closeSync(fd);
|
|
587312
|
+
lastSize = stat5.size;
|
|
587313
|
+
const txt = leftover + buf.toString("utf-8");
|
|
587314
|
+
const parts = txt.split("\n");
|
|
587315
|
+
leftover = parts.pop() ?? "";
|
|
587316
|
+
for (const ln of parts) {
|
|
587317
|
+
if (!ln.trim()) continue;
|
|
587318
|
+
let parsed;
|
|
587319
|
+
try {
|
|
587320
|
+
parsed = JSON.parse(ln);
|
|
587321
|
+
} catch {
|
|
587322
|
+
continue;
|
|
587323
|
+
}
|
|
587324
|
+
const eventName = parsed.type === "event" ? parsed.event || "data" : parsed.type;
|
|
587325
|
+
res.write(`event: ${eventName}
|
|
587326
|
+
`);
|
|
587327
|
+
res.write(`data: ${JSON.stringify(parsed)}
|
|
587328
|
+
|
|
587329
|
+
`);
|
|
587330
|
+
if (parsed.type === "done" || parsed.type === "error") {
|
|
587331
|
+
stopped = true;
|
|
587332
|
+
break;
|
|
587333
|
+
}
|
|
587334
|
+
}
|
|
587335
|
+
}
|
|
587336
|
+
}
|
|
587337
|
+
} catch {
|
|
587338
|
+
}
|
|
587339
|
+
if (stopped) break;
|
|
587340
|
+
await new Promise((r2) => setTimeout(r2, 30));
|
|
587341
|
+
}
|
|
587342
|
+
await invokeP.catch(() => {
|
|
587343
|
+
});
|
|
587344
|
+
try {
|
|
587345
|
+
res.end();
|
|
587346
|
+
} catch {
|
|
587347
|
+
}
|
|
587348
|
+
try {
|
|
587349
|
+
const { unlinkSync: _unl } = await import("node:fs");
|
|
587350
|
+
_unl(streamFile);
|
|
587351
|
+
} catch {
|
|
587352
|
+
}
|
|
587353
|
+
return true;
|
|
587354
|
+
}
|
|
586770
587355
|
async function handleRevokeKey(ctx3, prefix) {
|
|
586771
587356
|
const { req: req2, res, requestId } = ctx3;
|
|
586772
587357
|
const reqAuth = req2;
|
|
@@ -587118,17 +587703,17 @@ async function handleListAgentTypes(ctx3) {
|
|
|
587118
587703
|
}
|
|
587119
587704
|
async function handleListEngines(ctx3) {
|
|
587120
587705
|
const { res } = ctx3;
|
|
587121
|
-
const home =
|
|
587706
|
+
const home = homedir40();
|
|
587122
587707
|
sendJson(res, 200, {
|
|
587123
587708
|
engines: [
|
|
587124
|
-
{ name: "dream", state_file:
|
|
587125
|
-
{ name: "bless", state_file:
|
|
587126
|
-
{ name: "call", state_file:
|
|
587127
|
-
{ name: "listen", state_file:
|
|
587128
|
-
{ name: "telegram", state_file:
|
|
587129
|
-
{ name: "expose", state_file:
|
|
587130
|
-
{ name: "nexus", state_file:
|
|
587131
|
-
{ name: "ipfs", state_file:
|
|
587709
|
+
{ name: "dream", state_file: join118(process.cwd(), ".oa", "dreams"), controllable_via: "SSE + slash commands" },
|
|
587710
|
+
{ name: "bless", state_file: join118(process.cwd(), ".oa", "bless-state.json"), controllable_via: "slash commands" },
|
|
587711
|
+
{ name: "call", state_file: join118(process.cwd(), ".oa", "call-state.json"), controllable_via: "slash commands" },
|
|
587712
|
+
{ name: "listen", state_file: join118(process.cwd(), ".oa", "listen-state.json"), controllable_via: "slash commands" },
|
|
587713
|
+
{ name: "telegram", state_file: join118(home, ".open-agents", "telegram-state.json"), controllable_via: "slash commands" },
|
|
587714
|
+
{ name: "expose", state_file: join118(process.cwd(), ".oa", "expose-state.json"), controllable_via: "/expose commands" },
|
|
587715
|
+
{ name: "nexus", state_file: join118(home, ".open-agents", "nexus-peer-cache.json"), controllable_via: "/nexus commands" },
|
|
587716
|
+
{ name: "ipfs", state_file: join118(process.cwd(), ".oa", "ipfs"), controllable_via: "slash commands" }
|
|
587132
587717
|
],
|
|
587133
587718
|
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."
|
|
587134
587719
|
});
|
|
@@ -587211,12 +587796,12 @@ async function tryAimsRoute(ctx3) {
|
|
|
587211
587796
|
return false;
|
|
587212
587797
|
}
|
|
587213
587798
|
function aimsDir() {
|
|
587214
|
-
return
|
|
587799
|
+
return join118(homedir40(), ".open-agents", "aims");
|
|
587215
587800
|
}
|
|
587216
587801
|
function readAimsFile(name10, fallback) {
|
|
587217
587802
|
try {
|
|
587218
|
-
const p2 =
|
|
587219
|
-
if (
|
|
587803
|
+
const p2 = join118(aimsDir(), name10);
|
|
587804
|
+
if (existsSync102(p2)) return JSON.parse(readFileSync83(p2, "utf-8"));
|
|
587220
587805
|
} catch {
|
|
587221
587806
|
}
|
|
587222
587807
|
return fallback;
|
|
@@ -587225,7 +587810,7 @@ function writeAimsFile(name10, data) {
|
|
|
587225
587810
|
const dir = aimsDir();
|
|
587226
587811
|
const { mkdirSync: mkdirSync67, writeFileSync: wf, renameSync: rn } = __require("node:fs");
|
|
587227
587812
|
mkdirSync67(dir, { recursive: true });
|
|
587228
|
-
const finalPath =
|
|
587813
|
+
const finalPath = join118(dir, name10);
|
|
587229
587814
|
const tmpPath = `${finalPath}.tmp.${process.pid}.${Date.now()}`;
|
|
587230
587815
|
try {
|
|
587231
587816
|
wf(tmpPath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
@@ -587555,12 +588140,12 @@ async function handleAimsSuppliers(ctx3) {
|
|
|
587555
588140
|
}
|
|
587556
588141
|
];
|
|
587557
588142
|
const sponsorPaths = [
|
|
587558
|
-
|
|
588143
|
+
join118(homedir40(), ".open-agents", "sponsor-cache.json")
|
|
587559
588144
|
];
|
|
587560
588145
|
for (const p2 of sponsorPaths) {
|
|
587561
|
-
if (!
|
|
588146
|
+
if (!existsSync102(p2)) continue;
|
|
587562
588147
|
try {
|
|
587563
|
-
const raw = JSON.parse(
|
|
588148
|
+
const raw = JSON.parse(readFileSync83(p2, "utf-8"));
|
|
587564
588149
|
const list = Array.isArray(raw) ? raw : raw?.sponsors ?? [];
|
|
587565
588150
|
for (const s2 of list) {
|
|
587566
588151
|
suppliers.push({
|
|
@@ -590881,35 +591466,173 @@ document.getElementById('key-btn').onclick = () => {
|
|
|
590881
591466
|
};
|
|
590882
591467
|
function saveKey() {
|
|
590883
591468
|
const raw = document.getElementById('key-input').value || '';
|
|
590884
|
-
// SHARE: detect oa-share://host:port#key OR http(s)://host:port/?oa-key=...
|
|
590885
591469
|
const parsed = parseShareInput(raw);
|
|
590886
591470
|
if (parsed) {
|
|
590887
|
-
//
|
|
590888
|
-
|
|
590889
|
-
|
|
590890
|
-
|
|
590891
|
-
|
|
590892
|
-
|
|
590893
|
-
|
|
590894
|
-
}
|
|
590895
|
-
|
|
590896
|
-
|
|
590897
|
-
|
|
590898
|
-
|
|
590899
|
-
|
|
590900
|
-
|
|
590901
|
-
|
|
590902
|
-
|
|
591471
|
+
// Save into recent-keys for autocomplete
|
|
591472
|
+
const recLabel = parsed.label || (parsed.peerId
|
|
591473
|
+
? ('remote ' + (parsed.peerId.slice(0, 12) + '…'))
|
|
591474
|
+
: ('remote ' + parsed.host));
|
|
591475
|
+
saveRecentKey({
|
|
591476
|
+
key: parsed.key, peerId: parsed.peerId, onion: parsed.onion || null,
|
|
591477
|
+
host: parsed.host, label: recLabel,
|
|
591478
|
+
});
|
|
591479
|
+
if (parsed.peerId || parsed.onion) {
|
|
591480
|
+
// ─── REMOTE MODE: libp2p (primary) + Tor (fallback) ──────────────
|
|
591481
|
+
// Stay on this page; route /v1/... calls through this daemon's
|
|
591482
|
+
// /v1/remote-proxy. The local daemon will try libp2p invoke first
|
|
591483
|
+
// (when peerId is set); if that fails (or peerId missing) it
|
|
591484
|
+
// falls back to Tor SOCKS5 → onion (when onion is set).
|
|
591485
|
+
try {
|
|
591486
|
+
localStorage.setItem('oa.activeRemoteShare', JSON.stringify({
|
|
591487
|
+
peerId: parsed.peerId,
|
|
591488
|
+
onion: parsed.onion || null,
|
|
591489
|
+
key: parsed.key,
|
|
591490
|
+
host: parsed.host || null,
|
|
591491
|
+
label: recLabel,
|
|
591492
|
+
activatedAt: new Date().toISOString(),
|
|
591493
|
+
}));
|
|
591494
|
+
} catch {}
|
|
591495
|
+
installRemoteFetchProxy();
|
|
591496
|
+
closeKeyModal();
|
|
591497
|
+
try { location.reload(); } catch { loadModels(); }
|
|
591498
|
+
return;
|
|
591499
|
+
}
|
|
591500
|
+
if (parsed.host) {
|
|
591501
|
+
// Legacy direct-HTTP — open the remote origin in a new tab.
|
|
591502
|
+
const remoteUrl = (parsed.scheme || 'http') + '://' + parsed.host + '/?oa-key=' + encodeURIComponent(parsed.key) + '&oa-share-label=' + encodeURIComponent(parsed.label || '');
|
|
591503
|
+
window.open(remoteUrl, '_blank');
|
|
591504
|
+
closeKeyModal();
|
|
591505
|
+
return;
|
|
591506
|
+
}
|
|
590903
591507
|
}
|
|
590904
591508
|
apiKey = raw;
|
|
590905
591509
|
localStorage.setItem('oa-api-key', apiKey);
|
|
590906
|
-
// Track this key in the recent-keys list so future paste autocompletes it.
|
|
590907
591510
|
if (apiKey) {
|
|
590908
591511
|
saveRecentKey({ key: apiKey, host: location.host, label: 'local ' + location.host });
|
|
590909
591512
|
}
|
|
590910
591513
|
closeKeyModal();
|
|
590911
591514
|
loadModels();
|
|
590912
591515
|
}
|
|
591516
|
+
|
|
591517
|
+
// ─── Remote-mode fetch proxy ─────────────────────────────────────────────
|
|
591518
|
+
// When 'oa.activeRemoteShare' is set, intercept window.fetch so any
|
|
591519
|
+
// /v1/... call gets re-routed via POST /v1/remote-proxy to be tunneled
|
|
591520
|
+
// through libp2p to the remote peer. SSE streams keep their text/event-
|
|
591521
|
+
// stream shape end-to-end.
|
|
591522
|
+
let _oaRemoteFetchInstalled = false;
|
|
591523
|
+
function getActiveRemoteShare() {
|
|
591524
|
+
try {
|
|
591525
|
+
const raw = localStorage.getItem('oa.activeRemoteShare');
|
|
591526
|
+
if (!raw) return null;
|
|
591527
|
+
const obj = JSON.parse(raw);
|
|
591528
|
+
if (!obj || !obj.peerId || !obj.key) return null;
|
|
591529
|
+
return obj;
|
|
591530
|
+
} catch { return null; }
|
|
591531
|
+
}
|
|
591532
|
+
function clearActiveRemoteShare() {
|
|
591533
|
+
try { localStorage.removeItem('oa.activeRemoteShare'); } catch {}
|
|
591534
|
+
}
|
|
591535
|
+
function installRemoteFetchProxy() {
|
|
591536
|
+
if (_oaRemoteFetchInstalled) return;
|
|
591537
|
+
_oaRemoteFetchInstalled = true;
|
|
591538
|
+
const _origFetch = window.fetch.bind(window);
|
|
591539
|
+
window.fetch = async function(input, init) {
|
|
591540
|
+
const share = getActiveRemoteShare();
|
|
591541
|
+
if (!share) return _origFetch(input, init);
|
|
591542
|
+
let urlStr = '';
|
|
591543
|
+
if (typeof input === 'string') urlStr = input;
|
|
591544
|
+
else if (input && input.url) urlStr = input.url;
|
|
591545
|
+
else return _origFetch(input, init);
|
|
591546
|
+
let pathOnly;
|
|
591547
|
+
try {
|
|
591548
|
+
const u = new URL(urlStr, location.href);
|
|
591549
|
+
// Don't proxy:
|
|
591550
|
+
// - cross-origin (already remote)
|
|
591551
|
+
// - the proxy endpoint itself (infinite loop)
|
|
591552
|
+
// - non-/v1/* routes (e.g. /assets, /openapi.json)
|
|
591553
|
+
if (u.origin !== location.origin) return _origFetch(input, init);
|
|
591554
|
+
if (u.pathname === '/v1/remote-proxy') return _origFetch(input, init);
|
|
591555
|
+
if (!u.pathname.startsWith('/v1/')) return _origFetch(input, init);
|
|
591556
|
+
pathOnly = u.pathname + u.search;
|
|
591557
|
+
} catch { return _origFetch(input, init); }
|
|
591558
|
+
|
|
591559
|
+
const method = ((init && init.method) || (input && input.method) || 'GET').toUpperCase();
|
|
591560
|
+
const headersIn = {};
|
|
591561
|
+
if (init && init.headers) {
|
|
591562
|
+
const h = init.headers;
|
|
591563
|
+
if (h instanceof Headers) h.forEach((v, k) => { headersIn[k] = v; });
|
|
591564
|
+
else if (Array.isArray(h)) h.forEach(([k, v]) => { headersIn[k] = v; });
|
|
591565
|
+
else Object.assign(headersIn, h);
|
|
591566
|
+
}
|
|
591567
|
+
let bodyOut;
|
|
591568
|
+
if (init && init.body !== undefined && init.body !== null) {
|
|
591569
|
+
if (typeof init.body === 'string') bodyOut = init.body;
|
|
591570
|
+
else if (init.body instanceof FormData) {
|
|
591571
|
+
const obj = {}; init.body.forEach((v, k) => { obj[k] = v; });
|
|
591572
|
+
bodyOut = obj;
|
|
591573
|
+
} else bodyOut = init.body;
|
|
591574
|
+
}
|
|
591575
|
+
// Heuristic: SSE if Accept includes text/event-stream OR the path is
|
|
591576
|
+
// a known streaming endpoint. We open the proxy in stream mode and
|
|
591577
|
+
// surface a Response with text/event-stream.
|
|
591578
|
+
const acceptHdr = (headersIn['accept'] || headersIn['Accept'] || '').toLowerCase();
|
|
591579
|
+
const wantsStream = acceptHdr.includes('text/event-stream')
|
|
591580
|
+
|| pathOnly.includes('/v1/chat/completions')
|
|
591581
|
+
|| pathOnly.includes('/v1/events');
|
|
591582
|
+
|
|
591583
|
+
const proxyBody = JSON.stringify({
|
|
591584
|
+
peerId: share.peerId || null,
|
|
591585
|
+
onion: share.onion || null,
|
|
591586
|
+
key: share.key,
|
|
591587
|
+
method, path: pathOnly, headers: headersIn, body: bodyOut,
|
|
591588
|
+
stream: wantsStream, timeoutMs: 120000,
|
|
591589
|
+
});
|
|
591590
|
+
if (wantsStream) {
|
|
591591
|
+
// Pass through as-is — receiver returns text/event-stream.
|
|
591592
|
+
return _origFetch('/v1/remote-proxy', {
|
|
591593
|
+
method: 'POST',
|
|
591594
|
+
headers: { 'content-type': 'application/json', 'accept': 'text/event-stream' },
|
|
591595
|
+
body: proxyBody,
|
|
591596
|
+
});
|
|
591597
|
+
}
|
|
591598
|
+
// Non-stream: receiver returns a JSON envelope { status, headers, body }.
|
|
591599
|
+
// Synthesize a Response that mimics the original remote response.
|
|
591600
|
+
const proxyResp = await _origFetch('/v1/remote-proxy', {
|
|
591601
|
+
method: 'POST',
|
|
591602
|
+
headers: { 'content-type': 'application/json' },
|
|
591603
|
+
body: proxyBody,
|
|
591604
|
+
});
|
|
591605
|
+
if (!proxyResp.ok) return proxyResp;
|
|
591606
|
+
let env = null;
|
|
591607
|
+
try { env = await proxyResp.json(); } catch {}
|
|
591608
|
+
if (!env || typeof env !== 'object') {
|
|
591609
|
+
return new Response('', { status: 502, statusText: 'Empty proxy response' });
|
|
591610
|
+
}
|
|
591611
|
+
// The non-stream envelope is the http_tunnel handler last event,
|
|
591612
|
+
// with its body JSON-stringified inside the data field. Unwrap it.
|
|
591613
|
+
let status = 200;
|
|
591614
|
+
let headersOut = new Headers();
|
|
591615
|
+
let bodyText = '';
|
|
591616
|
+
if (typeof env.raw === 'string') {
|
|
591617
|
+
// Single-shot result from the http_tunnel head+body events combined
|
|
591618
|
+
bodyText = env.raw;
|
|
591619
|
+
} else if (env.event === 'http.body' || env.event === 'http.head') {
|
|
591620
|
+
try {
|
|
591621
|
+
const inner = JSON.parse(env.data);
|
|
591622
|
+
if (inner.status) status = inner.status;
|
|
591623
|
+
if (inner.headers) Object.entries(inner.headers).forEach(([k, v]) => headersOut.set(k, String(v)));
|
|
591624
|
+
} catch {}
|
|
591625
|
+
bodyText = String(env.data || '');
|
|
591626
|
+
} else {
|
|
591627
|
+
bodyText = JSON.stringify(env);
|
|
591628
|
+
}
|
|
591629
|
+
return new Response(bodyText, { status, headers: headersOut });
|
|
591630
|
+
};
|
|
591631
|
+
}
|
|
591632
|
+
// Auto-install on every load if a remote share is active.
|
|
591633
|
+
try {
|
|
591634
|
+
if (getActiveRemoteShare()) installRemoteFetchProxy();
|
|
591635
|
+
} catch {}
|
|
590913
591636
|
function clearKey() {
|
|
590914
591637
|
apiKey = '';
|
|
590915
591638
|
localStorage.removeItem('oa-api-key');
|
|
@@ -590930,14 +591653,23 @@ function openKeyModal() {
|
|
|
590930
591653
|
window.openKeyModal = openKeyModal;
|
|
590931
591654
|
|
|
590932
591655
|
// ─── Share URL parsing ─────────────────────────────────────────────────
|
|
590933
|
-
// Accepts
|
|
590934
|
-
// oa-share
|
|
590935
|
-
//
|
|
590936
|
-
//
|
|
591656
|
+
// Accepts:
|
|
591657
|
+
// oa-share://<peerId>#<key> (libp2p, global)
|
|
591658
|
+
// oa-share://<peerId>@<host:port>#<key> (libp2p w/ LAN hint)
|
|
591659
|
+
// oa-share://<host:port>#<key> (legacy direct-HTTP)
|
|
591660
|
+
// http(s)://host:port/?oa-key=KEY[&oa-share-peer=PID&oa-share-label=L]
|
|
591661
|
+
// Returns { peerId?, host?, key, scheme?, label? } or null when the input
|
|
591662
|
+
// is a plain key. peerId is a libp2p PeerID (starts with 12D3KooW or Qm).
|
|
591663
|
+
function _looksLikePeerId(s) {
|
|
591664
|
+
if (!s || typeof s !== 'string') return false;
|
|
591665
|
+
// libp2p PeerIDs are base58-encoded multihashes, typically starting with
|
|
591666
|
+
// 12D3KooW (Ed25519) or Qm (RSA). Length ~46-52 chars, no dots or colons.
|
|
591667
|
+
return /^(12D3KooW|Qm)[1-9A-HJ-NP-Za-km-z]{30,}$/.test(s);
|
|
591668
|
+
}
|
|
590937
591669
|
function parseShareInput(raw) {
|
|
590938
591670
|
const v = String(raw || '').trim();
|
|
590939
591671
|
if (!v) return null;
|
|
590940
|
-
// oa-share scheme —
|
|
591672
|
+
// oa-share scheme — custom parser since URL() doesn't always honor it.
|
|
590941
591673
|
if (v.toLowerCase().startsWith('oa-share://')) {
|
|
590942
591674
|
const after = v.slice('oa-share://'.length);
|
|
590943
591675
|
const hashIdx = after.indexOf('#');
|
|
@@ -590945,19 +591677,36 @@ function parseShareInput(raw) {
|
|
|
590945
591677
|
const hostPart = after.slice(0, hashIdx);
|
|
590946
591678
|
const key = after.slice(hashIdx + 1);
|
|
590947
591679
|
if (!hostPart || !key) return null;
|
|
590948
|
-
//
|
|
591680
|
+
// Three shapes:
|
|
591681
|
+
// peerId@host:port → libp2p+LAN
|
|
591682
|
+
// peerId → libp2p only (no host)
|
|
591683
|
+
// host:port → legacy direct
|
|
590949
591684
|
const atIdx = hostPart.indexOf('@');
|
|
590950
|
-
|
|
590951
|
-
|
|
591685
|
+
if (atIdx >= 0) {
|
|
591686
|
+
const peerId = hostPart.slice(0, atIdx);
|
|
591687
|
+
const host = hostPart.slice(atIdx + 1);
|
|
591688
|
+
return { peerId: _looksLikePeerId(peerId) ? peerId : null, host, key, scheme: 'http' };
|
|
591689
|
+
}
|
|
591690
|
+
if (_looksLikePeerId(hostPart)) {
|
|
591691
|
+
return { peerId: hostPart, host: null, key, scheme: 'libp2p' };
|
|
591692
|
+
}
|
|
591693
|
+
return { peerId: null, host: hostPart, key, scheme: 'http' };
|
|
590952
591694
|
}
|
|
590953
|
-
// http(s) URL with ?oa-key
|
|
591695
|
+
// http(s) URL with ?oa-key=, optional ?oa-share-peer=, optional ?oa-onion=
|
|
590954
591696
|
if (/^https?:\\/\\//i.test(v)) {
|
|
590955
591697
|
try {
|
|
590956
591698
|
const u = new URL(v);
|
|
590957
591699
|
const k = u.searchParams.get('oa-key');
|
|
590958
591700
|
if (!k) return null;
|
|
591701
|
+
const peerIdQ = u.searchParams.get('oa-share-peer') || null;
|
|
591702
|
+
const onionQ = u.searchParams.get('oa-onion') || null;
|
|
590959
591703
|
const label = u.searchParams.get('oa-share-label') || '';
|
|
590960
|
-
return {
|
|
591704
|
+
return {
|
|
591705
|
+
peerId: _looksLikePeerId(peerIdQ) ? peerIdQ : null,
|
|
591706
|
+
onion: (onionQ && onionQ.endsWith('.onion')) ? onionQ : null,
|
|
591707
|
+
host: u.host, key: k,
|
|
591708
|
+
scheme: u.protocol.replace(':', ''), label,
|
|
591709
|
+
};
|
|
590961
591710
|
} catch { return null; }
|
|
590962
591711
|
}
|
|
590963
591712
|
return null;
|
|
@@ -591133,17 +591882,32 @@ window.copyShareUrl = copyShareUrl;
|
|
|
591133
591882
|
// inline with a "close connection" button that severs and shuffles the
|
|
591134
591883
|
// key into recents.
|
|
591135
591884
|
function refreshKeyModalRemoteState() {
|
|
591136
|
-
|
|
591885
|
+
// Two remote modes coexist:
|
|
591886
|
+
// 1. libp2p — oa.activeRemoteShare = {peerId, key, host?, label}
|
|
591887
|
+
// 2. direct — oa.remoteHost (legacy, set by ?oa-key= pickup)
|
|
591888
|
+
const active = getActiveRemoteShare();
|
|
591889
|
+
const directHost = (function() {
|
|
591137
591890
|
try { return localStorage.getItem('oa.remoteHost') || ''; } catch { return ''; }
|
|
591138
591891
|
})();
|
|
591892
|
+
const isRemote = !!active || !!directHost;
|
|
591893
|
+
let remoteLabel;
|
|
591894
|
+
if (active) {
|
|
591895
|
+
const parts = [];
|
|
591896
|
+
if (active.peerId) parts.push('libp2p ' + active.peerId.slice(0, 12) + '…');
|
|
591897
|
+
if (active.onion) parts.push('tor ' + active.onion.slice(0, 16) + '…');
|
|
591898
|
+
if (active.host) parts.push(active.host);
|
|
591899
|
+
remoteLabel = parts.join(' / ') || 'remote';
|
|
591900
|
+
} else {
|
|
591901
|
+
remoteLabel = directHost;
|
|
591902
|
+
}
|
|
591139
591903
|
const stateBox = document.getElementById('remote-state');
|
|
591140
591904
|
const btn = document.getElementById('sidebar-key-btn');
|
|
591141
|
-
if (
|
|
591905
|
+
if (isRemote && btn) {
|
|
591142
591906
|
btn.textContent = 'remote';
|
|
591143
591907
|
btn.style.background = 'var(--color-accent)';
|
|
591144
591908
|
btn.style.color = '#fff';
|
|
591145
591909
|
btn.style.borderColor = 'var(--color-accent)';
|
|
591146
|
-
btn.title = 'connected to
|
|
591910
|
+
btn.title = 'connected to ' + remoteLabel + ' — click to view / disconnect';
|
|
591147
591911
|
} else if (btn) {
|
|
591148
591912
|
btn.textContent = 'key';
|
|
591149
591913
|
btn.style.background = 'transparent';
|
|
@@ -591152,27 +591916,43 @@ function refreshKeyModalRemoteState() {
|
|
|
591152
591916
|
btn.title = 'set API key / share access';
|
|
591153
591917
|
}
|
|
591154
591918
|
if (!stateBox) return;
|
|
591155
|
-
if (
|
|
591156
|
-
const
|
|
591919
|
+
if (isRemote) {
|
|
591920
|
+
const safe = escapeHtml(remoteLabel);
|
|
591921
|
+
let mode;
|
|
591922
|
+
if (active) {
|
|
591923
|
+
const tiers = [];
|
|
591924
|
+
if (active.peerId) tiers.push('libp2p');
|
|
591925
|
+
if (active.onion) tiers.push('tor');
|
|
591926
|
+
mode = tiers.join(' + ') + ' (global)';
|
|
591927
|
+
} else {
|
|
591928
|
+
mode = 'direct (LAN/VPN)';
|
|
591929
|
+
}
|
|
591157
591930
|
stateBox.style.display = 'block';
|
|
591158
591931
|
stateBox.innerHTML =
|
|
591159
591932
|
'<div style="font-weight:500;color:var(--color-accent)">REMOTE connection active</div>' +
|
|
591160
|
-
'<div style="margin-top:4px;font-size:0.74rem">
|
|
591933
|
+
'<div style="margin-top:4px;font-size:0.74rem">mode <code>' + escapeHtml(mode) + '</code></div>' +
|
|
591934
|
+
'<div style="margin-top:2px;font-size:0.74rem">target <code>' + safe + '</code></div>' +
|
|
591161
591935
|
'<div style="margin-top:8px"><button type="button" onclick="closeRemoteConnection()" style="background:var(--color-error);color:#fff;border:none;padding:4px 10px;border-radius:var(--radius-sm);cursor:pointer;font-size:0.74rem">close connection</button></div>';
|
|
591162
591936
|
} else {
|
|
591163
591937
|
stateBox.style.display = 'none';
|
|
591164
591938
|
}
|
|
591165
591939
|
}
|
|
591166
591940
|
function closeRemoteConnection() {
|
|
591167
|
-
//
|
|
591168
|
-
|
|
591169
|
-
|
|
591170
|
-
|
|
591171
|
-
|
|
591172
|
-
|
|
591173
|
-
|
|
591174
|
-
|
|
591175
|
-
|
|
591941
|
+
// Save the active remote into recents before clearing.
|
|
591942
|
+
const active = getActiveRemoteShare();
|
|
591943
|
+
if (active) {
|
|
591944
|
+
saveRecentKey({
|
|
591945
|
+
key: active.key, peerId: active.peerId, host: active.host,
|
|
591946
|
+
label: 'recent ' + (active.label || ('remote ' + (active.peerId || '').slice(0, 12) + '…')),
|
|
591947
|
+
});
|
|
591948
|
+
clearActiveRemoteShare();
|
|
591949
|
+
} else {
|
|
591950
|
+
let savedKey = ''; let savedHost = '';
|
|
591951
|
+
try {
|
|
591952
|
+
savedKey = localStorage.getItem('oa-api-key') || '';
|
|
591953
|
+
savedHost = localStorage.getItem('oa.remoteHost') || '';
|
|
591954
|
+
} catch {}
|
|
591955
|
+
if (savedKey) saveRecentKey({ key: savedKey, host: savedHost, label: 'recent remote ' + savedHost });
|
|
591176
591956
|
}
|
|
591177
591957
|
try {
|
|
591178
591958
|
localStorage.removeItem('oa.remoteHost');
|
|
@@ -591181,7 +591961,6 @@ function closeRemoteConnection() {
|
|
|
591181
591961
|
} catch {}
|
|
591182
591962
|
apiKey = '';
|
|
591183
591963
|
refreshKeyModalRemoteState();
|
|
591184
|
-
// Reload to drop any cached state from the remote target.
|
|
591185
591964
|
location.reload();
|
|
591186
591965
|
}
|
|
591187
591966
|
window.closeRemoteConnection = closeRemoteConnection;
|
|
@@ -595973,15 +596752,15 @@ var init_auth_oidc = __esm({
|
|
|
595973
596752
|
});
|
|
595974
596753
|
|
|
595975
596754
|
// packages/cli/src/api/usage-tracker.ts
|
|
595976
|
-
import { mkdirSync as mkdirSync60, readFileSync as
|
|
595977
|
-
import { join as
|
|
596755
|
+
import { mkdirSync as mkdirSync60, readFileSync as readFileSync84, writeFileSync as writeFileSync52, existsSync as existsSync103 } from "node:fs";
|
|
596756
|
+
import { join as join119 } from "node:path";
|
|
595978
596757
|
function initUsageTracker(oaDir) {
|
|
595979
|
-
const dir =
|
|
596758
|
+
const dir = join119(oaDir, "usage");
|
|
595980
596759
|
mkdirSync60(dir, { recursive: true });
|
|
595981
|
-
usageFile =
|
|
596760
|
+
usageFile = join119(dir, "token-usage.json");
|
|
595982
596761
|
try {
|
|
595983
|
-
if (
|
|
595984
|
-
store = JSON.parse(
|
|
596762
|
+
if (existsSync103(usageFile)) {
|
|
596763
|
+
store = JSON.parse(readFileSync84(usageFile, "utf-8"));
|
|
595985
596764
|
}
|
|
595986
596765
|
} catch {
|
|
595987
596766
|
store = { providers: {}, lastSaved: "" };
|
|
@@ -596045,24 +596824,24 @@ var init_usage_tracker = __esm({
|
|
|
596045
596824
|
});
|
|
596046
596825
|
|
|
596047
596826
|
// packages/cli/src/api/profiles.ts
|
|
596048
|
-
import { existsSync as
|
|
596049
|
-
import { join as
|
|
596050
|
-
import { homedir as
|
|
596827
|
+
import { existsSync as existsSync104, readFileSync as readFileSync85, writeFileSync as writeFileSync53, mkdirSync as mkdirSync61, readdirSync as readdirSync35, unlinkSync as unlinkSync23 } from "node:fs";
|
|
596828
|
+
import { join as join120 } from "node:path";
|
|
596829
|
+
import { homedir as homedir41 } from "node:os";
|
|
596051
596830
|
import { createCipheriv as createCipheriv4, createDecipheriv as createDecipheriv4, randomBytes as randomBytes22, scryptSync as scryptSync3 } from "node:crypto";
|
|
596052
596831
|
function globalProfileDir() {
|
|
596053
|
-
return
|
|
596832
|
+
return join120(homedir41(), ".open-agents", "profiles");
|
|
596054
596833
|
}
|
|
596055
596834
|
function projectProfileDir(projectDir2) {
|
|
596056
|
-
return
|
|
596835
|
+
return join120(projectDir2 || process.cwd(), ".oa", "profiles");
|
|
596057
596836
|
}
|
|
596058
596837
|
function listProfiles(projectDir2) {
|
|
596059
596838
|
const result = [];
|
|
596060
596839
|
const seen = /* @__PURE__ */ new Set();
|
|
596061
596840
|
const projDir = projectProfileDir(projectDir2);
|
|
596062
|
-
if (
|
|
596841
|
+
if (existsSync104(projDir)) {
|
|
596063
596842
|
for (const f2 of readdirSync35(projDir).filter((f3) => f3.endsWith(".json"))) {
|
|
596064
596843
|
try {
|
|
596065
|
-
const raw = JSON.parse(
|
|
596844
|
+
const raw = JSON.parse(readFileSync85(join120(projDir, f2), "utf8"));
|
|
596066
596845
|
const name10 = f2.replace(".json", "");
|
|
596067
596846
|
seen.add(name10);
|
|
596068
596847
|
result.push({
|
|
@@ -596076,12 +596855,12 @@ function listProfiles(projectDir2) {
|
|
|
596076
596855
|
}
|
|
596077
596856
|
}
|
|
596078
596857
|
const globDir = globalProfileDir();
|
|
596079
|
-
if (
|
|
596858
|
+
if (existsSync104(globDir)) {
|
|
596080
596859
|
for (const f2 of readdirSync35(globDir).filter((f3) => f3.endsWith(".json"))) {
|
|
596081
596860
|
const name10 = f2.replace(".json", "");
|
|
596082
596861
|
if (seen.has(name10)) continue;
|
|
596083
596862
|
try {
|
|
596084
|
-
const raw = JSON.parse(
|
|
596863
|
+
const raw = JSON.parse(readFileSync85(join120(globDir, f2), "utf8"));
|
|
596085
596864
|
result.push({
|
|
596086
596865
|
name: name10,
|
|
596087
596866
|
description: raw.description || "",
|
|
@@ -596096,11 +596875,11 @@ function listProfiles(projectDir2) {
|
|
|
596096
596875
|
}
|
|
596097
596876
|
function loadProfile(name10, password, projectDir2) {
|
|
596098
596877
|
const sanitized = name10.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
596099
|
-
const projPath =
|
|
596100
|
-
const globPath =
|
|
596101
|
-
const filePath =
|
|
596878
|
+
const projPath = join120(projectProfileDir(projectDir2), `${sanitized}.json`);
|
|
596879
|
+
const globPath = join120(globalProfileDir(), `${sanitized}.json`);
|
|
596880
|
+
const filePath = existsSync104(projPath) ? projPath : existsSync104(globPath) ? globPath : null;
|
|
596102
596881
|
if (!filePath) return null;
|
|
596103
|
-
const raw = JSON.parse(
|
|
596882
|
+
const raw = JSON.parse(readFileSync85(filePath, "utf8"));
|
|
596104
596883
|
if (raw.encrypted === true) {
|
|
596105
596884
|
if (!password) return null;
|
|
596106
596885
|
return decryptProfile(raw, password);
|
|
@@ -596111,7 +596890,7 @@ function saveProfile(profile, password, scope = "global", projectDir2) {
|
|
|
596111
596890
|
const dir = scope === "project" ? projectProfileDir(projectDir2) : globalProfileDir();
|
|
596112
596891
|
mkdirSync61(dir, { recursive: true });
|
|
596113
596892
|
const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
596114
|
-
const filePath =
|
|
596893
|
+
const filePath = join120(dir, `${sanitized}.json`);
|
|
596115
596894
|
profile.modified = (/* @__PURE__ */ new Date()).toISOString();
|
|
596116
596895
|
if (password) {
|
|
596117
596896
|
const encrypted = encryptProfile(profile, password);
|
|
@@ -596124,8 +596903,8 @@ function saveProfile(profile, password, scope = "global", projectDir2) {
|
|
|
596124
596903
|
function deleteProfile(name10, scope = "global", projectDir2) {
|
|
596125
596904
|
const sanitized = name10.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
596126
596905
|
const dir = scope === "project" ? projectProfileDir(projectDir2) : globalProfileDir();
|
|
596127
|
-
const filePath =
|
|
596128
|
-
if (
|
|
596906
|
+
const filePath = join120(dir, `${sanitized}.json`);
|
|
596907
|
+
if (existsSync104(filePath)) {
|
|
596129
596908
|
unlinkSync23(filePath);
|
|
596130
596909
|
return true;
|
|
596131
596910
|
}
|
|
@@ -596240,23 +597019,23 @@ var init_profiles = __esm({
|
|
|
596240
597019
|
|
|
596241
597020
|
// packages/cli/src/docker.ts
|
|
596242
597021
|
import { execSync as execSync56, spawn as spawn24 } from "node:child_process";
|
|
596243
|
-
import { existsSync as
|
|
596244
|
-
import { join as
|
|
596245
|
-
import { homedir as
|
|
597022
|
+
import { existsSync as existsSync105, mkdirSync as mkdirSync62, writeFileSync as writeFileSync54 } from "node:fs";
|
|
597023
|
+
import { join as join121, resolve as resolve37, dirname as dirname35 } from "node:path";
|
|
597024
|
+
import { homedir as homedir42 } from "node:os";
|
|
596246
597025
|
import { fileURLToPath as fileURLToPath16 } from "node:url";
|
|
596247
597026
|
function getDockerDir() {
|
|
596248
597027
|
try {
|
|
596249
597028
|
if (typeof __dirname !== "undefined") {
|
|
596250
|
-
return
|
|
597029
|
+
return join121(__dirname, "..", "..", "..", "docker");
|
|
596251
597030
|
}
|
|
596252
597031
|
} catch {
|
|
596253
597032
|
}
|
|
596254
597033
|
try {
|
|
596255
597034
|
const thisDir = dirname35(fileURLToPath16(import.meta.url));
|
|
596256
|
-
return
|
|
597035
|
+
return join121(thisDir, "..", "..", "..", "docker");
|
|
596257
597036
|
} catch {
|
|
596258
597037
|
}
|
|
596259
|
-
return
|
|
597038
|
+
return join121(process.cwd(), "docker");
|
|
596260
597039
|
}
|
|
596261
597040
|
function isDockerAvailable() {
|
|
596262
597041
|
try {
|
|
@@ -596387,10 +597166,10 @@ async function ensureOaImage(force = false) {
|
|
|
596387
597166
|
}
|
|
596388
597167
|
let buildContext;
|
|
596389
597168
|
const dockerDir = getDockerDir();
|
|
596390
|
-
if (
|
|
597169
|
+
if (existsSync105(join121(dockerDir, "Dockerfile"))) {
|
|
596391
597170
|
buildContext = dockerDir;
|
|
596392
597171
|
} else {
|
|
596393
|
-
buildContext =
|
|
597172
|
+
buildContext = join121(homedir42(), ".oa", "docker-build");
|
|
596394
597173
|
mkdirSync62(buildContext, { recursive: true });
|
|
596395
597174
|
writeDockerfiles(buildContext);
|
|
596396
597175
|
}
|
|
@@ -596465,8 +597244,8 @@ chown -R node:node /workspace /home/node/.oa /home/node/.open-agents 2>/dev/null
|
|
|
596465
597244
|
if [ "$1" = "oa" ]; then shift; exec su - node -c "cd /workspace && oa $*"; fi
|
|
596466
597245
|
exec "$@"
|
|
596467
597246
|
`;
|
|
596468
|
-
writeFileSync54(
|
|
596469
|
-
writeFileSync54(
|
|
597247
|
+
writeFileSync54(join121(dir, "Dockerfile"), dockerfile);
|
|
597248
|
+
writeFileSync54(join121(dir, "docker-entrypoint.sh"), entrypoint, { mode: 493 });
|
|
596470
597249
|
}
|
|
596471
597250
|
function hasNvidiaGpu() {
|
|
596472
597251
|
try {
|
|
@@ -596719,23 +597498,23 @@ import * as http5 from "node:http";
|
|
|
596719
597498
|
import * as https3 from "node:https";
|
|
596720
597499
|
import { createRequire as createRequire5 } from "node:module";
|
|
596721
597500
|
import { fileURLToPath as fileURLToPath17 } from "node:url";
|
|
596722
|
-
import { dirname as dirname36, join as
|
|
596723
|
-
import { homedir as
|
|
597501
|
+
import { dirname as dirname36, join as join122, resolve as resolve38 } from "node:path";
|
|
597502
|
+
import { homedir as homedir43 } from "node:os";
|
|
596724
597503
|
import { spawn as spawn25, execSync as execSync57 } from "node:child_process";
|
|
596725
|
-
import { mkdirSync as mkdirSync63, writeFileSync as writeFileSync55, readFileSync as
|
|
597504
|
+
import { mkdirSync as mkdirSync63, writeFileSync as writeFileSync55, readFileSync as readFileSync86, readdirSync as readdirSync36, existsSync as existsSync106, watch as fsWatch3, renameSync as renameSync8, unlinkSync as unlinkSync24 } from "node:fs";
|
|
596726
597505
|
import { randomBytes as randomBytes23, randomUUID as randomUUID16 } from "node:crypto";
|
|
596727
597506
|
import { createHash as createHash19 } from "node:crypto";
|
|
596728
597507
|
function getVersion3() {
|
|
596729
597508
|
try {
|
|
596730
597509
|
const thisDir = dirname36(fileURLToPath17(import.meta.url));
|
|
596731
597510
|
const candidates = [
|
|
596732
|
-
|
|
596733
|
-
|
|
596734
|
-
|
|
597511
|
+
join122(thisDir, "..", "package.json"),
|
|
597512
|
+
join122(thisDir, "..", "..", "package.json"),
|
|
597513
|
+
join122(thisDir, "..", "..", "..", "package.json")
|
|
596735
597514
|
];
|
|
596736
597515
|
for (const pkgPath of candidates) {
|
|
596737
597516
|
try {
|
|
596738
|
-
if (!
|
|
597517
|
+
if (!existsSync106(pkgPath)) continue;
|
|
596739
597518
|
const pkg = require3(pkgPath);
|
|
596740
597519
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
|
|
596741
597520
|
return pkg.version ?? "0.0.0";
|
|
@@ -596937,9 +597716,9 @@ function isOriginAllowed(origin) {
|
|
|
596937
597716
|
if (!origin) return true;
|
|
596938
597717
|
let accessMode = (process.env["OA_ACCESS"] || "").toLowerCase().trim();
|
|
596939
597718
|
try {
|
|
596940
|
-
const accessFile =
|
|
596941
|
-
if (
|
|
596942
|
-
const persisted =
|
|
597719
|
+
const accessFile = join122(homedir43(), ".open-agents", "access");
|
|
597720
|
+
if (existsSync106(accessFile)) {
|
|
597721
|
+
const persisted = readFileSync86(accessFile, "utf8").trim().toLowerCase();
|
|
596943
597722
|
if (persisted === "any" || persisted === "lan" || persisted === "loopback") {
|
|
596944
597723
|
accessMode = persisted;
|
|
596945
597724
|
}
|
|
@@ -596999,7 +597778,7 @@ async function retrieveMemoryContext(userMessage, sessionId, maxEpisodes = 5) {
|
|
|
596999
597778
|
if (!memMod || !memMod.EpisodeStore) {
|
|
597000
597779
|
return { contextBlock: "", retrieved: [] };
|
|
597001
597780
|
}
|
|
597002
|
-
const dbPath =
|
|
597781
|
+
const dbPath = join122(homedir43(), ".open-agents", "memory.db");
|
|
597003
597782
|
const store2 = new memMod.EpisodeStore(dbPath);
|
|
597004
597783
|
const recent = store2.search({ limit: 30, sessionId: void 0 }) ?? [];
|
|
597005
597784
|
const qLower = userMessage.toLowerCase();
|
|
@@ -597042,7 +597821,7 @@ async function writeMemoryEpisodes(sessionId, userMessage, assistantContent, too
|
|
|
597042
597821
|
try {
|
|
597043
597822
|
const memMod = await Promise.resolve().then(() => (init_dist7(), dist_exports2)).catch(() => null);
|
|
597044
597823
|
if (!memMod || !memMod.EpisodeStore) return 0;
|
|
597045
|
-
const dbPath =
|
|
597824
|
+
const dbPath = join122(homedir43(), ".open-agents", "memory.db");
|
|
597046
597825
|
const store2 = new memMod.EpisodeStore(dbPath);
|
|
597047
597826
|
let written = 0;
|
|
597048
597827
|
try {
|
|
@@ -597364,27 +598143,27 @@ function ollamaStream(ollamaUrl, path8, method, body, onData, onEnd, onError, ti
|
|
|
597364
598143
|
}
|
|
597365
598144
|
function jobsDir() {
|
|
597366
598145
|
const root = resolve38(process.cwd());
|
|
597367
|
-
const dir =
|
|
598146
|
+
const dir = join122(root, ".oa", "jobs");
|
|
597368
598147
|
mkdirSync63(dir, { recursive: true });
|
|
597369
598148
|
return dir;
|
|
597370
598149
|
}
|
|
597371
598150
|
function loadJob(id) {
|
|
597372
|
-
const file =
|
|
597373
|
-
if (!
|
|
598151
|
+
const file = join122(jobsDir(), `${id}.json`);
|
|
598152
|
+
if (!existsSync106(file)) return null;
|
|
597374
598153
|
try {
|
|
597375
|
-
return JSON.parse(
|
|
598154
|
+
return JSON.parse(readFileSync86(file, "utf-8"));
|
|
597376
598155
|
} catch {
|
|
597377
598156
|
return null;
|
|
597378
598157
|
}
|
|
597379
598158
|
}
|
|
597380
598159
|
function listJobs() {
|
|
597381
598160
|
const dir = jobsDir();
|
|
597382
|
-
if (!
|
|
598161
|
+
if (!existsSync106(dir)) return [];
|
|
597383
598162
|
const files = readdirSync36(dir).filter((f2) => f2.endsWith(".json")).sort();
|
|
597384
598163
|
const jobs = [];
|
|
597385
598164
|
for (const file of files) {
|
|
597386
598165
|
try {
|
|
597387
|
-
jobs.push(JSON.parse(
|
|
598166
|
+
jobs.push(JSON.parse(readFileSync86(join122(dir, file), "utf-8")));
|
|
597388
598167
|
} catch {
|
|
597389
598168
|
}
|
|
597390
598169
|
}
|
|
@@ -597394,14 +598173,14 @@ function pruneOldJobs() {
|
|
|
597394
598173
|
const retentionH = parseFloat(process.env["OA_RUN_RETENTION_H"] || "24");
|
|
597395
598174
|
const cutoffMs = Date.now() - (Number.isFinite(retentionH) && retentionH > 0 ? retentionH : 24) * 36e5;
|
|
597396
598175
|
const dir = jobsDir();
|
|
597397
|
-
if (!
|
|
598176
|
+
if (!existsSync106(dir)) return { pruned: 0, kept: 0 };
|
|
597398
598177
|
let pruned = 0;
|
|
597399
598178
|
let kept = 0;
|
|
597400
598179
|
for (const file of readdirSync36(dir)) {
|
|
597401
598180
|
if (!file.endsWith(".json")) continue;
|
|
597402
|
-
const path8 =
|
|
598181
|
+
const path8 = join122(dir, file);
|
|
597403
598182
|
try {
|
|
597404
|
-
const job = JSON.parse(
|
|
598183
|
+
const job = JSON.parse(readFileSync86(path8, "utf-8"));
|
|
597405
598184
|
if (job.status === "running") {
|
|
597406
598185
|
kept++;
|
|
597407
598186
|
continue;
|
|
@@ -597414,7 +598193,7 @@ function pruneOldJobs() {
|
|
|
597414
598193
|
} catch {
|
|
597415
598194
|
}
|
|
597416
598195
|
const outFile = path8.replace(/\.json$/, ".output");
|
|
597417
|
-
if (
|
|
598196
|
+
if (existsSync106(outFile)) {
|
|
597418
598197
|
try {
|
|
597419
598198
|
unlinkSync24(outFile);
|
|
597420
598199
|
} catch {
|
|
@@ -597707,7 +598486,7 @@ function autoSeedTodosFromPrompt(prompt) {
|
|
|
597707
598486
|
return [];
|
|
597708
598487
|
}
|
|
597709
598488
|
function atomicJobWrite(dir, id, job) {
|
|
597710
|
-
const finalPath =
|
|
598489
|
+
const finalPath = join122(dir, `${id}.json`);
|
|
597711
598490
|
const tmpPath = `${finalPath}.tmp.${process.pid}.${Date.now()}`;
|
|
597712
598491
|
try {
|
|
597713
598492
|
writeFileSync55(tmpPath, JSON.stringify(job, null, 2), "utf-8");
|
|
@@ -599133,23 +599912,23 @@ ${task}` : task;
|
|
|
599133
599912
|
});
|
|
599134
599913
|
}
|
|
599135
599914
|
function updateStateFile() {
|
|
599136
|
-
return
|
|
599915
|
+
return join122(homedir43(), ".open-agents", "update-state.json");
|
|
599137
599916
|
}
|
|
599138
599917
|
function updateLogPath() {
|
|
599139
|
-
return
|
|
599918
|
+
return join122(homedir43(), ".open-agents", "update.log");
|
|
599140
599919
|
}
|
|
599141
599920
|
function readUpdateState() {
|
|
599142
599921
|
try {
|
|
599143
599922
|
const p2 = updateStateFile();
|
|
599144
|
-
if (!
|
|
599145
|
-
return JSON.parse(
|
|
599923
|
+
if (!existsSync106(p2)) return null;
|
|
599924
|
+
return JSON.parse(readFileSync86(p2, "utf-8"));
|
|
599146
599925
|
} catch {
|
|
599147
599926
|
return null;
|
|
599148
599927
|
}
|
|
599149
599928
|
}
|
|
599150
599929
|
function writeUpdateState(state) {
|
|
599151
599930
|
try {
|
|
599152
|
-
const dir =
|
|
599931
|
+
const dir = join122(homedir43(), ".open-agents");
|
|
599153
599932
|
mkdirSync63(dir, { recursive: true });
|
|
599154
599933
|
const finalPath = updateStateFile();
|
|
599155
599934
|
const tmpPath = `${finalPath}.tmp.${process.pid}`;
|
|
@@ -599197,15 +599976,15 @@ async function handleV1Update(req2, res, requestId) {
|
|
|
599197
599976
|
const { execSync: es } = require3("node:child_process");
|
|
599198
599977
|
const isWin2 = process.platform === "win32";
|
|
599199
599978
|
let npmBin = "";
|
|
599200
|
-
for (const candidate of isWin2 ? [
|
|
599201
|
-
if (
|
|
599979
|
+
for (const candidate of isWin2 ? [join122(nodeDir, "npm.cmd"), join122(nodeDir, "npm")] : [join122(nodeDir, "npm"), "/usr/local/bin/npm", "/usr/bin/npm"]) {
|
|
599980
|
+
if (existsSync106(candidate)) {
|
|
599202
599981
|
npmBin = candidate;
|
|
599203
599982
|
break;
|
|
599204
599983
|
}
|
|
599205
599984
|
}
|
|
599206
599985
|
if (!npmBin) npmBin = isWin2 ? "npm.cmd" : "npm";
|
|
599207
599986
|
const pkgSpec = `open-agents-ai@${targetVersion}`;
|
|
599208
|
-
const dir =
|
|
599987
|
+
const dir = join122(homedir43(), ".open-agents");
|
|
599209
599988
|
fs7.mkdirSync(dir, { recursive: true });
|
|
599210
599989
|
const logFd = fs7.openSync(logPath3, "w");
|
|
599211
599990
|
const npmPrefix = dirname36(nodeDir);
|
|
@@ -599215,13 +599994,13 @@ async function handleV1Update(req2, res, requestId) {
|
|
|
599215
599994
|
globalBinDir = es(`${npmBin} bin -g`, { encoding: "utf8", timeout: 5e3, stdio: "pipe" }).trim();
|
|
599216
599995
|
} else {
|
|
599217
599996
|
const npmCliCandidates = [
|
|
599218
|
-
|
|
599219
|
-
|
|
599997
|
+
join122(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
|
|
599998
|
+
join122(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
|
|
599220
599999
|
];
|
|
599221
600000
|
let npmCli = "";
|
|
599222
600001
|
for (const c9 of npmCliCandidates) {
|
|
599223
600002
|
try {
|
|
599224
|
-
if (
|
|
600003
|
+
if (existsSync106(c9)) {
|
|
599225
600004
|
npmCli = c9;
|
|
599226
600005
|
break;
|
|
599227
600006
|
}
|
|
@@ -599253,13 +600032,13 @@ async function handleV1Update(req2, res, requestId) {
|
|
|
599253
600032
|
});
|
|
599254
600033
|
} else {
|
|
599255
600034
|
const npmCliCandidates = [
|
|
599256
|
-
|
|
599257
|
-
|
|
600035
|
+
join122(nodeDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
|
|
600036
|
+
join122(npmBin, "..", "..", "lib", "node_modules", "npm", "bin", "npm-cli.js")
|
|
599258
600037
|
];
|
|
599259
600038
|
let npmCli = "";
|
|
599260
600039
|
for (const c9 of npmCliCandidates) {
|
|
599261
600040
|
try {
|
|
599262
|
-
if (
|
|
600041
|
+
if (existsSync106(c9)) {
|
|
599263
600042
|
npmCli = c9;
|
|
599264
600043
|
break;
|
|
599265
600044
|
}
|
|
@@ -599356,8 +600135,8 @@ function handleV1UpdateStatus(res) {
|
|
|
599356
600135
|
let logTail = "";
|
|
599357
600136
|
let exitCode = null;
|
|
599358
600137
|
try {
|
|
599359
|
-
if (
|
|
599360
|
-
const raw =
|
|
600138
|
+
if (existsSync106(logPath3)) {
|
|
600139
|
+
const raw = readFileSync86(logPath3, "utf-8");
|
|
599361
600140
|
const m2 = raw.match(/__EXIT_CODE=(\d+)/);
|
|
599362
600141
|
if (m2) exitCode = parseInt(m2[1], 10);
|
|
599363
600142
|
logTail = raw.slice(-2e3);
|
|
@@ -599453,7 +600232,7 @@ async function handleV1Run(req2, res) {
|
|
|
599453
600232
|
if (workingDir) {
|
|
599454
600233
|
cwd4 = resolve38(workingDir);
|
|
599455
600234
|
} else if (isolate) {
|
|
599456
|
-
const wsDir =
|
|
600235
|
+
const wsDir = join122(dir, "..", "workspaces", id);
|
|
599457
600236
|
mkdirSync63(wsDir, { recursive: true });
|
|
599458
600237
|
cwd4 = wsDir;
|
|
599459
600238
|
} else {
|
|
@@ -599640,7 +600419,7 @@ async function handleV1Run(req2, res) {
|
|
|
599640
600419
|
let output = "";
|
|
599641
600420
|
let tailBytes = 0;
|
|
599642
600421
|
const TAIL_BUDGET = 1048576;
|
|
599643
|
-
const outputWriter = new DiskTaskOutput(
|
|
600422
|
+
const outputWriter = new DiskTaskOutput(join122(dir, `${id}.output`));
|
|
599644
600423
|
job.outputFile = outputWriter.path;
|
|
599645
600424
|
atomicJobWrite(dir, id, job);
|
|
599646
600425
|
child.stdout?.on("data", (chunk) => {
|
|
@@ -602214,7 +602993,7 @@ ${steering}`;
|
|
|
602214
602993
|
function getScheduleRoots() {
|
|
602215
602994
|
const rootsEnv = process.env["OA_SCHEDULE_ROOTS"] || "";
|
|
602216
602995
|
const roots = rootsEnv.split(rootsEnv.includes(";") ? ";" : ":").filter(Boolean);
|
|
602217
|
-
const defaults3 = [process.cwd(),
|
|
602996
|
+
const defaults3 = [process.cwd(), join122(homedir43(), "Documents")];
|
|
602218
602997
|
const set = /* @__PURE__ */ new Set([...defaults3, ...roots]);
|
|
602219
602998
|
return [...set];
|
|
602220
602999
|
}
|
|
@@ -602226,10 +603005,10 @@ function listScheduledTasks() {
|
|
|
602226
603005
|
for (const root of roots) {
|
|
602227
603006
|
try {
|
|
602228
603007
|
walk(root, 0, (dir) => {
|
|
602229
|
-
if (dir.endsWith(`${
|
|
602230
|
-
const file =
|
|
603008
|
+
if (dir.endsWith(`${join122(".oa", "scheduled")}`) || dir.includes(`${join122(".oa", "scheduled")}`)) {
|
|
603009
|
+
const file = join122(dir, "tasks.json");
|
|
602231
603010
|
try {
|
|
602232
|
-
const raw =
|
|
603011
|
+
const raw = readFileSync86(file, "utf-8");
|
|
602233
603012
|
const json = JSON.parse(raw);
|
|
602234
603013
|
const tasks = Array.isArray(json?.tasks) ? json.tasks : Array.isArray(json) ? json : [];
|
|
602235
603014
|
tasks.forEach((t2, i2) => {
|
|
@@ -602294,7 +603073,7 @@ function walk(dir, depth, onDir, maxDepth) {
|
|
|
602294
603073
|
if (e2.name === "node_modules" || e2.name.startsWith(".")) {
|
|
602295
603074
|
if (e2.name !== ".oa") continue;
|
|
602296
603075
|
}
|
|
602297
|
-
const child =
|
|
603076
|
+
const child = join122(dir, e2.name);
|
|
602298
603077
|
walk(child, depth + 1, onDir, maxDepth);
|
|
602299
603078
|
}
|
|
602300
603079
|
}
|
|
@@ -602303,7 +603082,7 @@ function setScheduledEnabled(id, enabled2) {
|
|
|
602303
603082
|
const target = tasks.find((t2) => t2.id === id);
|
|
602304
603083
|
if (!target) return false;
|
|
602305
603084
|
try {
|
|
602306
|
-
const raw =
|
|
603085
|
+
const raw = readFileSync86(target.file, "utf-8");
|
|
602307
603086
|
const json = JSON.parse(raw);
|
|
602308
603087
|
const arr = Array.isArray(json?.tasks) ? json.tasks : Array.isArray(json) ? json : [];
|
|
602309
603088
|
if (!arr[target.index]) return false;
|
|
@@ -602336,7 +603115,7 @@ function deleteScheduledById(id) {
|
|
|
602336
603115
|
const target = tasks.find((t2) => t2.id === id);
|
|
602337
603116
|
if (!target) return false;
|
|
602338
603117
|
try {
|
|
602339
|
-
const raw =
|
|
603118
|
+
const raw = readFileSync86(target.file, "utf-8");
|
|
602340
603119
|
const json = JSON.parse(raw);
|
|
602341
603120
|
const arr = Array.isArray(json?.tasks) ? json.tasks : Array.isArray(json) ? json : [];
|
|
602342
603121
|
if (!arr[target.index]) return false;
|
|
@@ -602601,11 +603380,11 @@ function reconcileScheduledTasks(apply) {
|
|
|
602601
603380
|
const errors = [];
|
|
602602
603381
|
for (const f2 of found) {
|
|
602603
603382
|
const wdir = f2.workingDir || process.cwd();
|
|
602604
|
-
const file =
|
|
603383
|
+
const file = join122(wdir, ".oa", "scheduled", "tasks.json");
|
|
602605
603384
|
try {
|
|
602606
603385
|
let json = { tasks: [] };
|
|
602607
603386
|
try {
|
|
602608
|
-
const raw =
|
|
603387
|
+
const raw = readFileSync86(file, "utf-8");
|
|
602609
603388
|
json = JSON.parse(raw);
|
|
602610
603389
|
} catch {
|
|
602611
603390
|
}
|
|
@@ -602616,8 +603395,8 @@ function reconcileScheduledTasks(apply) {
|
|
|
602616
603395
|
const entry = { task: f2.task || `legacy ${f2.id}`, schedule: f2.cron, enabled: true };
|
|
602617
603396
|
arr.push(entry);
|
|
602618
603397
|
const toWrite = Array.isArray(json?.tasks) ? { ...json, tasks: arr } : Array.isArray(json) ? arr : { tasks: arr };
|
|
602619
|
-
mkdirSync63(
|
|
602620
|
-
mkdirSync63(
|
|
603398
|
+
mkdirSync63(join122(wdir, ".oa", "scheduled"), { recursive: true });
|
|
603399
|
+
mkdirSync63(join122(wdir, ".oa", "scheduled", "logs"), { recursive: true });
|
|
602621
603400
|
writeFileSync55(file, JSON.stringify(toWrite, null, 2));
|
|
602622
603401
|
adopted.push({ file, index: arr.length - 1 });
|
|
602623
603402
|
}
|
|
@@ -602662,32 +603441,32 @@ function writeCrontabLines(lines) {
|
|
|
602662
603441
|
}
|
|
602663
603442
|
function canonicalCronLine(rec) {
|
|
602664
603443
|
const oaBin = findOaBinary4();
|
|
602665
|
-
const logDir =
|
|
602666
|
-
const logFile =
|
|
602667
|
-
const storeFile =
|
|
603444
|
+
const logDir = join122(rec.workingDir, ".oa", "scheduled", "logs");
|
|
603445
|
+
const logFile = join122(logDir, `${rec.id}.log`);
|
|
603446
|
+
const storeFile = join122(rec.workingDir, ".oa", "scheduled", "tasks.json");
|
|
602668
603447
|
const taskEsc = rec.task.replace(/'/g, "'\\''");
|
|
602669
|
-
const lockDir =
|
|
602670
|
-
const lockPath =
|
|
603448
|
+
const lockDir = join122(rec.workingDir, ".oa", "run");
|
|
603449
|
+
const lockPath = join122(lockDir, `${rec.id}.lock`);
|
|
602671
603450
|
const wrapper = [
|
|
602672
603451
|
`cd ${JSON.stringify(rec.workingDir)}`,
|
|
602673
603452
|
`mkdir -p ${JSON.stringify(logDir)}`,
|
|
602674
603453
|
`mkdir -p ${JSON.stringify(lockDir)}`,
|
|
602675
603454
|
`if mkdir ${JSON.stringify(lockPath)} 2>/dev/null; then`,
|
|
602676
|
-
` echo $$ > ${JSON.stringify(
|
|
603455
|
+
` echo $$ > ${JSON.stringify(join122(lockPath, "pid"))}`,
|
|
602677
603456
|
` trap 'rm -rf ${lockPath}' EXIT`,
|
|
602678
603457
|
`else`,
|
|
602679
|
-
` if [ -f ${JSON.stringify(
|
|
602680
|
-
` oldpid=$(cat ${JSON.stringify(
|
|
603458
|
+
` if [ -f ${JSON.stringify(join122(lockPath, "pid"))} ]; then`,
|
|
603459
|
+
` oldpid=$(cat ${JSON.stringify(join122(lockPath, "pid"))} 2>/dev/null || echo)`,
|
|
602681
603460
|
` if [ -n "$oldpid" ] && kill -0 "$oldpid" 2>/dev/null; then`,
|
|
602682
603461
|
` echo "[oa-scheduler] ${rec.id} already running as PID $oldpid; skipping" >> ${JSON.stringify(logFile)}`,
|
|
602683
603462
|
` exit 0`,
|
|
602684
603463
|
` else`,
|
|
602685
603464
|
` rm -rf ${JSON.stringify(lockPath)} 2>/dev/null || true`,
|
|
602686
|
-
` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(
|
|
603465
|
+
` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(join122(lockPath, "pid"))} && trap 'rm -rf ${lockPath}' EXIT`,
|
|
602687
603466
|
` fi`,
|
|
602688
603467
|
` else`,
|
|
602689
603468
|
` rm -rf ${JSON.stringify(lockPath)} 2>/dev/null || true`,
|
|
602690
|
-
` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(
|
|
603469
|
+
` mkdir -p ${JSON.stringify(lockPath)} && echo $$ > ${JSON.stringify(join122(lockPath, "pid"))} && trap 'rm -rf ${lockPath}' EXIT`,
|
|
602691
603470
|
` fi`,
|
|
602692
603471
|
`fi`,
|
|
602693
603472
|
`${oaBin} '${taskEsc}' >> ${JSON.stringify(logFile)} 2>&1; _oa_exit=$?`,
|
|
@@ -602719,9 +603498,9 @@ function fixupOrMigrateScheduled(mode, dryRun) {
|
|
|
602719
603498
|
try {
|
|
602720
603499
|
if (!f2.workingDir || !f2.task) continue;
|
|
602721
603500
|
const unitBase = `oa-${f2.id}`;
|
|
602722
|
-
const unitDir =
|
|
602723
|
-
const svc =
|
|
602724
|
-
const tim =
|
|
603501
|
+
const unitDir = join122(homedir43(), ".config", "systemd", "user");
|
|
603502
|
+
const svc = join122(unitDir, `${unitBase}.service`);
|
|
603503
|
+
const tim = join122(unitDir, `${unitBase}.timer`);
|
|
602725
603504
|
const oaBin = findOaBinary4();
|
|
602726
603505
|
const rec = { id: f2.id, cron: f2.cron, workingDir: f2.workingDir, task: f2.task };
|
|
602727
603506
|
const cmd = canonicalCronLine(rec).split(" ").slice(5).join(" ");
|
|
@@ -602847,8 +603626,8 @@ function startApiServer(options2 = {}) {
|
|
|
602847
603626
|
const config = loadConfig();
|
|
602848
603627
|
const ollamaUrl = options2.ollamaUrl ?? config.backendUrl;
|
|
602849
603628
|
const cwd4 = process.cwd();
|
|
602850
|
-
initAuditLog(
|
|
602851
|
-
initUsageTracker(
|
|
603629
|
+
initAuditLog(join122(cwd4, ".oa"));
|
|
603630
|
+
initUsageTracker(join122(cwd4, ".oa"));
|
|
602852
603631
|
try {
|
|
602853
603632
|
const taskMgr = getSharedTaskManager();
|
|
602854
603633
|
taskMgr.setEventPublisher((type, data, opts) => {
|
|
@@ -602899,7 +603678,7 @@ function startApiServer(options2 = {}) {
|
|
|
602899
603678
|
if (!f2.endsWith(".json") || f2.includes(".tmp.")) continue;
|
|
602900
603679
|
const sid = f2.replace(/\.json$/, "");
|
|
602901
603680
|
try {
|
|
602902
|
-
const items = JSON.parse(
|
|
603681
|
+
const items = JSON.parse(readFileSync86(join122(dir, f2), "utf-8"));
|
|
602903
603682
|
if (Array.isArray(items)) {
|
|
602904
603683
|
cache8.set(sid, new Map(items.map((t2) => [t2.id, t2])));
|
|
602905
603684
|
}
|
|
@@ -602911,10 +603690,10 @@ function startApiServer(options2 = {}) {
|
|
|
602911
603690
|
const watcher = fsWatch3(dir, (_evt, fname) => {
|
|
602912
603691
|
if (!fname || !fname.endsWith(".json") || fname.includes(".tmp.")) return;
|
|
602913
603692
|
const sid = fname.replace(/\.json$/, "");
|
|
602914
|
-
const fp =
|
|
603693
|
+
const fp = join122(dir, fname);
|
|
602915
603694
|
let next = [];
|
|
602916
603695
|
try {
|
|
602917
|
-
if (!
|
|
603696
|
+
if (!existsSync106(fp)) {
|
|
602918
603697
|
const old = cache8.get(sid);
|
|
602919
603698
|
if (old) {
|
|
602920
603699
|
for (const t2 of old.values()) {
|
|
@@ -602927,7 +603706,7 @@ function startApiServer(options2 = {}) {
|
|
|
602927
603706
|
}
|
|
602928
603707
|
return;
|
|
602929
603708
|
}
|
|
602930
|
-
next = JSON.parse(
|
|
603709
|
+
next = JSON.parse(readFileSync86(fp, "utf-8"));
|
|
602931
603710
|
if (!Array.isArray(next)) return;
|
|
602932
603711
|
} catch {
|
|
602933
603712
|
return;
|
|
@@ -602966,14 +603745,14 @@ function startApiServer(options2 = {}) {
|
|
|
602966
603745
|
const retentionDays = parseInt(process.env["OA_JOB_RETENTION_DAYS"] ?? "30", 10);
|
|
602967
603746
|
if (retentionDays > 0) {
|
|
602968
603747
|
try {
|
|
602969
|
-
const jobsDir3 =
|
|
602970
|
-
if (
|
|
603748
|
+
const jobsDir3 = join122(cwd4, ".oa", "jobs");
|
|
603749
|
+
if (existsSync106(jobsDir3)) {
|
|
602971
603750
|
const cutoff = Date.now() - retentionDays * 864e5;
|
|
602972
603751
|
for (const f2 of readdirSync36(jobsDir3)) {
|
|
602973
603752
|
if (!f2.endsWith(".json")) continue;
|
|
602974
603753
|
try {
|
|
602975
|
-
const jobPath =
|
|
602976
|
-
const job = JSON.parse(
|
|
603754
|
+
const jobPath = join122(jobsDir3, f2);
|
|
603755
|
+
const job = JSON.parse(readFileSync86(jobPath, "utf-8"));
|
|
602977
603756
|
const jobTime = new Date(job.startedAt ?? job.completedAt ?? 0).getTime();
|
|
602978
603757
|
if (jobTime > 0 && jobTime < cutoff && job.status !== "running") {
|
|
602979
603758
|
const { unlinkSync: unlinkSync25 } = require3("node:fs");
|
|
@@ -602993,8 +603772,8 @@ function startApiServer(options2 = {}) {
|
|
|
602993
603772
|
if (useTls) {
|
|
602994
603773
|
try {
|
|
602995
603774
|
tlsOpts = {
|
|
602996
|
-
cert:
|
|
602997
|
-
key:
|
|
603775
|
+
cert: readFileSync86(resolve38(tlsCert)),
|
|
603776
|
+
key: readFileSync86(resolve38(tlsKey))
|
|
602998
603777
|
};
|
|
602999
603778
|
} catch (e2) {
|
|
603000
603779
|
log22(`
|
|
@@ -603005,9 +603784,9 @@ function startApiServer(options2 = {}) {
|
|
|
603005
603784
|
}
|
|
603006
603785
|
let runtimeAccessMode = resolveAccessMode(process.env["OA_ACCESS"], host);
|
|
603007
603786
|
try {
|
|
603008
|
-
const accessFile =
|
|
603009
|
-
if (
|
|
603010
|
-
const persisted =
|
|
603787
|
+
const accessFile = join122(homedir43(), ".open-agents", "access");
|
|
603788
|
+
if (existsSync106(accessFile)) {
|
|
603789
|
+
const persisted = readFileSync86(accessFile, "utf8").trim();
|
|
603011
603790
|
const resolved = resolveAccessMode(persisted, host);
|
|
603012
603791
|
if (resolved) runtimeAccessMode = resolved;
|
|
603013
603792
|
}
|
|
@@ -603060,9 +603839,9 @@ function startApiServer(options2 = {}) {
|
|
|
603060
603839
|
const previous = runtimeAccessMode;
|
|
603061
603840
|
runtimeAccessMode = requested;
|
|
603062
603841
|
try {
|
|
603063
|
-
const dir =
|
|
603842
|
+
const dir = join122(homedir43(), ".open-agents");
|
|
603064
603843
|
mkdirSync63(dir, { recursive: true });
|
|
603065
|
-
writeFileSync55(
|
|
603844
|
+
writeFileSync55(join122(dir, "access"), `${runtimeAccessMode}
|
|
603066
603845
|
`, "utf8");
|
|
603067
603846
|
} catch {
|
|
603068
603847
|
}
|
|
@@ -603275,9 +604054,9 @@ function startApiServer(options2 = {}) {
|
|
|
603275
604054
|
try {
|
|
603276
604055
|
const { startEmbeddingWorkers: startEmbeddingWorkers2 } = await Promise.resolve().then(() => (init_embedding_workers(), embedding_workers_exports));
|
|
603277
604056
|
const { ensureEmbedDeps: ensureEmbedDeps2, runEmbedImage: runEmbedImage2, runEmbedAudio: runEmbedAudio2 } = await Promise.resolve().then(() => (init_py_embed(), py_embed_exports));
|
|
603278
|
-
const dbBase =
|
|
603279
|
-
const epStore = new mem.EpisodeStore(
|
|
603280
|
-
const kg = new mem.TemporalGraph(
|
|
604057
|
+
const dbBase = join122(cwd4, ".oa");
|
|
604058
|
+
const epStore = new mem.EpisodeStore(join122(dbBase, "memory.db"));
|
|
604059
|
+
const kg = new mem.TemporalGraph(join122(dbBase, "kg.db"));
|
|
603281
604060
|
try {
|
|
603282
604061
|
ensureEmbedDeps2();
|
|
603283
604062
|
} catch {
|
|
@@ -603354,6 +604133,34 @@ function startApiServer(options2 = {}) {
|
|
|
603354
604133
|
`);
|
|
603355
604134
|
log22(` Primary: ${config.backendUrl} (${config.backendType || "ollama"})
|
|
603356
604135
|
`);
|
|
604136
|
+
try {
|
|
604137
|
+
const { writeFileSync: writeFileSync59, mkdirSync: mkdirSync67, existsSync: _exists } = require3("node:fs");
|
|
604138
|
+
const { join: _join } = require3("node:path");
|
|
604139
|
+
const { homedir: _homedir } = require3("node:os");
|
|
604140
|
+
const apiHint = JSON.stringify({
|
|
604141
|
+
port,
|
|
604142
|
+
host: host === "0.0.0.0" ? "127.0.0.1" : host,
|
|
604143
|
+
scheme: proto,
|
|
604144
|
+
pid: process.pid,
|
|
604145
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
604146
|
+
version: version4
|
|
604147
|
+
}, null, 2);
|
|
604148
|
+
const candidates = [
|
|
604149
|
+
_join(process.cwd(), ".oa", "nexus"),
|
|
604150
|
+
_join(_homedir(), ".oa", "nexus"),
|
|
604151
|
+
_join(_homedir(), ".open-agents", "nexus")
|
|
604152
|
+
];
|
|
604153
|
+
for (const dir of candidates) {
|
|
604154
|
+
try {
|
|
604155
|
+
if (!_exists(dir)) mkdirSync67(dir, { recursive: true });
|
|
604156
|
+
writeFileSync59(_join(dir, "api-port.json"), apiHint);
|
|
604157
|
+
} catch {
|
|
604158
|
+
}
|
|
604159
|
+
}
|
|
604160
|
+
} catch (e2) {
|
|
604161
|
+
log22(` WARN: api-port hint write failed: ${e2.message}
|
|
604162
|
+
`);
|
|
604163
|
+
}
|
|
603357
604164
|
try {
|
|
603358
604165
|
adoptHandoffRuns();
|
|
603359
604166
|
} catch (e2) {
|
|
@@ -603587,10 +604394,10 @@ async function handleMemoryIngest(req2, res, ollamaUrl) {
|
|
|
603587
604394
|
const labels = Array.isArray(b.labels) ? b.labels : [];
|
|
603588
604395
|
const mediaPath = typeof b.media_path === "string" ? b.media_path : void 0;
|
|
603589
604396
|
const cwd4 = process.cwd();
|
|
603590
|
-
const dbBase =
|
|
604397
|
+
const dbBase = join122(cwd4, ".oa");
|
|
603591
604398
|
const { EpisodeStore: EpisodeStore3, TemporalGraph: TemporalGraph3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
|
|
603592
|
-
const epStore = new EpisodeStore3(
|
|
603593
|
-
const kg = new TemporalGraph3(
|
|
604399
|
+
const epStore = new EpisodeStore3(join122(dbBase, "memory.db"));
|
|
604400
|
+
const kg = new TemporalGraph3(join122(dbBase, "kg.db"));
|
|
603594
604401
|
const meta = {};
|
|
603595
604402
|
if (mediaPath) meta.media_path = mediaPath;
|
|
603596
604403
|
const epId = epStore.insert({ modality, content: content || (mediaPath || ""), metadata: meta, toolName: "memory_ingest" });
|
|
@@ -603657,7 +604464,7 @@ async function handleEntitiesList(req2, res) {
|
|
|
603657
604464
|
const type = url.searchParams.get("type") || "person";
|
|
603658
604465
|
const limit = Math.max(1, Math.min(1e3, parseInt(url.searchParams.get("limit") || "100", 10)));
|
|
603659
604466
|
const { TemporalGraph: TemporalGraph3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
|
|
603660
|
-
const kg = new TemporalGraph3(
|
|
604467
|
+
const kg = new TemporalGraph3(join122(process.cwd(), ".oa", "kg.db"));
|
|
603661
604468
|
const nodes = kg.nodesByType(type, limit).map((n2) => ({ id: n2.id, text: n2.text, mentionCount: n2.mentionCount, firstSeen: n2.firstSeen, lastSeen: n2.lastSeen }));
|
|
603662
604469
|
jsonResponse(res, 200, { object: "list", data: nodes });
|
|
603663
604470
|
} catch (err) {
|
|
@@ -603679,7 +604486,7 @@ async function handleMemorySearch2(req2, res) {
|
|
|
603679
604486
|
const wLex = typeof b.lexical_weight === "number" ? b.lexical_weight : 1;
|
|
603680
604487
|
const wEmb = typeof b.embedding_weight === "number" ? b.embedding_weight : 1;
|
|
603681
604488
|
const { EpisodeStore: EpisodeStore3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
|
|
603682
|
-
const epStore = new EpisodeStore3(
|
|
604489
|
+
const epStore = new EpisodeStore3(join122(process.cwd(), ".oa", "memory.db"));
|
|
603683
604490
|
const results = epStore.search({ query, modality, limit }, { queryEmbedding: qEmb, lexicalWeight: wLex, embeddingWeight: wEmb });
|
|
603684
604491
|
jsonResponse(res, 200, { object: "list", data: results.map((e2) => ({ id: e2.id, modality: e2.modality, content: e2.content, timestamp: e2.timestamp })) });
|
|
603685
604492
|
} catch (err) {
|
|
@@ -603796,13 +604603,13 @@ var init_serve = __esm({
|
|
|
603796
604603
|
|
|
603797
604604
|
// packages/cli/src/tui/interactive.ts
|
|
603798
604605
|
import { cwd } from "node:process";
|
|
603799
|
-
import { resolve as resolve39, join as
|
|
604606
|
+
import { resolve as resolve39, join as join123, dirname as dirname37, extname as extname12 } from "node:path";
|
|
603800
604607
|
import { createRequire as createRequire6 } from "node:module";
|
|
603801
604608
|
import { fileURLToPath as fileURLToPath18 } from "node:url";
|
|
603802
|
-
import { readFileSync as
|
|
603803
|
-
import { existsSync as
|
|
604609
|
+
import { readFileSync as readFileSync87, writeFileSync as writeFileSync56, appendFileSync as appendFileSync8, rmSync as rmSync5, readdirSync as readdirSync37, mkdirSync as mkdirSync64 } from "node:fs";
|
|
604610
|
+
import { existsSync as existsSync107 } from "node:fs";
|
|
603804
604611
|
import { execSync as execSync58 } from "node:child_process";
|
|
603805
|
-
import { homedir as
|
|
604612
|
+
import { homedir as homedir44 } from "node:os";
|
|
603806
604613
|
function formatTimeAgo2(date) {
|
|
603807
604614
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
603808
604615
|
if (seconds < 60) return "just now";
|
|
@@ -603818,12 +604625,12 @@ function getVersion4() {
|
|
|
603818
604625
|
const require4 = createRequire6(import.meta.url);
|
|
603819
604626
|
const thisDir = dirname37(fileURLToPath18(import.meta.url));
|
|
603820
604627
|
const candidates = [
|
|
603821
|
-
|
|
603822
|
-
|
|
603823
|
-
|
|
604628
|
+
join123(thisDir, "..", "package.json"),
|
|
604629
|
+
join123(thisDir, "..", "..", "package.json"),
|
|
604630
|
+
join123(thisDir, "..", "..", "..", "package.json")
|
|
603824
604631
|
];
|
|
603825
604632
|
for (const pkgPath of candidates) {
|
|
603826
|
-
if (
|
|
604633
|
+
if (existsSync107(pkgPath)) {
|
|
603827
604634
|
const pkg = require4(pkgPath);
|
|
603828
604635
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
|
|
603829
604636
|
return pkg.version ?? "0.0.0";
|
|
@@ -604629,14 +605436,14 @@ Meta-critique: quality ${meta.quality}/5, thorough: ${meta.thorough}`;
|
|
|
604629
605436
|
function gatherMemorySnippets(root) {
|
|
604630
605437
|
const snippets = [];
|
|
604631
605438
|
const dirs = [
|
|
604632
|
-
|
|
604633
|
-
|
|
605439
|
+
join123(root, ".oa", "memory"),
|
|
605440
|
+
join123(root, ".open-agents", "memory")
|
|
604634
605441
|
];
|
|
604635
605442
|
for (const dir of dirs) {
|
|
604636
|
-
if (!
|
|
605443
|
+
if (!existsSync107(dir)) continue;
|
|
604637
605444
|
try {
|
|
604638
605445
|
for (const f2 of readdirSync37(dir).filter((f3) => f3.endsWith(".json"))) {
|
|
604639
|
-
const data = JSON.parse(
|
|
605446
|
+
const data = JSON.parse(readFileSync87(join123(dir, f2), "utf-8"));
|
|
604640
605447
|
for (const val of Object.values(data)) {
|
|
604641
605448
|
const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
604642
605449
|
if (v.length > 10) snippets.push(v);
|
|
@@ -604790,9 +605597,9 @@ ${metabolismMemories}
|
|
|
604790
605597
|
} catch {
|
|
604791
605598
|
}
|
|
604792
605599
|
try {
|
|
604793
|
-
const archeFile =
|
|
604794
|
-
if (
|
|
604795
|
-
const variants = JSON.parse(
|
|
605600
|
+
const archeFile = join123(repoRoot, ".oa", "arche", "variants.json");
|
|
605601
|
+
if (existsSync107(archeFile)) {
|
|
605602
|
+
const variants = JSON.parse(readFileSync87(archeFile, "utf8"));
|
|
604796
605603
|
if (variants.length > 0) {
|
|
604797
605604
|
let filtered = variants;
|
|
604798
605605
|
if (taskType) {
|
|
@@ -604964,9 +605771,9 @@ RULES:
|
|
|
604964
605771
|
const compactionThreshold = Number.isFinite(envOverride) && envOverride > 0 ? envOverride : modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
|
|
604965
605772
|
let identityInjection = "";
|
|
604966
605773
|
try {
|
|
604967
|
-
const ikStateFile =
|
|
604968
|
-
if (
|
|
604969
|
-
const selfState = JSON.parse(
|
|
605774
|
+
const ikStateFile = join123(repoRoot, ".oa", "identity", "self-state.json");
|
|
605775
|
+
if (existsSync107(ikStateFile)) {
|
|
605776
|
+
const selfState = JSON.parse(readFileSync87(ikStateFile, "utf8"));
|
|
604970
605777
|
const lines = [
|
|
604971
605778
|
`[Identity State v${selfState.version}]`,
|
|
604972
605779
|
`Self: ${selfState.narrative_summary}`,
|
|
@@ -605828,11 +606635,11 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
605828
606635
|
});
|
|
605829
606636
|
}
|
|
605830
606637
|
try {
|
|
605831
|
-
const ikDir =
|
|
605832
|
-
const ikFile =
|
|
606638
|
+
const ikDir = join123(repoRoot, ".oa", "identity");
|
|
606639
|
+
const ikFile = join123(ikDir, "self-state.json");
|
|
605833
606640
|
let ikState;
|
|
605834
|
-
if (
|
|
605835
|
-
ikState = JSON.parse(
|
|
606641
|
+
if (existsSync107(ikFile)) {
|
|
606642
|
+
ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
|
|
605836
606643
|
} else {
|
|
605837
606644
|
mkdirSync64(ikDir, { recursive: true });
|
|
605838
606645
|
const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
@@ -605909,9 +606716,9 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
605909
606716
|
} else {
|
|
605910
606717
|
renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
|
|
605911
606718
|
try {
|
|
605912
|
-
const ikFile =
|
|
605913
|
-
if (
|
|
605914
|
-
const ikState = JSON.parse(
|
|
606719
|
+
const ikFile = join123(repoRoot, ".oa", "identity", "self-state.json");
|
|
606720
|
+
if (existsSync107(ikFile)) {
|
|
606721
|
+
const ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
|
|
605915
606722
|
if (!ikState.stats) ikState.stats = { queries_served: 0 };
|
|
605916
606723
|
ikState.stats.queries_served = (ikState.stats.queries_served || 0) + 1;
|
|
605917
606724
|
ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.03);
|
|
@@ -606167,10 +606974,10 @@ async function startInteractive(config, repoPath) {
|
|
|
606167
606974
|
process.stdin.pause();
|
|
606168
606975
|
}
|
|
606169
606976
|
try {
|
|
606170
|
-
const oaDir =
|
|
606171
|
-
const nexusPidFile =
|
|
606172
|
-
if (
|
|
606173
|
-
const pid = parseInt(
|
|
606977
|
+
const oaDir = join123(repoRoot, ".oa");
|
|
606978
|
+
const nexusPidFile = join123(oaDir, "nexus", "daemon.pid");
|
|
606979
|
+
if (existsSync107(nexusPidFile)) {
|
|
606980
|
+
const pid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
|
|
606174
606981
|
if (pid > 0) {
|
|
606175
606982
|
try {
|
|
606176
606983
|
process.kill(pid, 0);
|
|
@@ -606830,7 +607637,7 @@ ${result.summary}`
|
|
|
606830
607637
|
let p2pGateway = null;
|
|
606831
607638
|
let peerMesh = null;
|
|
606832
607639
|
let inferenceRouter = null;
|
|
606833
|
-
const secretVault = new SecretVault(
|
|
607640
|
+
const secretVault = new SecretVault(join123(repoRoot, ".oa", "vault.enc"));
|
|
606834
607641
|
let adminSessionKey = null;
|
|
606835
607642
|
const callSubAgents = /* @__PURE__ */ new Map();
|
|
606836
607643
|
const streamRenderer = new StreamRenderer();
|
|
@@ -607061,13 +607868,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
607061
607868
|
const hits = allCompletions.filter((c9) => c9.toLowerCase().startsWith(lower));
|
|
607062
607869
|
return [hits, line];
|
|
607063
607870
|
}
|
|
607064
|
-
const HISTORY_DIR =
|
|
607065
|
-
const HISTORY_FILE =
|
|
607871
|
+
const HISTORY_DIR = join123(homedir44(), ".open-agents");
|
|
607872
|
+
const HISTORY_FILE = join123(HISTORY_DIR, "repl-history");
|
|
607066
607873
|
const MAX_HISTORY_LINES = 500;
|
|
607067
607874
|
let savedHistory = [];
|
|
607068
607875
|
try {
|
|
607069
|
-
if (
|
|
607070
|
-
const raw =
|
|
607876
|
+
if (existsSync107(HISTORY_FILE)) {
|
|
607877
|
+
const raw = readFileSync87(HISTORY_FILE, "utf8").trim();
|
|
607071
607878
|
if (raw) savedHistory = raw.split("\n").reverse();
|
|
607072
607879
|
}
|
|
607073
607880
|
} catch {
|
|
@@ -607217,7 +608024,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
607217
608024
|
mkdirSync64(HISTORY_DIR, { recursive: true });
|
|
607218
608025
|
appendFileSync8(HISTORY_FILE, line + "\n", "utf8");
|
|
607219
608026
|
if (Math.random() < 0.02) {
|
|
607220
|
-
const all2 =
|
|
608027
|
+
const all2 = readFileSync87(HISTORY_FILE, "utf8").trim().split("\n");
|
|
607221
608028
|
if (all2.length > MAX_HISTORY_LINES) {
|
|
607222
608029
|
writeFileSync56(HISTORY_FILE, all2.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
|
|
607223
608030
|
}
|
|
@@ -607404,10 +608211,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
607404
608211
|
const { unlinkSync: _rmStale } = await import("node:fs");
|
|
607405
608212
|
const { homedir: _hdir } = await import("node:os");
|
|
607406
608213
|
for (const dp of [
|
|
607407
|
-
|
|
607408
|
-
|
|
608214
|
+
join123(repoRoot, ".oa", "nexus", "nexus-daemon.mjs"),
|
|
608215
|
+
join123(_hdir(), ".open-agents", ".oa", "nexus", "nexus-daemon.mjs")
|
|
607409
608216
|
]) {
|
|
607410
|
-
if (
|
|
608217
|
+
if (existsSync107(dp)) try {
|
|
607411
608218
|
_rmStale(dp);
|
|
607412
608219
|
} catch {
|
|
607413
608220
|
}
|
|
@@ -607418,9 +608225,9 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
607418
608225
|
const autoNexus = new NexusTool(repoRoot);
|
|
607419
608226
|
const _registerNexusDaemon = () => {
|
|
607420
608227
|
try {
|
|
607421
|
-
const nexusPidFile =
|
|
607422
|
-
if (
|
|
607423
|
-
const nPid = parseInt(
|
|
608228
|
+
const nexusPidFile = join123(repoRoot, ".oa", "nexus", "daemon.pid");
|
|
608229
|
+
if (existsSync107(nexusPidFile)) {
|
|
608230
|
+
const nPid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
|
|
607424
608231
|
if (nPid > 0 && !registry2.daemons.has("Nexus")) {
|
|
607425
608232
|
registry2.register({ name: "Nexus", pid: nPid, startedAt: Date.now(), status: "running" });
|
|
607426
608233
|
statusBar.ensureMonitorTimer();
|
|
@@ -607477,7 +608284,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
607477
608284
|
} catch {
|
|
607478
608285
|
}
|
|
607479
608286
|
try {
|
|
607480
|
-
const oaDir =
|
|
608287
|
+
const oaDir = join123(repoRoot, ".oa");
|
|
607481
608288
|
const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
|
|
607482
608289
|
onInfo: (msg) => writeContent(() => renderInfo2(msg)),
|
|
607483
608290
|
onError: (msg) => writeContent(() => renderWarning2(msg))
|
|
@@ -607509,7 +608316,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
607509
608316
|
} catch {
|
|
607510
608317
|
}
|
|
607511
608318
|
try {
|
|
607512
|
-
const oaDir =
|
|
608319
|
+
const oaDir = join123(repoRoot, ".oa");
|
|
607513
608320
|
const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
|
|
607514
608321
|
onInfo: (msg) => writeContent(() => renderInfo2(msg)),
|
|
607515
608322
|
onError: (msg) => writeContent(() => renderWarning2(msg))
|
|
@@ -607550,10 +608357,10 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
607550
608357
|
}
|
|
607551
608358
|
try {
|
|
607552
608359
|
const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
|
|
607553
|
-
const globalNamePath =
|
|
608360
|
+
const globalNamePath = join123(_hd(), ".open-agents", "agent-name");
|
|
607554
608361
|
let agName = "";
|
|
607555
608362
|
try {
|
|
607556
|
-
if (
|
|
608363
|
+
if (existsSync107(globalNamePath)) agName = readFileSync87(globalNamePath, "utf8").trim();
|
|
607557
608364
|
} catch {
|
|
607558
608365
|
}
|
|
607559
608366
|
if (!agName) {
|
|
@@ -607582,11 +608389,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
607582
608389
|
}
|
|
607583
608390
|
if (!ollamaAlive) {
|
|
607584
608391
|
try {
|
|
607585
|
-
const savedSponsorsPath =
|
|
608392
|
+
const savedSponsorsPath = join123(repoRoot, ".oa", "sponsor", "known-sponsors.json");
|
|
607586
608393
|
let savedSponsors = [];
|
|
607587
608394
|
try {
|
|
607588
|
-
if (
|
|
607589
|
-
savedSponsors = JSON.parse(
|
|
608395
|
+
if (existsSync107(savedSponsorsPath)) {
|
|
608396
|
+
savedSponsors = JSON.parse(readFileSync87(savedSponsorsPath, "utf8"));
|
|
607590
608397
|
const oneHourAgo = Date.now() - 36e5;
|
|
607591
608398
|
savedSponsors = savedSponsors.filter((s2) => (s2.lastVerified || 0) > oneHourAgo);
|
|
607592
608399
|
}
|
|
@@ -608678,10 +609485,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
608678
609485
|
if (name10 === "voice_list_files") {
|
|
608679
609486
|
const baseDir = String(args?.dir ?? ".");
|
|
608680
609487
|
const { readdirSync: readdirSync39, statSync: statSync36 } = __require("node:fs");
|
|
608681
|
-
const { join:
|
|
608682
|
-
const base3 = baseDir.startsWith("/") ? baseDir : resolve43(
|
|
609488
|
+
const { join: join128, resolve: resolve43 } = __require("node:path");
|
|
609489
|
+
const base3 = baseDir.startsWith("/") ? baseDir : resolve43(join128(repoRoot, baseDir));
|
|
608683
609490
|
const items = readdirSync39(base3).slice(0, 200).map((f2) => {
|
|
608684
|
-
const s2 = statSync36(
|
|
609491
|
+
const s2 = statSync36(join128(base3, f2));
|
|
608685
609492
|
return { name: f2, dir: s2.isDirectory(), size: s2.size };
|
|
608686
609493
|
});
|
|
608687
609494
|
return JSON.stringify({ dir: base3, items }, null, 2);
|
|
@@ -608769,7 +609576,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
608769
609576
|
kind,
|
|
608770
609577
|
targetUrl,
|
|
608771
609578
|
authKey,
|
|
608772
|
-
stateDir:
|
|
609579
|
+
stateDir: join123(repoRoot, ".oa"),
|
|
608773
609580
|
passthrough: passthrough ?? false,
|
|
608774
609581
|
loadbalance: loadbalance ?? false,
|
|
608775
609582
|
endpointAuth: passthrough ? currentConfig.apiKey : void 0,
|
|
@@ -608815,7 +609622,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
608815
609622
|
await tunnelGateway.stop();
|
|
608816
609623
|
tunnelGateway = null;
|
|
608817
609624
|
}
|
|
608818
|
-
const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir:
|
|
609625
|
+
const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join123(repoRoot, ".oa") });
|
|
608819
609626
|
newTunnel.on("stats", (stats) => {
|
|
608820
609627
|
statusBar.setExposeStatus({
|
|
608821
609628
|
status: stats.status,
|
|
@@ -608902,9 +609709,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
608902
609709
|
});
|
|
608903
609710
|
if (!result.success) throw new Error(result.error || "Connect failed");
|
|
608904
609711
|
try {
|
|
608905
|
-
const nexusPidFile =
|
|
608906
|
-
if (
|
|
608907
|
-
const pid = parseInt(
|
|
609712
|
+
const nexusPidFile = join123(repoRoot, ".oa", "nexus", "daemon.pid");
|
|
609713
|
+
if (existsSync107(nexusPidFile)) {
|
|
609714
|
+
const pid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
|
|
608908
609715
|
if (pid > 0) {
|
|
608909
609716
|
registry2.register({
|
|
608910
609717
|
name: "Nexus",
|
|
@@ -609092,10 +609899,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
609092
609899
|
writeContent(() => renderInfo2(`Killed ${bgKilled} background task(s).`));
|
|
609093
609900
|
}
|
|
609094
609901
|
try {
|
|
609095
|
-
const nexusDir =
|
|
609096
|
-
const pidFile =
|
|
609097
|
-
if (
|
|
609098
|
-
const pid = parseInt(
|
|
609902
|
+
const nexusDir = join123(repoRoot, OA_DIR, "nexus");
|
|
609903
|
+
const pidFile = join123(nexusDir, "daemon.pid");
|
|
609904
|
+
if (existsSync107(pidFile)) {
|
|
609905
|
+
const pid = parseInt(readFileSync87(pidFile, "utf8").trim(), 10);
|
|
609099
609906
|
if (pid > 0) {
|
|
609100
609907
|
try {
|
|
609101
609908
|
if (process.platform === "win32") {
|
|
@@ -609117,13 +609924,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
609117
609924
|
} catch {
|
|
609118
609925
|
}
|
|
609119
609926
|
try {
|
|
609120
|
-
const voiceDir2 =
|
|
609927
|
+
const voiceDir2 = join123(homedir44(), ".open-agents", "voice");
|
|
609121
609928
|
const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
|
|
609122
609929
|
for (const pf of voicePidFiles) {
|
|
609123
|
-
const pidPath =
|
|
609124
|
-
if (
|
|
609930
|
+
const pidPath = join123(voiceDir2, pf);
|
|
609931
|
+
if (existsSync107(pidPath)) {
|
|
609125
609932
|
try {
|
|
609126
|
-
const pid = parseInt(
|
|
609933
|
+
const pid = parseInt(readFileSync87(pidPath, "utf8").trim(), 10);
|
|
609127
609934
|
if (pid > 0) {
|
|
609128
609935
|
if (process.platform === "win32") {
|
|
609129
609936
|
try {
|
|
@@ -609147,8 +609954,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
609147
609954
|
execSync58(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
|
|
609148
609955
|
} catch {
|
|
609149
609956
|
}
|
|
609150
|
-
const oaPath =
|
|
609151
|
-
if (
|
|
609957
|
+
const oaPath = join123(repoRoot, OA_DIR);
|
|
609958
|
+
if (existsSync107(oaPath)) {
|
|
609152
609959
|
let deleted = false;
|
|
609153
609960
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
609154
609961
|
try {
|
|
@@ -609232,19 +610039,19 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
609232
610039
|
try {
|
|
609233
610040
|
const { isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
|
|
609234
610041
|
if (isPersonaPlexRunning2()) {
|
|
609235
|
-
const ppPidFile =
|
|
609236
|
-
const ppPortFile =
|
|
609237
|
-
if (
|
|
609238
|
-
const ppPid = parseInt(
|
|
609239
|
-
const ppPort =
|
|
610042
|
+
const ppPidFile = join123(homedir44(), ".open-agents", "voice", "personaplex", "daemon.pid");
|
|
610043
|
+
const ppPortFile = join123(homedir44(), ".open-agents", "voice", "personaplex", "daemon.port");
|
|
610044
|
+
if (existsSync107(ppPidFile)) {
|
|
610045
|
+
const ppPid = parseInt(readFileSync87(ppPidFile, "utf8").trim(), 10);
|
|
610046
|
+
const ppPort = existsSync107(ppPortFile) ? parseInt(readFileSync87(ppPortFile, "utf8").trim(), 10) : void 0;
|
|
609240
610047
|
if (ppPid > 0 && !registry2.daemons.has("PersonaPlex")) {
|
|
609241
610048
|
registry2.register({ name: "PersonaPlex", pid: ppPid, port: ppPort, startedAt: Date.now(), status: "running" });
|
|
609242
610049
|
}
|
|
609243
610050
|
}
|
|
609244
610051
|
}
|
|
609245
|
-
const nexusPidFile =
|
|
609246
|
-
if (
|
|
609247
|
-
const nPid = parseInt(
|
|
610052
|
+
const nexusPidFile = join123(repoRoot, ".oa", "nexus", "daemon.pid");
|
|
610053
|
+
if (existsSync107(nexusPidFile)) {
|
|
610054
|
+
const nPid = parseInt(readFileSync87(nexusPidFile, "utf8").trim(), 10);
|
|
609248
610055
|
if (nPid > 0 && !registry2.daemons.has("Nexus")) {
|
|
609249
610056
|
try {
|
|
609250
610057
|
process.kill(nPid, 0);
|
|
@@ -609611,9 +610418,9 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
609611
610418
|
}
|
|
609612
610419
|
}
|
|
609613
610420
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
609614
|
-
const isImage = isImagePath(cleanPath) &&
|
|
609615
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
609616
|
-
const isMarkdown = !isImage && !isMedia && /\.(md|markdown)$/i.test(cleanPath) &&
|
|
610421
|
+
const isImage = isImagePath(cleanPath) && existsSync107(resolve39(repoRoot, cleanPath));
|
|
610422
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync107(resolve39(repoRoot, cleanPath));
|
|
610423
|
+
const isMarkdown = !isImage && !isMedia && /\.(md|markdown)$/i.test(cleanPath) && existsSync107(resolve39(repoRoot, cleanPath));
|
|
609617
610424
|
if (activeTask) {
|
|
609618
610425
|
if (activeTask.runner.isPaused) {
|
|
609619
610426
|
activeTask.runner.resume();
|
|
@@ -609622,7 +610429,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
609622
610429
|
if (isImage) {
|
|
609623
610430
|
try {
|
|
609624
610431
|
const imgPath = resolve39(repoRoot, cleanPath);
|
|
609625
|
-
const imgBuffer =
|
|
610432
|
+
const imgBuffer = readFileSync87(imgPath);
|
|
609626
610433
|
const base642 = imgBuffer.toString("base64");
|
|
609627
610434
|
const ext = extname12(cleanPath).toLowerCase();
|
|
609628
610435
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -609778,7 +610585,7 @@ ${result.text}`;
|
|
|
609778
610585
|
if (isMarkdown && fullInput === input) {
|
|
609779
610586
|
try {
|
|
609780
610587
|
const mdPath = resolve39(repoRoot, cleanPath);
|
|
609781
|
-
const mdContent =
|
|
610588
|
+
const mdContent = readFileSync87(mdPath, "utf8");
|
|
609782
610589
|
const { parseMcpMarkdown: parseMcpMarkdown2 } = await Promise.resolve().then(() => (init_dist5(), dist_exports));
|
|
609783
610590
|
const result = parseMcpMarkdown2(mdContent);
|
|
609784
610591
|
if (result.servers.length > 0) {
|
|
@@ -610200,11 +611007,11 @@ async function runWithTUI(task, config, repoPath, callbacks) {
|
|
|
610200
611007
|
const handle2 = startTask(task, config, repoRoot);
|
|
610201
611008
|
await handle2.promise;
|
|
610202
611009
|
try {
|
|
610203
|
-
const ikDir =
|
|
610204
|
-
const ikFile =
|
|
611010
|
+
const ikDir = join123(repoRoot, ".oa", "identity");
|
|
611011
|
+
const ikFile = join123(ikDir, "self-state.json");
|
|
610205
611012
|
let ikState;
|
|
610206
|
-
if (
|
|
610207
|
-
ikState = JSON.parse(
|
|
611013
|
+
if (existsSync107(ikFile)) {
|
|
611014
|
+
ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
|
|
610208
611015
|
} else {
|
|
610209
611016
|
mkdirSync64(ikDir, { recursive: true });
|
|
610210
611017
|
ikState = {
|
|
@@ -610241,11 +611048,11 @@ async function runWithTUI(task, config, repoPath, callbacks) {
|
|
|
610241
611048
|
);
|
|
610242
611049
|
} catch {
|
|
610243
611050
|
try {
|
|
610244
|
-
const archeDir =
|
|
610245
|
-
const archeFile =
|
|
611051
|
+
const archeDir = join123(repoRoot, ".oa", "arche");
|
|
611052
|
+
const archeFile = join123(archeDir, "variants.json");
|
|
610246
611053
|
let variants = [];
|
|
610247
611054
|
try {
|
|
610248
|
-
if (
|
|
611055
|
+
if (existsSync107(archeFile)) variants = JSON.parse(readFileSync87(archeFile, "utf8"));
|
|
610249
611056
|
} catch {
|
|
610250
611057
|
}
|
|
610251
611058
|
variants.push({
|
|
@@ -610265,9 +611072,9 @@ async function runWithTUI(task, config, repoPath, callbacks) {
|
|
|
610265
611072
|
}
|
|
610266
611073
|
}
|
|
610267
611074
|
try {
|
|
610268
|
-
const metaFile =
|
|
610269
|
-
if (
|
|
610270
|
-
const store2 = JSON.parse(
|
|
611075
|
+
const metaFile = join123(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
611076
|
+
if (existsSync107(metaFile)) {
|
|
611077
|
+
const store2 = JSON.parse(readFileSync87(metaFile, "utf8"));
|
|
610271
611078
|
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);
|
|
610272
611079
|
let updated = false;
|
|
610273
611080
|
for (const item of surfaced) {
|
|
@@ -610331,9 +611138,9 @@ Rules:
|
|
|
610331
611138
|
try {
|
|
610332
611139
|
const { initDb: initDb2 } = __require("@open-agents/memory");
|
|
610333
611140
|
const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
610334
|
-
const dbDir =
|
|
611141
|
+
const dbDir = join123(repoRoot, ".oa", "memory");
|
|
610335
611142
|
mkdirSync64(dbDir, { recursive: true });
|
|
610336
|
-
const db = initDb2(
|
|
611143
|
+
const db = initDb2(join123(dbDir, "structured.db"));
|
|
610337
611144
|
const memStore = new ProceduralMemoryStore2(db);
|
|
610338
611145
|
memStore.createWithEmbedding({
|
|
610339
611146
|
content: content.slice(0, 600),
|
|
@@ -610348,11 +611155,11 @@ Rules:
|
|
|
610348
611155
|
db.close();
|
|
610349
611156
|
} catch {
|
|
610350
611157
|
}
|
|
610351
|
-
const metaDir =
|
|
610352
|
-
const storeFile =
|
|
611158
|
+
const metaDir = join123(repoRoot, ".oa", "memory", "metabolism");
|
|
611159
|
+
const storeFile = join123(metaDir, "store.json");
|
|
610353
611160
|
let store2 = [];
|
|
610354
611161
|
try {
|
|
610355
|
-
if (
|
|
611162
|
+
if (existsSync107(storeFile)) store2 = JSON.parse(readFileSync87(storeFile, "utf8"));
|
|
610356
611163
|
} catch {
|
|
610357
611164
|
}
|
|
610358
611165
|
store2.push({
|
|
@@ -610374,19 +611181,19 @@ Rules:
|
|
|
610374
611181
|
} catch {
|
|
610375
611182
|
}
|
|
610376
611183
|
try {
|
|
610377
|
-
const cohereSettingsFile =
|
|
611184
|
+
const cohereSettingsFile = join123(repoRoot, ".oa", "settings.json");
|
|
610378
611185
|
let cohereActive = false;
|
|
610379
611186
|
try {
|
|
610380
|
-
if (
|
|
610381
|
-
const settings = JSON.parse(
|
|
611187
|
+
if (existsSync107(cohereSettingsFile)) {
|
|
611188
|
+
const settings = JSON.parse(readFileSync87(cohereSettingsFile, "utf8"));
|
|
610382
611189
|
cohereActive = settings.cohere === true;
|
|
610383
611190
|
}
|
|
610384
611191
|
} catch {
|
|
610385
611192
|
}
|
|
610386
611193
|
if (cohereActive) {
|
|
610387
|
-
const metaFile =
|
|
610388
|
-
if (
|
|
610389
|
-
const store2 = JSON.parse(
|
|
611194
|
+
const metaFile = join123(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
611195
|
+
if (existsSync107(metaFile)) {
|
|
611196
|
+
const store2 = JSON.parse(readFileSync87(metaFile, "utf8"));
|
|
610390
611197
|
const latest = store2.filter((m2) => m2.sourceTrace === "trajectory-extraction" || m2.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
|
|
610391
611198
|
if (latest && latest.scores?.confidence >= 0.6) {
|
|
610392
611199
|
try {
|
|
@@ -610411,18 +611218,18 @@ Rules:
|
|
|
610411
611218
|
}
|
|
610412
611219
|
} catch (err) {
|
|
610413
611220
|
try {
|
|
610414
|
-
const ikFile =
|
|
610415
|
-
if (
|
|
610416
|
-
const ikState = JSON.parse(
|
|
611221
|
+
const ikFile = join123(repoRoot, ".oa", "identity", "self-state.json");
|
|
611222
|
+
if (existsSync107(ikFile)) {
|
|
611223
|
+
const ikState = JSON.parse(readFileSync87(ikFile, "utf8"));
|
|
610417
611224
|
ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
|
|
610418
611225
|
ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
|
|
610419
611226
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
610420
611227
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
610421
611228
|
writeFileSync56(ikFile, JSON.stringify(ikState, null, 2));
|
|
610422
611229
|
}
|
|
610423
|
-
const metaFile =
|
|
610424
|
-
if (
|
|
610425
|
-
const store2 = JSON.parse(
|
|
611230
|
+
const metaFile = join123(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
611231
|
+
if (existsSync107(metaFile)) {
|
|
611232
|
+
const store2 = JSON.parse(readFileSync87(metaFile, "utf8"));
|
|
610426
611233
|
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);
|
|
610427
611234
|
for (const item of surfaced) {
|
|
610428
611235
|
item.accessCount = (item.accessCount || 0) + 1;
|
|
@@ -610433,11 +611240,11 @@ Rules:
|
|
|
610433
611240
|
writeFileSync56(metaFile, JSON.stringify(store2, null, 2));
|
|
610434
611241
|
}
|
|
610435
611242
|
try {
|
|
610436
|
-
const archeDir =
|
|
610437
|
-
const archeFile =
|
|
611243
|
+
const archeDir = join123(repoRoot, ".oa", "arche");
|
|
611244
|
+
const archeFile = join123(archeDir, "variants.json");
|
|
610438
611245
|
let variants = [];
|
|
610439
611246
|
try {
|
|
610440
|
-
if (
|
|
611247
|
+
if (existsSync107(archeFile)) variants = JSON.parse(readFileSync87(archeFile, "utf8"));
|
|
610441
611248
|
} catch {
|
|
610442
611249
|
}
|
|
610443
611250
|
variants.push({
|
|
@@ -610541,12 +611348,12 @@ __export(run_exports, {
|
|
|
610541
611348
|
});
|
|
610542
611349
|
import { resolve as resolve40 } from "node:path";
|
|
610543
611350
|
import { spawn as spawn26 } from "node:child_process";
|
|
610544
|
-
import { mkdirSync as mkdirSync65, writeFileSync as writeFileSync57, readFileSync as
|
|
611351
|
+
import { mkdirSync as mkdirSync65, writeFileSync as writeFileSync57, readFileSync as readFileSync88, readdirSync as readdirSync38, existsSync as existsSync108 } from "node:fs";
|
|
610545
611352
|
import { randomBytes as randomBytes24 } from "node:crypto";
|
|
610546
|
-
import { join as
|
|
611353
|
+
import { join as join124 } from "node:path";
|
|
610547
611354
|
function jobsDir2(repoPath) {
|
|
610548
611355
|
const root = resolve40(repoPath ?? process.cwd());
|
|
610549
|
-
const dir =
|
|
611356
|
+
const dir = join124(root, ".oa", "jobs");
|
|
610550
611357
|
mkdirSync65(dir, { recursive: true });
|
|
610551
611358
|
return dir;
|
|
610552
611359
|
}
|
|
@@ -610669,7 +611476,7 @@ async function runBackground(task, config, opts) {
|
|
|
610669
611476
|
}
|
|
610670
611477
|
});
|
|
610671
611478
|
job.pid = child.pid ?? 0;
|
|
610672
|
-
writeFileSync57(
|
|
611479
|
+
writeFileSync57(join124(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
610673
611480
|
let output = "";
|
|
610674
611481
|
child.stdout?.on("data", (chunk) => {
|
|
610675
611482
|
output += chunk.toString();
|
|
@@ -610685,7 +611492,7 @@ async function runBackground(task, config, opts) {
|
|
|
610685
611492
|
job.summary = result.summary;
|
|
610686
611493
|
job.durationMs = result.durationMs;
|
|
610687
611494
|
job.error = result.error;
|
|
610688
|
-
writeFileSync57(
|
|
611495
|
+
writeFileSync57(join124(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
610689
611496
|
} catch {
|
|
610690
611497
|
}
|
|
610691
611498
|
});
|
|
@@ -610701,13 +611508,13 @@ async function runBackground(task, config, opts) {
|
|
|
610701
611508
|
}
|
|
610702
611509
|
function statusCommand(jobId, repoPath) {
|
|
610703
611510
|
const dir = jobsDir2(repoPath);
|
|
610704
|
-
const file =
|
|
610705
|
-
if (!
|
|
611511
|
+
const file = join124(dir, `${jobId}.json`);
|
|
611512
|
+
if (!existsSync108(file)) {
|
|
610706
611513
|
console.error(`Job not found: ${jobId}`);
|
|
610707
611514
|
console.log(`Available jobs: oa jobs`);
|
|
610708
611515
|
process.exit(1);
|
|
610709
611516
|
}
|
|
610710
|
-
const job = JSON.parse(
|
|
611517
|
+
const job = JSON.parse(readFileSync88(file, "utf-8"));
|
|
610711
611518
|
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`;
|
|
610712
611519
|
const icon = job.status === "completed" ? "✓" : job.status === "failed" ? "✗" : "●";
|
|
610713
611520
|
console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
|
|
@@ -610728,7 +611535,7 @@ function jobsCommand(repoPath) {
|
|
|
610728
611535
|
console.log("Jobs:");
|
|
610729
611536
|
for (const file of files) {
|
|
610730
611537
|
try {
|
|
610731
|
-
const job = JSON.parse(
|
|
611538
|
+
const job = JSON.parse(readFileSync88(join124(dir, file), "utf-8"));
|
|
610732
611539
|
const icon = job.status === "completed" ? "✓" : job.status === "failed" ? "✗" : "●";
|
|
610733
611540
|
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`;
|
|
610734
611541
|
const cleanListTask = cleanForStorage(job.task) || job.task;
|
|
@@ -610752,13 +611559,13 @@ __export(index_repo_exports, {
|
|
|
610752
611559
|
indexRepoCommand: () => indexRepoCommand
|
|
610753
611560
|
});
|
|
610754
611561
|
import { resolve as resolve41 } from "node:path";
|
|
610755
|
-
import { existsSync as
|
|
611562
|
+
import { existsSync as existsSync109, statSync as statSync35 } from "node:fs";
|
|
610756
611563
|
import { cwd as cwd2 } from "node:process";
|
|
610757
611564
|
async function indexRepoCommand(opts, _config3) {
|
|
610758
611565
|
const repoRoot = resolve41(opts.repoPath ?? cwd2());
|
|
610759
611566
|
printHeader("Index Repository");
|
|
610760
611567
|
printInfo(`Indexing: ${repoRoot}`);
|
|
610761
|
-
if (!
|
|
611568
|
+
if (!existsSync109(repoRoot)) {
|
|
610762
611569
|
printError(`Path does not exist: ${repoRoot}`);
|
|
610763
611570
|
process.exit(1);
|
|
610764
611571
|
}
|
|
@@ -611010,8 +611817,8 @@ var config_exports2 = {};
|
|
|
611010
611817
|
__export(config_exports2, {
|
|
611011
611818
|
configCommand: () => configCommand
|
|
611012
611819
|
});
|
|
611013
|
-
import { join as
|
|
611014
|
-
import { homedir as
|
|
611820
|
+
import { join as join125, resolve as resolve42 } from "node:path";
|
|
611821
|
+
import { homedir as homedir45 } from "node:os";
|
|
611015
611822
|
import { cwd as cwd3 } from "node:process";
|
|
611016
611823
|
function redactIfSensitive(key, value2) {
|
|
611017
611824
|
if (SENSITIVE_KEYS.has(key) && typeof value2 === "string" && value2.length > 0) {
|
|
@@ -611092,7 +611899,7 @@ function handleShow(opts, config) {
|
|
|
611092
611899
|
}
|
|
611093
611900
|
}
|
|
611094
611901
|
printSection("Config File");
|
|
611095
|
-
printInfo(`~/.open-agents/config.json (${
|
|
611902
|
+
printInfo(`~/.open-agents/config.json (${join125(homedir45(), ".open-agents", "config.json")})`);
|
|
611096
611903
|
printSection("Priority Chain");
|
|
611097
611904
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
611098
611905
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -611131,7 +611938,7 @@ function handleSet(opts, _config3) {
|
|
|
611131
611938
|
const coerced = coerceForSettings(key, value2);
|
|
611132
611939
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
611133
611940
|
printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value2)}`);
|
|
611134
|
-
printInfo(`Saved to ${
|
|
611941
|
+
printInfo(`Saved to ${join125(repoRoot, ".oa", "settings.json")}`);
|
|
611135
611942
|
printInfo("This override applies only when running in this workspace.");
|
|
611136
611943
|
} catch (err) {
|
|
611137
611944
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -611316,7 +612123,7 @@ __export(eval_exports, {
|
|
|
611316
612123
|
});
|
|
611317
612124
|
import { tmpdir as tmpdir21 } from "node:os";
|
|
611318
612125
|
import { mkdirSync as mkdirSync66, writeFileSync as writeFileSync58 } from "node:fs";
|
|
611319
|
-
import { join as
|
|
612126
|
+
import { join as join126 } from "node:path";
|
|
611320
612127
|
async function evalCommand(opts, config) {
|
|
611321
612128
|
const suiteName = opts.suite ?? "basic";
|
|
611322
612129
|
const suite = SUITES[suiteName];
|
|
@@ -611445,10 +612252,10 @@ async function evalCommand(opts, config) {
|
|
|
611445
612252
|
process.exit(failed > 0 ? 1 : 0);
|
|
611446
612253
|
}
|
|
611447
612254
|
function createTempEvalRepo() {
|
|
611448
|
-
const dir =
|
|
612255
|
+
const dir = join126(tmpdir21(), `open-agents-eval-${Date.now()}`);
|
|
611449
612256
|
mkdirSync66(dir, { recursive: true });
|
|
611450
612257
|
writeFileSync58(
|
|
611451
|
-
|
|
612258
|
+
join126(dir, "package.json"),
|
|
611452
612259
|
JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n",
|
|
611453
612260
|
"utf8"
|
|
611454
612261
|
);
|
|
@@ -611512,7 +612319,7 @@ init_typed_node_events();
|
|
|
611512
612319
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
611513
612320
|
import { createRequire as createRequire7 } from "node:module";
|
|
611514
612321
|
import { fileURLToPath as fileURLToPath19 } from "node:url";
|
|
611515
|
-
import { dirname as dirname38, join as
|
|
612322
|
+
import { dirname as dirname38, join as join127 } from "node:path";
|
|
611516
612323
|
|
|
611517
612324
|
// packages/cli/src/cli.ts
|
|
611518
612325
|
init_typed_node_events();
|
|
@@ -611652,7 +612459,7 @@ init_output();
|
|
|
611652
612459
|
function getVersion5() {
|
|
611653
612460
|
try {
|
|
611654
612461
|
const require4 = createRequire7(import.meta.url);
|
|
611655
|
-
const pkgPath =
|
|
612462
|
+
const pkgPath = join127(dirname38(fileURLToPath19(import.meta.url)), "..", "package.json");
|
|
611656
612463
|
const pkg = require4(pkgPath);
|
|
611657
612464
|
return pkg.version;
|
|
611658
612465
|
} catch {
|
|
@@ -611967,11 +612774,11 @@ function crashLog(label, err) {
|
|
|
611967
612774
|
`;
|
|
611968
612775
|
try {
|
|
611969
612776
|
const { appendFileSync: appendFileSync9, mkdirSync: mkdirSync67 } = __require("node:fs");
|
|
611970
|
-
const { join:
|
|
611971
|
-
const { homedir:
|
|
611972
|
-
const logDir =
|
|
612777
|
+
const { join: join128 } = __require("node:path");
|
|
612778
|
+
const { homedir: homedir46 } = __require("node:os");
|
|
612779
|
+
const logDir = join128(homedir46(), ".open-agents");
|
|
611973
612780
|
mkdirSync67(logDir, { recursive: true });
|
|
611974
|
-
appendFileSync9(
|
|
612781
|
+
appendFileSync9(join128(logDir, "crash.log"), logLine);
|
|
611975
612782
|
} catch {
|
|
611976
612783
|
}
|
|
611977
612784
|
try {
|