open-agents-ai 0.103.11 → 0.103.13
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 +579 -357
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5422,8 +5422,8 @@ function deleteCustomToolDefinition(name, scope, repoRoot) {
|
|
|
5422
5422
|
const dir = scope === "project" && repoRoot ? projectToolsDir(repoRoot) : globalToolsDir();
|
|
5423
5423
|
const filePath = join13(dir, `${name}.json`);
|
|
5424
5424
|
if (existsSync10(filePath)) {
|
|
5425
|
-
const { unlinkSync:
|
|
5426
|
-
|
|
5425
|
+
const { unlinkSync: unlinkSync8 } = __require("node:fs");
|
|
5426
|
+
unlinkSync8(filePath);
|
|
5427
5427
|
return true;
|
|
5428
5428
|
}
|
|
5429
5429
|
return false;
|
|
@@ -16290,8 +16290,8 @@ var init_verifierRunner = __esm({
|
|
|
16290
16290
|
if (patch.testsToRun.length === 0)
|
|
16291
16291
|
return "(no tests specified)";
|
|
16292
16292
|
const { execFile: execFile6 } = await import("node:child_process");
|
|
16293
|
-
const { promisify:
|
|
16294
|
-
const execFileAsync5 =
|
|
16293
|
+
const { promisify: promisify6 } = await import("node:util");
|
|
16294
|
+
const execFileAsync5 = promisify6(execFile6);
|
|
16295
16295
|
const outputs = [];
|
|
16296
16296
|
const workDir = this.options.workingDir || repoRoot;
|
|
16297
16297
|
for (const cmd of patch.testsToRun.slice(0, 3)) {
|
|
@@ -18258,9 +18258,9 @@ ${marker}` : marker);
|
|
|
18258
18258
|
if (!this._workingDirectory)
|
|
18259
18259
|
return;
|
|
18260
18260
|
try {
|
|
18261
|
-
const { mkdirSync: mkdirSync19, writeFileSync:
|
|
18262
|
-
const { join:
|
|
18263
|
-
const sessionDir =
|
|
18261
|
+
const { mkdirSync: mkdirSync19, writeFileSync: writeFileSync18 } = __require("node:fs");
|
|
18262
|
+
const { join: join55 } = __require("node:path");
|
|
18263
|
+
const sessionDir = join55(this._workingDirectory, ".oa", "session", this._sessionId);
|
|
18264
18264
|
mkdirSync19(sessionDir, { recursive: true });
|
|
18265
18265
|
const checkpoint = {
|
|
18266
18266
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -18273,7 +18273,7 @@ ${marker}` : marker);
|
|
|
18273
18273
|
memexEntryCount: this._memexArchive.size,
|
|
18274
18274
|
fileRegistrySize: this._fileRegistry.size
|
|
18275
18275
|
};
|
|
18276
|
-
|
|
18276
|
+
writeFileSync18(join55(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
|
|
18277
18277
|
} catch {
|
|
18278
18278
|
}
|
|
18279
18279
|
}
|
|
@@ -20362,9 +20362,9 @@ function ensureTranscribeCliBackground() {
|
|
|
20362
20362
|
} catch {
|
|
20363
20363
|
}
|
|
20364
20364
|
try {
|
|
20365
|
-
const { exec:
|
|
20365
|
+
const { exec: exec3 } = await import("node:child_process");
|
|
20366
20366
|
return new Promise((resolve31) => {
|
|
20367
|
-
|
|
20367
|
+
exec3("npm i -g transcribe-cli", { timeout: 18e4 }, (err) => {
|
|
20368
20368
|
resolve31(!err);
|
|
20369
20369
|
});
|
|
20370
20370
|
});
|
|
@@ -25185,7 +25185,7 @@ function formatToolArgs(toolName, args, verbose) {
|
|
|
25185
25185
|
case "memory_write":
|
|
25186
25186
|
return `${args["topic"]}.${args["key"]}`;
|
|
25187
25187
|
case "task_complete":
|
|
25188
|
-
return
|
|
25188
|
+
return "";
|
|
25189
25189
|
case "aiwg_setup":
|
|
25190
25190
|
return String(args["framework"] ?? "sdlc");
|
|
25191
25191
|
case "aiwg_health":
|
|
@@ -26203,6 +26203,8 @@ import { EventEmitter as EventEmitter3 } from "node:events";
|
|
|
26203
26203
|
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
26204
26204
|
import { URL as URL2 } from "node:url";
|
|
26205
26205
|
import { loadavg, cpus, totalmem, freemem } from "node:os";
|
|
26206
|
+
import { existsSync as existsSync26, readFileSync as readFileSync18, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3 } from "node:fs";
|
|
26207
|
+
import { join as join35 } from "node:path";
|
|
26206
26208
|
function cleanForwardHeaders(raw, targetHost) {
|
|
26207
26209
|
const out = {};
|
|
26208
26210
|
for (const [key, value] of Object.entries(raw)) {
|
|
@@ -26221,6 +26223,40 @@ function cleanForwardHeaders(raw, targetHost) {
|
|
|
26221
26223
|
out.host = targetHost;
|
|
26222
26224
|
return out;
|
|
26223
26225
|
}
|
|
26226
|
+
function readExposeState(stateDir) {
|
|
26227
|
+
try {
|
|
26228
|
+
const path = join35(stateDir, STATE_FILE_NAME);
|
|
26229
|
+
if (!existsSync26(path))
|
|
26230
|
+
return null;
|
|
26231
|
+
const raw = readFileSync18(path, "utf8");
|
|
26232
|
+
const data = JSON.parse(raw);
|
|
26233
|
+
if (!data.pid || !data.tunnelUrl || !data.authKey || !data.proxyPort)
|
|
26234
|
+
return null;
|
|
26235
|
+
return data;
|
|
26236
|
+
} catch {
|
|
26237
|
+
return null;
|
|
26238
|
+
}
|
|
26239
|
+
}
|
|
26240
|
+
function writeExposeState(stateDir, state) {
|
|
26241
|
+
try {
|
|
26242
|
+
writeFileSync8(join35(stateDir, STATE_FILE_NAME), JSON.stringify(state, null, 2));
|
|
26243
|
+
} catch {
|
|
26244
|
+
}
|
|
26245
|
+
}
|
|
26246
|
+
function removeExposeState(stateDir) {
|
|
26247
|
+
try {
|
|
26248
|
+
unlinkSync3(join35(stateDir, STATE_FILE_NAME));
|
|
26249
|
+
} catch {
|
|
26250
|
+
}
|
|
26251
|
+
}
|
|
26252
|
+
function isProcessAlive(pid) {
|
|
26253
|
+
try {
|
|
26254
|
+
process.kill(pid, 0);
|
|
26255
|
+
return true;
|
|
26256
|
+
} catch {
|
|
26257
|
+
return false;
|
|
26258
|
+
}
|
|
26259
|
+
}
|
|
26224
26260
|
async function collectSystemMetricsAsync() {
|
|
26225
26261
|
const [l1, l5, l15] = loadavg();
|
|
26226
26262
|
const cores = cpus().length;
|
|
@@ -26269,7 +26305,7 @@ async function collectSystemMetricsAsync() {
|
|
|
26269
26305
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
26270
26306
|
};
|
|
26271
26307
|
}
|
|
26272
|
-
var HOP_BY_HOP_HEADERS, CF_HEADERS_PREFIX, DEFAULT_TARGETS, ExposeGateway;
|
|
26308
|
+
var HOP_BY_HOP_HEADERS, CF_HEADERS_PREFIX, DEFAULT_TARGETS, STATE_FILE_NAME, ExposeGateway;
|
|
26273
26309
|
var init_expose = __esm({
|
|
26274
26310
|
"packages/cli/dist/tui/expose.js"() {
|
|
26275
26311
|
"use strict";
|
|
@@ -26291,14 +26327,18 @@ var init_expose = __esm({
|
|
|
26291
26327
|
llvm: "http://127.0.0.1:8080",
|
|
26292
26328
|
custom: "http://127.0.0.1:11434"
|
|
26293
26329
|
};
|
|
26294
|
-
|
|
26330
|
+
STATE_FILE_NAME = "expose-state.json";
|
|
26331
|
+
ExposeGateway = class _ExposeGateway extends EventEmitter3 {
|
|
26295
26332
|
options;
|
|
26296
26333
|
server = null;
|
|
26297
26334
|
cloudflaredProcess = null;
|
|
26335
|
+
/** PID of detached cloudflared (for killing on stop, even across OA restarts) */
|
|
26336
|
+
_cloudflaredPid = null;
|
|
26298
26337
|
_tunnelUrl = null;
|
|
26299
26338
|
_authKey;
|
|
26300
26339
|
_targetUrl;
|
|
26301
26340
|
_kind;
|
|
26341
|
+
_stateDir;
|
|
26302
26342
|
_stats = {
|
|
26303
26343
|
status: "standby",
|
|
26304
26344
|
totalRequests: 0,
|
|
@@ -26326,6 +26366,7 @@ var init_expose = __esm({
|
|
|
26326
26366
|
this.options = options;
|
|
26327
26367
|
this._kind = options.kind;
|
|
26328
26368
|
this._targetUrl = options.targetUrl ?? DEFAULT_TARGETS[options.kind];
|
|
26369
|
+
this._stateDir = options.stateDir ?? null;
|
|
26329
26370
|
if (options.authKey === void 0 || options.authKey === "") {
|
|
26330
26371
|
this._authKey = randomBytes7(24).toString("base64url");
|
|
26331
26372
|
} else {
|
|
@@ -26345,24 +26386,101 @@ var init_expose = __esm({
|
|
|
26345
26386
|
this._tunnelUrl = await this.startCloudflared(port);
|
|
26346
26387
|
this._stats.status = "active";
|
|
26347
26388
|
this.emitStats();
|
|
26389
|
+
if (this._stateDir) {
|
|
26390
|
+
writeExposeState(this._stateDir, {
|
|
26391
|
+
pid: this._cloudflaredPid,
|
|
26392
|
+
tunnelUrl: this._tunnelUrl,
|
|
26393
|
+
authKey: this._authKey,
|
|
26394
|
+
proxyPort: port,
|
|
26395
|
+
targetUrl: this._targetUrl,
|
|
26396
|
+
kind: this._kind,
|
|
26397
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
26398
|
+
});
|
|
26399
|
+
}
|
|
26400
|
+
return this._tunnelUrl;
|
|
26401
|
+
}
|
|
26402
|
+
/**
|
|
26403
|
+
* Reconnect to an existing detached cloudflared tunnel from a previous
|
|
26404
|
+
* OA session. Starts the proxy on the same port so cloudflared routes
|
|
26405
|
+
* traffic to it seamlessly.
|
|
26406
|
+
*/
|
|
26407
|
+
async reconnect(state) {
|
|
26408
|
+
if (this.server)
|
|
26409
|
+
throw new Error("Gateway already running");
|
|
26410
|
+
if (!isProcessAlive(state.pid)) {
|
|
26411
|
+
if (this._stateDir)
|
|
26412
|
+
removeExposeState(this._stateDir);
|
|
26413
|
+
throw new Error("Cloudflared process is no longer running");
|
|
26414
|
+
}
|
|
26415
|
+
this._tunnelUrl = state.tunnelUrl;
|
|
26416
|
+
this._authKey = state.authKey;
|
|
26417
|
+
this._targetUrl = state.targetUrl;
|
|
26418
|
+
this._kind = state.kind;
|
|
26419
|
+
this._cloudflaredPid = state.pid;
|
|
26420
|
+
this._proxyPort = state.proxyPort;
|
|
26421
|
+
this.server = this.createProxyServer(state.proxyPort);
|
|
26422
|
+
await new Promise((resolve31, reject) => {
|
|
26423
|
+
this.server.listen(state.proxyPort, "127.0.0.1", () => resolve31());
|
|
26424
|
+
this.server.on("error", reject);
|
|
26425
|
+
});
|
|
26426
|
+
this._stats.status = "active";
|
|
26427
|
+
this.emitStats();
|
|
26348
26428
|
return this._tunnelUrl;
|
|
26349
26429
|
}
|
|
26350
26430
|
async stop() {
|
|
26431
|
+
if (this._cloudflaredPid && isProcessAlive(this._cloudflaredPid)) {
|
|
26432
|
+
try {
|
|
26433
|
+
process.kill(this._cloudflaredPid, "SIGTERM");
|
|
26434
|
+
} catch {
|
|
26435
|
+
}
|
|
26436
|
+
}
|
|
26351
26437
|
if (this.cloudflaredProcess) {
|
|
26352
|
-
|
|
26438
|
+
try {
|
|
26439
|
+
this.cloudflaredProcess.kill("SIGTERM");
|
|
26440
|
+
} catch {
|
|
26441
|
+
}
|
|
26353
26442
|
this.cloudflaredProcess = null;
|
|
26354
26443
|
}
|
|
26444
|
+
this._cloudflaredPid = null;
|
|
26355
26445
|
if (this.server) {
|
|
26356
26446
|
await new Promise((resolve31) => {
|
|
26357
26447
|
this.server.close(() => resolve31());
|
|
26358
26448
|
});
|
|
26359
26449
|
this.server = null;
|
|
26360
26450
|
}
|
|
26451
|
+
if (this._stateDir)
|
|
26452
|
+
removeExposeState(this._stateDir);
|
|
26361
26453
|
this._tunnelUrl = null;
|
|
26362
26454
|
this._stats.status = "standby";
|
|
26363
26455
|
this._stats.activeConnections = 0;
|
|
26364
26456
|
this.emitStats();
|
|
26365
26457
|
}
|
|
26458
|
+
/**
|
|
26459
|
+
* Check for and reconnect to a surviving expose tunnel from a previous session.
|
|
26460
|
+
* Returns the gateway if reconnection succeeded, or null if no valid state found.
|
|
26461
|
+
*/
|
|
26462
|
+
static async checkAndReconnect(stateDir, options) {
|
|
26463
|
+
const state = readExposeState(stateDir);
|
|
26464
|
+
if (!state)
|
|
26465
|
+
return null;
|
|
26466
|
+
if (!isProcessAlive(state.pid)) {
|
|
26467
|
+
removeExposeState(stateDir);
|
|
26468
|
+
return null;
|
|
26469
|
+
}
|
|
26470
|
+
const gateway = new _ExposeGateway({
|
|
26471
|
+
kind: state.kind,
|
|
26472
|
+
targetUrl: state.targetUrl,
|
|
26473
|
+
authKey: state.authKey,
|
|
26474
|
+
stateDir,
|
|
26475
|
+
...options
|
|
26476
|
+
});
|
|
26477
|
+
try {
|
|
26478
|
+
await gateway.reconnect(state);
|
|
26479
|
+
return gateway;
|
|
26480
|
+
} catch {
|
|
26481
|
+
return null;
|
|
26482
|
+
}
|
|
26483
|
+
}
|
|
26366
26484
|
// ── Proxy server ────────────────────────────────────────────────────────
|
|
26367
26485
|
createProxyServer(localPort) {
|
|
26368
26486
|
const target = new URL2(this._targetUrl);
|
|
@@ -26539,8 +26657,10 @@ var init_expose = __esm({
|
|
|
26539
26657
|
"--proxy-keepalive-timeout",
|
|
26540
26658
|
"300s"
|
|
26541
26659
|
], {
|
|
26660
|
+
detached: true,
|
|
26542
26661
|
stdio: ["ignore", "pipe", "pipe"]
|
|
26543
26662
|
});
|
|
26663
|
+
this._cloudflaredPid = this.cloudflaredProcess.pid ?? null;
|
|
26544
26664
|
let urlFound = false;
|
|
26545
26665
|
const handleOutput = (data) => {
|
|
26546
26666
|
const text = data.toString();
|
|
@@ -26548,6 +26668,9 @@ var init_expose = __esm({
|
|
|
26548
26668
|
if (urlMatch && !urlFound) {
|
|
26549
26669
|
urlFound = true;
|
|
26550
26670
|
clearTimeout(timeout);
|
|
26671
|
+
this.cloudflaredProcess?.unref();
|
|
26672
|
+
this.cloudflaredProcess?.stdout?.destroy();
|
|
26673
|
+
this.cloudflaredProcess?.stderr?.destroy();
|
|
26551
26674
|
resolve31(urlMatch[0]);
|
|
26552
26675
|
}
|
|
26553
26676
|
};
|
|
@@ -26580,6 +26703,17 @@ var init_expose = __esm({
|
|
|
26580
26703
|
this._stats.status = "active";
|
|
26581
26704
|
this.emitStats();
|
|
26582
26705
|
this.options.onInfo?.(`Tunnel restarted: ${this._tunnelUrl}`);
|
|
26706
|
+
if (this._stateDir) {
|
|
26707
|
+
writeExposeState(this._stateDir, {
|
|
26708
|
+
pid: this._cloudflaredPid,
|
|
26709
|
+
tunnelUrl: this._tunnelUrl,
|
|
26710
|
+
authKey: this._authKey,
|
|
26711
|
+
proxyPort: this._proxyPort,
|
|
26712
|
+
targetUrl: this._targetUrl,
|
|
26713
|
+
kind: this._kind,
|
|
26714
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
26715
|
+
});
|
|
26716
|
+
}
|
|
26583
26717
|
} catch (err) {
|
|
26584
26718
|
this.options.onError?.(`Tunnel restart failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
26585
26719
|
}
|
|
@@ -26652,8 +26786,8 @@ var init_types = __esm({
|
|
|
26652
26786
|
|
|
26653
26787
|
// packages/cli/dist/tui/p2p/secret-vault.js
|
|
26654
26788
|
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes8, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
|
|
26655
|
-
import { readFileSync as
|
|
26656
|
-
import { join as
|
|
26789
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync9, existsSync as existsSync27, mkdirSync as mkdirSync8 } from "node:fs";
|
|
26790
|
+
import { join as join36, dirname as dirname13 } from "node:path";
|
|
26657
26791
|
var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
|
|
26658
26792
|
var init_secret_vault = __esm({
|
|
26659
26793
|
"packages/cli/dist/tui/p2p/secret-vault.js"() {
|
|
@@ -26865,18 +26999,18 @@ var init_secret_vault = __esm({
|
|
|
26865
26999
|
const tag = cipher.getAuthTag();
|
|
26866
27000
|
const blob = Buffer.concat([salt, iv, tag, encrypted]);
|
|
26867
27001
|
const dir = dirname13(this.storePath);
|
|
26868
|
-
if (!
|
|
27002
|
+
if (!existsSync27(dir))
|
|
26869
27003
|
mkdirSync8(dir, { recursive: true });
|
|
26870
|
-
|
|
27004
|
+
writeFileSync9(this.storePath, blob, { mode: 384 });
|
|
26871
27005
|
}
|
|
26872
27006
|
/**
|
|
26873
27007
|
* Load vault from disk, decrypting with the given passphrase.
|
|
26874
27008
|
* Returns the number of secrets loaded.
|
|
26875
27009
|
*/
|
|
26876
27010
|
load(passphrase) {
|
|
26877
|
-
if (!this.storePath || !
|
|
27011
|
+
if (!this.storePath || !existsSync27(this.storePath))
|
|
26878
27012
|
return 0;
|
|
26879
|
-
const blob =
|
|
27013
|
+
const blob = readFileSync19(this.storePath);
|
|
26880
27014
|
if (blob.length < SALT_LEN + IV_LEN + 16) {
|
|
26881
27015
|
throw new Error("Vault file is corrupted (too small)");
|
|
26882
27016
|
}
|
|
@@ -28096,17 +28230,17 @@ var init_render2 = __esm({
|
|
|
28096
28230
|
});
|
|
28097
28231
|
|
|
28098
28232
|
// packages/prompts/dist/promptLoader.js
|
|
28099
|
-
import { readFileSync as
|
|
28100
|
-
import { join as
|
|
28233
|
+
import { readFileSync as readFileSync20, existsSync as existsSync28 } from "node:fs";
|
|
28234
|
+
import { join as join37, dirname as dirname14 } from "node:path";
|
|
28101
28235
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
28102
28236
|
function loadPrompt2(promptPath, vars) {
|
|
28103
28237
|
let content = cache2.get(promptPath);
|
|
28104
28238
|
if (content === void 0) {
|
|
28105
|
-
const fullPath =
|
|
28106
|
-
if (!
|
|
28239
|
+
const fullPath = join37(PROMPTS_DIR2, promptPath);
|
|
28240
|
+
if (!existsSync28(fullPath)) {
|
|
28107
28241
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
28108
28242
|
}
|
|
28109
|
-
content =
|
|
28243
|
+
content = readFileSync20(fullPath, "utf-8");
|
|
28110
28244
|
cache2.set(promptPath, content);
|
|
28111
28245
|
}
|
|
28112
28246
|
if (!vars)
|
|
@@ -28119,9 +28253,9 @@ var init_promptLoader2 = __esm({
|
|
|
28119
28253
|
"use strict";
|
|
28120
28254
|
__filename2 = fileURLToPath9(import.meta.url);
|
|
28121
28255
|
__dirname5 = dirname14(__filename2);
|
|
28122
|
-
devPath =
|
|
28123
|
-
publishedPath =
|
|
28124
|
-
PROMPTS_DIR2 =
|
|
28256
|
+
devPath = join37(__dirname5, "..", "templates");
|
|
28257
|
+
publishedPath = join37(__dirname5, "..", "prompts", "templates");
|
|
28258
|
+
PROMPTS_DIR2 = existsSync28(devPath) ? devPath : publishedPath;
|
|
28125
28259
|
cache2 = /* @__PURE__ */ new Map();
|
|
28126
28260
|
}
|
|
28127
28261
|
});
|
|
@@ -28232,7 +28366,7 @@ var init_task_templates = __esm({
|
|
|
28232
28366
|
});
|
|
28233
28367
|
|
|
28234
28368
|
// packages/prompts/dist/index.js
|
|
28235
|
-
import { join as
|
|
28369
|
+
import { join as join38, dirname as dirname15 } from "node:path";
|
|
28236
28370
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
28237
28371
|
var _dir, _packageRoot;
|
|
28238
28372
|
var init_dist6 = __esm({
|
|
@@ -28243,26 +28377,26 @@ var init_dist6 = __esm({
|
|
|
28243
28377
|
init_task_templates();
|
|
28244
28378
|
init_render2();
|
|
28245
28379
|
_dir = dirname15(fileURLToPath10(import.meta.url));
|
|
28246
|
-
_packageRoot =
|
|
28380
|
+
_packageRoot = join38(_dir, "..");
|
|
28247
28381
|
}
|
|
28248
28382
|
});
|
|
28249
28383
|
|
|
28250
28384
|
// packages/cli/dist/tui/oa-directory.js
|
|
28251
|
-
import { existsSync as
|
|
28252
|
-
import { join as
|
|
28385
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync9, readFileSync as readFileSync21, writeFileSync as writeFileSync10, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync4 } from "node:fs";
|
|
28386
|
+
import { join as join39, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
|
|
28253
28387
|
import { homedir as homedir9 } from "node:os";
|
|
28254
28388
|
function initOaDirectory(repoRoot) {
|
|
28255
|
-
const oaPath =
|
|
28389
|
+
const oaPath = join39(repoRoot, OA_DIR);
|
|
28256
28390
|
for (const sub of SUBDIRS) {
|
|
28257
|
-
mkdirSync9(
|
|
28391
|
+
mkdirSync9(join39(oaPath, sub), { recursive: true });
|
|
28258
28392
|
}
|
|
28259
28393
|
try {
|
|
28260
|
-
const gitignorePath =
|
|
28394
|
+
const gitignorePath = join39(repoRoot, ".gitignore");
|
|
28261
28395
|
const settingsPattern = ".oa/settings.json";
|
|
28262
|
-
if (
|
|
28263
|
-
const content =
|
|
28396
|
+
if (existsSync29(gitignorePath)) {
|
|
28397
|
+
const content = readFileSync21(gitignorePath, "utf-8");
|
|
28264
28398
|
if (!content.includes(settingsPattern)) {
|
|
28265
|
-
|
|
28399
|
+
writeFileSync10(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
|
|
28266
28400
|
}
|
|
28267
28401
|
}
|
|
28268
28402
|
} catch {
|
|
@@ -28270,41 +28404,41 @@ function initOaDirectory(repoRoot) {
|
|
|
28270
28404
|
return oaPath;
|
|
28271
28405
|
}
|
|
28272
28406
|
function hasOaDirectory(repoRoot) {
|
|
28273
|
-
return
|
|
28407
|
+
return existsSync29(join39(repoRoot, OA_DIR, "index"));
|
|
28274
28408
|
}
|
|
28275
28409
|
function loadProjectSettings(repoRoot) {
|
|
28276
|
-
const settingsPath =
|
|
28410
|
+
const settingsPath = join39(repoRoot, OA_DIR, "settings.json");
|
|
28277
28411
|
try {
|
|
28278
|
-
if (
|
|
28279
|
-
return JSON.parse(
|
|
28412
|
+
if (existsSync29(settingsPath)) {
|
|
28413
|
+
return JSON.parse(readFileSync21(settingsPath, "utf-8"));
|
|
28280
28414
|
}
|
|
28281
28415
|
} catch {
|
|
28282
28416
|
}
|
|
28283
28417
|
return {};
|
|
28284
28418
|
}
|
|
28285
28419
|
function saveProjectSettings(repoRoot, settings) {
|
|
28286
|
-
const oaPath =
|
|
28420
|
+
const oaPath = join39(repoRoot, OA_DIR);
|
|
28287
28421
|
mkdirSync9(oaPath, { recursive: true });
|
|
28288
28422
|
const existing = loadProjectSettings(repoRoot);
|
|
28289
28423
|
const merged = { ...existing, ...settings };
|
|
28290
|
-
|
|
28424
|
+
writeFileSync10(join39(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
28291
28425
|
}
|
|
28292
28426
|
function loadGlobalSettings() {
|
|
28293
|
-
const settingsPath =
|
|
28427
|
+
const settingsPath = join39(homedir9(), ".open-agents", "settings.json");
|
|
28294
28428
|
try {
|
|
28295
|
-
if (
|
|
28296
|
-
return JSON.parse(
|
|
28429
|
+
if (existsSync29(settingsPath)) {
|
|
28430
|
+
return JSON.parse(readFileSync21(settingsPath, "utf-8"));
|
|
28297
28431
|
}
|
|
28298
28432
|
} catch {
|
|
28299
28433
|
}
|
|
28300
28434
|
return {};
|
|
28301
28435
|
}
|
|
28302
28436
|
function saveGlobalSettings(settings) {
|
|
28303
|
-
const dir =
|
|
28437
|
+
const dir = join39(homedir9(), ".open-agents");
|
|
28304
28438
|
mkdirSync9(dir, { recursive: true });
|
|
28305
28439
|
const existing = loadGlobalSettings();
|
|
28306
28440
|
const merged = { ...existing, ...settings };
|
|
28307
|
-
|
|
28441
|
+
writeFileSync10(join39(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
28308
28442
|
}
|
|
28309
28443
|
function resolveSettings(repoRoot) {
|
|
28310
28444
|
const global = loadGlobalSettings();
|
|
@@ -28319,12 +28453,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
28319
28453
|
while (dir && !visited.has(dir)) {
|
|
28320
28454
|
visited.add(dir);
|
|
28321
28455
|
for (const name of CONTEXT_FILES) {
|
|
28322
|
-
const filePath =
|
|
28456
|
+
const filePath = join39(dir, name);
|
|
28323
28457
|
const normalizedName = name.toLowerCase();
|
|
28324
|
-
if (
|
|
28458
|
+
if (existsSync29(filePath) && !seen.has(filePath)) {
|
|
28325
28459
|
seen.add(filePath);
|
|
28326
28460
|
try {
|
|
28327
|
-
let content =
|
|
28461
|
+
let content = readFileSync21(filePath, "utf-8");
|
|
28328
28462
|
if (content.length > maxContentLen) {
|
|
28329
28463
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
28330
28464
|
}
|
|
@@ -28338,11 +28472,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
28338
28472
|
}
|
|
28339
28473
|
}
|
|
28340
28474
|
}
|
|
28341
|
-
const projectMap =
|
|
28342
|
-
if (
|
|
28475
|
+
const projectMap = join39(dir, OA_DIR, "context", "project-map.md");
|
|
28476
|
+
if (existsSync29(projectMap) && !seen.has(projectMap)) {
|
|
28343
28477
|
seen.add(projectMap);
|
|
28344
28478
|
try {
|
|
28345
|
-
let content =
|
|
28479
|
+
let content = readFileSync21(projectMap, "utf-8");
|
|
28346
28480
|
if (content.length > maxContentLen) {
|
|
28347
28481
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
28348
28482
|
}
|
|
@@ -28354,7 +28488,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
28354
28488
|
} catch {
|
|
28355
28489
|
}
|
|
28356
28490
|
}
|
|
28357
|
-
const parent =
|
|
28491
|
+
const parent = join39(dir, "..");
|
|
28358
28492
|
if (parent === dir)
|
|
28359
28493
|
break;
|
|
28360
28494
|
dir = parent;
|
|
@@ -28372,9 +28506,9 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
28372
28506
|
return found;
|
|
28373
28507
|
}
|
|
28374
28508
|
function readIndexMeta(repoRoot) {
|
|
28375
|
-
const metaPath =
|
|
28509
|
+
const metaPath = join39(repoRoot, OA_DIR, "index", "meta.json");
|
|
28376
28510
|
try {
|
|
28377
|
-
return JSON.parse(
|
|
28511
|
+
return JSON.parse(readFileSync21(metaPath, "utf-8"));
|
|
28378
28512
|
} catch {
|
|
28379
28513
|
return null;
|
|
28380
28514
|
}
|
|
@@ -28425,28 +28559,28 @@ ${tree}\`\`\`
|
|
|
28425
28559
|
sections.push("");
|
|
28426
28560
|
}
|
|
28427
28561
|
const content = sections.join("\n");
|
|
28428
|
-
const contextDir =
|
|
28562
|
+
const contextDir = join39(repoRoot, OA_DIR, "context");
|
|
28429
28563
|
mkdirSync9(contextDir, { recursive: true });
|
|
28430
|
-
|
|
28564
|
+
writeFileSync10(join39(contextDir, "project-map.md"), content, "utf-8");
|
|
28431
28565
|
return content;
|
|
28432
28566
|
}
|
|
28433
28567
|
function saveSession(repoRoot, session) {
|
|
28434
|
-
const historyDir =
|
|
28568
|
+
const historyDir = join39(repoRoot, OA_DIR, "history");
|
|
28435
28569
|
mkdirSync9(historyDir, { recursive: true });
|
|
28436
|
-
|
|
28570
|
+
writeFileSync10(join39(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
|
|
28437
28571
|
}
|
|
28438
28572
|
function loadRecentSessions(repoRoot, limit = 5) {
|
|
28439
|
-
const historyDir =
|
|
28440
|
-
if (!
|
|
28573
|
+
const historyDir = join39(repoRoot, OA_DIR, "history");
|
|
28574
|
+
if (!existsSync29(historyDir))
|
|
28441
28575
|
return [];
|
|
28442
28576
|
try {
|
|
28443
28577
|
const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
|
|
28444
|
-
const stat5 = statSync9(
|
|
28578
|
+
const stat5 = statSync9(join39(historyDir, f));
|
|
28445
28579
|
return { file: f, mtime: stat5.mtimeMs };
|
|
28446
28580
|
}).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
|
|
28447
28581
|
return files.map((f) => {
|
|
28448
28582
|
try {
|
|
28449
|
-
return JSON.parse(
|
|
28583
|
+
return JSON.parse(readFileSync21(join39(historyDir, f.file), "utf-8"));
|
|
28450
28584
|
} catch {
|
|
28451
28585
|
return null;
|
|
28452
28586
|
}
|
|
@@ -28456,18 +28590,18 @@ function loadRecentSessions(repoRoot, limit = 5) {
|
|
|
28456
28590
|
}
|
|
28457
28591
|
}
|
|
28458
28592
|
function savePendingTask(repoRoot, task) {
|
|
28459
|
-
const historyDir =
|
|
28593
|
+
const historyDir = join39(repoRoot, OA_DIR, "history");
|
|
28460
28594
|
mkdirSync9(historyDir, { recursive: true });
|
|
28461
|
-
|
|
28595
|
+
writeFileSync10(join39(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
|
|
28462
28596
|
}
|
|
28463
28597
|
function loadPendingTask(repoRoot) {
|
|
28464
|
-
const filePath =
|
|
28598
|
+
const filePath = join39(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
|
|
28465
28599
|
try {
|
|
28466
|
-
if (!
|
|
28600
|
+
if (!existsSync29(filePath))
|
|
28467
28601
|
return null;
|
|
28468
|
-
const data = JSON.parse(
|
|
28602
|
+
const data = JSON.parse(readFileSync21(filePath, "utf-8"));
|
|
28469
28603
|
try {
|
|
28470
|
-
|
|
28604
|
+
unlinkSync4(filePath);
|
|
28471
28605
|
} catch {
|
|
28472
28606
|
}
|
|
28473
28607
|
return data;
|
|
@@ -28476,13 +28610,13 @@ function loadPendingTask(repoRoot) {
|
|
|
28476
28610
|
}
|
|
28477
28611
|
}
|
|
28478
28612
|
function saveSessionContext(repoRoot, entry) {
|
|
28479
|
-
const contextDir =
|
|
28613
|
+
const contextDir = join39(repoRoot, OA_DIR, "context");
|
|
28480
28614
|
mkdirSync9(contextDir, { recursive: true });
|
|
28481
|
-
const filePath =
|
|
28615
|
+
const filePath = join39(contextDir, CONTEXT_SAVE_FILE);
|
|
28482
28616
|
let ctx;
|
|
28483
28617
|
try {
|
|
28484
|
-
if (
|
|
28485
|
-
ctx = JSON.parse(
|
|
28618
|
+
if (existsSync29(filePath)) {
|
|
28619
|
+
ctx = JSON.parse(readFileSync21(filePath, "utf-8"));
|
|
28486
28620
|
} else {
|
|
28487
28621
|
ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
|
|
28488
28622
|
}
|
|
@@ -28494,14 +28628,14 @@ function saveSessionContext(repoRoot, entry) {
|
|
|
28494
28628
|
ctx.entries = ctx.entries.slice(-ctx.maxEntries);
|
|
28495
28629
|
}
|
|
28496
28630
|
ctx.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
28497
|
-
|
|
28631
|
+
writeFileSync10(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
|
|
28498
28632
|
}
|
|
28499
28633
|
function loadSessionContext(repoRoot) {
|
|
28500
|
-
const filePath =
|
|
28634
|
+
const filePath = join39(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
|
|
28501
28635
|
try {
|
|
28502
|
-
if (!
|
|
28636
|
+
if (!existsSync29(filePath))
|
|
28503
28637
|
return null;
|
|
28504
|
-
return JSON.parse(
|
|
28638
|
+
return JSON.parse(readFileSync21(filePath, "utf-8"));
|
|
28505
28639
|
} catch {
|
|
28506
28640
|
return null;
|
|
28507
28641
|
}
|
|
@@ -28548,12 +28682,12 @@ function detectManifests(repoRoot) {
|
|
|
28548
28682
|
{ file: "docker-compose.yaml", type: "Docker Compose" }
|
|
28549
28683
|
];
|
|
28550
28684
|
for (const check of checks) {
|
|
28551
|
-
const filePath =
|
|
28552
|
-
if (
|
|
28685
|
+
const filePath = join39(repoRoot, check.file);
|
|
28686
|
+
if (existsSync29(filePath)) {
|
|
28553
28687
|
let name;
|
|
28554
28688
|
if (check.nameField) {
|
|
28555
28689
|
try {
|
|
28556
|
-
const data = JSON.parse(
|
|
28690
|
+
const data = JSON.parse(readFileSync21(filePath, "utf-8"));
|
|
28557
28691
|
name = data[check.nameField];
|
|
28558
28692
|
} catch {
|
|
28559
28693
|
}
|
|
@@ -28582,7 +28716,7 @@ function findKeyFiles(repoRoot) {
|
|
|
28582
28716
|
{ pattern: "CLAUDE.md", description: "Claude Code context" }
|
|
28583
28717
|
];
|
|
28584
28718
|
for (const check of checks) {
|
|
28585
|
-
if (
|
|
28719
|
+
if (existsSync29(join39(repoRoot, check.pattern))) {
|
|
28586
28720
|
keyFiles.push({ path: check.pattern, description: check.description });
|
|
28587
28721
|
}
|
|
28588
28722
|
}
|
|
@@ -28608,12 +28742,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
28608
28742
|
if (entry.isDirectory()) {
|
|
28609
28743
|
let fileCount = 0;
|
|
28610
28744
|
try {
|
|
28611
|
-
fileCount = readdirSync7(
|
|
28745
|
+
fileCount = readdirSync7(join39(root, entry.name)).filter((f) => !f.startsWith(".")).length;
|
|
28612
28746
|
} catch {
|
|
28613
28747
|
}
|
|
28614
28748
|
result += `${prefix}${connector}${entry.name}/ (${fileCount})
|
|
28615
28749
|
`;
|
|
28616
|
-
result += buildDirTree(
|
|
28750
|
+
result += buildDirTree(join39(root, entry.name), maxDepth, childPrefix, depth + 1);
|
|
28617
28751
|
} else if (depth < maxDepth) {
|
|
28618
28752
|
result += `${prefix}${connector}${entry.name}
|
|
28619
28753
|
`;
|
|
@@ -28625,17 +28759,17 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
28625
28759
|
}
|
|
28626
28760
|
function loadUsageFile(filePath) {
|
|
28627
28761
|
try {
|
|
28628
|
-
if (
|
|
28629
|
-
return JSON.parse(
|
|
28762
|
+
if (existsSync29(filePath)) {
|
|
28763
|
+
return JSON.parse(readFileSync21(filePath, "utf-8"));
|
|
28630
28764
|
}
|
|
28631
28765
|
} catch {
|
|
28632
28766
|
}
|
|
28633
28767
|
return { records: [] };
|
|
28634
28768
|
}
|
|
28635
28769
|
function saveUsageFile(filePath, data) {
|
|
28636
|
-
const dir =
|
|
28770
|
+
const dir = join39(filePath, "..");
|
|
28637
28771
|
mkdirSync9(dir, { recursive: true });
|
|
28638
|
-
|
|
28772
|
+
writeFileSync10(filePath, JSON.stringify(data, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
28639
28773
|
}
|
|
28640
28774
|
function recordUsage(kind, value, opts) {
|
|
28641
28775
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -28663,15 +28797,15 @@ function recordUsage(kind, value, opts) {
|
|
|
28663
28797
|
}
|
|
28664
28798
|
saveUsageFile(filePath, data);
|
|
28665
28799
|
};
|
|
28666
|
-
update(
|
|
28800
|
+
update(join39(homedir9(), ".open-agents", USAGE_HISTORY_FILE));
|
|
28667
28801
|
if (opts?.repoRoot) {
|
|
28668
|
-
update(
|
|
28802
|
+
update(join39(opts.repoRoot, OA_DIR, USAGE_HISTORY_FILE));
|
|
28669
28803
|
}
|
|
28670
28804
|
}
|
|
28671
28805
|
function loadUsageHistory(kind, repoRoot) {
|
|
28672
|
-
const globalPath =
|
|
28806
|
+
const globalPath = join39(homedir9(), ".open-agents", USAGE_HISTORY_FILE);
|
|
28673
28807
|
const globalData = loadUsageFile(globalPath);
|
|
28674
|
-
const localData = repoRoot ? loadUsageFile(
|
|
28808
|
+
const localData = repoRoot ? loadUsageFile(join39(repoRoot, OA_DIR, USAGE_HISTORY_FILE)) : { records: [] };
|
|
28675
28809
|
const map = /* @__PURE__ */ new Map();
|
|
28676
28810
|
for (const r of globalData.records) {
|
|
28677
28811
|
if (r.kind !== kind)
|
|
@@ -28738,9 +28872,10 @@ var init_oa_directory = __esm({
|
|
|
28738
28872
|
|
|
28739
28873
|
// packages/cli/dist/tui/setup.js
|
|
28740
28874
|
import * as readline from "node:readline";
|
|
28741
|
-
import { execSync as execSync25, spawn as spawn15 } from "node:child_process";
|
|
28742
|
-
import {
|
|
28743
|
-
import {
|
|
28875
|
+
import { execSync as execSync25, spawn as spawn15, exec as exec2 } from "node:child_process";
|
|
28876
|
+
import { promisify as promisify5 } from "node:util";
|
|
28877
|
+
import { existsSync as existsSync30, writeFileSync as writeFileSync11, mkdirSync as mkdirSync10 } from "node:fs";
|
|
28878
|
+
import { join as join40 } from "node:path";
|
|
28744
28879
|
import { homedir as homedir10, platform } from "node:os";
|
|
28745
28880
|
function detectSystemSpecs() {
|
|
28746
28881
|
let totalRamGB = 0;
|
|
@@ -28789,6 +28924,50 @@ function detectSystemSpecs() {
|
|
|
28789
28924
|
gpuName
|
|
28790
28925
|
};
|
|
28791
28926
|
}
|
|
28927
|
+
async function detectSystemSpecsAsync() {
|
|
28928
|
+
let totalRamGB = 0;
|
|
28929
|
+
let availableRamGB = 0;
|
|
28930
|
+
let gpuVramGB = 0;
|
|
28931
|
+
let gpuName = "";
|
|
28932
|
+
try {
|
|
28933
|
+
const { stdout: memInfo } = await execAsync("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", { timeout: 5e3 });
|
|
28934
|
+
if (memInfo.includes("Mem:")) {
|
|
28935
|
+
const match = memInfo.match(/^Mem:\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)/m);
|
|
28936
|
+
if (match) {
|
|
28937
|
+
totalRamGB = parseInt(match[1], 10) / 1024 ** 3;
|
|
28938
|
+
availableRamGB = parseInt(match[2], 10) / 1024 ** 3;
|
|
28939
|
+
}
|
|
28940
|
+
} else {
|
|
28941
|
+
const bytes = parseInt(memInfo.trim(), 10);
|
|
28942
|
+
if (!isNaN(bytes)) {
|
|
28943
|
+
totalRamGB = bytes / 1024 ** 3;
|
|
28944
|
+
availableRamGB = totalRamGB * 0.7;
|
|
28945
|
+
}
|
|
28946
|
+
}
|
|
28947
|
+
} catch {
|
|
28948
|
+
}
|
|
28949
|
+
try {
|
|
28950
|
+
const { stdout: nvidiaSmi } = await execAsync("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { timeout: 5e3 });
|
|
28951
|
+
const lines = nvidiaSmi.trim().split("\n");
|
|
28952
|
+
if (lines.length > 0) {
|
|
28953
|
+
for (const line of lines) {
|
|
28954
|
+
const parts = line.split(",").map((s) => s.trim());
|
|
28955
|
+
const vramMB = parseInt(parts[0] ?? "0", 10);
|
|
28956
|
+
if (!isNaN(vramMB))
|
|
28957
|
+
gpuVramGB += vramMB / 1024;
|
|
28958
|
+
if (!gpuName && parts[1])
|
|
28959
|
+
gpuName = parts[1];
|
|
28960
|
+
}
|
|
28961
|
+
}
|
|
28962
|
+
} catch {
|
|
28963
|
+
}
|
|
28964
|
+
return {
|
|
28965
|
+
totalRamGB: Math.round(totalRamGB * 10) / 10,
|
|
28966
|
+
availableRamGB: Math.round(availableRamGB * 10) / 10,
|
|
28967
|
+
gpuVramGB: Math.round(gpuVramGB * 10) / 10,
|
|
28968
|
+
gpuName
|
|
28969
|
+
};
|
|
28970
|
+
}
|
|
28792
28971
|
function recommendModel(specs) {
|
|
28793
28972
|
const effectiveGB = Math.max(specs.gpuVramGB, specs.availableRamGB);
|
|
28794
28973
|
const budget = effectiveGB * 0.8;
|
|
@@ -28973,7 +29152,7 @@ async function installOllamaMac(_rl) {
|
|
|
28973
29152
|
execSync25('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
|
|
28974
29153
|
if (!hasCmd("brew")) {
|
|
28975
29154
|
try {
|
|
28976
|
-
const brewPrefix =
|
|
29155
|
+
const brewPrefix = existsSync30("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
|
|
28977
29156
|
process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
|
|
28978
29157
|
} catch {
|
|
28979
29158
|
}
|
|
@@ -29727,10 +29906,10 @@ async function doSetup(config, rl) {
|
|
|
29727
29906
|
`PARAMETER num_predict ${numPredict}`,
|
|
29728
29907
|
`PARAMETER stop "<|endoftext|>"`
|
|
29729
29908
|
].join("\n");
|
|
29730
|
-
const modelDir2 =
|
|
29909
|
+
const modelDir2 = join40(homedir10(), ".open-agents", "models");
|
|
29731
29910
|
mkdirSync10(modelDir2, { recursive: true });
|
|
29732
|
-
const modelfilePath =
|
|
29733
|
-
|
|
29911
|
+
const modelfilePath = join40(modelDir2, `Modelfile.${customName}`);
|
|
29912
|
+
writeFileSync11(modelfilePath, modelfileContent + "\n", "utf8");
|
|
29734
29913
|
process.stdout.write(` ${c2.dim("Creating model...")} `);
|
|
29735
29914
|
execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
29736
29915
|
stdio: "pipe",
|
|
@@ -29775,7 +29954,7 @@ async function isModelAvailable(config) {
|
|
|
29775
29954
|
}
|
|
29776
29955
|
function isFirstRun() {
|
|
29777
29956
|
try {
|
|
29778
|
-
return !
|
|
29957
|
+
return !existsSync30(join40(homedir10(), ".open-agents", "config.json"));
|
|
29779
29958
|
} catch {
|
|
29780
29959
|
return true;
|
|
29781
29960
|
}
|
|
@@ -29812,7 +29991,7 @@ function detectPkgManager() {
|
|
|
29812
29991
|
return null;
|
|
29813
29992
|
}
|
|
29814
29993
|
function getVenvDir() {
|
|
29815
|
-
return
|
|
29994
|
+
return join40(homedir10(), ".open-agents", "venv");
|
|
29816
29995
|
}
|
|
29817
29996
|
function hasVenvModule() {
|
|
29818
29997
|
try {
|
|
@@ -29824,8 +30003,8 @@ function hasVenvModule() {
|
|
|
29824
30003
|
}
|
|
29825
30004
|
function ensureVenv(log) {
|
|
29826
30005
|
const venvDir = getVenvDir();
|
|
29827
|
-
const venvPip =
|
|
29828
|
-
if (
|
|
30006
|
+
const venvPip = join40(venvDir, "bin", "pip");
|
|
30007
|
+
if (existsSync30(venvPip))
|
|
29829
30008
|
return venvDir;
|
|
29830
30009
|
log("Creating Python venv for vision deps...");
|
|
29831
30010
|
if (!hasCmd("python3")) {
|
|
@@ -29837,9 +30016,9 @@ function ensureVenv(log) {
|
|
|
29837
30016
|
return null;
|
|
29838
30017
|
}
|
|
29839
30018
|
try {
|
|
29840
|
-
mkdirSync10(
|
|
30019
|
+
mkdirSync10(join40(homedir10(), ".open-agents"), { recursive: true });
|
|
29841
30020
|
execSync25(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
29842
|
-
execSync25(`"${
|
|
30021
|
+
execSync25(`"${join40(venvDir, "bin", "pip")}" install --upgrade pip`, {
|
|
29843
30022
|
stdio: "pipe",
|
|
29844
30023
|
timeout: 6e4
|
|
29845
30024
|
});
|
|
@@ -30030,15 +30209,15 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
30030
30209
|
}
|
|
30031
30210
|
}
|
|
30032
30211
|
const venvDir = getVenvDir();
|
|
30033
|
-
const venvBin =
|
|
30034
|
-
const venvMoondream =
|
|
30212
|
+
const venvBin = join40(venvDir, "bin");
|
|
30213
|
+
const venvMoondream = join40(venvBin, "moondream-station");
|
|
30035
30214
|
const venv = ensureVenv(log);
|
|
30036
|
-
if (venv && !hasCmd("moondream-station") && !
|
|
30037
|
-
const venvPip =
|
|
30215
|
+
if (venv && !hasCmd("moondream-station") && !existsSync30(venvMoondream)) {
|
|
30216
|
+
const venvPip = join40(venvBin, "pip");
|
|
30038
30217
|
log("Installing moondream-station in ~/.open-agents/venv...");
|
|
30039
30218
|
try {
|
|
30040
30219
|
execSync25(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
30041
|
-
if (
|
|
30220
|
+
if (existsSync30(venvMoondream)) {
|
|
30042
30221
|
log("moondream-station installed successfully.");
|
|
30043
30222
|
} else {
|
|
30044
30223
|
try {
|
|
@@ -30055,8 +30234,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
30055
30234
|
}
|
|
30056
30235
|
}
|
|
30057
30236
|
if (venv) {
|
|
30058
|
-
const venvPython =
|
|
30059
|
-
const venvPip2 =
|
|
30237
|
+
const venvPython = join40(venvBin, "python");
|
|
30238
|
+
const venvPip2 = join40(venvBin, "pip");
|
|
30060
30239
|
let ocrStackInstalled = false;
|
|
30061
30240
|
try {
|
|
30062
30241
|
execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
@@ -30157,7 +30336,7 @@ function modelSizeGB(models, modelName) {
|
|
|
30157
30336
|
const known = QWEN_VARIANTS.find((v) => modelName.includes(v.tag.split(":")[1] ?? ""));
|
|
30158
30337
|
return known?.sizeGB ?? 4;
|
|
30159
30338
|
}
|
|
30160
|
-
function
|
|
30339
|
+
async function createExpandedVariantAsync(baseModel, specs, sizeGB) {
|
|
30161
30340
|
const customName = expandedModelName(baseModel);
|
|
30162
30341
|
const ctx = calculateContextWindow(specs, sizeGB);
|
|
30163
30342
|
try {
|
|
@@ -30169,12 +30348,11 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
|
|
|
30169
30348
|
`PARAMETER num_predict ${numPredict}`,
|
|
30170
30349
|
`PARAMETER stop "<|endoftext|>"`
|
|
30171
30350
|
].join("\n");
|
|
30172
|
-
const modelDir2 =
|
|
30351
|
+
const modelDir2 = join40(homedir10(), ".open-agents", "models");
|
|
30173
30352
|
mkdirSync10(modelDir2, { recursive: true });
|
|
30174
|
-
const modelfilePath =
|
|
30175
|
-
|
|
30176
|
-
|
|
30177
|
-
stdio: "pipe",
|
|
30353
|
+
const modelfilePath = join40(modelDir2, `Modelfile.${customName}`);
|
|
30354
|
+
writeFileSync11(modelfilePath, modelfileContent + "\n", "utf8");
|
|
30355
|
+
await execAsync(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
30178
30356
|
timeout: 12e4
|
|
30179
30357
|
});
|
|
30180
30358
|
return customName;
|
|
@@ -30184,7 +30362,7 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
|
|
|
30184
30362
|
}
|
|
30185
30363
|
async function ensureExpandedContext(modelName, backendUrl) {
|
|
30186
30364
|
if (modelName.startsWith("open-agents-")) {
|
|
30187
|
-
const specs2 =
|
|
30365
|
+
const specs2 = await detectSystemSpecsAsync();
|
|
30188
30366
|
const ctx2 = calculateContextWindow(specs2, 4);
|
|
30189
30367
|
return { model: modelName, created: false, contextLabel: ctx2.label, numCtx: ctx2.numCtx };
|
|
30190
30368
|
}
|
|
@@ -30195,7 +30373,7 @@ async function ensureExpandedContext(modelName, backendUrl) {
|
|
|
30195
30373
|
if (existing === null) {
|
|
30196
30374
|
return { model: modelName, created: false, contextLabel: "", numCtx: 0 };
|
|
30197
30375
|
}
|
|
30198
|
-
const specs =
|
|
30376
|
+
const specs = await detectSystemSpecsAsync();
|
|
30199
30377
|
if (typeof existing === "string") {
|
|
30200
30378
|
let sizeGB2 = 4;
|
|
30201
30379
|
try {
|
|
@@ -30213,13 +30391,13 @@ async function ensureExpandedContext(modelName, backendUrl) {
|
|
|
30213
30391
|
} catch {
|
|
30214
30392
|
}
|
|
30215
30393
|
const ctx = calculateContextWindow(specs, sizeGB);
|
|
30216
|
-
const created =
|
|
30394
|
+
const created = await createExpandedVariantAsync(modelName, specs, sizeGB);
|
|
30217
30395
|
if (created) {
|
|
30218
30396
|
return { model: created, created: true, contextLabel: ctx.label, numCtx: ctx.numCtx };
|
|
30219
30397
|
}
|
|
30220
30398
|
return { model: modelName, created: false, contextLabel: ctx.label, numCtx: ctx.numCtx };
|
|
30221
30399
|
}
|
|
30222
|
-
var QWEN_VARIANTS, TOOL_CALLING_MODELS, _cloudflaredInstallPromise;
|
|
30400
|
+
var execAsync, QWEN_VARIANTS, TOOL_CALLING_MODELS, _cloudflaredInstallPromise;
|
|
30223
30401
|
var init_setup = __esm({
|
|
30224
30402
|
"packages/cli/dist/tui/setup.js"() {
|
|
30225
30403
|
"use strict";
|
|
@@ -30227,6 +30405,7 @@ var init_setup = __esm({
|
|
|
30227
30405
|
init_render();
|
|
30228
30406
|
init_config();
|
|
30229
30407
|
init_dist();
|
|
30408
|
+
execAsync = promisify5(exec2);
|
|
30230
30409
|
QWEN_VARIANTS = [
|
|
30231
30410
|
{ tag: "qwen3.5:0.8b", sizeGB: 1, label: "0.8B params (1.0 GB)", cloud: false },
|
|
30232
30411
|
{ tag: "qwen3.5:2b", sizeGB: 2.7, label: "2B params (2.7 GB)", cloud: false },
|
|
@@ -32105,17 +32284,17 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
32105
32284
|
try {
|
|
32106
32285
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
32107
32286
|
const { fileURLToPath: fileURLToPath14 } = await import("node:url");
|
|
32108
|
-
const { dirname: dirname19, join:
|
|
32109
|
-
const { existsSync:
|
|
32287
|
+
const { dirname: dirname19, join: join55 } = await import("node:path");
|
|
32288
|
+
const { existsSync: existsSync41 } = await import("node:fs");
|
|
32110
32289
|
const req = createRequire4(import.meta.url);
|
|
32111
32290
|
const thisDir = dirname19(fileURLToPath14(import.meta.url));
|
|
32112
32291
|
const candidates = [
|
|
32113
|
-
|
|
32114
|
-
|
|
32115
|
-
|
|
32292
|
+
join55(thisDir, "..", "package.json"),
|
|
32293
|
+
join55(thisDir, "..", "..", "package.json"),
|
|
32294
|
+
join55(thisDir, "..", "..", "..", "package.json")
|
|
32116
32295
|
];
|
|
32117
32296
|
for (const pkgPath of candidates) {
|
|
32118
|
-
if (
|
|
32297
|
+
if (existsSync41(pkgPath)) {
|
|
32119
32298
|
const pkg = req(pkgPath);
|
|
32120
32299
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
32121
32300
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -32151,7 +32330,7 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
32151
32330
|
return;
|
|
32152
32331
|
}
|
|
32153
32332
|
checkSpinner.stop(`Update available: v${info.currentVersion} \u2192 v${c2.bold(c2.green(info.latestVersion))}`);
|
|
32154
|
-
const { exec:
|
|
32333
|
+
const { exec: exec3, execSync: es2 } = await import("node:child_process");
|
|
32155
32334
|
let needsSudo = false;
|
|
32156
32335
|
try {
|
|
32157
32336
|
const prefix = es2("npm prefix -g", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
@@ -32180,7 +32359,7 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
32180
32359
|
let installOk = false;
|
|
32181
32360
|
let installError = "";
|
|
32182
32361
|
const runInstall2 = (cmd) => new Promise((resolve31) => {
|
|
32183
|
-
const child =
|
|
32362
|
+
const child = exec3(cmd, { timeout: 18e4 }, (err, _stdout, stderr) => {
|
|
32184
32363
|
if (err)
|
|
32185
32364
|
installError = (stderr || err.message || "").trim();
|
|
32186
32365
|
resolve31(!err);
|
|
@@ -32218,7 +32397,7 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
32218
32397
|
installSpinner.stop(`Update installed (v${info.latestVersion}).`);
|
|
32219
32398
|
const rebuildSpinner = startInlineSpinner("Rebuilding native modules");
|
|
32220
32399
|
const rebuildOk = await new Promise((resolve31) => {
|
|
32221
|
-
const child =
|
|
32400
|
+
const child = exec3(`${sudoPrefix}npm rebuild -g open-agents-ai 2>/dev/null || true`, { timeout: 12e4 }, () => resolve31(true));
|
|
32222
32401
|
child.stdout?.resume();
|
|
32223
32402
|
child.stderr?.resume();
|
|
32224
32403
|
});
|
|
@@ -32251,7 +32430,7 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
32251
32430
|
if (fsExists(venvPip)) {
|
|
32252
32431
|
const pySpinner = startInlineSpinner("Upgrading Python venv packages");
|
|
32253
32432
|
const pyOk = await new Promise((resolve31) => {
|
|
32254
|
-
const child =
|
|
32433
|
+
const child = exec3(`"${venvPip}" install --upgrade moondream-station pytesseract Pillow opencv-python-headless numpy 2>/dev/null || true`, { timeout: 3e5 }, (err) => resolve31(!err));
|
|
32255
32434
|
child.stdout?.resume();
|
|
32256
32435
|
child.stderr?.resume();
|
|
32257
32436
|
});
|
|
@@ -32400,8 +32579,8 @@ var init_commands = __esm({
|
|
|
32400
32579
|
});
|
|
32401
32580
|
|
|
32402
32581
|
// packages/cli/dist/tui/project-context.js
|
|
32403
|
-
import { existsSync as
|
|
32404
|
-
import { join as
|
|
32582
|
+
import { existsSync as existsSync31, readFileSync as readFileSync22, readdirSync as readdirSync8 } from "node:fs";
|
|
32583
|
+
import { join as join41, basename as basename10 } from "node:path";
|
|
32405
32584
|
import { execSync as execSync26 } from "node:child_process";
|
|
32406
32585
|
import { homedir as homedir11, platform as platform2, release } from "node:os";
|
|
32407
32586
|
function getModelTier(modelName) {
|
|
@@ -32436,10 +32615,10 @@ function loadProjectMap(repoRoot) {
|
|
|
32436
32615
|
if (!hasOaDirectory(repoRoot)) {
|
|
32437
32616
|
initOaDirectory(repoRoot);
|
|
32438
32617
|
}
|
|
32439
|
-
const mapPath =
|
|
32440
|
-
if (
|
|
32618
|
+
const mapPath = join41(repoRoot, OA_DIR, "context", "project-map.md");
|
|
32619
|
+
if (existsSync31(mapPath)) {
|
|
32441
32620
|
try {
|
|
32442
|
-
const content =
|
|
32621
|
+
const content = readFileSync22(mapPath, "utf-8");
|
|
32443
32622
|
return content;
|
|
32444
32623
|
} catch {
|
|
32445
32624
|
}
|
|
@@ -32480,31 +32659,31 @@ ${log}`);
|
|
|
32480
32659
|
}
|
|
32481
32660
|
function loadMemoryContext(repoRoot) {
|
|
32482
32661
|
const sections = [];
|
|
32483
|
-
const oaMemDir =
|
|
32662
|
+
const oaMemDir = join41(repoRoot, OA_DIR, "memory");
|
|
32484
32663
|
const oaEntries = loadMemoryDir(oaMemDir, "project");
|
|
32485
32664
|
if (oaEntries)
|
|
32486
32665
|
sections.push(oaEntries);
|
|
32487
|
-
const legacyMemDir =
|
|
32488
|
-
if (legacyMemDir !== oaMemDir &&
|
|
32666
|
+
const legacyMemDir = join41(repoRoot, ".open-agents", "memory");
|
|
32667
|
+
if (legacyMemDir !== oaMemDir && existsSync31(legacyMemDir)) {
|
|
32489
32668
|
const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
|
|
32490
32669
|
if (legacyEntries)
|
|
32491
32670
|
sections.push(legacyEntries);
|
|
32492
32671
|
}
|
|
32493
|
-
const globalMemDir =
|
|
32672
|
+
const globalMemDir = join41(homedir11(), ".open-agents", "memory");
|
|
32494
32673
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
32495
32674
|
if (globalEntries)
|
|
32496
32675
|
sections.push(globalEntries);
|
|
32497
32676
|
return sections.join("\n\n");
|
|
32498
32677
|
}
|
|
32499
32678
|
function loadMemoryDir(memDir, scope) {
|
|
32500
|
-
if (!
|
|
32679
|
+
if (!existsSync31(memDir))
|
|
32501
32680
|
return "";
|
|
32502
32681
|
const lines = [];
|
|
32503
32682
|
try {
|
|
32504
32683
|
const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
|
|
32505
32684
|
for (const file of files.slice(0, 10)) {
|
|
32506
32685
|
try {
|
|
32507
|
-
const raw =
|
|
32686
|
+
const raw = readFileSync22(join41(memDir, file), "utf-8");
|
|
32508
32687
|
const entries = JSON.parse(raw);
|
|
32509
32688
|
const topic = basename10(file, ".json");
|
|
32510
32689
|
const keys = Object.keys(entries);
|
|
@@ -33408,11 +33587,7 @@ var init_carousel = __esm({
|
|
|
33408
33587
|
process.stdout.write(`\x1B[${this.reservedRows + 1};1H`);
|
|
33409
33588
|
this.resizeHandler = () => {
|
|
33410
33589
|
this.width = process.stdout.columns ?? 80;
|
|
33411
|
-
const newRows = process.stdout.rows ?? 24;
|
|
33412
33590
|
this.rebuildRibbons();
|
|
33413
|
-
if (this.started) {
|
|
33414
|
-
process.stdout.write(`\x1B[${this.reservedRows + 1};${newRows}r`);
|
|
33415
|
-
}
|
|
33416
33591
|
};
|
|
33417
33592
|
process.stdout.on("resize", this.resizeHandler);
|
|
33418
33593
|
this.renderFrame();
|
|
@@ -33531,22 +33706,22 @@ var init_carousel = __esm({
|
|
|
33531
33706
|
});
|
|
33532
33707
|
|
|
33533
33708
|
// packages/cli/dist/tui/carousel-descriptors.js
|
|
33534
|
-
import { existsSync as
|
|
33535
|
-
import { join as
|
|
33709
|
+
import { existsSync as existsSync32, readFileSync as readFileSync23, writeFileSync as writeFileSync12, mkdirSync as mkdirSync11, readdirSync as readdirSync9 } from "node:fs";
|
|
33710
|
+
import { join as join42, basename as basename11 } from "node:path";
|
|
33536
33711
|
function loadToolProfile(repoRoot) {
|
|
33537
|
-
const filePath =
|
|
33712
|
+
const filePath = join42(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
33538
33713
|
try {
|
|
33539
|
-
if (!
|
|
33714
|
+
if (!existsSync32(filePath))
|
|
33540
33715
|
return null;
|
|
33541
|
-
return JSON.parse(
|
|
33716
|
+
return JSON.parse(readFileSync23(filePath, "utf-8"));
|
|
33542
33717
|
} catch {
|
|
33543
33718
|
return null;
|
|
33544
33719
|
}
|
|
33545
33720
|
}
|
|
33546
33721
|
function saveToolProfile(repoRoot, profile) {
|
|
33547
|
-
const contextDir =
|
|
33722
|
+
const contextDir = join42(repoRoot, OA_DIR, "context");
|
|
33548
33723
|
mkdirSync11(contextDir, { recursive: true });
|
|
33549
|
-
|
|
33724
|
+
writeFileSync12(join42(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
|
|
33550
33725
|
}
|
|
33551
33726
|
function categorizeToolCall(toolName) {
|
|
33552
33727
|
for (const cat of TOOL_CATEGORIES) {
|
|
@@ -33604,25 +33779,25 @@ function weightedColor(profile) {
|
|
|
33604
33779
|
return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
|
|
33605
33780
|
}
|
|
33606
33781
|
function loadCachedDescriptors(repoRoot) {
|
|
33607
|
-
const filePath =
|
|
33782
|
+
const filePath = join42(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
|
|
33608
33783
|
try {
|
|
33609
|
-
if (!
|
|
33784
|
+
if (!existsSync32(filePath))
|
|
33610
33785
|
return null;
|
|
33611
|
-
const cached = JSON.parse(
|
|
33786
|
+
const cached = JSON.parse(readFileSync23(filePath, "utf-8"));
|
|
33612
33787
|
return cached.phrases.length > 0 ? cached.phrases : null;
|
|
33613
33788
|
} catch {
|
|
33614
33789
|
return null;
|
|
33615
33790
|
}
|
|
33616
33791
|
}
|
|
33617
33792
|
function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
|
|
33618
|
-
const contextDir =
|
|
33793
|
+
const contextDir = join42(repoRoot, OA_DIR, "context");
|
|
33619
33794
|
mkdirSync11(contextDir, { recursive: true });
|
|
33620
33795
|
const cached = {
|
|
33621
33796
|
phrases,
|
|
33622
33797
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
33623
33798
|
sourceHash
|
|
33624
33799
|
};
|
|
33625
|
-
|
|
33800
|
+
writeFileSync12(join42(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
|
|
33626
33801
|
}
|
|
33627
33802
|
function generateDescriptors(repoRoot) {
|
|
33628
33803
|
const profile = loadToolProfile(repoRoot);
|
|
@@ -33670,11 +33845,11 @@ function generateDescriptors(repoRoot) {
|
|
|
33670
33845
|
return phrases;
|
|
33671
33846
|
}
|
|
33672
33847
|
function extractFromPackageJson(repoRoot, tags) {
|
|
33673
|
-
const pkgPath =
|
|
33848
|
+
const pkgPath = join42(repoRoot, "package.json");
|
|
33674
33849
|
try {
|
|
33675
|
-
if (!
|
|
33850
|
+
if (!existsSync32(pkgPath))
|
|
33676
33851
|
return;
|
|
33677
|
-
const pkg = JSON.parse(
|
|
33852
|
+
const pkg = JSON.parse(readFileSync23(pkgPath, "utf-8"));
|
|
33678
33853
|
if (pkg.name && typeof pkg.name === "string") {
|
|
33679
33854
|
const parts = pkg.name.replace(/^@/, "").split("/");
|
|
33680
33855
|
for (const p of parts)
|
|
@@ -33718,7 +33893,7 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
33718
33893
|
{ file: ".github/workflows", tag: "ci/cd" }
|
|
33719
33894
|
];
|
|
33720
33895
|
for (const check of manifestChecks) {
|
|
33721
|
-
if (
|
|
33896
|
+
if (existsSync32(join42(repoRoot, check.file))) {
|
|
33722
33897
|
tags.push(check.tag);
|
|
33723
33898
|
}
|
|
33724
33899
|
}
|
|
@@ -33740,16 +33915,16 @@ function extractFromSessions(repoRoot, tags) {
|
|
|
33740
33915
|
}
|
|
33741
33916
|
}
|
|
33742
33917
|
function extractFromMemory(repoRoot, tags) {
|
|
33743
|
-
const memoryDir =
|
|
33918
|
+
const memoryDir = join42(repoRoot, OA_DIR, "memory");
|
|
33744
33919
|
try {
|
|
33745
|
-
if (!
|
|
33920
|
+
if (!existsSync32(memoryDir))
|
|
33746
33921
|
return;
|
|
33747
33922
|
const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
|
|
33748
33923
|
for (const file of files) {
|
|
33749
33924
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
33750
33925
|
tags.push(topic);
|
|
33751
33926
|
try {
|
|
33752
|
-
const data = JSON.parse(
|
|
33927
|
+
const data = JSON.parse(readFileSync23(join42(memoryDir, file), "utf-8"));
|
|
33753
33928
|
if (data && typeof data === "object") {
|
|
33754
33929
|
const keys = Object.keys(data).slice(0, 3);
|
|
33755
33930
|
for (const key of keys) {
|
|
@@ -33884,25 +34059,25 @@ var init_carousel_descriptors = __esm({
|
|
|
33884
34059
|
});
|
|
33885
34060
|
|
|
33886
34061
|
// packages/cli/dist/tui/voice.js
|
|
33887
|
-
import { existsSync as
|
|
33888
|
-
import { join as
|
|
34062
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync12, writeFileSync as writeFileSync13, readFileSync as readFileSync24, unlinkSync as unlinkSync5 } from "node:fs";
|
|
34063
|
+
import { join as join43 } from "node:path";
|
|
33889
34064
|
import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
|
|
33890
34065
|
import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
|
|
33891
34066
|
import { createRequire } from "node:module";
|
|
33892
34067
|
function voiceDir() {
|
|
33893
|
-
return
|
|
34068
|
+
return join43(homedir12(), ".open-agents", "voice");
|
|
33894
34069
|
}
|
|
33895
34070
|
function modelsDir() {
|
|
33896
|
-
return
|
|
34071
|
+
return join43(voiceDir(), "models");
|
|
33897
34072
|
}
|
|
33898
34073
|
function modelDir(id) {
|
|
33899
|
-
return
|
|
34074
|
+
return join43(modelsDir(), id);
|
|
33900
34075
|
}
|
|
33901
34076
|
function modelOnnxPath(id) {
|
|
33902
|
-
return
|
|
34077
|
+
return join43(modelDir(id), "model.onnx");
|
|
33903
34078
|
}
|
|
33904
34079
|
function modelConfigPath(id) {
|
|
33905
|
-
return
|
|
34080
|
+
return join43(modelDir(id), "config.json");
|
|
33906
34081
|
}
|
|
33907
34082
|
function emotionToPitchBias(emotion, stark = false, autist = false) {
|
|
33908
34083
|
if (autist)
|
|
@@ -34762,11 +34937,11 @@ var init_voice = __esm({
|
|
|
34762
34937
|
}
|
|
34763
34938
|
this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
|
|
34764
34939
|
}
|
|
34765
|
-
const wavPath =
|
|
34940
|
+
const wavPath = join43(tmpdir6(), `oa-voice-${Date.now()}.wav`);
|
|
34766
34941
|
this.writeWav(audioData, sampleRate, wavPath);
|
|
34767
34942
|
await this.playWav(wavPath);
|
|
34768
34943
|
try {
|
|
34769
|
-
|
|
34944
|
+
unlinkSync5(wavPath);
|
|
34770
34945
|
} catch {
|
|
34771
34946
|
}
|
|
34772
34947
|
}
|
|
@@ -34894,7 +35069,7 @@ var init_voice = __esm({
|
|
|
34894
35069
|
return buffer;
|
|
34895
35070
|
}
|
|
34896
35071
|
writeWav(samples, sampleRate, path) {
|
|
34897
|
-
|
|
35072
|
+
writeFileSync13(path, this.buildWavBuffer(samples, sampleRate));
|
|
34898
35073
|
}
|
|
34899
35074
|
// -------------------------------------------------------------------------
|
|
34900
35075
|
// Audio playback (system default speakers)
|
|
@@ -35053,7 +35228,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
35053
35228
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
35054
35229
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
35055
35230
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
35056
|
-
const wavPath =
|
|
35231
|
+
const wavPath = join43(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
|
|
35057
35232
|
const pyScript = [
|
|
35058
35233
|
"import sys, json",
|
|
35059
35234
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -35070,11 +35245,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
35070
35245
|
return;
|
|
35071
35246
|
}
|
|
35072
35247
|
}
|
|
35073
|
-
if (!
|
|
35248
|
+
if (!existsSync33(wavPath))
|
|
35074
35249
|
return;
|
|
35075
35250
|
if (volume !== 1) {
|
|
35076
35251
|
try {
|
|
35077
|
-
const wavData =
|
|
35252
|
+
const wavData = readFileSync24(wavPath);
|
|
35078
35253
|
if (wavData.length > 44) {
|
|
35079
35254
|
const header = wavData.subarray(0, 44);
|
|
35080
35255
|
const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
|
|
@@ -35082,14 +35257,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
35082
35257
|
samples[i] = Math.round(samples[i] * volume);
|
|
35083
35258
|
}
|
|
35084
35259
|
const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
|
|
35085
|
-
|
|
35260
|
+
writeFileSync13(wavPath, scaled);
|
|
35086
35261
|
}
|
|
35087
35262
|
} catch {
|
|
35088
35263
|
}
|
|
35089
35264
|
}
|
|
35090
35265
|
if (this.onPCMOutput) {
|
|
35091
35266
|
try {
|
|
35092
|
-
const wavData =
|
|
35267
|
+
const wavData = readFileSync24(wavPath);
|
|
35093
35268
|
if (wavData.length > 44) {
|
|
35094
35269
|
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
35095
35270
|
const sampleRate = wavData.readUInt32LE(24);
|
|
@@ -35100,7 +35275,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
35100
35275
|
}
|
|
35101
35276
|
await this.playWav(wavPath);
|
|
35102
35277
|
try {
|
|
35103
|
-
|
|
35278
|
+
unlinkSync5(wavPath);
|
|
35104
35279
|
} catch {
|
|
35105
35280
|
}
|
|
35106
35281
|
}
|
|
@@ -35121,7 +35296,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
35121
35296
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
35122
35297
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
35123
35298
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
35124
|
-
const wavPath =
|
|
35299
|
+
const wavPath = join43(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
|
|
35125
35300
|
const pyScript = [
|
|
35126
35301
|
"import sys, json",
|
|
35127
35302
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -35138,11 +35313,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
35138
35313
|
return null;
|
|
35139
35314
|
}
|
|
35140
35315
|
}
|
|
35141
|
-
if (!
|
|
35316
|
+
if (!existsSync33(wavPath))
|
|
35142
35317
|
return null;
|
|
35143
35318
|
try {
|
|
35144
|
-
const data =
|
|
35145
|
-
|
|
35319
|
+
const data = readFileSync24(wavPath);
|
|
35320
|
+
unlinkSync5(wavPath);
|
|
35146
35321
|
return data;
|
|
35147
35322
|
} catch {
|
|
35148
35323
|
return null;
|
|
@@ -35156,40 +35331,40 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
35156
35331
|
return;
|
|
35157
35332
|
const arch = process.arch;
|
|
35158
35333
|
mkdirSync12(voiceDir(), { recursive: true });
|
|
35159
|
-
const pkgPath =
|
|
35334
|
+
const pkgPath = join43(voiceDir(), "package.json");
|
|
35160
35335
|
const expectedDeps = {
|
|
35161
35336
|
"onnxruntime-node": "^1.21.0",
|
|
35162
35337
|
"phonemizer": "^1.2.1"
|
|
35163
35338
|
};
|
|
35164
|
-
if (
|
|
35339
|
+
if (existsSync33(pkgPath)) {
|
|
35165
35340
|
try {
|
|
35166
|
-
const existing = JSON.parse(
|
|
35341
|
+
const existing = JSON.parse(readFileSync24(pkgPath, "utf8"));
|
|
35167
35342
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
35168
35343
|
existing.dependencies = { ...existing.dependencies, ...expectedDeps };
|
|
35169
|
-
|
|
35344
|
+
writeFileSync13(pkgPath, JSON.stringify(existing, null, 2));
|
|
35170
35345
|
}
|
|
35171
35346
|
} catch {
|
|
35172
35347
|
}
|
|
35173
35348
|
}
|
|
35174
|
-
if (!
|
|
35175
|
-
|
|
35349
|
+
if (!existsSync33(pkgPath)) {
|
|
35350
|
+
writeFileSync13(pkgPath, JSON.stringify({
|
|
35176
35351
|
name: "open-agents-voice",
|
|
35177
35352
|
private: true,
|
|
35178
35353
|
dependencies: expectedDeps
|
|
35179
35354
|
}, null, 2));
|
|
35180
35355
|
}
|
|
35181
|
-
const voiceRequire = createRequire(
|
|
35356
|
+
const voiceRequire = createRequire(join43(voiceDir(), "index.js"));
|
|
35182
35357
|
const probeOnnx = () => {
|
|
35183
35358
|
try {
|
|
35184
|
-
const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH:
|
|
35359
|
+
const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join43(voiceDir(), "node_modules") } });
|
|
35185
35360
|
const output = result.toString().trim();
|
|
35186
35361
|
return output === "OK";
|
|
35187
35362
|
} catch {
|
|
35188
35363
|
return false;
|
|
35189
35364
|
}
|
|
35190
35365
|
};
|
|
35191
|
-
const onnxNodeModules =
|
|
35192
|
-
const onnxInstalled =
|
|
35366
|
+
const onnxNodeModules = join43(voiceDir(), "node_modules", "onnxruntime-node");
|
|
35367
|
+
const onnxInstalled = existsSync33(onnxNodeModules);
|
|
35193
35368
|
if (onnxInstalled && !probeOnnx()) {
|
|
35194
35369
|
throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
|
|
35195
35370
|
}
|
|
@@ -35247,18 +35422,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
35247
35422
|
const dir = modelDir(id);
|
|
35248
35423
|
const onnxPath = modelOnnxPath(id);
|
|
35249
35424
|
const configPath = modelConfigPath(id);
|
|
35250
|
-
if (
|
|
35425
|
+
if (existsSync33(onnxPath) && existsSync33(configPath))
|
|
35251
35426
|
return;
|
|
35252
35427
|
mkdirSync12(dir, { recursive: true });
|
|
35253
|
-
if (!
|
|
35428
|
+
if (!existsSync33(configPath)) {
|
|
35254
35429
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
35255
35430
|
const configResp = await fetch(model.configUrl);
|
|
35256
35431
|
if (!configResp.ok)
|
|
35257
35432
|
throw new Error(`Failed to download config: HTTP ${configResp.status}`);
|
|
35258
35433
|
const configText = await configResp.text();
|
|
35259
|
-
|
|
35434
|
+
writeFileSync13(configPath, configText);
|
|
35260
35435
|
}
|
|
35261
|
-
if (!
|
|
35436
|
+
if (!existsSync33(onnxPath)) {
|
|
35262
35437
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
35263
35438
|
const onnxResp = await fetch(model.onnxUrl);
|
|
35264
35439
|
if (!onnxResp.ok)
|
|
@@ -35283,7 +35458,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
35283
35458
|
}
|
|
35284
35459
|
}
|
|
35285
35460
|
const fullBuffer = Buffer.concat(chunks);
|
|
35286
|
-
|
|
35461
|
+
writeFileSync13(onnxPath, fullBuffer);
|
|
35287
35462
|
renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
|
|
35288
35463
|
}
|
|
35289
35464
|
}
|
|
@@ -35295,10 +35470,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
35295
35470
|
throw new Error("ONNX runtime not loaded");
|
|
35296
35471
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
35297
35472
|
const configPath = modelConfigPath(this.modelId);
|
|
35298
|
-
if (!
|
|
35473
|
+
if (!existsSync33(onnxPath) || !existsSync33(configPath)) {
|
|
35299
35474
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
35300
35475
|
}
|
|
35301
|
-
this.config = JSON.parse(
|
|
35476
|
+
this.config = JSON.parse(readFileSync24(configPath, "utf8"));
|
|
35302
35477
|
this.session = await this.ort.InferenceSession.create(onnxPath, {
|
|
35303
35478
|
executionProviders: ["cpu"],
|
|
35304
35479
|
graphOptimizationLevel: "all"
|
|
@@ -36160,10 +36335,10 @@ var init_stream_renderer = __esm({
|
|
|
36160
36335
|
|
|
36161
36336
|
// packages/cli/dist/tui/edit-history.js
|
|
36162
36337
|
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync13 } from "node:fs";
|
|
36163
|
-
import { join as
|
|
36338
|
+
import { join as join44 } from "node:path";
|
|
36164
36339
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
36165
|
-
const historyDir =
|
|
36166
|
-
const logPath =
|
|
36340
|
+
const historyDir = join44(repoRoot, ".oa", "history");
|
|
36341
|
+
const logPath = join44(historyDir, "edits.jsonl");
|
|
36167
36342
|
try {
|
|
36168
36343
|
mkdirSync13(historyDir, { recursive: true });
|
|
36169
36344
|
} catch {
|
|
@@ -36274,17 +36449,17 @@ var init_edit_history = __esm({
|
|
|
36274
36449
|
});
|
|
36275
36450
|
|
|
36276
36451
|
// packages/cli/dist/tui/promptLoader.js
|
|
36277
|
-
import { readFileSync as
|
|
36278
|
-
import { join as
|
|
36452
|
+
import { readFileSync as readFileSync25, existsSync as existsSync34 } from "node:fs";
|
|
36453
|
+
import { join as join45, dirname as dirname16 } from "node:path";
|
|
36279
36454
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
36280
36455
|
function loadPrompt3(promptPath, vars) {
|
|
36281
36456
|
let content = cache3.get(promptPath);
|
|
36282
36457
|
if (content === void 0) {
|
|
36283
|
-
const fullPath =
|
|
36284
|
-
if (!
|
|
36458
|
+
const fullPath = join45(PROMPTS_DIR3, promptPath);
|
|
36459
|
+
if (!existsSync34(fullPath)) {
|
|
36285
36460
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
36286
36461
|
}
|
|
36287
|
-
content =
|
|
36462
|
+
content = readFileSync25(fullPath, "utf-8");
|
|
36288
36463
|
cache3.set(promptPath, content);
|
|
36289
36464
|
}
|
|
36290
36465
|
if (!vars)
|
|
@@ -36297,23 +36472,23 @@ var init_promptLoader3 = __esm({
|
|
|
36297
36472
|
"use strict";
|
|
36298
36473
|
__filename3 = fileURLToPath11(import.meta.url);
|
|
36299
36474
|
__dirname6 = dirname16(__filename3);
|
|
36300
|
-
devPath2 =
|
|
36301
|
-
publishedPath2 =
|
|
36302
|
-
PROMPTS_DIR3 =
|
|
36475
|
+
devPath2 = join45(__dirname6, "..", "..", "prompts");
|
|
36476
|
+
publishedPath2 = join45(__dirname6, "..", "prompts");
|
|
36477
|
+
PROMPTS_DIR3 = existsSync34(devPath2) ? devPath2 : publishedPath2;
|
|
36303
36478
|
cache3 = /* @__PURE__ */ new Map();
|
|
36304
36479
|
}
|
|
36305
36480
|
});
|
|
36306
36481
|
|
|
36307
36482
|
// packages/cli/dist/tui/dream-engine.js
|
|
36308
|
-
import { mkdirSync as mkdirSync14, writeFileSync as
|
|
36309
|
-
import { join as
|
|
36483
|
+
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync14, readFileSync as readFileSync26, existsSync as existsSync35, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
|
|
36484
|
+
import { join as join46, basename as basename12 } from "node:path";
|
|
36310
36485
|
import { execSync as execSync28 } from "node:child_process";
|
|
36311
36486
|
function loadAutoresearchMemory(repoRoot) {
|
|
36312
|
-
const memoryPath =
|
|
36313
|
-
if (!
|
|
36487
|
+
const memoryPath = join46(repoRoot, ".oa", "memory", "autoresearch.json");
|
|
36488
|
+
if (!existsSync35(memoryPath))
|
|
36314
36489
|
return "";
|
|
36315
36490
|
try {
|
|
36316
|
-
const raw =
|
|
36491
|
+
const raw = readFileSync26(memoryPath, "utf-8");
|
|
36317
36492
|
const data = JSON.parse(raw);
|
|
36318
36493
|
const sections = [];
|
|
36319
36494
|
for (const key of AUTORESEARCH_MEMORY_KEYS) {
|
|
@@ -36503,14 +36678,14 @@ var init_dream_engine = __esm({
|
|
|
36503
36678
|
const content = String(args["content"] ?? "");
|
|
36504
36679
|
if (!rawPath)
|
|
36505
36680
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
36506
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
36681
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join46(this.autoresearchDir, basename12(rawPath)) : join46(this.autoresearchDir, rawPath);
|
|
36507
36682
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
36508
36683
|
return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
|
|
36509
36684
|
}
|
|
36510
36685
|
try {
|
|
36511
|
-
const dir =
|
|
36686
|
+
const dir = join46(targetPath, "..");
|
|
36512
36687
|
mkdirSync14(dir, { recursive: true });
|
|
36513
|
-
|
|
36688
|
+
writeFileSync14(targetPath, content, "utf-8");
|
|
36514
36689
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
36515
36690
|
} catch (err) {
|
|
36516
36691
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -36538,20 +36713,20 @@ var init_dream_engine = __esm({
|
|
|
36538
36713
|
const rawPath = String(args["path"] ?? "");
|
|
36539
36714
|
const oldStr = String(args["old_string"] ?? "");
|
|
36540
36715
|
const newStr = String(args["new_string"] ?? "");
|
|
36541
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
36716
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join46(this.autoresearchDir, basename12(rawPath)) : join46(this.autoresearchDir, rawPath);
|
|
36542
36717
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
36543
36718
|
return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
|
|
36544
36719
|
}
|
|
36545
36720
|
try {
|
|
36546
|
-
if (!
|
|
36721
|
+
if (!existsSync35(targetPath)) {
|
|
36547
36722
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
36548
36723
|
}
|
|
36549
|
-
let content =
|
|
36724
|
+
let content = readFileSync26(targetPath, "utf-8");
|
|
36550
36725
|
if (!content.includes(oldStr)) {
|
|
36551
36726
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
36552
36727
|
}
|
|
36553
36728
|
content = content.replace(oldStr, newStr);
|
|
36554
|
-
|
|
36729
|
+
writeFileSync14(targetPath, content, "utf-8");
|
|
36555
36730
|
return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
|
|
36556
36731
|
} catch (err) {
|
|
36557
36732
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -36592,14 +36767,14 @@ var init_dream_engine = __esm({
|
|
|
36592
36767
|
const content = String(args["content"] ?? "");
|
|
36593
36768
|
if (!rawPath)
|
|
36594
36769
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
36595
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
36770
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join46(this.dreamsDir, basename12(rawPath)) : join46(this.dreamsDir, rawPath);
|
|
36596
36771
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
36597
36772
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
36598
36773
|
}
|
|
36599
36774
|
try {
|
|
36600
|
-
const dir =
|
|
36775
|
+
const dir = join46(targetPath, "..");
|
|
36601
36776
|
mkdirSync14(dir, { recursive: true });
|
|
36602
|
-
|
|
36777
|
+
writeFileSync14(targetPath, content, "utf-8");
|
|
36603
36778
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
36604
36779
|
} catch (err) {
|
|
36605
36780
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -36627,20 +36802,20 @@ var init_dream_engine = __esm({
|
|
|
36627
36802
|
const rawPath = String(args["path"] ?? "");
|
|
36628
36803
|
const oldStr = String(args["old_string"] ?? "");
|
|
36629
36804
|
const newStr = String(args["new_string"] ?? "");
|
|
36630
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
36805
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join46(this.dreamsDir, basename12(rawPath)) : join46(this.dreamsDir, rawPath);
|
|
36631
36806
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
36632
36807
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
36633
36808
|
}
|
|
36634
36809
|
try {
|
|
36635
|
-
if (!
|
|
36810
|
+
if (!existsSync35(targetPath)) {
|
|
36636
36811
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
36637
36812
|
}
|
|
36638
|
-
let content =
|
|
36813
|
+
let content = readFileSync26(targetPath, "utf-8");
|
|
36639
36814
|
if (!content.includes(oldStr)) {
|
|
36640
36815
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
36641
36816
|
}
|
|
36642
36817
|
content = content.replace(oldStr, newStr);
|
|
36643
|
-
|
|
36818
|
+
writeFileSync14(targetPath, content, "utf-8");
|
|
36644
36819
|
return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
|
|
36645
36820
|
} catch (err) {
|
|
36646
36821
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -36694,7 +36869,7 @@ var init_dream_engine = __esm({
|
|
|
36694
36869
|
constructor(config, repoRoot) {
|
|
36695
36870
|
this.config = config;
|
|
36696
36871
|
this.repoRoot = repoRoot;
|
|
36697
|
-
this.dreamsDir =
|
|
36872
|
+
this.dreamsDir = join46(repoRoot, ".oa", "dreams");
|
|
36698
36873
|
this.state = {
|
|
36699
36874
|
mode: "default",
|
|
36700
36875
|
active: false,
|
|
@@ -36778,8 +36953,8 @@ ${result.summary}`;
|
|
|
36778
36953
|
if (mode !== "default" || cycle === totalCycles) {
|
|
36779
36954
|
renderDreamContraction(cycle);
|
|
36780
36955
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
36781
|
-
const summaryPath =
|
|
36782
|
-
|
|
36956
|
+
const summaryPath = join46(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
36957
|
+
writeFileSync14(summaryPath, cycleSummary, "utf-8");
|
|
36783
36958
|
}
|
|
36784
36959
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
36785
36960
|
this.saveVersionCheckpoint(cycle);
|
|
@@ -36991,7 +37166,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
|
|
|
36991
37166
|
}
|
|
36992
37167
|
/** Build role-specific tool sets for swarm agents */
|
|
36993
37168
|
buildSwarmTools(role, _workspace) {
|
|
36994
|
-
const autoresearchDir =
|
|
37169
|
+
const autoresearchDir = join46(this.repoRoot, ".oa", "autoresearch");
|
|
36995
37170
|
const taskComplete = this.createSwarmTaskCompleteTool(role);
|
|
36996
37171
|
switch (role) {
|
|
36997
37172
|
case "researcher": {
|
|
@@ -37355,7 +37530,7 @@ INSTRUCTIONS:
|
|
|
37355
37530
|
2. Summarize the key learnings and next steps
|
|
37356
37531
|
|
|
37357
37532
|
Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
|
|
37358
|
-
const reportPath =
|
|
37533
|
+
const reportPath = join46(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
|
|
37359
37534
|
const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
|
|
37360
37535
|
|
|
37361
37536
|
**Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -37378,7 +37553,7 @@ ${summaryResult}
|
|
|
37378
37553
|
`;
|
|
37379
37554
|
try {
|
|
37380
37555
|
mkdirSync14(this.dreamsDir, { recursive: true });
|
|
37381
|
-
|
|
37556
|
+
writeFileSync14(reportPath, report, "utf-8");
|
|
37382
37557
|
} catch {
|
|
37383
37558
|
}
|
|
37384
37559
|
renderSwarmComplete(workspace);
|
|
@@ -37444,7 +37619,7 @@ ${summaryResult}
|
|
|
37444
37619
|
}
|
|
37445
37620
|
/** Save workspace backup for lucid mode */
|
|
37446
37621
|
saveVersionCheckpoint(cycle) {
|
|
37447
|
-
const checkpointDir =
|
|
37622
|
+
const checkpointDir = join46(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
37448
37623
|
try {
|
|
37449
37624
|
mkdirSync14(checkpointDir, { recursive: true });
|
|
37450
37625
|
try {
|
|
@@ -37463,10 +37638,10 @@ ${summaryResult}
|
|
|
37463
37638
|
encoding: "utf-8",
|
|
37464
37639
|
timeout: 5e3
|
|
37465
37640
|
}).trim();
|
|
37466
|
-
|
|
37467
|
-
|
|
37468
|
-
|
|
37469
|
-
|
|
37641
|
+
writeFileSync14(join46(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
|
|
37642
|
+
writeFileSync14(join46(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
|
|
37643
|
+
writeFileSync14(join46(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
|
|
37644
|
+
writeFileSync14(join46(checkpointDir, "checkpoint.json"), JSON.stringify({
|
|
37470
37645
|
cycle,
|
|
37471
37646
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
37472
37647
|
gitHash,
|
|
@@ -37474,7 +37649,7 @@ ${summaryResult}
|
|
|
37474
37649
|
}, null, 2), "utf-8");
|
|
37475
37650
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
37476
37651
|
} catch {
|
|
37477
|
-
|
|
37652
|
+
writeFileSync14(join46(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
|
|
37478
37653
|
renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
|
|
37479
37654
|
}
|
|
37480
37655
|
} catch (err) {
|
|
@@ -37532,14 +37707,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
|
|
|
37532
37707
|
---
|
|
37533
37708
|
*Auto-generated by open-agents dream engine*
|
|
37534
37709
|
`;
|
|
37535
|
-
|
|
37710
|
+
writeFileSync14(join46(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
37536
37711
|
} catch {
|
|
37537
37712
|
}
|
|
37538
37713
|
}
|
|
37539
37714
|
/** Save dream state for resume/inspection */
|
|
37540
37715
|
saveDreamState() {
|
|
37541
37716
|
try {
|
|
37542
|
-
|
|
37717
|
+
writeFileSync14(join46(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
37543
37718
|
} catch {
|
|
37544
37719
|
}
|
|
37545
37720
|
}
|
|
@@ -37913,8 +38088,8 @@ var init_bless_engine = __esm({
|
|
|
37913
38088
|
});
|
|
37914
38089
|
|
|
37915
38090
|
// packages/cli/dist/tui/dmn-engine.js
|
|
37916
|
-
import { existsSync as
|
|
37917
|
-
import { join as
|
|
38091
|
+
import { existsSync as existsSync36, readFileSync as readFileSync27, writeFileSync as writeFileSync15, mkdirSync as mkdirSync15, readdirSync as readdirSync11, unlinkSync as unlinkSync6 } from "node:fs";
|
|
38092
|
+
import { join as join47, basename as basename13 } from "node:path";
|
|
37918
38093
|
function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
|
|
37919
38094
|
const competenceReport = competence.length > 0 ? competence.map((c3) => {
|
|
37920
38095
|
const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
|
|
@@ -38027,8 +38202,8 @@ var init_dmn_engine = __esm({
|
|
|
38027
38202
|
constructor(config, repoRoot) {
|
|
38028
38203
|
this.config = config;
|
|
38029
38204
|
this.repoRoot = repoRoot;
|
|
38030
|
-
this.stateDir =
|
|
38031
|
-
this.historyDir =
|
|
38205
|
+
this.stateDir = join47(repoRoot, ".oa", "dmn");
|
|
38206
|
+
this.historyDir = join47(repoRoot, ".oa", "dmn", "cycles");
|
|
38032
38207
|
mkdirSync15(this.historyDir, { recursive: true });
|
|
38033
38208
|
this.loadState();
|
|
38034
38209
|
}
|
|
@@ -38618,11 +38793,11 @@ OUTPUT: Call task_complete with JSON:
|
|
|
38618
38793
|
async gatherMemoryTopics() {
|
|
38619
38794
|
const topics = [];
|
|
38620
38795
|
const dirs = [
|
|
38621
|
-
|
|
38622
|
-
|
|
38796
|
+
join47(this.repoRoot, ".oa", "memory"),
|
|
38797
|
+
join47(this.repoRoot, ".open-agents", "memory")
|
|
38623
38798
|
];
|
|
38624
38799
|
for (const dir of dirs) {
|
|
38625
|
-
if (!
|
|
38800
|
+
if (!existsSync36(dir))
|
|
38626
38801
|
continue;
|
|
38627
38802
|
try {
|
|
38628
38803
|
const files = readdirSync11(dir).filter((f) => f.endsWith(".json"));
|
|
@@ -38638,29 +38813,29 @@ OUTPUT: Call task_complete with JSON:
|
|
|
38638
38813
|
}
|
|
38639
38814
|
// ── State persistence ─────────────────────────────────────────────────
|
|
38640
38815
|
loadState() {
|
|
38641
|
-
const path =
|
|
38642
|
-
if (
|
|
38816
|
+
const path = join47(this.stateDir, "state.json");
|
|
38817
|
+
if (existsSync36(path)) {
|
|
38643
38818
|
try {
|
|
38644
|
-
this.state = JSON.parse(
|
|
38819
|
+
this.state = JSON.parse(readFileSync27(path, "utf-8"));
|
|
38645
38820
|
} catch {
|
|
38646
38821
|
}
|
|
38647
38822
|
}
|
|
38648
38823
|
}
|
|
38649
38824
|
saveState() {
|
|
38650
38825
|
try {
|
|
38651
|
-
|
|
38826
|
+
writeFileSync15(join47(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
38652
38827
|
} catch {
|
|
38653
38828
|
}
|
|
38654
38829
|
}
|
|
38655
38830
|
saveCycleResult(result) {
|
|
38656
38831
|
try {
|
|
38657
38832
|
const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
|
|
38658
|
-
|
|
38833
|
+
writeFileSync15(join47(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
|
|
38659
38834
|
const files = readdirSync11(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
|
|
38660
38835
|
if (files.length > 50) {
|
|
38661
38836
|
for (const old of files.slice(0, files.length - 50)) {
|
|
38662
38837
|
try {
|
|
38663
|
-
|
|
38838
|
+
unlinkSync6(join47(this.historyDir, old));
|
|
38664
38839
|
} catch {
|
|
38665
38840
|
}
|
|
38666
38841
|
}
|
|
@@ -38673,8 +38848,8 @@ OUTPUT: Call task_complete with JSON:
|
|
|
38673
38848
|
});
|
|
38674
38849
|
|
|
38675
38850
|
// packages/cli/dist/tui/snr-engine.js
|
|
38676
|
-
import { existsSync as
|
|
38677
|
-
import { join as
|
|
38851
|
+
import { existsSync as existsSync37, readdirSync as readdirSync12, readFileSync as readFileSync28 } from "node:fs";
|
|
38852
|
+
import { join as join48, basename as basename14 } from "node:path";
|
|
38678
38853
|
function computeDPrime(signalScores, noiseScores) {
|
|
38679
38854
|
if (signalScores.length === 0 || noiseScores.length === 0)
|
|
38680
38855
|
return 0;
|
|
@@ -38914,11 +39089,11 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
38914
39089
|
loadMemoryEntries(topics) {
|
|
38915
39090
|
const entries = [];
|
|
38916
39091
|
const dirs = [
|
|
38917
|
-
|
|
38918
|
-
|
|
39092
|
+
join48(this.repoRoot, ".oa", "memory"),
|
|
39093
|
+
join48(this.repoRoot, ".open-agents", "memory")
|
|
38919
39094
|
];
|
|
38920
39095
|
for (const dir of dirs) {
|
|
38921
|
-
if (!
|
|
39096
|
+
if (!existsSync37(dir))
|
|
38922
39097
|
continue;
|
|
38923
39098
|
try {
|
|
38924
39099
|
const files = readdirSync12(dir).filter((f) => f.endsWith(".json"));
|
|
@@ -38927,7 +39102,7 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
38927
39102
|
if (topics.length > 0 && !topics.includes(topic))
|
|
38928
39103
|
continue;
|
|
38929
39104
|
try {
|
|
38930
|
-
const data = JSON.parse(
|
|
39105
|
+
const data = JSON.parse(readFileSync28(join48(dir, f), "utf-8"));
|
|
38931
39106
|
for (const [key, val] of Object.entries(data)) {
|
|
38932
39107
|
const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
38933
39108
|
entries.push({ topic, key, value });
|
|
@@ -39494,8 +39669,8 @@ var init_tool_policy = __esm({
|
|
|
39494
39669
|
});
|
|
39495
39670
|
|
|
39496
39671
|
// packages/cli/dist/tui/telegram-bridge.js
|
|
39497
|
-
import { mkdirSync as mkdirSync16, existsSync as
|
|
39498
|
-
import { join as
|
|
39672
|
+
import { mkdirSync as mkdirSync16, existsSync as existsSync38, unlinkSync as unlinkSync7, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
|
|
39673
|
+
import { join as join49, resolve as resolve27 } from "node:path";
|
|
39499
39674
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
39500
39675
|
function convertMarkdownToTelegramHTML(md) {
|
|
39501
39676
|
let html = md;
|
|
@@ -40260,7 +40435,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
|
|
|
40260
40435
|
return null;
|
|
40261
40436
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
40262
40437
|
const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
|
|
40263
|
-
const localPath =
|
|
40438
|
+
const localPath = join49(this.mediaCacheDir, fileName);
|
|
40264
40439
|
await writeFileAsync(localPath, buffer);
|
|
40265
40440
|
return localPath;
|
|
40266
40441
|
} catch {
|
|
@@ -40348,7 +40523,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
|
|
|
40348
40523
|
for (const [key, entry] of this.mediaCache) {
|
|
40349
40524
|
if (now - entry.cachedAt > MEDIA_CACHE_TTL_MS) {
|
|
40350
40525
|
try {
|
|
40351
|
-
|
|
40526
|
+
unlinkSync7(entry.localPath);
|
|
40352
40527
|
} catch {
|
|
40353
40528
|
}
|
|
40354
40529
|
this.mediaCache.delete(key);
|
|
@@ -42093,11 +42268,11 @@ var init_status_bar = __esm({
|
|
|
42093
42268
|
import * as readline2 from "node:readline";
|
|
42094
42269
|
import { Writable } from "node:stream";
|
|
42095
42270
|
import { cwd } from "node:process";
|
|
42096
|
-
import { resolve as resolve28, join as
|
|
42271
|
+
import { resolve as resolve28, join as join50, dirname as dirname17, extname as extname9 } from "node:path";
|
|
42097
42272
|
import { createRequire as createRequire2 } from "node:module";
|
|
42098
42273
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
42099
|
-
import { readFileSync as
|
|
42100
|
-
import { existsSync as
|
|
42274
|
+
import { readFileSync as readFileSync29, writeFileSync as writeFileSync16, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync17 } from "node:fs";
|
|
42275
|
+
import { existsSync as existsSync39 } from "node:fs";
|
|
42101
42276
|
import { homedir as homedir13 } from "node:os";
|
|
42102
42277
|
function formatTimeAgo(date) {
|
|
42103
42278
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
@@ -42117,12 +42292,12 @@ function getVersion3() {
|
|
|
42117
42292
|
const require2 = createRequire2(import.meta.url);
|
|
42118
42293
|
const thisDir = dirname17(fileURLToPath12(import.meta.url));
|
|
42119
42294
|
const candidates = [
|
|
42120
|
-
|
|
42121
|
-
|
|
42122
|
-
|
|
42295
|
+
join50(thisDir, "..", "package.json"),
|
|
42296
|
+
join50(thisDir, "..", "..", "package.json"),
|
|
42297
|
+
join50(thisDir, "..", "..", "..", "package.json")
|
|
42123
42298
|
];
|
|
42124
42299
|
for (const pkgPath of candidates) {
|
|
42125
|
-
if (
|
|
42300
|
+
if (existsSync39(pkgPath)) {
|
|
42126
42301
|
const pkg = require2(pkgPath);
|
|
42127
42302
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
42128
42303
|
return pkg.version ?? "0.0.0";
|
|
@@ -42328,15 +42503,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
|
|
|
42328
42503
|
function gatherMemorySnippets(root) {
|
|
42329
42504
|
const snippets = [];
|
|
42330
42505
|
const dirs = [
|
|
42331
|
-
|
|
42332
|
-
|
|
42506
|
+
join50(root, ".oa", "memory"),
|
|
42507
|
+
join50(root, ".open-agents", "memory")
|
|
42333
42508
|
];
|
|
42334
42509
|
for (const dir of dirs) {
|
|
42335
|
-
if (!
|
|
42510
|
+
if (!existsSync39(dir))
|
|
42336
42511
|
continue;
|
|
42337
42512
|
try {
|
|
42338
42513
|
for (const f of readdirSync14(dir).filter((f2) => f2.endsWith(".json"))) {
|
|
42339
|
-
const data = JSON.parse(
|
|
42514
|
+
const data = JSON.parse(readFileSync29(join50(dir, f), "utf-8"));
|
|
42340
42515
|
for (const val of Object.values(data)) {
|
|
42341
42516
|
const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
42342
42517
|
if (v.length > 10)
|
|
@@ -42690,7 +42865,7 @@ ${entry.fullContent}`
|
|
|
42690
42865
|
const sizeStr = resultLen > 0 ? ` | ${resultLen.toLocaleString()} chars (~${Math.ceil(resultLen / 4).toLocaleString()} tokens)` : "";
|
|
42691
42866
|
renderVerbose(`${event.toolName ?? "unknown"}: ${durStr}${sizeStr}`);
|
|
42692
42867
|
}
|
|
42693
|
-
if (voice?.enabled) {
|
|
42868
|
+
if (voice?.enabled && event.toolName !== "task_complete") {
|
|
42694
42869
|
const emoState2 = emotionEngine?.getState();
|
|
42695
42870
|
const emoCtx2 = emoState2 ? { valence: emoState2.valence, arousal: emoState2.arousal, label: emoState2.label, emoji: emoState2.emoji } : void 0;
|
|
42696
42871
|
const desc = describeToolResult(event.toolName ?? "unknown", event.success ?? false, vLevel, event.content ?? void 0, emoCtx2, isStark);
|
|
@@ -42926,48 +43101,14 @@ async function startInteractive(config, repoPath) {
|
|
|
42926
43101
|
setEmojisEnabled(savedSettings.emojis);
|
|
42927
43102
|
if (savedSettings.colors !== void 0)
|
|
42928
43103
|
setColorsEnabled(savedSettings.colors);
|
|
42929
|
-
if (!isResumed) {
|
|
42930
|
-
const needsSetup =
|
|
42931
|
-
if (needsSetup
|
|
43104
|
+
if (!isResumed && isFirstRun() && config.backendType === "ollama") {
|
|
43105
|
+
const needsSetup = !await isModelAvailable(config);
|
|
43106
|
+
if (needsSetup) {
|
|
42932
43107
|
const setupModel = await runSetupWizard(config);
|
|
42933
43108
|
const freshConfig = loadConfig();
|
|
42934
43109
|
config = { ...config, ...freshConfig, model: setupModel ?? freshConfig.model };
|
|
42935
43110
|
}
|
|
42936
43111
|
}
|
|
42937
|
-
if (config.backendType === "ollama" && !config.model.startsWith("open-agents-")) {
|
|
42938
|
-
try {
|
|
42939
|
-
const expandResult = await ensureExpandedContext(config.model, config.backendUrl);
|
|
42940
|
-
if (expandResult.created) {
|
|
42941
|
-
renderInfo(`Created expanded context model: ${expandResult.model} (${expandResult.contextLabel}, ${expandResult.numCtx} tokens)`);
|
|
42942
|
-
config = { ...config, model: expandResult.model };
|
|
42943
|
-
} else if (expandResult.model !== config.model) {
|
|
42944
|
-
renderInfo(`Using expanded context model: ${expandResult.model} (${expandResult.contextLabel})`);
|
|
42945
|
-
config = { ...config, model: expandResult.model };
|
|
42946
|
-
}
|
|
42947
|
-
} catch {
|
|
42948
|
-
}
|
|
42949
|
-
}
|
|
42950
|
-
if (!isResumed) {
|
|
42951
|
-
try {
|
|
42952
|
-
const baseUrl = normalizeBaseUrl(config.backendUrl);
|
|
42953
|
-
const provider2 = detectProvider(config.backendUrl);
|
|
42954
|
-
const healthUrl = `${baseUrl}${provider2.modelsPath}`;
|
|
42955
|
-
const headers = {};
|
|
42956
|
-
if (config.apiKey) {
|
|
42957
|
-
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
42958
|
-
}
|
|
42959
|
-
const resp = await fetch(healthUrl, { headers, signal: AbortSignal.timeout(1e4) });
|
|
42960
|
-
if (!resp.ok)
|
|
42961
|
-
throw new Error(`HTTP ${resp.status}`);
|
|
42962
|
-
} catch {
|
|
42963
|
-
const provider2 = detectProvider(config.backendUrl);
|
|
42964
|
-
renderWarning(`Cannot reach ${provider2.label} at ${config.backendUrl}`);
|
|
42965
|
-
if (provider2.id === "ollama") {
|
|
42966
|
-
renderInfo("Use /endpoint http://127.0.0.1:11434 to auto-install & start Ollama.");
|
|
42967
|
-
}
|
|
42968
|
-
renderInfo("Use /endpoint to configure a different backend. Starting anyway...");
|
|
42969
|
-
}
|
|
42970
|
-
}
|
|
42971
43112
|
let carouselPhrases = null;
|
|
42972
43113
|
try {
|
|
42973
43114
|
carouselPhrases = loadCachedDescriptors(repoRoot) ?? generateDescriptors(repoRoot);
|
|
@@ -43102,7 +43243,7 @@ async function startInteractive(config, repoPath) {
|
|
|
43102
43243
|
let exposeGateway = null;
|
|
43103
43244
|
let peerMesh = null;
|
|
43104
43245
|
let inferenceRouter = null;
|
|
43105
|
-
const secretVault = new SecretVault(
|
|
43246
|
+
const secretVault = new SecretVault(join50(repoRoot, ".oa", "vault.enc"));
|
|
43106
43247
|
let adminSessionKey = null;
|
|
43107
43248
|
const callSubAgents = /* @__PURE__ */ new Map();
|
|
43108
43249
|
const streamRenderer = new StreamRenderer();
|
|
@@ -43307,13 +43448,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
43307
43448
|
const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
|
|
43308
43449
|
return [hits, line];
|
|
43309
43450
|
}
|
|
43310
|
-
const HISTORY_DIR =
|
|
43311
|
-
const HISTORY_FILE =
|
|
43451
|
+
const HISTORY_DIR = join50(homedir13(), ".open-agents");
|
|
43452
|
+
const HISTORY_FILE = join50(HISTORY_DIR, "repl-history");
|
|
43312
43453
|
const MAX_HISTORY_LINES = 500;
|
|
43313
43454
|
let savedHistory = [];
|
|
43314
43455
|
try {
|
|
43315
|
-
if (
|
|
43316
|
-
const raw =
|
|
43456
|
+
if (existsSync39(HISTORY_FILE)) {
|
|
43457
|
+
const raw = readFileSync29(HISTORY_FILE, "utf8").trim();
|
|
43317
43458
|
if (raw)
|
|
43318
43459
|
savedHistory = raw.split("\n").reverse();
|
|
43319
43460
|
}
|
|
@@ -43335,9 +43476,9 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
43335
43476
|
mkdirSync17(HISTORY_DIR, { recursive: true });
|
|
43336
43477
|
appendFileSync3(HISTORY_FILE, line + "\n", "utf8");
|
|
43337
43478
|
if (Math.random() < 0.02) {
|
|
43338
|
-
const all =
|
|
43479
|
+
const all = readFileSync29(HISTORY_FILE, "utf8").trim().split("\n");
|
|
43339
43480
|
if (all.length > MAX_HISTORY_LINES) {
|
|
43340
|
-
|
|
43481
|
+
writeFileSync16(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
|
|
43341
43482
|
}
|
|
43342
43483
|
}
|
|
43343
43484
|
} catch {
|
|
@@ -43358,8 +43499,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
43358
43499
|
const termRows = process.stdout.rows ?? 24;
|
|
43359
43500
|
const scrollStart = carousel.reservedRows + 1;
|
|
43360
43501
|
const scrollEnd = Math.max(termRows - statusBar.reservedRows, scrollStart + 1);
|
|
43361
|
-
|
|
43362
|
-
|
|
43502
|
+
let clearBuf = "";
|
|
43503
|
+
for (let r = scrollStart; r <= scrollEnd; r++) {
|
|
43504
|
+
clearBuf += `\x1B[${r};1H\x1B[2K`;
|
|
43505
|
+
}
|
|
43506
|
+
process.stdout.write(clearBuf);
|
|
43363
43507
|
renderRichHeader({
|
|
43364
43508
|
model: currentConfig.model,
|
|
43365
43509
|
version,
|
|
@@ -43390,6 +43534,88 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
43390
43534
|
fn();
|
|
43391
43535
|
}
|
|
43392
43536
|
}
|
|
43537
|
+
(async () => {
|
|
43538
|
+
if (!isResumed && !isFirstRun()) {
|
|
43539
|
+
try {
|
|
43540
|
+
const available = await isModelAvailable(config);
|
|
43541
|
+
if (!available && config.backendType === "ollama") {
|
|
43542
|
+
writeContent(() => {
|
|
43543
|
+
renderWarning(`Model "${config.model}" not available. Use /model to pick one.`);
|
|
43544
|
+
});
|
|
43545
|
+
}
|
|
43546
|
+
} catch {
|
|
43547
|
+
}
|
|
43548
|
+
}
|
|
43549
|
+
if (config.backendType === "ollama" && !config.model.startsWith("open-agents-")) {
|
|
43550
|
+
try {
|
|
43551
|
+
const expandResult = await ensureExpandedContext(config.model, config.backendUrl);
|
|
43552
|
+
if (expandResult.created) {
|
|
43553
|
+
config = { ...config, model: expandResult.model };
|
|
43554
|
+
currentConfig = { ...currentConfig, model: expandResult.model };
|
|
43555
|
+
statusBar.setModelName(expandResult.model);
|
|
43556
|
+
writeContent(() => renderInfo(`Created expanded context model: ${expandResult.model} (${expandResult.contextLabel}, ${expandResult.numCtx} tokens)`));
|
|
43557
|
+
} else if (expandResult.model !== config.model) {
|
|
43558
|
+
config = { ...config, model: expandResult.model };
|
|
43559
|
+
currentConfig = { ...currentConfig, model: expandResult.model };
|
|
43560
|
+
statusBar.setModelName(expandResult.model);
|
|
43561
|
+
writeContent(() => renderInfo(`Using expanded context model: ${expandResult.model} (${expandResult.contextLabel})`));
|
|
43562
|
+
}
|
|
43563
|
+
} catch {
|
|
43564
|
+
}
|
|
43565
|
+
}
|
|
43566
|
+
if (!isResumed) {
|
|
43567
|
+
try {
|
|
43568
|
+
const baseUrl = normalizeBaseUrl(config.backendUrl);
|
|
43569
|
+
const prov = detectProvider(config.backendUrl);
|
|
43570
|
+
const healthUrl = `${baseUrl}${prov.modelsPath}`;
|
|
43571
|
+
const headers = {};
|
|
43572
|
+
if (config.apiKey)
|
|
43573
|
+
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
43574
|
+
const resp = await fetch(healthUrl, { headers, signal: AbortSignal.timeout(1e4) });
|
|
43575
|
+
if (!resp.ok)
|
|
43576
|
+
throw new Error(`HTTP ${resp.status}`);
|
|
43577
|
+
} catch {
|
|
43578
|
+
const prov = detectProvider(config.backendUrl);
|
|
43579
|
+
writeContent(() => {
|
|
43580
|
+
renderWarning(`Cannot reach ${prov.label} at ${config.backendUrl}`);
|
|
43581
|
+
if (prov.id === "ollama") {
|
|
43582
|
+
renderInfo("Use /endpoint http://127.0.0.1:11434 to auto-install & start Ollama.");
|
|
43583
|
+
}
|
|
43584
|
+
renderInfo("Use /endpoint to configure a different backend.");
|
|
43585
|
+
});
|
|
43586
|
+
}
|
|
43587
|
+
}
|
|
43588
|
+
try {
|
|
43589
|
+
const oaDir = join50(repoRoot, ".oa");
|
|
43590
|
+
const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
|
|
43591
|
+
onInfo: (msg) => writeContent(() => renderInfo(msg)),
|
|
43592
|
+
onError: (msg) => writeContent(() => renderWarning(msg))
|
|
43593
|
+
});
|
|
43594
|
+
if (reconnected) {
|
|
43595
|
+
exposeGateway = reconnected;
|
|
43596
|
+
reconnected.on("stats", (stats) => {
|
|
43597
|
+
statusBar.setExposeStatus({
|
|
43598
|
+
status: stats.status,
|
|
43599
|
+
totalRequests: stats.totalRequests,
|
|
43600
|
+
activeConnections: stats.activeConnections,
|
|
43601
|
+
modelUsage: stats.modelUsage
|
|
43602
|
+
});
|
|
43603
|
+
});
|
|
43604
|
+
writeContent(() => {
|
|
43605
|
+
renderInfo(`Reconnected to existing expose tunnel: ${reconnected.tunnelUrl}`);
|
|
43606
|
+
});
|
|
43607
|
+
}
|
|
43608
|
+
} catch {
|
|
43609
|
+
}
|
|
43610
|
+
try {
|
|
43611
|
+
const isRemote = !currentConfig.backendUrl.includes("127.0.0.1") && !currentConfig.backendUrl.includes("localhost");
|
|
43612
|
+
if (isRemote) {
|
|
43613
|
+
statusBar.startRemoteMetricsPolling(currentConfig.backendUrl, currentConfig.apiKey);
|
|
43614
|
+
}
|
|
43615
|
+
} catch {
|
|
43616
|
+
}
|
|
43617
|
+
})().catch(() => {
|
|
43618
|
+
});
|
|
43393
43619
|
function handleSudoRequest(_command) {
|
|
43394
43620
|
if (sudoPromptPending)
|
|
43395
43621
|
return;
|
|
@@ -44021,7 +44247,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
44021
44247
|
kind = "custom";
|
|
44022
44248
|
targetUrl = kindOrUrl.includes("://") ? kindOrUrl : `http://${kindOrUrl}`;
|
|
44023
44249
|
}
|
|
44024
|
-
exposeGateway = new ExposeGateway({ kind, targetUrl, authKey });
|
|
44250
|
+
exposeGateway = new ExposeGateway({ kind, targetUrl, authKey, stateDir: join50(repoRoot, ".oa") });
|
|
44025
44251
|
exposeGateway.on("stats", (stats) => {
|
|
44026
44252
|
statusBar.setExposeStatus({
|
|
44027
44253
|
status: stats.status,
|
|
@@ -44208,8 +44434,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
44208
44434
|
return true;
|
|
44209
44435
|
},
|
|
44210
44436
|
destroyProject() {
|
|
44211
|
-
const oaPath =
|
|
44212
|
-
if (
|
|
44437
|
+
const oaPath = join50(repoRoot, OA_DIR);
|
|
44438
|
+
if (existsSync39(oaPath)) {
|
|
44213
44439
|
try {
|
|
44214
44440
|
rmSync2(oaPath, { recursive: true, force: true });
|
|
44215
44441
|
writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
|
|
@@ -44540,13 +44766,13 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
44540
44766
|
}
|
|
44541
44767
|
}
|
|
44542
44768
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
44543
|
-
const isImage = isImagePath(cleanPath) &&
|
|
44544
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
44769
|
+
const isImage = isImagePath(cleanPath) && existsSync39(resolve28(repoRoot, cleanPath));
|
|
44770
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync39(resolve28(repoRoot, cleanPath));
|
|
44545
44771
|
if (activeTask) {
|
|
44546
44772
|
if (isImage) {
|
|
44547
44773
|
try {
|
|
44548
44774
|
const imgPath = resolve28(repoRoot, cleanPath);
|
|
44549
|
-
const imgBuffer =
|
|
44775
|
+
const imgBuffer = readFileSync29(imgPath);
|
|
44550
44776
|
const base64 = imgBuffer.toString("base64");
|
|
44551
44777
|
const ext = extname9(cleanPath).toLowerCase();
|
|
44552
44778
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -44793,8 +45019,8 @@ NEW TASK: ${fullInput}`;
|
|
|
44793
45019
|
try {
|
|
44794
45020
|
const updateInfo = await checkForUpdate(version);
|
|
44795
45021
|
if (updateInfo) {
|
|
44796
|
-
const { exec:
|
|
44797
|
-
|
|
45022
|
+
const { exec: exec3 } = await import("node:child_process");
|
|
45023
|
+
exec3(`npm install -g open-agents-ai@latest --prefer-online`, { timeout: 18e4 }, (err) => {
|
|
44798
45024
|
if (!err) {
|
|
44799
45025
|
writeContent(() => renderInfo(`Updated to v${updateInfo.latestVersion} in background. Takes effect next session.`));
|
|
44800
45026
|
}
|
|
@@ -44898,10 +45124,6 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
44898
45124
|
showPrompt();
|
|
44899
45125
|
}
|
|
44900
45126
|
rl.on("close", () => {
|
|
44901
|
-
if (exposeGateway?.isActive) {
|
|
44902
|
-
exposeGateway.stop().catch(() => {
|
|
44903
|
-
});
|
|
44904
|
-
}
|
|
44905
45127
|
if (peerMesh) {
|
|
44906
45128
|
peerMesh.stop().catch(() => {
|
|
44907
45129
|
});
|
|
@@ -45060,7 +45282,7 @@ import { glob } from "glob";
|
|
|
45060
45282
|
import ignore from "ignore";
|
|
45061
45283
|
import { readFile as readFile16, stat as stat4 } from "node:fs/promises";
|
|
45062
45284
|
import { createHash as createHash4 } from "node:crypto";
|
|
45063
|
-
import { join as
|
|
45285
|
+
import { join as join51, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
|
|
45064
45286
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
45065
45287
|
var init_codebase_indexer = __esm({
|
|
45066
45288
|
"packages/indexer/dist/codebase-indexer.js"() {
|
|
@@ -45104,7 +45326,7 @@ var init_codebase_indexer = __esm({
|
|
|
45104
45326
|
const ig = ignore.default();
|
|
45105
45327
|
if (this.config.respectGitignore) {
|
|
45106
45328
|
try {
|
|
45107
|
-
const gitignoreContent = await readFile16(
|
|
45329
|
+
const gitignoreContent = await readFile16(join51(this.config.rootDir, ".gitignore"), "utf-8");
|
|
45108
45330
|
ig.add(gitignoreContent);
|
|
45109
45331
|
} catch {
|
|
45110
45332
|
}
|
|
@@ -45119,7 +45341,7 @@ var init_codebase_indexer = __esm({
|
|
|
45119
45341
|
for (const relativePath of files) {
|
|
45120
45342
|
if (ig.ignores(relativePath))
|
|
45121
45343
|
continue;
|
|
45122
|
-
const fullPath =
|
|
45344
|
+
const fullPath = join51(this.config.rootDir, relativePath);
|
|
45123
45345
|
try {
|
|
45124
45346
|
const fileStat = await stat4(fullPath);
|
|
45125
45347
|
if (fileStat.size > this.config.maxFileSize)
|
|
@@ -45165,7 +45387,7 @@ var init_codebase_indexer = __esm({
|
|
|
45165
45387
|
if (!child) {
|
|
45166
45388
|
child = {
|
|
45167
45389
|
name: part,
|
|
45168
|
-
path:
|
|
45390
|
+
path: join51(current.path, part),
|
|
45169
45391
|
type: "directory",
|
|
45170
45392
|
children: []
|
|
45171
45393
|
};
|
|
@@ -45248,13 +45470,13 @@ __export(index_repo_exports, {
|
|
|
45248
45470
|
indexRepoCommand: () => indexRepoCommand
|
|
45249
45471
|
});
|
|
45250
45472
|
import { resolve as resolve29 } from "node:path";
|
|
45251
|
-
import { existsSync as
|
|
45473
|
+
import { existsSync as existsSync40, statSync as statSync11 } from "node:fs";
|
|
45252
45474
|
import { cwd as cwd2 } from "node:process";
|
|
45253
45475
|
async function indexRepoCommand(opts, _config) {
|
|
45254
45476
|
const repoRoot = resolve29(opts.repoPath ?? cwd2());
|
|
45255
45477
|
printHeader("Index Repository");
|
|
45256
45478
|
printInfo(`Indexing: ${repoRoot}`);
|
|
45257
|
-
if (!
|
|
45479
|
+
if (!existsSync40(repoRoot)) {
|
|
45258
45480
|
printError(`Path does not exist: ${repoRoot}`);
|
|
45259
45481
|
process.exit(1);
|
|
45260
45482
|
}
|
|
@@ -45506,7 +45728,7 @@ var config_exports = {};
|
|
|
45506
45728
|
__export(config_exports, {
|
|
45507
45729
|
configCommand: () => configCommand
|
|
45508
45730
|
});
|
|
45509
|
-
import { join as
|
|
45731
|
+
import { join as join52, resolve as resolve30 } from "node:path";
|
|
45510
45732
|
import { homedir as homedir14 } from "node:os";
|
|
45511
45733
|
import { cwd as cwd3 } from "node:process";
|
|
45512
45734
|
function redactIfSensitive(key, value) {
|
|
@@ -45589,7 +45811,7 @@ function handleShow(opts, config) {
|
|
|
45589
45811
|
}
|
|
45590
45812
|
}
|
|
45591
45813
|
printSection("Config File");
|
|
45592
|
-
printInfo(`~/.open-agents/config.json (${
|
|
45814
|
+
printInfo(`~/.open-agents/config.json (${join52(homedir14(), ".open-agents", "config.json")})`);
|
|
45593
45815
|
printSection("Priority Chain");
|
|
45594
45816
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
45595
45817
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -45628,7 +45850,7 @@ function handleSet(opts, _config) {
|
|
|
45628
45850
|
const coerced = coerceForSettings(key, value);
|
|
45629
45851
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
45630
45852
|
printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
|
|
45631
|
-
printInfo(`Saved to ${
|
|
45853
|
+
printInfo(`Saved to ${join52(repoRoot, ".oa", "settings.json")}`);
|
|
45632
45854
|
printInfo("This override applies only when running in this workspace.");
|
|
45633
45855
|
} catch (err) {
|
|
45634
45856
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -45886,8 +46108,8 @@ __export(eval_exports, {
|
|
|
45886
46108
|
evalCommand: () => evalCommand
|
|
45887
46109
|
});
|
|
45888
46110
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
45889
|
-
import { mkdirSync as mkdirSync18, writeFileSync as
|
|
45890
|
-
import { join as
|
|
46111
|
+
import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync17 } from "node:fs";
|
|
46112
|
+
import { join as join53 } from "node:path";
|
|
45891
46113
|
async function evalCommand(opts, config) {
|
|
45892
46114
|
const suiteName = opts.suite ?? "basic";
|
|
45893
46115
|
const suite = SUITES[suiteName];
|
|
@@ -46012,9 +46234,9 @@ async function evalCommand(opts, config) {
|
|
|
46012
46234
|
process.exit(failed > 0 ? 1 : 0);
|
|
46013
46235
|
}
|
|
46014
46236
|
function createTempEvalRepo() {
|
|
46015
|
-
const dir =
|
|
46237
|
+
const dir = join53(tmpdir7(), `open-agents-eval-${Date.now()}`);
|
|
46016
46238
|
mkdirSync18(dir, { recursive: true });
|
|
46017
|
-
|
|
46239
|
+
writeFileSync17(join53(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
46018
46240
|
return dir;
|
|
46019
46241
|
}
|
|
46020
46242
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -46074,7 +46296,7 @@ init_updater();
|
|
|
46074
46296
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
46075
46297
|
import { createRequire as createRequire3 } from "node:module";
|
|
46076
46298
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
46077
|
-
import { dirname as dirname18, join as
|
|
46299
|
+
import { dirname as dirname18, join as join54 } from "node:path";
|
|
46078
46300
|
|
|
46079
46301
|
// packages/cli/dist/cli.js
|
|
46080
46302
|
import { createInterface } from "node:readline";
|
|
@@ -46181,7 +46403,7 @@ init_output();
|
|
|
46181
46403
|
function getVersion4() {
|
|
46182
46404
|
try {
|
|
46183
46405
|
const require2 = createRequire3(import.meta.url);
|
|
46184
|
-
const pkgPath =
|
|
46406
|
+
const pkgPath = join54(dirname18(fileURLToPath13(import.meta.url)), "..", "package.json");
|
|
46185
46407
|
const pkg = require2(pkgPath);
|
|
46186
46408
|
return pkg.version;
|
|
46187
46409
|
} catch {
|