open-agents-ai 0.185.22 → 0.185.24
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 +1163 -768
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13741,9 +13741,9 @@ print("${sentinel}")
|
|
|
13741
13741
|
if (!this.proc || this.proc.killed) {
|
|
13742
13742
|
return { success: false, path: "" };
|
|
13743
13743
|
}
|
|
13744
|
-
const { mkdirSync:
|
|
13744
|
+
const { mkdirSync: mkdirSync31, writeFileSync: writeFileSync30 } = await import("node:fs");
|
|
13745
13745
|
const sessionDir = join22(this.cwd, ".oa", "rlm");
|
|
13746
|
-
|
|
13746
|
+
mkdirSync31(sessionDir, { recursive: true });
|
|
13747
13747
|
const sessionPath = join22(sessionDir, "session.json");
|
|
13748
13748
|
try {
|
|
13749
13749
|
const inspectCode = `
|
|
@@ -13767,7 +13767,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
13767
13767
|
trajectoryCount: this.trajectory.length,
|
|
13768
13768
|
subCallCount: this.subCallCount
|
|
13769
13769
|
};
|
|
13770
|
-
|
|
13770
|
+
writeFileSync30(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
|
|
13771
13771
|
return { success: true, path: sessionPath };
|
|
13772
13772
|
}
|
|
13773
13773
|
} catch {
|
|
@@ -13779,11 +13779,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
13779
13779
|
* what was previously computed. */
|
|
13780
13780
|
async loadSessionInfo() {
|
|
13781
13781
|
try {
|
|
13782
|
-
const { readFileSync:
|
|
13782
|
+
const { readFileSync: readFileSync45, existsSync: existsSync57 } = await import("node:fs");
|
|
13783
13783
|
const sessionPath = join22(this.cwd, ".oa", "rlm", "session.json");
|
|
13784
|
-
if (!
|
|
13784
|
+
if (!existsSync57(sessionPath))
|
|
13785
13785
|
return null;
|
|
13786
|
-
return JSON.parse(
|
|
13786
|
+
return JSON.parse(readFileSync45(sessionPath, "utf8"));
|
|
13787
13787
|
} catch {
|
|
13788
13788
|
return null;
|
|
13789
13789
|
}
|
|
@@ -13960,10 +13960,10 @@ var init_memory_metabolism = __esm({
|
|
|
13960
13960
|
const trajDir = join23(this.cwd, ".oa", "rlm-trajectories");
|
|
13961
13961
|
let lessons = [];
|
|
13962
13962
|
try {
|
|
13963
|
-
const { readdirSync: readdirSync23, readFileSync:
|
|
13963
|
+
const { readdirSync: readdirSync23, readFileSync: readFileSync45 } = await import("node:fs");
|
|
13964
13964
|
const files = readdirSync23(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
|
|
13965
13965
|
for (const file of files) {
|
|
13966
|
-
const lines =
|
|
13966
|
+
const lines = readFileSync45(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
|
|
13967
13967
|
for (const line of lines) {
|
|
13968
13968
|
try {
|
|
13969
13969
|
const entry = JSON.parse(line);
|
|
@@ -14347,14 +14347,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14347
14347
|
* Optionally filter by task type for phase-aware context (FSM paper insight).
|
|
14348
14348
|
*/
|
|
14349
14349
|
getTopMemoriesSync(k = 5, taskType) {
|
|
14350
|
-
const { readFileSync:
|
|
14350
|
+
const { readFileSync: readFileSync45, existsSync: existsSync57 } = __require("node:fs");
|
|
14351
14351
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14352
14352
|
const storeFile = join23(metaDir, "store.json");
|
|
14353
|
-
if (!
|
|
14353
|
+
if (!existsSync57(storeFile))
|
|
14354
14354
|
return "";
|
|
14355
14355
|
let store = [];
|
|
14356
14356
|
try {
|
|
14357
|
-
store = JSON.parse(
|
|
14357
|
+
store = JSON.parse(readFileSync45(storeFile, "utf8"));
|
|
14358
14358
|
} catch {
|
|
14359
14359
|
return "";
|
|
14360
14360
|
}
|
|
@@ -14376,14 +14376,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14376
14376
|
/** Update memory scores based on task outcome. Called after task completion.
|
|
14377
14377
|
* Memories used in successful tasks get boosted. Memories present during failures get decayed. */
|
|
14378
14378
|
updateFromOutcomeSync(surfacedMemoryText, succeeded) {
|
|
14379
|
-
const { readFileSync:
|
|
14379
|
+
const { readFileSync: readFileSync45, writeFileSync: writeFileSync30, existsSync: existsSync57, mkdirSync: mkdirSync31 } = __require("node:fs");
|
|
14380
14380
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14381
14381
|
const storeFile = join23(metaDir, "store.json");
|
|
14382
|
-
if (!
|
|
14382
|
+
if (!existsSync57(storeFile))
|
|
14383
14383
|
return;
|
|
14384
14384
|
let store = [];
|
|
14385
14385
|
try {
|
|
14386
|
-
store = JSON.parse(
|
|
14386
|
+
store = JSON.parse(readFileSync45(storeFile, "utf8"));
|
|
14387
14387
|
} catch {
|
|
14388
14388
|
return;
|
|
14389
14389
|
}
|
|
@@ -14407,8 +14407,8 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14407
14407
|
updated = true;
|
|
14408
14408
|
}
|
|
14409
14409
|
if (updated) {
|
|
14410
|
-
|
|
14411
|
-
|
|
14410
|
+
mkdirSync31(metaDir, { recursive: true });
|
|
14411
|
+
writeFileSync30(storeFile, JSON.stringify(store, null, 2));
|
|
14412
14412
|
}
|
|
14413
14413
|
}
|
|
14414
14414
|
// ── Storage ──────────────────────────────────────────────────────────
|
|
@@ -14830,13 +14830,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14830
14830
|
// Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
|
|
14831
14831
|
/** Retrieve top-K strategies for context injection. Returns "" if none. */
|
|
14832
14832
|
getRelevantStrategiesSync(k = 3, taskType) {
|
|
14833
|
-
const { readFileSync:
|
|
14833
|
+
const { readFileSync: readFileSync45, existsSync: existsSync57 } = __require("node:fs");
|
|
14834
14834
|
const archiveFile = join25(this.cwd, ".oa", "arche", "variants.json");
|
|
14835
|
-
if (!
|
|
14835
|
+
if (!existsSync57(archiveFile))
|
|
14836
14836
|
return "";
|
|
14837
14837
|
let variants = [];
|
|
14838
14838
|
try {
|
|
14839
|
-
variants = JSON.parse(
|
|
14839
|
+
variants = JSON.parse(readFileSync45(archiveFile, "utf8"));
|
|
14840
14840
|
} catch {
|
|
14841
14841
|
return "";
|
|
14842
14842
|
}
|
|
@@ -14854,13 +14854,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14854
14854
|
}
|
|
14855
14855
|
/** Archive a strategy variant synchronously (for task completion path) */
|
|
14856
14856
|
archiveVariantSync(strategy, outcome, tags = []) {
|
|
14857
|
-
const { readFileSync:
|
|
14857
|
+
const { readFileSync: readFileSync45, writeFileSync: writeFileSync30, existsSync: existsSync57, mkdirSync: mkdirSync31 } = __require("node:fs");
|
|
14858
14858
|
const dir = join25(this.cwd, ".oa", "arche");
|
|
14859
14859
|
const archiveFile = join25(dir, "variants.json");
|
|
14860
14860
|
let variants = [];
|
|
14861
14861
|
try {
|
|
14862
|
-
if (
|
|
14863
|
-
variants = JSON.parse(
|
|
14862
|
+
if (existsSync57(archiveFile))
|
|
14863
|
+
variants = JSON.parse(readFileSync45(archiveFile, "utf8"));
|
|
14864
14864
|
} catch {
|
|
14865
14865
|
}
|
|
14866
14866
|
variants.push({
|
|
@@ -14875,8 +14875,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14875
14875
|
});
|
|
14876
14876
|
if (variants.length > 50)
|
|
14877
14877
|
variants = variants.slice(-50);
|
|
14878
|
-
|
|
14879
|
-
|
|
14878
|
+
mkdirSync31(dir, { recursive: true });
|
|
14879
|
+
writeFileSync30(archiveFile, JSON.stringify(variants, null, 2));
|
|
14880
14880
|
}
|
|
14881
14881
|
async saveArchive(variants) {
|
|
14882
14882
|
const dir = join25(this.cwd, ".oa", "arche");
|
|
@@ -15840,9 +15840,9 @@ var init_vision = __esm({
|
|
|
15840
15840
|
if (ollamaResult)
|
|
15841
15841
|
return ollamaResult;
|
|
15842
15842
|
try {
|
|
15843
|
-
const { execSync:
|
|
15843
|
+
const { execSync: execSync35 } = await import("node:child_process");
|
|
15844
15844
|
try {
|
|
15845
|
-
|
|
15845
|
+
execSync35("pip3 install --user moondream 2>/dev/null || pip install --user moondream 2>/dev/null", {
|
|
15846
15846
|
timeout: 12e4,
|
|
15847
15847
|
stdio: "pipe"
|
|
15848
15848
|
});
|
|
@@ -15855,7 +15855,7 @@ var init_vision = __esm({
|
|
|
15855
15855
|
} catch {
|
|
15856
15856
|
}
|
|
15857
15857
|
try {
|
|
15858
|
-
|
|
15858
|
+
execSync35("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
|
|
15859
15859
|
const retryOllama = await this.tryOllamaVision(buffer, filename, action, prompt, length, start);
|
|
15860
15860
|
if (retryOllama)
|
|
15861
15861
|
return retryOllama;
|
|
@@ -15963,8 +15963,8 @@ Coordinates are normalized (0-1). Multiply by image width/height for pixel value
|
|
|
15963
15963
|
const errText = await res.text().catch(() => "");
|
|
15964
15964
|
if (res.status === 404 || /not found|does not exist/i.test(errText)) {
|
|
15965
15965
|
try {
|
|
15966
|
-
const { execSync:
|
|
15967
|
-
|
|
15966
|
+
const { execSync: execSync35 } = await import("node:child_process");
|
|
15967
|
+
execSync35("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
|
|
15968
15968
|
res = await fetch(`${ollamaHost}/api/generate`, {
|
|
15969
15969
|
method: "POST",
|
|
15970
15970
|
headers: { "Content-Type": "application/json" },
|
|
@@ -27351,10 +27351,10 @@ ${marker}` : marker);
|
|
|
27351
27351
|
if (!this._workingDirectory)
|
|
27352
27352
|
return;
|
|
27353
27353
|
try {
|
|
27354
|
-
const { mkdirSync:
|
|
27355
|
-
const { join:
|
|
27356
|
-
const sessionDir =
|
|
27357
|
-
|
|
27354
|
+
const { mkdirSync: mkdirSync31, writeFileSync: writeFileSync30 } = __require("node:fs");
|
|
27355
|
+
const { join: join77 } = __require("node:path");
|
|
27356
|
+
const sessionDir = join77(this._workingDirectory, ".oa", "session", this._sessionId);
|
|
27357
|
+
mkdirSync31(sessionDir, { recursive: true });
|
|
27358
27358
|
const checkpoint = {
|
|
27359
27359
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27360
27360
|
sessionId: this._sessionId,
|
|
@@ -27366,7 +27366,7 @@ ${marker}` : marker);
|
|
|
27366
27366
|
memexEntryCount: this._memexArchive.size,
|
|
27367
27367
|
fileRegistrySize: this._fileRegistry.size
|
|
27368
27368
|
};
|
|
27369
|
-
|
|
27369
|
+
writeFileSync30(join77(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
|
|
27370
27370
|
} catch {
|
|
27371
27371
|
}
|
|
27372
27372
|
}
|
|
@@ -35253,97 +35253,98 @@ function generateFrontendHTML() {
|
|
|
35253
35253
|
<head>
|
|
35254
35254
|
<meta charset="UTF-8">
|
|
35255
35255
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
35256
|
-
<title>
|
|
35256
|
+
<title>OA \u2014 Voice</title>
|
|
35257
35257
|
<style>
|
|
35258
35258
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
35259
35259
|
body {
|
|
35260
|
-
background: #
|
|
35261
|
-
color: #
|
|
35262
|
-
font-family: 'SF Mono', 'Cascadia Code', 'Fira Code',
|
|
35260
|
+
background: #1a1a1e;
|
|
35261
|
+
color: #b0b0b0;
|
|
35262
|
+
font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;
|
|
35263
35263
|
display: flex;
|
|
35264
35264
|
flex-direction: column;
|
|
35265
|
-
align-items: center;
|
|
35266
|
-
justify-content: center;
|
|
35267
35265
|
min-height: 100vh;
|
|
35268
|
-
overflow: hidden;
|
|
35269
35266
|
}
|
|
35267
|
+
#header {
|
|
35268
|
+
background: #1e1e22;
|
|
35269
|
+
padding: 8px 16px;
|
|
35270
|
+
display: flex;
|
|
35271
|
+
align-items: center;
|
|
35272
|
+
gap: 12px;
|
|
35273
|
+
border-bottom: 1px solid #2a2a30;
|
|
35274
|
+
}
|
|
35275
|
+
#header .accent { color: #b2920a; font-weight: bold; font-size: 0.8rem; }
|
|
35276
|
+
#header .status { font-size: 0.7rem; color: #555; }
|
|
35277
|
+
#header .status.live { color: #b2920a; }
|
|
35270
35278
|
#waveform {
|
|
35271
|
-
|
|
35272
|
-
height: 80px;
|
|
35279
|
+
height: 48px;
|
|
35273
35280
|
display: flex;
|
|
35274
35281
|
align-items: center;
|
|
35275
35282
|
justify-content: center;
|
|
35276
|
-
font-size:
|
|
35283
|
+
font-size: 1.6rem;
|
|
35277
35284
|
line-height: 1;
|
|
35278
|
-
letter-spacing: 0.
|
|
35285
|
+
letter-spacing: 0.04em;
|
|
35279
35286
|
white-space: nowrap;
|
|
35280
35287
|
overflow: hidden;
|
|
35281
|
-
margin-bottom: 1.5rem;
|
|
35282
35288
|
user-select: none;
|
|
35289
|
+
background: #1e1e22;
|
|
35290
|
+
border-bottom: 1px solid #2a2a30;
|
|
35291
|
+
}
|
|
35292
|
+
#conversation {
|
|
35293
|
+
flex: 1;
|
|
35294
|
+
overflow-y: auto;
|
|
35295
|
+
padding: 12px 16px;
|
|
35296
|
+
}
|
|
35297
|
+
.msg {
|
|
35298
|
+
padding: 6px 0;
|
|
35299
|
+
font-size: 0.82rem;
|
|
35300
|
+
line-height: 1.4;
|
|
35301
|
+
}
|
|
35302
|
+
.msg.user { color: #888; }
|
|
35303
|
+
.msg.user::before { content: '\u25B8 '; color: #555; }
|
|
35304
|
+
.msg.agent { color: #b2920a; }
|
|
35305
|
+
.msg.agent::before { content: '\u25B9 '; color: #b2920a; }
|
|
35306
|
+
#footer {
|
|
35307
|
+
background: #1e1e22;
|
|
35308
|
+
padding: 8px 16px;
|
|
35309
|
+
display: flex;
|
|
35310
|
+
align-items: center;
|
|
35311
|
+
gap: 10px;
|
|
35312
|
+
border-top: 1px solid #2a2a30;
|
|
35283
35313
|
}
|
|
35284
|
-
#title {
|
|
35285
|
-
font-size: 0.75rem;
|
|
35286
|
-
color: #7c3aed;
|
|
35287
|
-
letter-spacing: 0.3em;
|
|
35288
|
-
text-transform: uppercase;
|
|
35289
|
-
margin-bottom: 1.5rem;
|
|
35290
|
-
}
|
|
35291
|
-
#status {
|
|
35292
|
-
font-size: 0.85rem;
|
|
35293
|
-
color: #6b6b8a;
|
|
35294
|
-
margin-bottom: 1rem;
|
|
35295
|
-
}
|
|
35296
|
-
#status .connected { color: #a78bfa; }
|
|
35297
|
-
#status .disconnected { color: #f87171; }
|
|
35298
|
-
#transcripts {
|
|
35299
|
-
width: 90%; max-width: 600px; max-height: 40vh;
|
|
35300
|
-
overflow-y: auto; padding: 1rem;
|
|
35301
|
-
background: rgba(139,92,246,0.04);
|
|
35302
|
-
border-radius: 4px;
|
|
35303
|
-
border: 1px solid rgba(139,92,246,0.12);
|
|
35304
|
-
}
|
|
35305
|
-
.transcript {
|
|
35306
|
-
padding: 0.35rem 0;
|
|
35307
|
-
border-bottom: 1px solid rgba(139,92,246,0.08);
|
|
35308
|
-
font-size: 0.8rem;
|
|
35309
|
-
color: #a5a0c8;
|
|
35310
|
-
}
|
|
35311
|
-
.transcript .speaker { font-weight: bold; margin-right: 0.5rem; }
|
|
35312
|
-
.transcript .speaker.user { color: #c084fc; }
|
|
35313
|
-
.transcript .speaker.agent { color: #8b5cf6; }
|
|
35314
|
-
#controls { margin-top: 1.5rem; }
|
|
35315
35314
|
button {
|
|
35316
|
-
background:
|
|
35317
|
-
border: 1px solid
|
|
35318
|
-
color: #
|
|
35319
|
-
padding:
|
|
35320
|
-
border-radius:
|
|
35315
|
+
background: #2a2a30;
|
|
35316
|
+
border: 1px solid #3a3a42;
|
|
35317
|
+
color: #b2920a;
|
|
35318
|
+
padding: 6px 16px;
|
|
35319
|
+
border-radius: 3px;
|
|
35321
35320
|
font-family: inherit;
|
|
35322
|
-
font-size: 0.
|
|
35321
|
+
font-size: 0.75rem;
|
|
35323
35322
|
cursor: pointer;
|
|
35324
|
-
transition:
|
|
35325
|
-
letter-spacing: 0.05em;
|
|
35323
|
+
transition: background 0.15s;
|
|
35326
35324
|
}
|
|
35327
|
-
button:hover { background:
|
|
35328
|
-
button.active { background:
|
|
35325
|
+
button:hover { background: #3a3a42; }
|
|
35326
|
+
button.active { background: #3a2a10; border-color: #b2920a; }
|
|
35327
|
+
#footer .hint { font-size: 0.65rem; color: #444; }
|
|
35329
35328
|
</style>
|
|
35330
35329
|
</head>
|
|
35331
35330
|
<body>
|
|
35332
|
-
<div id="
|
|
35333
|
-
<
|
|
35334
|
-
<
|
|
35335
|
-
<span class="disconnected">connecting...</span>
|
|
35331
|
+
<div id="header">
|
|
35332
|
+
<span class="accent">OA</span>
|
|
35333
|
+
<span id="status" class="status">connecting</span>
|
|
35336
35334
|
</div>
|
|
35337
|
-
<div id="
|
|
35338
|
-
<div id="
|
|
35339
|
-
|
|
35335
|
+
<div id="waveform"></div>
|
|
35336
|
+
<div id="conversation"></div>
|
|
35337
|
+
<div id="footer">
|
|
35338
|
+
<button id="micBtn" onclick="toggleMic()">mic</button>
|
|
35339
|
+
<span class="hint" id="hint">tap to start</span>
|
|
35340
35340
|
</div>
|
|
35341
35341
|
|
|
35342
35342
|
<script>
|
|
35343
35343
|
const waveEl = document.getElementById('waveform');
|
|
35344
35344
|
const statusEl = document.getElementById('status');
|
|
35345
|
-
const
|
|
35345
|
+
const convoEl = document.getElementById('conversation');
|
|
35346
35346
|
const micBtn = document.getElementById('micBtn');
|
|
35347
|
+
const hintEl = document.getElementById('hint');
|
|
35347
35348
|
|
|
35348
35349
|
// ---------------------------------------------------------------------------
|
|
35349
35350
|
// Braille waveform \u2014 ported from TUI braille-spinner.ts
|
|
@@ -35354,10 +35355,10 @@ const DENSITY = [
|
|
|
35354
35355
|
];
|
|
35355
35356
|
const WAVE = [...DENSITY, ...DENSITY.slice(1, -1).reverse()]; // 16 entries
|
|
35356
35357
|
|
|
35357
|
-
// Color themes:
|
|
35358
|
-
const THEME_IDLE = ['#
|
|
35359
|
-
const THEME_SPEAKING = ['#
|
|
35360
|
-
const THEME_LISTENING = ['#
|
|
35358
|
+
// Color themes: TUI-aligned dark grey + yellow accent
|
|
35359
|
+
const THEME_IDLE = ['#1e1e22','#2a2a30','#333338','#3e3e44','#4a4a52','#555560','#666670','#777780','#888890'];
|
|
35360
|
+
const THEME_SPEAKING = ['#1e1e22','#2a2510','#3a3518','#4a4520','#5a5528','#6a6530','#8a7a20','#a89010','#b2920a'];
|
|
35361
|
+
const THEME_LISTENING = ['#1e1e22','#2a2818','#3a3820','#4a4828','#5a5830','#6a6838','#8a8830','#a8a020','#b2920a'];
|
|
35361
35362
|
|
|
35362
35363
|
function buildColorRamp(ramp) {
|
|
35363
35364
|
return [...ramp, ...ramp.slice(1, -1).reverse()]; // 16 entries
|
|
@@ -35459,7 +35460,8 @@ function connect() {
|
|
|
35459
35460
|
ws.onopen = () => {
|
|
35460
35461
|
connecting = false;
|
|
35461
35462
|
if (disconnectGrace) { clearTimeout(disconnectGrace); disconnectGrace = null; }
|
|
35462
|
-
statusEl.
|
|
35463
|
+
statusEl.textContent = 'connected';
|
|
35464
|
+
statusEl.className = 'status live';
|
|
35463
35465
|
reconnectDelay = 1000;
|
|
35464
35466
|
};
|
|
35465
35467
|
|
|
@@ -35471,7 +35473,8 @@ function connect() {
|
|
|
35471
35473
|
if (!disconnectGrace) {
|
|
35472
35474
|
disconnectGrace = setTimeout(() => {
|
|
35473
35475
|
disconnectGrace = null;
|
|
35474
|
-
statusEl.
|
|
35476
|
+
statusEl.textContent = 'reconnecting';
|
|
35477
|
+
statusEl.className = 'status';
|
|
35475
35478
|
}, 2000);
|
|
35476
35479
|
}
|
|
35477
35480
|
reconnectTimer = setTimeout(connect, reconnectDelay);
|
|
@@ -35503,11 +35506,10 @@ function connect() {
|
|
|
35503
35506
|
|
|
35504
35507
|
function addTranscript(speaker, text) {
|
|
35505
35508
|
const div = document.createElement('div');
|
|
35506
|
-
div.className = '
|
|
35507
|
-
div.
|
|
35508
|
-
|
|
35509
|
-
|
|
35510
|
-
transcriptsEl.scrollTop = transcriptsEl.scrollHeight;
|
|
35509
|
+
div.className = 'msg ' + speaker;
|
|
35510
|
+
div.textContent = text;
|
|
35511
|
+
convoEl.appendChild(div);
|
|
35512
|
+
convoEl.scrollTop = convoEl.scrollHeight;
|
|
35511
35513
|
}
|
|
35512
35514
|
|
|
35513
35515
|
function escapeHtml(s) {
|
|
@@ -35565,11 +35567,12 @@ async function toggleMic() {
|
|
|
35565
35567
|
scriptProcessor.connect(micCtx.destination);
|
|
35566
35568
|
micActive = true;
|
|
35567
35569
|
waveState = 'listening';
|
|
35568
|
-
micBtn.textContent = 'stop
|
|
35570
|
+
micBtn.textContent = 'stop';
|
|
35569
35571
|
micBtn.classList.add('active');
|
|
35572
|
+
hintEl.textContent = 'listening...';
|
|
35570
35573
|
ws.send(JSON.stringify({ type: 'mic_start', username: 'web-user' }));
|
|
35571
35574
|
} catch (err) {
|
|
35572
|
-
|
|
35575
|
+
hintEl.textContent = 'mic error: ' + err.message;
|
|
35573
35576
|
}
|
|
35574
35577
|
}
|
|
35575
35578
|
|
|
@@ -35579,8 +35582,9 @@ function stopMic() {
|
|
|
35579
35582
|
waveState = 'idle';
|
|
35580
35583
|
if (scriptProcessor) { scriptProcessor.disconnect(); scriptProcessor = null; }
|
|
35581
35584
|
if (micStream) { micStream.getTracks().forEach(t => t.stop()); micStream = null; }
|
|
35582
|
-
micBtn.textContent = '
|
|
35585
|
+
micBtn.textContent = 'mic';
|
|
35583
35586
|
micBtn.classList.remove('active');
|
|
35587
|
+
hintEl.textContent = 'tap to start';
|
|
35584
35588
|
if (ws && ws.readyState === 1) {
|
|
35585
35589
|
ws.send(JSON.stringify({ type: 'mic_stop' }));
|
|
35586
35590
|
}
|
|
@@ -38525,6 +38529,7 @@ var init_call_agent = __esm({
|
|
|
38525
38529
|
tier;
|
|
38526
38530
|
clientId;
|
|
38527
38531
|
runner = null;
|
|
38532
|
+
backend = null;
|
|
38528
38533
|
config;
|
|
38529
38534
|
repoRoot;
|
|
38530
38535
|
opts;
|
|
@@ -38543,6 +38548,7 @@ var init_call_agent = __esm({
|
|
|
38543
38548
|
/** Initialize the runner with appropriate tools for the access tier */
|
|
38544
38549
|
async init() {
|
|
38545
38550
|
const backend = new OllamaAgenticBackend(this.config.backendUrl, this.config.model, this.config.apiKey);
|
|
38551
|
+
this.backend = backend;
|
|
38546
38552
|
const feed = getActivityFeed();
|
|
38547
38553
|
const systemPrompt = this.buildSystemPrompt();
|
|
38548
38554
|
const runnerOpts = {
|
|
@@ -38652,21 +38658,46 @@ var init_call_agent = __esm({
|
|
|
38652
38658
|
const historyContext = this.conversationHistory.slice(-10).map((h) => `${h.role === "user" ? "User" : "You"}: ${h.text}`).join("\n");
|
|
38653
38659
|
const feed = getActivityFeed();
|
|
38654
38660
|
const activitySummary = feed.getSummary(this.tier === "admin" ? 20 : 10, this.tier === "admin");
|
|
38655
|
-
const wantsAction = /\b(read|open|show|run|execute|check|look at|find|search|grep|edit|write|fix|test|build|deploy|install)\b/i.test(text) && !/\b(how are you|what's up|hello|hi|hey|can you hear|stop|quit|bye)\b/i.test(text);
|
|
38656
|
-
|
|
38657
|
-
|
|
38658
|
-
|
|
38659
|
-
|
|
38661
|
+
const wantsAction = /\b(read|open|show|run|execute|check|look at|find|search|grep|edit|write|fix|test|build|deploy|install|create|delete|remove|update|change|modify|commit|push|pull)\b/i.test(text) && !/\b(how are you|what's up|hello|hi|hey|can you hear|stop|quit|bye|thanks|thank you|ok|okay|sure|yeah|yes|no)\b/i.test(text);
|
|
38662
|
+
if (!wantsAction) {
|
|
38663
|
+
try {
|
|
38664
|
+
const chatMessages = [
|
|
38665
|
+
{ role: "system", content: this.buildSystemPrompt() },
|
|
38666
|
+
...this.conversationHistory.slice(-6).map((h) => ({
|
|
38667
|
+
role: h.role === "user" ? "user" : "assistant",
|
|
38668
|
+
content: h.text
|
|
38669
|
+
})),
|
|
38670
|
+
{ role: "user", content: text }
|
|
38671
|
+
];
|
|
38672
|
+
const chatResult = await this.backend.chatCompletion({
|
|
38673
|
+
messages: chatMessages,
|
|
38674
|
+
tools: [],
|
|
38675
|
+
temperature: 0.4,
|
|
38676
|
+
maxTokens: 256,
|
|
38677
|
+
timeoutMs: 15e3
|
|
38678
|
+
});
|
|
38679
|
+
const reply = chatResult.choices[0]?.message?.content ?? "I heard you.";
|
|
38680
|
+
this.conversationHistory.push({ role: "assistant", text: reply });
|
|
38681
|
+
this.emit("response", reply);
|
|
38682
|
+
} catch {
|
|
38683
|
+
this.emit("response", "Sorry, I couldn't process that.");
|
|
38684
|
+
}
|
|
38685
|
+
} else {
|
|
38686
|
+
const taskPrompt = [
|
|
38687
|
+
`User said: "${text}"`,
|
|
38688
|
+
"",
|
|
38689
|
+
historyContext ? `Conversation so far:
|
|
38660
38690
|
${historyContext}
|
|
38661
38691
|
` : "",
|
|
38662
|
-
|
|
38692
|
+
`Background activity:
|
|
38663
38693
|
${activitySummary}
|
|
38664
38694
|
`,
|
|
38665
|
-
|
|
38666
|
-
|
|
38667
|
-
|
|
38668
|
-
|
|
38669
|
-
|
|
38695
|
+
"The user is requesting an action. Use tools as needed, then call task_complete with a brief spoken summary of what you did (1-2 sentences)."
|
|
38696
|
+
].join("\n");
|
|
38697
|
+
const result = await this.runner.run(taskPrompt, `Working directory: ${this.repoRoot}`);
|
|
38698
|
+
if (result.summary) {
|
|
38699
|
+
this.conversationHistory.push({ role: "assistant", text: result.summary });
|
|
38700
|
+
}
|
|
38670
38701
|
}
|
|
38671
38702
|
} catch (err) {
|
|
38672
38703
|
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
@@ -38875,26 +38906,26 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
|
|
|
38875
38906
|
async function fetchPeerModels(peerId, authKey) {
|
|
38876
38907
|
try {
|
|
38877
38908
|
const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
38878
|
-
const { existsSync:
|
|
38879
|
-
const { join:
|
|
38909
|
+
const { existsSync: existsSync57, readFileSync: readFileSync45 } = await import("node:fs");
|
|
38910
|
+
const { join: join77 } = await import("node:path");
|
|
38880
38911
|
const cwd4 = process.cwd();
|
|
38881
38912
|
const nexusTool = new NexusTool2(cwd4);
|
|
38882
38913
|
const nexusDir = nexusTool.getNexusDir();
|
|
38883
38914
|
let isLocalPeer = false;
|
|
38884
38915
|
try {
|
|
38885
|
-
const statusPath =
|
|
38886
|
-
if (
|
|
38887
|
-
const status = JSON.parse(
|
|
38916
|
+
const statusPath = join77(nexusDir, "status.json");
|
|
38917
|
+
if (existsSync57(statusPath)) {
|
|
38918
|
+
const status = JSON.parse(readFileSync45(statusPath, "utf8"));
|
|
38888
38919
|
if (status.peerId === peerId)
|
|
38889
38920
|
isLocalPeer = true;
|
|
38890
38921
|
}
|
|
38891
38922
|
} catch {
|
|
38892
38923
|
}
|
|
38893
38924
|
if (isLocalPeer) {
|
|
38894
|
-
const pricingPath =
|
|
38895
|
-
if (
|
|
38925
|
+
const pricingPath = join77(nexusDir, "pricing.json");
|
|
38926
|
+
if (existsSync57(pricingPath)) {
|
|
38896
38927
|
try {
|
|
38897
|
-
const pricing = JSON.parse(
|
|
38928
|
+
const pricing = JSON.parse(readFileSync45(pricingPath, "utf8"));
|
|
38898
38929
|
const localModels = (pricing.models || []).map((m) => ({
|
|
38899
38930
|
name: m.model || "unknown",
|
|
38900
38931
|
size: m.parameterSize || "",
|
|
@@ -38908,10 +38939,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
38908
38939
|
}
|
|
38909
38940
|
}
|
|
38910
38941
|
}
|
|
38911
|
-
const cachePath =
|
|
38912
|
-
if (
|
|
38942
|
+
const cachePath = join77(nexusDir, "peer-models-cache.json");
|
|
38943
|
+
if (existsSync57(cachePath)) {
|
|
38913
38944
|
try {
|
|
38914
|
-
const cache4 = JSON.parse(
|
|
38945
|
+
const cache4 = JSON.parse(readFileSync45(cachePath, "utf8"));
|
|
38915
38946
|
if (cache4.peerId === peerId && cache4.models?.length > 0) {
|
|
38916
38947
|
const age = Date.now() - new Date(cache4.cachedAt).getTime();
|
|
38917
38948
|
if (age < 5 * 60 * 1e3) {
|
|
@@ -39026,10 +39057,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
39026
39057
|
} catch {
|
|
39027
39058
|
}
|
|
39028
39059
|
if (isLocalPeer) {
|
|
39029
|
-
const pricingPath =
|
|
39030
|
-
if (
|
|
39060
|
+
const pricingPath = join77(nexusDir, "pricing.json");
|
|
39061
|
+
if (existsSync57(pricingPath)) {
|
|
39031
39062
|
try {
|
|
39032
|
-
const pricing = JSON.parse(
|
|
39063
|
+
const pricing = JSON.parse(readFileSync45(pricingPath, "utf8"));
|
|
39033
39064
|
return (pricing.models || []).map((m) => ({
|
|
39034
39065
|
name: m.model || "unknown",
|
|
39035
39066
|
size: m.parameterSize || "",
|
|
@@ -40693,13 +40724,321 @@ var init_tui_select = __esm({
|
|
|
40693
40724
|
}
|
|
40694
40725
|
});
|
|
40695
40726
|
|
|
40727
|
+
// packages/cli/dist/tui/personaplex.js
|
|
40728
|
+
var personaplex_exports = {};
|
|
40729
|
+
__export(personaplex_exports, {
|
|
40730
|
+
detectPersonaPlexCapability: () => detectPersonaPlexCapability,
|
|
40731
|
+
getPersonaPlexWSUrl: () => getPersonaPlexWSUrl,
|
|
40732
|
+
installPersonaPlex: () => installPersonaPlex,
|
|
40733
|
+
isPersonaPlexInstalled: () => isPersonaPlexInstalled,
|
|
40734
|
+
isPersonaPlexRunning: () => isPersonaPlexRunning,
|
|
40735
|
+
startPersonaPlexDaemon: () => startPersonaPlexDaemon,
|
|
40736
|
+
stopPersonaPlex: () => stopPersonaPlex
|
|
40737
|
+
});
|
|
40738
|
+
import { existsSync as existsSync37, writeFileSync as writeFileSync16, readFileSync as readFileSync28, mkdirSync as mkdirSync15 } from "node:fs";
|
|
40739
|
+
import { join as join54 } from "node:path";
|
|
40740
|
+
import { homedir as homedir13 } from "node:os";
|
|
40741
|
+
import { execSync as execSync27, spawn as spawn19 } from "node:child_process";
|
|
40742
|
+
function detectPersonaPlexCapability() {
|
|
40743
|
+
try {
|
|
40744
|
+
const nvsmi = execSync27("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits", {
|
|
40745
|
+
encoding: "utf8",
|
|
40746
|
+
timeout: 5e3,
|
|
40747
|
+
stdio: "pipe"
|
|
40748
|
+
}).trim();
|
|
40749
|
+
if (!nvsmi) {
|
|
40750
|
+
return { supported: false, reason: "No NVIDIA GPU detected", gpuName: "", vramGB: 0 };
|
|
40751
|
+
}
|
|
40752
|
+
const [gpuName, vramMB] = nvsmi.split("\n")[0].split(", ");
|
|
40753
|
+
const vramGB = parseInt(vramMB ?? "0", 10) / 1024;
|
|
40754
|
+
if (vramGB < 16) {
|
|
40755
|
+
return { supported: false, reason: `GPU has ${vramGB.toFixed(1)}GB VRAM (need \u226516GB)`, gpuName: gpuName ?? "", vramGB };
|
|
40756
|
+
}
|
|
40757
|
+
try {
|
|
40758
|
+
execSync27('python3 -c "import torch; assert torch.cuda.is_available()"', {
|
|
40759
|
+
timeout: 1e4,
|
|
40760
|
+
stdio: "pipe"
|
|
40761
|
+
});
|
|
40762
|
+
} catch {
|
|
40763
|
+
return { supported: false, reason: "PyTorch CUDA not available", gpuName: gpuName ?? "", vramGB };
|
|
40764
|
+
}
|
|
40765
|
+
return { supported: true, reason: "OK", gpuName: gpuName ?? "", vramGB };
|
|
40766
|
+
} catch {
|
|
40767
|
+
return { supported: false, reason: "nvidia-smi not found", gpuName: "", vramGB: 0 };
|
|
40768
|
+
}
|
|
40769
|
+
}
|
|
40770
|
+
function isPersonaPlexRunning() {
|
|
40771
|
+
if (!existsSync37(PID_FILE))
|
|
40772
|
+
return false;
|
|
40773
|
+
const pid = parseInt(readFileSync28(PID_FILE, "utf8").trim(), 10);
|
|
40774
|
+
if (isNaN(pid) || pid <= 0)
|
|
40775
|
+
return false;
|
|
40776
|
+
try {
|
|
40777
|
+
process.kill(pid, 0);
|
|
40778
|
+
return true;
|
|
40779
|
+
} catch {
|
|
40780
|
+
return false;
|
|
40781
|
+
}
|
|
40782
|
+
}
|
|
40783
|
+
function getPersonaPlexWSUrl() {
|
|
40784
|
+
if (!isPersonaPlexRunning())
|
|
40785
|
+
return null;
|
|
40786
|
+
if (!existsSync37(PORT_FILE))
|
|
40787
|
+
return null;
|
|
40788
|
+
const port = parseInt(readFileSync28(PORT_FILE, "utf8").trim(), 10);
|
|
40789
|
+
return isNaN(port) ? null : `ws://127.0.0.1:${port}`;
|
|
40790
|
+
}
|
|
40791
|
+
function isPersonaPlexInstalled() {
|
|
40792
|
+
return existsSync37(join54(PERSONAPLEX_DIR, "model_ready"));
|
|
40793
|
+
}
|
|
40794
|
+
async function installPersonaPlex(onInfo) {
|
|
40795
|
+
const log = onInfo ?? (() => {
|
|
40796
|
+
});
|
|
40797
|
+
mkdirSync15(PERSONAPLEX_DIR, { recursive: true });
|
|
40798
|
+
const venvDir = join54(PERSONAPLEX_DIR, "venv");
|
|
40799
|
+
if (!existsSync37(venvDir)) {
|
|
40800
|
+
log("Creating Python virtual environment...");
|
|
40801
|
+
try {
|
|
40802
|
+
execSync27(`python3 -m venv "${venvDir}"`, { timeout: 6e4, stdio: "pipe" });
|
|
40803
|
+
} catch (err) {
|
|
40804
|
+
log(`Failed to create venv: ${err instanceof Error ? err.message : String(err)}`);
|
|
40805
|
+
return false;
|
|
40806
|
+
}
|
|
40807
|
+
}
|
|
40808
|
+
const pip = process.platform === "win32" ? join54(venvDir, "Scripts", "pip.exe") : join54(venvDir, "bin", "pip");
|
|
40809
|
+
const python = process.platform === "win32" ? join54(venvDir, "Scripts", "python.exe") : join54(venvDir, "bin", "python3");
|
|
40810
|
+
log("Installing PersonaPlex dependencies (torch, transformers, websockets)...");
|
|
40811
|
+
try {
|
|
40812
|
+
execSync27(`"${pip}" install --quiet torch torchaudio transformers websockets soundfile huggingface_hub`, { timeout: 3e5, stdio: "pipe" });
|
|
40813
|
+
} catch (err) {
|
|
40814
|
+
log(`Dependency install failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
40815
|
+
return false;
|
|
40816
|
+
}
|
|
40817
|
+
log("Downloading PersonaPlex-7B model (~14GB, this may take a while)...");
|
|
40818
|
+
try {
|
|
40819
|
+
execSync27(`"${python}" -c "from huggingface_hub import snapshot_download; snapshot_download('nvidia/personaplex-7b-v1', local_dir='${join54(PERSONAPLEX_DIR, "model").replace(/\\/g, "\\\\")}')"`, { timeout: 36e5, stdio: "pipe" });
|
|
40820
|
+
} catch (err) {
|
|
40821
|
+
log(`Model download failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
40822
|
+
return false;
|
|
40823
|
+
}
|
|
40824
|
+
writeFileSync16(join54(PERSONAPLEX_DIR, "model_ready"), (/* @__PURE__ */ new Date()).toISOString());
|
|
40825
|
+
log("PersonaPlex installed successfully.");
|
|
40826
|
+
return true;
|
|
40827
|
+
}
|
|
40828
|
+
function writeDaemonScript() {
|
|
40829
|
+
const scriptPath2 = join54(PERSONAPLEX_DIR, "daemon.py");
|
|
40830
|
+
const modelDir2 = join54(PERSONAPLEX_DIR, "model");
|
|
40831
|
+
const script = `#!/usr/bin/env python3
|
|
40832
|
+
"""PersonaPlex daemon \u2014 full-duplex voice WebSocket server."""
|
|
40833
|
+
import asyncio
|
|
40834
|
+
import json
|
|
40835
|
+
import os
|
|
40836
|
+
import signal
|
|
40837
|
+
import sys
|
|
40838
|
+
import numpy as np
|
|
40839
|
+
|
|
40840
|
+
# Write PID file
|
|
40841
|
+
pid_file = os.path.join(os.path.dirname(__file__), "daemon.pid")
|
|
40842
|
+
with open(pid_file, "w") as f:
|
|
40843
|
+
f.write(str(os.getpid()))
|
|
40844
|
+
|
|
40845
|
+
try:
|
|
40846
|
+
import torch
|
|
40847
|
+
import torchaudio
|
|
40848
|
+
from transformers import AutoModel, AutoProcessor
|
|
40849
|
+
import websockets
|
|
40850
|
+
import soundfile as sf
|
|
40851
|
+
except ImportError as e:
|
|
40852
|
+
print(f"Missing dependency: {e}", file=sys.stderr)
|
|
40853
|
+
sys.exit(1)
|
|
40854
|
+
|
|
40855
|
+
MODEL_DIR = ${JSON.stringify(modelDir2)}
|
|
40856
|
+
SAMPLE_RATE = 24000
|
|
40857
|
+
PORT = int(os.environ.get("PERSONAPLEX_PORT", "0")) # 0 = auto-assign
|
|
40858
|
+
|
|
40859
|
+
print("Loading PersonaPlex model...", file=sys.stderr)
|
|
40860
|
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
|
40861
|
+
dtype = torch.bfloat16 if device == "cuda" else torch.float32
|
|
40862
|
+
|
|
40863
|
+
try:
|
|
40864
|
+
model = AutoModel.from_pretrained(MODEL_DIR, trust_remote_code=True, torch_dtype=dtype)
|
|
40865
|
+
model = model.to(device)
|
|
40866
|
+
model.eval()
|
|
40867
|
+
processor = AutoProcessor.from_pretrained(MODEL_DIR, trust_remote_code=True)
|
|
40868
|
+
print(f"Model loaded on {device}", file=sys.stderr)
|
|
40869
|
+
except Exception as e:
|
|
40870
|
+
print(f"Model load failed: {e}", file=sys.stderr)
|
|
40871
|
+
sys.exit(1)
|
|
40872
|
+
|
|
40873
|
+
# Persona state
|
|
40874
|
+
persona_text = "You are a helpful voice assistant."
|
|
40875
|
+
voice_prompt = None # Audio conditioning tensor
|
|
40876
|
+
|
|
40877
|
+
async def handle_client(websocket, path):
|
|
40878
|
+
"""Handle a single WebSocket client connection."""
|
|
40879
|
+
global persona_text, voice_prompt
|
|
40880
|
+
print(f"Client connected from {websocket.remote_address}", file=sys.stderr)
|
|
40881
|
+
|
|
40882
|
+
try:
|
|
40883
|
+
async for message in websocket:
|
|
40884
|
+
if isinstance(message, str):
|
|
40885
|
+
# JSON control message
|
|
40886
|
+
try:
|
|
40887
|
+
msg = json.loads(message)
|
|
40888
|
+
if msg.get("type") == "persona":
|
|
40889
|
+
persona_text = msg.get("text", persona_text)
|
|
40890
|
+
print(f"Persona updated: {persona_text[:60]}", file=sys.stderr)
|
|
40891
|
+
elif msg.get("type") == "voice_prompt":
|
|
40892
|
+
# Audio conditioning: base64 PCM \u2192 tensor
|
|
40893
|
+
import base64
|
|
40894
|
+
pcm_bytes = base64.b64decode(msg["audio"])
|
|
40895
|
+
audio = np.frombuffer(pcm_bytes, dtype=np.int16).astype(np.float32) / 32768.0
|
|
40896
|
+
voice_prompt = torch.tensor(audio, dtype=dtype, device=device).unsqueeze(0)
|
|
40897
|
+
print(f"Voice prompt set ({len(audio)} samples)", file=sys.stderr)
|
|
40898
|
+
elif msg.get("type") == "keepalive":
|
|
40899
|
+
await websocket.send(json.dumps({"type": "pong"}))
|
|
40900
|
+
except json.JSONDecodeError:
|
|
40901
|
+
pass
|
|
40902
|
+
else:
|
|
40903
|
+
# Binary audio data: PCM Int16 @ 24kHz
|
|
40904
|
+
pcm = np.frombuffer(message, dtype=np.int16).astype(np.float32) / 32768.0
|
|
40905
|
+
audio_tensor = torch.tensor(pcm, dtype=dtype, device=device).unsqueeze(0)
|
|
40906
|
+
|
|
40907
|
+
# Generate response
|
|
40908
|
+
with torch.no_grad():
|
|
40909
|
+
inputs = processor(
|
|
40910
|
+
audio=audio_tensor,
|
|
40911
|
+
text=persona_text,
|
|
40912
|
+
sampling_rate=SAMPLE_RATE,
|
|
40913
|
+
return_tensors="pt"
|
|
40914
|
+
).to(device)
|
|
40915
|
+
|
|
40916
|
+
if voice_prompt is not None:
|
|
40917
|
+
inputs["voice_prompt"] = voice_prompt
|
|
40918
|
+
|
|
40919
|
+
outputs = model.generate(**inputs, max_new_tokens=512)
|
|
40920
|
+
|
|
40921
|
+
# Extract audio response
|
|
40922
|
+
if hasattr(outputs, "audio"):
|
|
40923
|
+
response_pcm = outputs.audio.cpu().numpy().flatten()
|
|
40924
|
+
else:
|
|
40925
|
+
response_pcm = outputs[0].cpu().numpy().flatten()
|
|
40926
|
+
|
|
40927
|
+
# Convert to Int16 and send
|
|
40928
|
+
response_int16 = (response_pcm * 32767).astype(np.int16)
|
|
40929
|
+
await websocket.send(response_int16.tobytes())
|
|
40930
|
+
|
|
40931
|
+
# Send text if available
|
|
40932
|
+
if hasattr(outputs, "text") and outputs.text:
|
|
40933
|
+
await websocket.send(json.dumps({
|
|
40934
|
+
"type": "transcript",
|
|
40935
|
+
"speaker": "agent",
|
|
40936
|
+
"text": outputs.text
|
|
40937
|
+
}))
|
|
40938
|
+
|
|
40939
|
+
except websockets.exceptions.ConnectionClosed:
|
|
40940
|
+
print("Client disconnected", file=sys.stderr)
|
|
40941
|
+
|
|
40942
|
+
async def main():
|
|
40943
|
+
port = PORT
|
|
40944
|
+
server = await websockets.serve(handle_client, "127.0.0.1", port)
|
|
40945
|
+
actual_port = server.sockets[0].getsockname()[1]
|
|
40946
|
+
|
|
40947
|
+
# Write port file
|
|
40948
|
+
port_file = os.path.join(os.path.dirname(__file__), "daemon.port")
|
|
40949
|
+
with open(port_file, "w") as f:
|
|
40950
|
+
f.write(str(actual_port))
|
|
40951
|
+
|
|
40952
|
+
print(f"PersonaPlex daemon listening on ws://127.0.0.1:{actual_port}", file=sys.stderr)
|
|
40953
|
+
|
|
40954
|
+
# Handle shutdown
|
|
40955
|
+
loop = asyncio.get_event_loop()
|
|
40956
|
+
stop = asyncio.Future()
|
|
40957
|
+
for sig in (signal.SIGINT, signal.SIGTERM):
|
|
40958
|
+
loop.add_signal_handler(sig, stop.set_result, None)
|
|
40959
|
+
await stop
|
|
40960
|
+
server.close()
|
|
40961
|
+
await server.wait_closed()
|
|
40962
|
+
|
|
40963
|
+
asyncio.run(main())
|
|
40964
|
+
`;
|
|
40965
|
+
writeFileSync16(scriptPath2, script, "utf8");
|
|
40966
|
+
return scriptPath2;
|
|
40967
|
+
}
|
|
40968
|
+
async function startPersonaPlexDaemon(onInfo) {
|
|
40969
|
+
const log = onInfo ?? (() => {
|
|
40970
|
+
});
|
|
40971
|
+
if (isPersonaPlexRunning()) {
|
|
40972
|
+
const url = getPersonaPlexWSUrl();
|
|
40973
|
+
if (url) {
|
|
40974
|
+
log(`PersonaPlex already running at ${url}`);
|
|
40975
|
+
return url;
|
|
40976
|
+
}
|
|
40977
|
+
}
|
|
40978
|
+
if (!isPersonaPlexInstalled()) {
|
|
40979
|
+
log("PersonaPlex not installed. Run /voice personaplex to set up.");
|
|
40980
|
+
return null;
|
|
40981
|
+
}
|
|
40982
|
+
mkdirSync15(PERSONAPLEX_DIR, { recursive: true });
|
|
40983
|
+
const scriptPath2 = writeDaemonScript();
|
|
40984
|
+
const venvPython2 = process.platform === "win32" ? join54(PERSONAPLEX_DIR, "venv", "Scripts", "python.exe") : join54(PERSONAPLEX_DIR, "venv", "bin", "python3");
|
|
40985
|
+
log("Starting PersonaPlex daemon...");
|
|
40986
|
+
const child = spawn19(venvPython2, [scriptPath2], {
|
|
40987
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
40988
|
+
detached: true,
|
|
40989
|
+
env: { ...process.env, PERSONAPLEX_PORT: "0" }
|
|
40990
|
+
});
|
|
40991
|
+
child.unref();
|
|
40992
|
+
const startTime = Date.now();
|
|
40993
|
+
const timeout = 6e4;
|
|
40994
|
+
while (Date.now() - startTime < timeout) {
|
|
40995
|
+
if (existsSync37(PORT_FILE)) {
|
|
40996
|
+
const port = parseInt(readFileSync28(PORT_FILE, "utf8").trim(), 10);
|
|
40997
|
+
if (!isNaN(port) && port > 0) {
|
|
40998
|
+
const url = `ws://127.0.0.1:${port}`;
|
|
40999
|
+
log(`PersonaPlex ready at ${url}`);
|
|
41000
|
+
return url;
|
|
41001
|
+
}
|
|
41002
|
+
}
|
|
41003
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
41004
|
+
}
|
|
41005
|
+
log("PersonaPlex daemon failed to start within 60s.");
|
|
41006
|
+
return null;
|
|
41007
|
+
}
|
|
41008
|
+
function stopPersonaPlex() {
|
|
41009
|
+
if (!existsSync37(PID_FILE))
|
|
41010
|
+
return;
|
|
41011
|
+
const pid = parseInt(readFileSync28(PID_FILE, "utf8").trim(), 10);
|
|
41012
|
+
if (isNaN(pid) || pid <= 0)
|
|
41013
|
+
return;
|
|
41014
|
+
try {
|
|
41015
|
+
if (process.platform === "win32") {
|
|
41016
|
+
execSync27(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
|
|
41017
|
+
} else {
|
|
41018
|
+
process.kill(pid, "SIGTERM");
|
|
41019
|
+
}
|
|
41020
|
+
} catch {
|
|
41021
|
+
}
|
|
41022
|
+
}
|
|
41023
|
+
var PERSONAPLEX_DIR, PID_FILE, PORT_FILE, LOG_FILE;
|
|
41024
|
+
var init_personaplex = __esm({
|
|
41025
|
+
"packages/cli/dist/tui/personaplex.js"() {
|
|
41026
|
+
"use strict";
|
|
41027
|
+
init_render();
|
|
41028
|
+
PERSONAPLEX_DIR = join54(homedir13(), ".open-agents", "voice", "personaplex");
|
|
41029
|
+
PID_FILE = join54(PERSONAPLEX_DIR, "daemon.pid");
|
|
41030
|
+
PORT_FILE = join54(PERSONAPLEX_DIR, "daemon.port");
|
|
41031
|
+
LOG_FILE = join54(PERSONAPLEX_DIR, "daemon.log");
|
|
41032
|
+
}
|
|
41033
|
+
});
|
|
41034
|
+
|
|
40696
41035
|
// packages/cli/dist/tui/setup.js
|
|
40697
41036
|
import * as readline from "node:readline";
|
|
40698
|
-
import { execSync as
|
|
41037
|
+
import { execSync as execSync28, spawn as spawn20, exec as exec2 } from "node:child_process";
|
|
40699
41038
|
import { promisify as promisify6 } from "node:util";
|
|
40700
|
-
import { existsSync as
|
|
40701
|
-
import { join as
|
|
40702
|
-
import { homedir as
|
|
41039
|
+
import { existsSync as existsSync38, writeFileSync as writeFileSync17, readFileSync as readFileSync29, appendFileSync as appendFileSync2, mkdirSync as mkdirSync16 } from "node:fs";
|
|
41040
|
+
import { join as join55 } from "node:path";
|
|
41041
|
+
import { homedir as homedir14, platform as platform2 } from "node:os";
|
|
40703
41042
|
async function checkToolSupport(modelName, backendUrl = "http://localhost:11434") {
|
|
40704
41043
|
if (_toolSupportCache.has(modelName))
|
|
40705
41044
|
return _toolSupportCache.get(modelName);
|
|
@@ -40730,7 +41069,7 @@ function detectSystemSpecs() {
|
|
|
40730
41069
|
let gpuVramGB = 0;
|
|
40731
41070
|
let gpuName = "";
|
|
40732
41071
|
try {
|
|
40733
|
-
const memInfo =
|
|
41072
|
+
const memInfo = execSync28("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
|
|
40734
41073
|
encoding: "utf8",
|
|
40735
41074
|
timeout: 5e3
|
|
40736
41075
|
});
|
|
@@ -40750,7 +41089,7 @@ function detectSystemSpecs() {
|
|
|
40750
41089
|
} catch {
|
|
40751
41090
|
}
|
|
40752
41091
|
try {
|
|
40753
|
-
const nvidiaSmi =
|
|
41092
|
+
const nvidiaSmi = execSync28("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
|
|
40754
41093
|
const lines = nvidiaSmi.trim().split("\n");
|
|
40755
41094
|
if (lines.length > 0) {
|
|
40756
41095
|
for (const line of lines) {
|
|
@@ -40921,7 +41260,7 @@ function ensureCurl() {
|
|
|
40921
41260
|
for (const s of strategies) {
|
|
40922
41261
|
if (hasCmd(s.check)) {
|
|
40923
41262
|
try {
|
|
40924
|
-
|
|
41263
|
+
execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
40925
41264
|
if (hasCmd("curl")) {
|
|
40926
41265
|
process.stdout.write(` ${c2.green("\u2714")} curl installed via ${s.label}.
|
|
40927
41266
|
`);
|
|
@@ -40935,7 +41274,7 @@ function ensureCurl() {
|
|
|
40935
41274
|
}
|
|
40936
41275
|
if (plat === "darwin") {
|
|
40937
41276
|
try {
|
|
40938
|
-
|
|
41277
|
+
execSync28("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
|
|
40939
41278
|
if (hasCmd("curl"))
|
|
40940
41279
|
return true;
|
|
40941
41280
|
} catch {
|
|
@@ -40970,7 +41309,7 @@ function installOllamaLinux() {
|
|
|
40970
41309
|
|
|
40971
41310
|
`);
|
|
40972
41311
|
try {
|
|
40973
|
-
|
|
41312
|
+
execSync28("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
40974
41313
|
stdio: "inherit",
|
|
40975
41314
|
timeout: 3e5
|
|
40976
41315
|
});
|
|
@@ -40998,10 +41337,10 @@ async function installOllamaMac(_rl) {
|
|
|
40998
41337
|
|
|
40999
41338
|
`);
|
|
41000
41339
|
try {
|
|
41001
|
-
|
|
41340
|
+
execSync28('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
|
|
41002
41341
|
if (!hasCmd("brew")) {
|
|
41003
41342
|
try {
|
|
41004
|
-
const brewPrefix =
|
|
41343
|
+
const brewPrefix = existsSync38("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
|
|
41005
41344
|
process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
|
|
41006
41345
|
} catch {
|
|
41007
41346
|
}
|
|
@@ -41031,7 +41370,7 @@ async function installOllamaMac(_rl) {
|
|
|
41031
41370
|
|
|
41032
41371
|
`);
|
|
41033
41372
|
try {
|
|
41034
|
-
|
|
41373
|
+
execSync28("brew install ollama", {
|
|
41035
41374
|
stdio: "inherit",
|
|
41036
41375
|
timeout: 3e5
|
|
41037
41376
|
});
|
|
@@ -41058,7 +41397,7 @@ function installOllamaWindows() {
|
|
|
41058
41397
|
|
|
41059
41398
|
`);
|
|
41060
41399
|
try {
|
|
41061
|
-
|
|
41400
|
+
execSync28('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
|
|
41062
41401
|
stdio: "inherit",
|
|
41063
41402
|
timeout: 3e5
|
|
41064
41403
|
});
|
|
@@ -41109,7 +41448,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
41109
41448
|
process.stdout.write(` ${c2.cyan("\u25CF")} Starting ollama serve...
|
|
41110
41449
|
`);
|
|
41111
41450
|
try {
|
|
41112
|
-
const child =
|
|
41451
|
+
const child = spawn20("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
41113
41452
|
child.unref();
|
|
41114
41453
|
} catch {
|
|
41115
41454
|
process.stdout.write(` ${c2.yellow("\u26A0")} Could not start ollama serve.
|
|
@@ -41139,7 +41478,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
|
|
|
41139
41478
|
}
|
|
41140
41479
|
function pullModelWithAutoUpdate(tag) {
|
|
41141
41480
|
try {
|
|
41142
|
-
|
|
41481
|
+
execSync28(`ollama pull ${tag}`, {
|
|
41143
41482
|
stdio: "inherit",
|
|
41144
41483
|
timeout: 36e5
|
|
41145
41484
|
// 1 hour max
|
|
@@ -41159,7 +41498,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
41159
41498
|
|
|
41160
41499
|
`);
|
|
41161
41500
|
try {
|
|
41162
|
-
|
|
41501
|
+
execSync28("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
41163
41502
|
stdio: "inherit",
|
|
41164
41503
|
timeout: 3e5
|
|
41165
41504
|
// 5 min max for install
|
|
@@ -41170,7 +41509,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
41170
41509
|
process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
|
|
41171
41510
|
|
|
41172
41511
|
`);
|
|
41173
|
-
|
|
41512
|
+
execSync28(`ollama pull ${tag}`, {
|
|
41174
41513
|
stdio: "inherit",
|
|
41175
41514
|
timeout: 36e5
|
|
41176
41515
|
});
|
|
@@ -41272,7 +41611,7 @@ function ensurePython3() {
|
|
|
41272
41611
|
if (plat === "darwin") {
|
|
41273
41612
|
if (hasCmd("brew")) {
|
|
41274
41613
|
try {
|
|
41275
|
-
|
|
41614
|
+
execSync28("brew install python3", { stdio: "inherit", timeout: 3e5 });
|
|
41276
41615
|
if (hasCmd("python3")) {
|
|
41277
41616
|
process.stdout.write(` ${c2.green("\u2714")} Python3 installed via Homebrew.
|
|
41278
41617
|
`);
|
|
@@ -41285,7 +41624,7 @@ function ensurePython3() {
|
|
|
41285
41624
|
for (const s of strategies) {
|
|
41286
41625
|
if (hasCmd(s.check)) {
|
|
41287
41626
|
try {
|
|
41288
|
-
|
|
41627
|
+
execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
41289
41628
|
if (hasCmd("python3") || hasCmd("python")) {
|
|
41290
41629
|
process.stdout.write(` ${c2.green("\u2714")} Python3 installed via ${s.label}.
|
|
41291
41630
|
`);
|
|
@@ -41301,11 +41640,11 @@ function ensurePython3() {
|
|
|
41301
41640
|
}
|
|
41302
41641
|
function checkPythonVenv() {
|
|
41303
41642
|
try {
|
|
41304
|
-
|
|
41643
|
+
execSync28("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
41305
41644
|
return true;
|
|
41306
41645
|
} catch {
|
|
41307
41646
|
try {
|
|
41308
|
-
|
|
41647
|
+
execSync28("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
41309
41648
|
return true;
|
|
41310
41649
|
} catch {
|
|
41311
41650
|
return false;
|
|
@@ -41324,7 +41663,7 @@ function ensurePythonVenv() {
|
|
|
41324
41663
|
for (const s of strategies) {
|
|
41325
41664
|
if (hasCmd(s.check)) {
|
|
41326
41665
|
try {
|
|
41327
|
-
|
|
41666
|
+
execSync28(s.install, { stdio: "inherit", timeout: 12e4 });
|
|
41328
41667
|
if (checkPythonVenv()) {
|
|
41329
41668
|
process.stdout.write(` ${c2.green("\u2714")} python3-venv installed via ${s.label}.
|
|
41330
41669
|
`);
|
|
@@ -41482,6 +41821,20 @@ async function doSetup(config, rl) {
|
|
|
41482
41821
|
} else {
|
|
41483
41822
|
process.stdout.write(` ${c2.dim(" GPU:")} No NVIDIA GPU detected (CPU inference)
|
|
41484
41823
|
`);
|
|
41824
|
+
}
|
|
41825
|
+
let personaPlexCapable = false;
|
|
41826
|
+
try {
|
|
41827
|
+
const { detectPersonaPlexCapability: detectPersonaPlexCapability2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
|
|
41828
|
+
const ppCaps = detectPersonaPlexCapability2();
|
|
41829
|
+
personaPlexCapable = ppCaps.supported;
|
|
41830
|
+
if (ppCaps.supported) {
|
|
41831
|
+
process.stdout.write(` ${c2.green("\u2714")} PersonaPlex full-duplex voice: ${c2.bold("compatible")} (${ppCaps.gpuName}, ${ppCaps.vramGB.toFixed(0)}GB VRAM)
|
|
41832
|
+
`);
|
|
41833
|
+
process.stdout.write(` ${c2.dim("Enable with: /voice personaplex")}
|
|
41834
|
+
|
|
41835
|
+
`);
|
|
41836
|
+
}
|
|
41837
|
+
} catch {
|
|
41485
41838
|
}
|
|
41486
41839
|
const score = computeInferenceScore(specs);
|
|
41487
41840
|
const bw = 30;
|
|
@@ -41571,7 +41924,7 @@ async function doSetup(config, rl) {
|
|
|
41571
41924
|
${c2.cyan("\u25CF")} Ollama is installed but not running. Starting automatically...
|
|
41572
41925
|
`);
|
|
41573
41926
|
try {
|
|
41574
|
-
const child =
|
|
41927
|
+
const child = spawn20("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
41575
41928
|
child.unref();
|
|
41576
41929
|
await new Promise((resolve36) => setTimeout(resolve36, 3e3));
|
|
41577
41930
|
try {
|
|
@@ -41599,7 +41952,7 @@ async function doSetup(config, rl) {
|
|
|
41599
41952
|
${c2.cyan("\u25CF")} Starting ollama serve...
|
|
41600
41953
|
`);
|
|
41601
41954
|
try {
|
|
41602
|
-
const child =
|
|
41955
|
+
const child = spawn20("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
41603
41956
|
child.unref();
|
|
41604
41957
|
await new Promise((resolve36) => setTimeout(resolve36, 3e3));
|
|
41605
41958
|
try {
|
|
@@ -41732,12 +42085,12 @@ async function doSetup(config, rl) {
|
|
|
41732
42085
|
`PARAMETER num_predict ${numPredict}`,
|
|
41733
42086
|
`PARAMETER stop "<|endoftext|>"`
|
|
41734
42087
|
].join("\n");
|
|
41735
|
-
const modelDir2 =
|
|
41736
|
-
|
|
41737
|
-
const modelfilePath =
|
|
41738
|
-
|
|
42088
|
+
const modelDir2 = join55(homedir14(), ".open-agents", "models");
|
|
42089
|
+
mkdirSync16(modelDir2, { recursive: true });
|
|
42090
|
+
const modelfilePath = join55(modelDir2, `Modelfile.${customName}`);
|
|
42091
|
+
writeFileSync17(modelfilePath, modelfileContent + "\n", "utf8");
|
|
41739
42092
|
process.stdout.write(` ${c2.dim("Creating model...")} `);
|
|
41740
|
-
|
|
42093
|
+
execSync28(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
41741
42094
|
stdio: "pipe",
|
|
41742
42095
|
timeout: 12e4
|
|
41743
42096
|
});
|
|
@@ -41780,7 +42133,7 @@ async function isModelAvailable(config) {
|
|
|
41780
42133
|
}
|
|
41781
42134
|
function isFirstRun() {
|
|
41782
42135
|
try {
|
|
41783
|
-
return !
|
|
42136
|
+
return !existsSync38(join55(homedir14(), ".open-agents", "config.json"));
|
|
41784
42137
|
} catch {
|
|
41785
42138
|
return true;
|
|
41786
42139
|
}
|
|
@@ -41788,7 +42141,7 @@ function isFirstRun() {
|
|
|
41788
42141
|
function hasCmd(cmd) {
|
|
41789
42142
|
try {
|
|
41790
42143
|
const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
41791
|
-
|
|
42144
|
+
execSync28(whichCmd, { stdio: "pipe", timeout: 3e3 });
|
|
41792
42145
|
return true;
|
|
41793
42146
|
} catch {
|
|
41794
42147
|
return false;
|
|
@@ -41817,11 +42170,11 @@ function detectPkgManager() {
|
|
|
41817
42170
|
return null;
|
|
41818
42171
|
}
|
|
41819
42172
|
function getVenvDir() {
|
|
41820
|
-
return
|
|
42173
|
+
return join55(homedir14(), ".open-agents", "venv");
|
|
41821
42174
|
}
|
|
41822
42175
|
function hasVenvModule() {
|
|
41823
42176
|
try {
|
|
41824
|
-
|
|
42177
|
+
execSync28("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
41825
42178
|
return true;
|
|
41826
42179
|
} catch {
|
|
41827
42180
|
return false;
|
|
@@ -41830,9 +42183,9 @@ function hasVenvModule() {
|
|
|
41830
42183
|
function ensureVenv(log) {
|
|
41831
42184
|
const venvDir = getVenvDir();
|
|
41832
42185
|
const isWin2 = process.platform === "win32";
|
|
41833
|
-
const pipPath = isWin2 ?
|
|
42186
|
+
const pipPath = isWin2 ? join55(venvDir, "Scripts", "pip.exe") : join55(venvDir, "bin", "pip");
|
|
41834
42187
|
const pythonCmd = isWin2 ? "python" : "python3";
|
|
41835
|
-
if (
|
|
42188
|
+
if (existsSync38(pipPath))
|
|
41836
42189
|
return venvDir;
|
|
41837
42190
|
log("Creating Python venv for vision deps...");
|
|
41838
42191
|
if (!hasCmd(pythonCmd) && !hasCmd("python3")) {
|
|
@@ -41844,10 +42197,10 @@ function ensureVenv(log) {
|
|
|
41844
42197
|
return null;
|
|
41845
42198
|
}
|
|
41846
42199
|
try {
|
|
41847
|
-
|
|
42200
|
+
mkdirSync16(join55(homedir14(), ".open-agents"), { recursive: true });
|
|
41848
42201
|
const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
|
|
41849
|
-
|
|
41850
|
-
|
|
42202
|
+
execSync28(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
42203
|
+
execSync28(`"${pipPath}" install --upgrade pip`, {
|
|
41851
42204
|
stdio: "pipe",
|
|
41852
42205
|
timeout: 6e4
|
|
41853
42206
|
});
|
|
@@ -41860,7 +42213,7 @@ function ensureVenv(log) {
|
|
|
41860
42213
|
}
|
|
41861
42214
|
function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
41862
42215
|
try {
|
|
41863
|
-
|
|
42216
|
+
execSync28(`sudo -n ${cmd}`, {
|
|
41864
42217
|
stdio: "pipe",
|
|
41865
42218
|
timeout: timeoutMs,
|
|
41866
42219
|
env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
|
|
@@ -41873,7 +42226,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
|
41873
42226
|
function runWithSudo(cmd, password, timeoutMs = 12e4) {
|
|
41874
42227
|
try {
|
|
41875
42228
|
const escaped = cmd.replace(/'/g, "'\\''");
|
|
41876
|
-
|
|
42229
|
+
execSync28(`sudo -S bash -c '${escaped}'`, {
|
|
41877
42230
|
input: password + "\n",
|
|
41878
42231
|
stdio: ["pipe", "pipe", "pipe"],
|
|
41879
42232
|
timeout: timeoutMs,
|
|
@@ -41990,7 +42343,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
41990
42343
|
ok = await sudoInstall(batchCmd, getPassword, log, cachedPasswordRef, 18e4);
|
|
41991
42344
|
} else {
|
|
41992
42345
|
try {
|
|
41993
|
-
|
|
42346
|
+
execSync28(batchCmd, { stdio: "pipe", timeout: 18e4 });
|
|
41994
42347
|
ok = true;
|
|
41995
42348
|
} catch {
|
|
41996
42349
|
ok = false;
|
|
@@ -42027,7 +42380,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
42027
42380
|
const venvCmds = {
|
|
42028
42381
|
apt: () => {
|
|
42029
42382
|
try {
|
|
42030
|
-
const pyVer =
|
|
42383
|
+
const pyVer = execSync28(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
|
|
42031
42384
|
return `apt-get install -y python3-venv python${pyVer}-venv`;
|
|
42032
42385
|
} catch {
|
|
42033
42386
|
return "apt-get install -y python3-venv";
|
|
@@ -42048,19 +42401,19 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
42048
42401
|
}
|
|
42049
42402
|
}
|
|
42050
42403
|
const venvDir = getVenvDir();
|
|
42051
|
-
const venvBin =
|
|
42052
|
-
const venvMoondream =
|
|
42404
|
+
const venvBin = join55(venvDir, "bin");
|
|
42405
|
+
const venvMoondream = join55(venvBin, "moondream-station");
|
|
42053
42406
|
const venv = ensureVenv(log);
|
|
42054
|
-
if (venv && !hasCmd("moondream-station") && !
|
|
42055
|
-
const venvPip2 =
|
|
42407
|
+
if (venv && !hasCmd("moondream-station") && !existsSync38(venvMoondream)) {
|
|
42408
|
+
const venvPip2 = join55(venvBin, "pip");
|
|
42056
42409
|
log("Installing moondream-station in ~/.open-agents/venv...");
|
|
42057
42410
|
try {
|
|
42058
|
-
|
|
42059
|
-
if (
|
|
42411
|
+
execSync28(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
42412
|
+
if (existsSync38(venvMoondream)) {
|
|
42060
42413
|
log("moondream-station installed successfully.");
|
|
42061
42414
|
} else {
|
|
42062
42415
|
try {
|
|
42063
|
-
const check =
|
|
42416
|
+
const check = execSync28(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
|
|
42064
42417
|
if (check.includes("moondream")) {
|
|
42065
42418
|
log("moondream-station package installed.");
|
|
42066
42419
|
}
|
|
@@ -42073,11 +42426,11 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
42073
42426
|
}
|
|
42074
42427
|
}
|
|
42075
42428
|
if (venv) {
|
|
42076
|
-
const venvPython2 =
|
|
42077
|
-
const venvPip2 =
|
|
42429
|
+
const venvPython2 = join55(venvBin, "python");
|
|
42430
|
+
const venvPip2 = join55(venvBin, "pip");
|
|
42078
42431
|
let ocrStackInstalled = false;
|
|
42079
42432
|
try {
|
|
42080
|
-
|
|
42433
|
+
execSync28(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
42081
42434
|
ocrStackInstalled = true;
|
|
42082
42435
|
} catch {
|
|
42083
42436
|
}
|
|
@@ -42085,9 +42438,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
42085
42438
|
const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
|
|
42086
42439
|
log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
|
|
42087
42440
|
try {
|
|
42088
|
-
|
|
42441
|
+
execSync28(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
|
|
42089
42442
|
try {
|
|
42090
|
-
|
|
42443
|
+
execSync28(`"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
42091
42444
|
log("OCR Python stack installed successfully.");
|
|
42092
42445
|
} catch {
|
|
42093
42446
|
log("OCR Python stack install completed but import verification failed.");
|
|
@@ -42121,9 +42474,9 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
42121
42474
|
const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
|
|
42122
42475
|
const cfArch = archMap[arch2] ?? "amd64";
|
|
42123
42476
|
try {
|
|
42124
|
-
|
|
42125
|
-
if (!process.env.PATH?.includes(`${
|
|
42126
|
-
process.env.PATH = `${
|
|
42477
|
+
execSync28(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir14()}/.local/bin" && mv /tmp/cloudflared "${homedir14()}/.local/bin/cloudflared"`, { stdio: "pipe", timeout: 6e4 });
|
|
42478
|
+
if (!process.env.PATH?.includes(`${homedir14()}/.local/bin`)) {
|
|
42479
|
+
process.env.PATH = `${homedir14()}/.local/bin:${process.env.PATH}`;
|
|
42127
42480
|
}
|
|
42128
42481
|
if (hasCmd("cloudflared")) {
|
|
42129
42482
|
log("cloudflared installed.");
|
|
@@ -42132,7 +42485,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
42132
42485
|
} catch {
|
|
42133
42486
|
}
|
|
42134
42487
|
try {
|
|
42135
|
-
|
|
42488
|
+
execSync28(`curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`, { stdio: "pipe", timeout: 6e4 });
|
|
42136
42489
|
if (hasCmd("cloudflared")) {
|
|
42137
42490
|
log("cloudflared installed.");
|
|
42138
42491
|
return true;
|
|
@@ -42141,7 +42494,7 @@ function ensureCloudflaredBackground(onInfo) {
|
|
|
42141
42494
|
}
|
|
42142
42495
|
} else if (os === "darwin") {
|
|
42143
42496
|
try {
|
|
42144
|
-
|
|
42497
|
+
execSync28("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
|
|
42145
42498
|
if (hasCmd("cloudflared")) {
|
|
42146
42499
|
log("cloudflared installed via Homebrew.");
|
|
42147
42500
|
return true;
|
|
@@ -42218,10 +42571,10 @@ async function createExpandedVariantAsync(baseModel, specs, sizeGB, kvBytesPerTo
|
|
|
42218
42571
|
`PARAMETER num_predict ${numPredict}`,
|
|
42219
42572
|
`PARAMETER stop "<|endoftext|>"`
|
|
42220
42573
|
].join("\n");
|
|
42221
|
-
const modelDir2 =
|
|
42222
|
-
|
|
42223
|
-
const modelfilePath =
|
|
42224
|
-
|
|
42574
|
+
const modelDir2 = join55(homedir14(), ".open-agents", "models");
|
|
42575
|
+
mkdirSync16(modelDir2, { recursive: true });
|
|
42576
|
+
const modelfilePath = join55(modelDir2, `Modelfile.${customName}`);
|
|
42577
|
+
writeFileSync17(modelfilePath, modelfileContent + "\n", "utf8");
|
|
42225
42578
|
await execAsync(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
42226
42579
|
timeout: 12e4
|
|
42227
42580
|
});
|
|
@@ -42283,7 +42636,7 @@ async function ensureExpandedContext(modelName, backendUrl) {
|
|
|
42283
42636
|
}
|
|
42284
42637
|
async function ensureNeovim() {
|
|
42285
42638
|
try {
|
|
42286
|
-
const nvimPath =
|
|
42639
|
+
const nvimPath = execSync28("which nvim 2>/dev/null || where nvim 2>nul", {
|
|
42287
42640
|
encoding: "utf8",
|
|
42288
42641
|
stdio: "pipe",
|
|
42289
42642
|
timeout: 5e3
|
|
@@ -42295,24 +42648,24 @@ async function ensureNeovim() {
|
|
|
42295
42648
|
const platform6 = process.platform;
|
|
42296
42649
|
const arch2 = process.arch;
|
|
42297
42650
|
if (platform6 === "linux") {
|
|
42298
|
-
const binDir =
|
|
42299
|
-
const nvimDest =
|
|
42651
|
+
const binDir = join55(homedir14(), ".local", "bin");
|
|
42652
|
+
const nvimDest = join55(binDir, "nvim");
|
|
42300
42653
|
try {
|
|
42301
|
-
|
|
42654
|
+
mkdirSync16(binDir, { recursive: true });
|
|
42302
42655
|
} catch {
|
|
42303
42656
|
}
|
|
42304
42657
|
const appImageName = arch2 === "arm64" ? "nvim-linux-arm64.appimage" : "nvim-linux-x86_64.appimage";
|
|
42305
42658
|
const url = `https://github.com/neovim/neovim/releases/latest/download/${appImageName}`;
|
|
42306
42659
|
console.log(` Downloading Neovim (${appImageName})...`);
|
|
42307
42660
|
try {
|
|
42308
|
-
|
|
42309
|
-
|
|
42661
|
+
execSync28(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
|
|
42662
|
+
execSync28(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
|
|
42310
42663
|
} catch (err) {
|
|
42311
42664
|
console.log(` Failed to download Neovim: ${err instanceof Error ? err.message : String(err)}`);
|
|
42312
42665
|
return null;
|
|
42313
42666
|
}
|
|
42314
42667
|
try {
|
|
42315
|
-
const ver =
|
|
42668
|
+
const ver = execSync28(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
|
|
42316
42669
|
console.log(` Installed: ${ver}`);
|
|
42317
42670
|
} catch {
|
|
42318
42671
|
console.log(" Warning: nvim binary downloaded but may not work (missing FUSE? Try: nvim --appimage-extract)");
|
|
@@ -42327,8 +42680,8 @@ async function ensureNeovim() {
|
|
|
42327
42680
|
if (hasCmd("brew")) {
|
|
42328
42681
|
console.log(" Installing Neovim via Homebrew...");
|
|
42329
42682
|
try {
|
|
42330
|
-
|
|
42331
|
-
const nvimPath =
|
|
42683
|
+
execSync28("brew install neovim", { stdio: "inherit", timeout: 12e4 });
|
|
42684
|
+
const nvimPath = execSync28("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
|
|
42332
42685
|
return nvimPath || null;
|
|
42333
42686
|
} catch {
|
|
42334
42687
|
console.log(" brew install neovim failed.");
|
|
@@ -42342,7 +42695,7 @@ async function ensureNeovim() {
|
|
|
42342
42695
|
if (hasCmd("choco")) {
|
|
42343
42696
|
console.log(" Installing Neovim via Chocolatey...");
|
|
42344
42697
|
try {
|
|
42345
|
-
|
|
42698
|
+
execSync28("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
|
|
42346
42699
|
return "nvim";
|
|
42347
42700
|
} catch {
|
|
42348
42701
|
console.log(" choco install neovim failed.");
|
|
@@ -42351,7 +42704,7 @@ async function ensureNeovim() {
|
|
|
42351
42704
|
if (hasCmd("winget")) {
|
|
42352
42705
|
console.log(" Installing Neovim via winget...");
|
|
42353
42706
|
try {
|
|
42354
|
-
|
|
42707
|
+
execSync28("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
|
|
42355
42708
|
stdio: "inherit",
|
|
42356
42709
|
timeout: 12e4
|
|
42357
42710
|
});
|
|
@@ -42367,9 +42720,9 @@ async function ensureNeovim() {
|
|
|
42367
42720
|
}
|
|
42368
42721
|
function ensurePathInShellRc(binDir) {
|
|
42369
42722
|
const shell = process.env.SHELL ?? "";
|
|
42370
|
-
const rcFile = shell.includes("zsh") ?
|
|
42723
|
+
const rcFile = shell.includes("zsh") ? join55(homedir14(), ".zshrc") : join55(homedir14(), ".bashrc");
|
|
42371
42724
|
try {
|
|
42372
|
-
const rcContent =
|
|
42725
|
+
const rcContent = existsSync38(rcFile) ? readFileSync29(rcFile, "utf8") : "";
|
|
42373
42726
|
if (rcContent.includes(binDir))
|
|
42374
42727
|
return;
|
|
42375
42728
|
const exportLine = `
|
|
@@ -42407,7 +42760,7 @@ var init_setup = __esm({
|
|
|
42407
42760
|
});
|
|
42408
42761
|
|
|
42409
42762
|
// packages/cli/dist/tui/drop-panel.js
|
|
42410
|
-
import { existsSync as
|
|
42763
|
+
import { existsSync as existsSync39 } from "node:fs";
|
|
42411
42764
|
import { extname as extname10, resolve as resolve29 } from "node:path";
|
|
42412
42765
|
function ansi4(code, text) {
|
|
42413
42766
|
return isTTY4 ? `\x1B[${code}m${text}\x1B[0m` : text;
|
|
@@ -42522,7 +42875,7 @@ function showDropPanel(opts) {
|
|
|
42522
42875
|
filePath = decodeURIComponent(filePath.slice(7));
|
|
42523
42876
|
}
|
|
42524
42877
|
filePath = resolve29(filePath);
|
|
42525
|
-
if (!
|
|
42878
|
+
if (!existsSync39(filePath)) {
|
|
42526
42879
|
errorMsg = `File not found: ${filePath}`;
|
|
42527
42880
|
render();
|
|
42528
42881
|
return;
|
|
@@ -42593,10 +42946,10 @@ var init_drop_panel = __esm({
|
|
|
42593
42946
|
});
|
|
42594
42947
|
|
|
42595
42948
|
// packages/cli/dist/tui/neovim-mode.js
|
|
42596
|
-
import { existsSync as
|
|
42949
|
+
import { existsSync as existsSync40, unlinkSync as unlinkSync8 } from "node:fs";
|
|
42597
42950
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
42598
|
-
import { join as
|
|
42599
|
-
import { execSync as
|
|
42951
|
+
import { join as join56 } from "node:path";
|
|
42952
|
+
import { execSync as execSync29 } from "node:child_process";
|
|
42600
42953
|
function isNeovimActive() {
|
|
42601
42954
|
return _state !== null && !_state.cleanedUp;
|
|
42602
42955
|
}
|
|
@@ -42614,7 +42967,7 @@ async function startNeovimMode(opts) {
|
|
|
42614
42967
|
}
|
|
42615
42968
|
let nvimPath;
|
|
42616
42969
|
try {
|
|
42617
|
-
nvimPath =
|
|
42970
|
+
nvimPath = execSync29("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
|
|
42618
42971
|
if (!nvimPath)
|
|
42619
42972
|
throw new Error();
|
|
42620
42973
|
} catch {
|
|
@@ -42643,9 +42996,9 @@ async function startNeovimMode(opts) {
|
|
|
42643
42996
|
);
|
|
42644
42997
|
} catch {
|
|
42645
42998
|
}
|
|
42646
|
-
const socketPath =
|
|
42999
|
+
const socketPath = join56(tmpdir8(), `oa-nvim-${process.pid}-${Date.now()}.sock`);
|
|
42647
43000
|
try {
|
|
42648
|
-
if (
|
|
43001
|
+
if (existsSync40(socketPath))
|
|
42649
43002
|
unlinkSync8(socketPath);
|
|
42650
43003
|
} catch {
|
|
42651
43004
|
}
|
|
@@ -42872,13 +43225,13 @@ function resizeNeovim(cols, contentRows) {
|
|
|
42872
43225
|
}
|
|
42873
43226
|
async function connectRPC(state, neovimPkg, cols) {
|
|
42874
43227
|
let attempts = 0;
|
|
42875
|
-
while (!
|
|
43228
|
+
while (!existsSync40(state.socketPath) && attempts < 30) {
|
|
42876
43229
|
await new Promise((r) => setTimeout(r, 200));
|
|
42877
43230
|
attempts++;
|
|
42878
43231
|
if (state.cleanedUp)
|
|
42879
43232
|
return;
|
|
42880
43233
|
}
|
|
42881
|
-
if (!
|
|
43234
|
+
if (!existsSync40(state.socketPath))
|
|
42882
43235
|
return;
|
|
42883
43236
|
const nvim = neovimPkg.attach({ socket: state.socketPath });
|
|
42884
43237
|
state.nvim = nvim;
|
|
@@ -43015,7 +43368,7 @@ function doCleanup(state) {
|
|
|
43015
43368
|
state.pty = null;
|
|
43016
43369
|
}
|
|
43017
43370
|
try {
|
|
43018
|
-
if (
|
|
43371
|
+
if (existsSync40(state.socketPath))
|
|
43019
43372
|
unlinkSync8(state.socketPath);
|
|
43020
43373
|
} catch {
|
|
43021
43374
|
}
|
|
@@ -43450,8 +43803,8 @@ __export(sponsor_wizard_exports, {
|
|
|
43450
43803
|
saveSponsorConfig: () => saveSponsorConfig,
|
|
43451
43804
|
showSponsorDashboard: () => showSponsorDashboard
|
|
43452
43805
|
});
|
|
43453
|
-
import { existsSync as
|
|
43454
|
-
import { join as
|
|
43806
|
+
import { existsSync as existsSync41, readFileSync as readFileSync30, writeFileSync as writeFileSync18, mkdirSync as mkdirSync17 } from "node:fs";
|
|
43807
|
+
import { join as join57 } from "node:path";
|
|
43455
43808
|
function colorPreview(code) {
|
|
43456
43809
|
return `\x1B[38;5;${code}m\u2588\u2588\u2588\u2588\x1B[0m (${code})`;
|
|
43457
43810
|
}
|
|
@@ -43464,26 +43817,26 @@ function gradientPreview(start, end) {
|
|
|
43464
43817
|
return s;
|
|
43465
43818
|
}
|
|
43466
43819
|
function sponsorDir(projectDir) {
|
|
43467
|
-
return
|
|
43820
|
+
return join57(projectDir, ".oa", "sponsor");
|
|
43468
43821
|
}
|
|
43469
43822
|
function configPath(projectDir) {
|
|
43470
|
-
return
|
|
43823
|
+
return join57(sponsorDir(projectDir), "config.json");
|
|
43471
43824
|
}
|
|
43472
43825
|
function loadSponsorConfig(projectDir) {
|
|
43473
43826
|
const p = configPath(projectDir);
|
|
43474
|
-
if (!
|
|
43827
|
+
if (!existsSync41(p))
|
|
43475
43828
|
return null;
|
|
43476
43829
|
try {
|
|
43477
|
-
return JSON.parse(
|
|
43830
|
+
return JSON.parse(readFileSync30(p, "utf8"));
|
|
43478
43831
|
} catch {
|
|
43479
43832
|
return null;
|
|
43480
43833
|
}
|
|
43481
43834
|
}
|
|
43482
43835
|
function saveSponsorConfig(projectDir, config) {
|
|
43483
43836
|
const dir = sponsorDir(projectDir);
|
|
43484
|
-
|
|
43837
|
+
mkdirSync17(dir, { recursive: true });
|
|
43485
43838
|
config.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43486
|
-
|
|
43839
|
+
writeFileSync18(configPath(projectDir), JSON.stringify(config, null, 2), "utf8");
|
|
43487
43840
|
}
|
|
43488
43841
|
function defaultConfig() {
|
|
43489
43842
|
return {
|
|
@@ -44186,10 +44539,10 @@ __export(voice_exports, {
|
|
|
44186
44539
|
registerCustomOnnxModel: () => registerCustomOnnxModel,
|
|
44187
44540
|
resetNarrationContext: () => resetNarrationContext
|
|
44188
44541
|
});
|
|
44189
|
-
import { existsSync as
|
|
44190
|
-
import { join as
|
|
44191
|
-
import { homedir as
|
|
44192
|
-
import { execSync as
|
|
44542
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync18, writeFileSync as writeFileSync19, readFileSync as readFileSync31, unlinkSync as unlinkSync9, readdirSync as readdirSync11, renameSync, statSync as statSync13 } from "node:fs";
|
|
44543
|
+
import { join as join58, dirname as dirname18 } from "node:path";
|
|
44544
|
+
import { homedir as homedir15, tmpdir as tmpdir9, platform as platform3 } from "node:os";
|
|
44545
|
+
import { execSync as execSync30, spawn as nodeSpawn } from "node:child_process";
|
|
44193
44546
|
import { createRequire } from "node:module";
|
|
44194
44547
|
function sanitizeForTTS(text) {
|
|
44195
44548
|
return text.replace(/^#{1,6}\s+/gm, "").replace(/\*{1,3}([^*]+)\*{1,3}/g, "$1").replace(/_{1,3}([^_]+)_{1,3}/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/^[\s]*[-*+]\s+/gm, "").replace(/^[\s]*\d+\.\s+/gm, "").replace(/^>\s+/gm, "").replace(/^[-*_]{3,}$/gm, "").replace(/\[[ xX]\]\s*/g, "").replace(/[\u{1F600}-\u{1F64F}]/gu, "").replace(/[\u{1F300}-\u{1F5FF}]/gu, "").replace(/[\u{1F680}-\u{1F6FF}]/gu, "").replace(/[\u{1F1E0}-\u{1F1FF}]/gu, "").replace(/[\u{2600}-\u{26FF}]/gu, "").replace(/[\u{2700}-\u{27BF}]/gu, "").replace(/[\u{FE00}-\u{FE0F}]/gu, "").replace(/[\u{1F900}-\u{1F9FF}]/gu, "").replace(/[\u{1FA00}-\u{1FA6F}]/gu, "").replace(/[\u{1FA70}-\u{1FAFF}]/gu, "").replace(/[\u{200D}]/gu, "").replace(/[\u{20E3}]/gu, "").replace(/[✓✔✗✘✕✖⚠️⏸⏹⏵●○◆◇■□▪▫►▼▲◀⬆⬇⬅➡↑↓←→⇐⇒⇑⇓]/g, "").replace(/[─━│┃┌┐└┘├┤┬┴┼╔╗╚╝╠╣╦╩╬⎿⎾▕▏⏐░▒▓█⠀-⣿]/g, "").replace(/\s{2,}/g, " ").trim();
|
|
@@ -44212,40 +44565,40 @@ function listVoiceModels() {
|
|
|
44212
44565
|
}));
|
|
44213
44566
|
}
|
|
44214
44567
|
function voiceDir() {
|
|
44215
|
-
return
|
|
44568
|
+
return join58(homedir15(), ".open-agents", "voice");
|
|
44216
44569
|
}
|
|
44217
44570
|
function modelsDir() {
|
|
44218
|
-
return
|
|
44571
|
+
return join58(voiceDir(), "models");
|
|
44219
44572
|
}
|
|
44220
44573
|
function modelDir(id) {
|
|
44221
|
-
return
|
|
44574
|
+
return join58(modelsDir(), id);
|
|
44222
44575
|
}
|
|
44223
44576
|
function modelOnnxPath(id) {
|
|
44224
|
-
return
|
|
44577
|
+
return join58(modelDir(id), "model.onnx");
|
|
44225
44578
|
}
|
|
44226
44579
|
function modelConfigPath(id) {
|
|
44227
|
-
return
|
|
44580
|
+
return join58(modelDir(id), "config.json");
|
|
44228
44581
|
}
|
|
44229
44582
|
function luxttsVenvDir() {
|
|
44230
|
-
return
|
|
44583
|
+
return join58(voiceDir(), "luxtts-venv");
|
|
44231
44584
|
}
|
|
44232
44585
|
function luxttsVenvPy() {
|
|
44233
|
-
return platform3() === "win32" ?
|
|
44586
|
+
return platform3() === "win32" ? join58(luxttsVenvDir(), "Scripts", "python.exe") : join58(luxttsVenvDir(), "bin", "python3");
|
|
44234
44587
|
}
|
|
44235
44588
|
function luxttsRepoDir() {
|
|
44236
|
-
return
|
|
44589
|
+
return join58(voiceDir(), "LuxTTS");
|
|
44237
44590
|
}
|
|
44238
44591
|
function luxttsCloneRefsDir() {
|
|
44239
|
-
return
|
|
44592
|
+
return join58(voiceDir(), "clone-refs");
|
|
44240
44593
|
}
|
|
44241
44594
|
function luxttsInferScript() {
|
|
44242
|
-
return
|
|
44595
|
+
return join58(voiceDir(), "luxtts-infer.py");
|
|
44243
44596
|
}
|
|
44244
44597
|
function writeDetectTorchScript(targetPath) {
|
|
44245
|
-
if (
|
|
44598
|
+
if (existsSync42(targetPath))
|
|
44246
44599
|
return;
|
|
44247
44600
|
try {
|
|
44248
|
-
|
|
44601
|
+
mkdirSync18(dirname18(targetPath), { recursive: true });
|
|
44249
44602
|
} catch {
|
|
44250
44603
|
}
|
|
44251
44604
|
const script = `#!/usr/bin/env python3
|
|
@@ -44318,7 +44671,7 @@ def main():
|
|
|
44318
44671
|
if __name__ == "__main__": main()
|
|
44319
44672
|
`;
|
|
44320
44673
|
try {
|
|
44321
|
-
|
|
44674
|
+
writeFileSync19(targetPath, script, { mode: 493 });
|
|
44322
44675
|
} catch {
|
|
44323
44676
|
}
|
|
44324
44677
|
}
|
|
@@ -45128,8 +45481,8 @@ var init_voice = __esm({
|
|
|
45128
45481
|
const refsDir = luxttsCloneRefsDir();
|
|
45129
45482
|
const targets = ["glados", "overwatch"];
|
|
45130
45483
|
for (const modelId of targets) {
|
|
45131
|
-
const refFile =
|
|
45132
|
-
if (
|
|
45484
|
+
const refFile = join58(refsDir, `${modelId}-ref.wav`);
|
|
45485
|
+
if (existsSync42(refFile))
|
|
45133
45486
|
continue;
|
|
45134
45487
|
try {
|
|
45135
45488
|
await this.generateCloneRef(modelId);
|
|
@@ -45208,24 +45561,24 @@ var init_voice = __esm({
|
|
|
45208
45561
|
}
|
|
45209
45562
|
p = p.replace(/\\ /g, " ");
|
|
45210
45563
|
if (p.startsWith("~/") || p === "~") {
|
|
45211
|
-
p =
|
|
45564
|
+
p = join58(homedir15(), p.slice(1));
|
|
45212
45565
|
}
|
|
45213
|
-
if (!
|
|
45566
|
+
if (!existsSync42(p)) {
|
|
45214
45567
|
return `File not found: ${p}
|
|
45215
45568
|
(original input: ${audioPath})`;
|
|
45216
45569
|
}
|
|
45217
45570
|
audioPath = p;
|
|
45218
45571
|
const refsDir = luxttsCloneRefsDir();
|
|
45219
|
-
if (!
|
|
45220
|
-
|
|
45572
|
+
if (!existsSync42(refsDir))
|
|
45573
|
+
mkdirSync18(refsDir, { recursive: true });
|
|
45221
45574
|
const ext = audioPath.split(".").pop() || "wav";
|
|
45222
45575
|
const srcName = (audioPath.split("/").pop() ?? "clone").replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
45223
45576
|
const ts = Date.now().toString(36);
|
|
45224
45577
|
const destFilename = `clone-${srcName}-${ts}.${ext}`;
|
|
45225
|
-
const destPath =
|
|
45578
|
+
const destPath = join58(refsDir, destFilename);
|
|
45226
45579
|
try {
|
|
45227
|
-
const data =
|
|
45228
|
-
|
|
45580
|
+
const data = readFileSync31(audioPath);
|
|
45581
|
+
writeFileSync19(destPath, data);
|
|
45229
45582
|
} catch (err) {
|
|
45230
45583
|
return `Failed to copy audio file: ${err instanceof Error ? err.message : String(err)}`;
|
|
45231
45584
|
}
|
|
@@ -45265,9 +45618,9 @@ var init_voice = __esm({
|
|
|
45265
45618
|
return `Failed to synthesize reference audio from ${source.label}.`;
|
|
45266
45619
|
}
|
|
45267
45620
|
const refsDir = luxttsCloneRefsDir();
|
|
45268
|
-
if (!
|
|
45269
|
-
|
|
45270
|
-
const destPath =
|
|
45621
|
+
if (!existsSync42(refsDir))
|
|
45622
|
+
mkdirSync18(refsDir, { recursive: true });
|
|
45623
|
+
const destPath = join58(refsDir, `${sourceModelId}-ref.wav`);
|
|
45271
45624
|
const sampleRate = this.config?.audio?.sample_rate ?? 22050;
|
|
45272
45625
|
this.writeWav(audioData, sampleRate, destPath);
|
|
45273
45626
|
this.luxttsCloneRef = destPath;
|
|
@@ -45283,23 +45636,23 @@ var init_voice = __esm({
|
|
|
45283
45636
|
// -------------------------------------------------------------------------
|
|
45284
45637
|
/** Metadata file for friendly names of clone refs */
|
|
45285
45638
|
static cloneMetaFile() {
|
|
45286
|
-
return
|
|
45639
|
+
return join58(luxttsCloneRefsDir(), "meta.json");
|
|
45287
45640
|
}
|
|
45288
45641
|
loadCloneMeta() {
|
|
45289
45642
|
const p = _VoiceEngine.cloneMetaFile();
|
|
45290
|
-
if (!
|
|
45643
|
+
if (!existsSync42(p))
|
|
45291
45644
|
return {};
|
|
45292
45645
|
try {
|
|
45293
|
-
return JSON.parse(
|
|
45646
|
+
return JSON.parse(readFileSync31(p, "utf8"));
|
|
45294
45647
|
} catch {
|
|
45295
45648
|
return {};
|
|
45296
45649
|
}
|
|
45297
45650
|
}
|
|
45298
45651
|
saveCloneMeta(meta) {
|
|
45299
45652
|
const dir = luxttsCloneRefsDir();
|
|
45300
|
-
if (!
|
|
45301
|
-
|
|
45302
|
-
|
|
45653
|
+
if (!existsSync42(dir))
|
|
45654
|
+
mkdirSync18(dir, { recursive: true });
|
|
45655
|
+
writeFileSync19(_VoiceEngine.cloneMetaFile(), JSON.stringify(meta, null, 2));
|
|
45303
45656
|
}
|
|
45304
45657
|
/** Audio file extensions recognized as clone references */
|
|
45305
45658
|
static AUDIO_EXTS = /* @__PURE__ */ new Set(["wav", "mp3", "ogg", "flac", "m4a", "opus", "aac"]);
|
|
@@ -45309,7 +45662,7 @@ var init_voice = __esm({
|
|
|
45309
45662
|
*/
|
|
45310
45663
|
listCloneRefs() {
|
|
45311
45664
|
const dir = luxttsCloneRefsDir();
|
|
45312
|
-
if (!
|
|
45665
|
+
if (!existsSync42(dir))
|
|
45313
45666
|
return [];
|
|
45314
45667
|
const meta = this.loadCloneMeta();
|
|
45315
45668
|
const files = readdirSync11(dir).filter((f) => {
|
|
@@ -45317,7 +45670,7 @@ var init_voice = __esm({
|
|
|
45317
45670
|
return _VoiceEngine.AUDIO_EXTS.has(ext);
|
|
45318
45671
|
});
|
|
45319
45672
|
return files.map((f) => {
|
|
45320
|
-
const p =
|
|
45673
|
+
const p = join58(dir, f);
|
|
45321
45674
|
let size = 0;
|
|
45322
45675
|
try {
|
|
45323
45676
|
size = statSync13(p).size;
|
|
@@ -45334,8 +45687,8 @@ var init_voice = __esm({
|
|
|
45334
45687
|
}
|
|
45335
45688
|
/** Delete a clone reference file by filename. Returns true if deleted. */
|
|
45336
45689
|
deleteCloneRef(filename) {
|
|
45337
|
-
const p =
|
|
45338
|
-
if (!
|
|
45690
|
+
const p = join58(luxttsCloneRefsDir(), filename);
|
|
45691
|
+
if (!existsSync42(p))
|
|
45339
45692
|
return false;
|
|
45340
45693
|
try {
|
|
45341
45694
|
unlinkSync9(p);
|
|
@@ -45359,8 +45712,8 @@ var init_voice = __esm({
|
|
|
45359
45712
|
}
|
|
45360
45713
|
/** Set the active clone reference by filename. */
|
|
45361
45714
|
setActiveCloneRef(filename) {
|
|
45362
|
-
const p =
|
|
45363
|
-
if (!
|
|
45715
|
+
const p = join58(luxttsCloneRefsDir(), filename);
|
|
45716
|
+
if (!existsSync42(p))
|
|
45364
45717
|
return `File not found: ${filename}`;
|
|
45365
45718
|
this.luxttsCloneRef = p;
|
|
45366
45719
|
return `Active clone voice set to: ${filename}`;
|
|
@@ -45685,7 +46038,7 @@ var init_voice = __esm({
|
|
|
45685
46038
|
}
|
|
45686
46039
|
this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
|
|
45687
46040
|
}
|
|
45688
|
-
const wavPath =
|
|
46041
|
+
const wavPath = join58(tmpdir9(), `oa-voice-${Date.now()}.wav`);
|
|
45689
46042
|
this.writeStereoWav(stereo.left, stereo.right, sampleRate, wavPath);
|
|
45690
46043
|
await this.playWav(wavPath);
|
|
45691
46044
|
try {
|
|
@@ -45802,7 +46155,7 @@ var init_voice = __esm({
|
|
|
45802
46155
|
buffer.writeInt16LE(rSample < 0 ? rSample * 32768 : rSample * 32767, pos);
|
|
45803
46156
|
pos += 2;
|
|
45804
46157
|
}
|
|
45805
|
-
|
|
46158
|
+
writeFileSync19(path, buffer);
|
|
45806
46159
|
}
|
|
45807
46160
|
// -------------------------------------------------------------------------
|
|
45808
46161
|
// Phonemization
|
|
@@ -45880,7 +46233,7 @@ var init_voice = __esm({
|
|
|
45880
46233
|
return buffer;
|
|
45881
46234
|
}
|
|
45882
46235
|
writeWav(samples, sampleRate, path) {
|
|
45883
|
-
|
|
46236
|
+
writeFileSync19(path, this.buildWavBuffer(samples, sampleRate));
|
|
45884
46237
|
}
|
|
45885
46238
|
// -------------------------------------------------------------------------
|
|
45886
46239
|
// Audio playback (system default speakers)
|
|
@@ -45930,7 +46283,7 @@ var init_voice = __esm({
|
|
|
45930
46283
|
}
|
|
45931
46284
|
for (const player of ["paplay", "pw-play", "aplay"]) {
|
|
45932
46285
|
try {
|
|
45933
|
-
|
|
46286
|
+
execSync30(`which ${player}`, { stdio: "pipe" });
|
|
45934
46287
|
return [player, path];
|
|
45935
46288
|
} catch {
|
|
45936
46289
|
}
|
|
@@ -45959,7 +46312,7 @@ var init_voice = __esm({
|
|
|
45959
46312
|
return this.python3Path;
|
|
45960
46313
|
for (const bin of ["python3", "python"]) {
|
|
45961
46314
|
try {
|
|
45962
|
-
const path =
|
|
46315
|
+
const path = execSync30(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
|
|
45963
46316
|
if (path) {
|
|
45964
46317
|
this.python3Path = path;
|
|
45965
46318
|
return path;
|
|
@@ -46025,7 +46378,7 @@ var init_voice = __esm({
|
|
|
46025
46378
|
return false;
|
|
46026
46379
|
}
|
|
46027
46380
|
try {
|
|
46028
|
-
|
|
46381
|
+
execSync30(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
|
|
46029
46382
|
this.mlxInstalled = true;
|
|
46030
46383
|
return true;
|
|
46031
46384
|
} catch {
|
|
@@ -46078,7 +46431,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46078
46431
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
46079
46432
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
46080
46433
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
46081
|
-
const wavPath =
|
|
46434
|
+
const wavPath = join58(tmpdir9(), `oa-mlx-${Date.now()}.wav`);
|
|
46082
46435
|
const pyScript = [
|
|
46083
46436
|
"import sys, json",
|
|
46084
46437
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -46086,20 +46439,20 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46086
46439
|
`tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
|
|
46087
46440
|
].join("; ");
|
|
46088
46441
|
try {
|
|
46089
|
-
|
|
46442
|
+
execSync30(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
|
|
46090
46443
|
} catch (err) {
|
|
46091
46444
|
try {
|
|
46092
46445
|
const safeText = cleaned.replace(/'/g, "'\\''");
|
|
46093
|
-
|
|
46446
|
+
execSync30(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
|
|
46094
46447
|
} catch (err2) {
|
|
46095
46448
|
return;
|
|
46096
46449
|
}
|
|
46097
46450
|
}
|
|
46098
|
-
if (!
|
|
46451
|
+
if (!existsSync42(wavPath))
|
|
46099
46452
|
return;
|
|
46100
46453
|
if (volume !== 1) {
|
|
46101
46454
|
try {
|
|
46102
|
-
const wavData =
|
|
46455
|
+
const wavData = readFileSync31(wavPath);
|
|
46103
46456
|
if (wavData.length > 44) {
|
|
46104
46457
|
const header = wavData.subarray(0, 44);
|
|
46105
46458
|
const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
|
|
@@ -46107,14 +46460,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46107
46460
|
samples[i] = Math.round(samples[i] * volume);
|
|
46108
46461
|
}
|
|
46109
46462
|
const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
|
|
46110
|
-
|
|
46463
|
+
writeFileSync19(wavPath, scaled);
|
|
46111
46464
|
}
|
|
46112
46465
|
} catch {
|
|
46113
46466
|
}
|
|
46114
46467
|
}
|
|
46115
46468
|
if (this.onPCMOutput) {
|
|
46116
46469
|
try {
|
|
46117
|
-
const wavData =
|
|
46470
|
+
const wavData = readFileSync31(wavPath);
|
|
46118
46471
|
if (wavData.length > 44) {
|
|
46119
46472
|
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
46120
46473
|
const sampleRate = wavData.readUInt32LE(24);
|
|
@@ -46146,7 +46499,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46146
46499
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
46147
46500
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
46148
46501
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
46149
|
-
const wavPath =
|
|
46502
|
+
const wavPath = join58(tmpdir9(), `oa-mlx-buf-${Date.now()}.wav`);
|
|
46150
46503
|
const pyScript = [
|
|
46151
46504
|
"import sys, json",
|
|
46152
46505
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -46154,19 +46507,19 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46154
46507
|
`tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
|
|
46155
46508
|
].join("; ");
|
|
46156
46509
|
try {
|
|
46157
|
-
|
|
46510
|
+
execSync30(`${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
|
|
46158
46511
|
} catch {
|
|
46159
46512
|
try {
|
|
46160
46513
|
const safeText = cleaned.replace(/'/g, "'\\''");
|
|
46161
|
-
|
|
46514
|
+
execSync30(`${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`, { stdio: "pipe", timeout: 6e4, cwd: tmpdir9() });
|
|
46162
46515
|
} catch {
|
|
46163
46516
|
return null;
|
|
46164
46517
|
}
|
|
46165
46518
|
}
|
|
46166
|
-
if (!
|
|
46519
|
+
if (!existsSync42(wavPath))
|
|
46167
46520
|
return null;
|
|
46168
46521
|
try {
|
|
46169
|
-
const data =
|
|
46522
|
+
const data = readFileSync31(wavPath);
|
|
46170
46523
|
unlinkSync9(wavPath);
|
|
46171
46524
|
return data;
|
|
46172
46525
|
} catch {
|
|
@@ -46189,7 +46542,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46189
46542
|
}
|
|
46190
46543
|
const venvDir = luxttsVenvDir();
|
|
46191
46544
|
const venvPy = luxttsVenvPy();
|
|
46192
|
-
if (
|
|
46545
|
+
if (existsSync42(venvPy)) {
|
|
46193
46546
|
try {
|
|
46194
46547
|
await this.asyncShell(`${venvPy} -c "import sys; sys.path.insert(0, '${luxttsRepoDir()}'); from zipvoice.luxvoice import LuxTTS; print('ok')"`, 3e4);
|
|
46195
46548
|
let hasCudaSys = false;
|
|
@@ -46203,7 +46556,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46203
46556
|
if (torchCheck === "cpu") {
|
|
46204
46557
|
renderWarning("GPU detected but PyTorch is CPU-only. Reinstalling with CUDA support in background...");
|
|
46205
46558
|
try {
|
|
46206
|
-
const detectScript =
|
|
46559
|
+
const detectScript = join58(voiceDir(), "detect-torch.py");
|
|
46207
46560
|
writeDetectTorchScript(detectScript);
|
|
46208
46561
|
let pipArgs = `torch torchaudio --index-url https://download.pytorch.org/whl/cu124`;
|
|
46209
46562
|
try {
|
|
@@ -46228,7 +46581,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46228
46581
|
}
|
|
46229
46582
|
}
|
|
46230
46583
|
renderInfo("Setting up LuxTTS voice cloning (first-time setup, this takes several minutes)...");
|
|
46231
|
-
if (!
|
|
46584
|
+
if (!existsSync42(venvDir)) {
|
|
46232
46585
|
renderInfo(" Creating Python virtual environment...");
|
|
46233
46586
|
try {
|
|
46234
46587
|
await this.asyncShell(`${py} -m venv ${JSON.stringify(venvDir)}`, 6e4);
|
|
@@ -46237,7 +46590,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46237
46590
|
}
|
|
46238
46591
|
}
|
|
46239
46592
|
{
|
|
46240
|
-
const detectScript =
|
|
46593
|
+
const detectScript = join58(voiceDir(), "detect-torch.py");
|
|
46241
46594
|
writeDetectTorchScript(detectScript);
|
|
46242
46595
|
let pipArgsStr = "torch torchaudio";
|
|
46243
46596
|
let torchDesc = "unknown platform";
|
|
@@ -46274,10 +46627,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46274
46627
|
}
|
|
46275
46628
|
}
|
|
46276
46629
|
const repoDir = luxttsRepoDir();
|
|
46277
|
-
if (!
|
|
46630
|
+
if (!existsSync42(join58(repoDir, "zipvoice", "luxvoice.py"))) {
|
|
46278
46631
|
renderInfo(" Cloning LuxTTS repository...");
|
|
46279
46632
|
try {
|
|
46280
|
-
if (
|
|
46633
|
+
if (existsSync42(repoDir)) {
|
|
46281
46634
|
const rmCmd = process.platform === "win32" ? `rmdir /s /q ${JSON.stringify(repoDir)}` : `rm -rf ${JSON.stringify(repoDir)}`;
|
|
46282
46635
|
await this.asyncShell(rmCmd, 3e4);
|
|
46283
46636
|
}
|
|
@@ -46356,7 +46709,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46356
46709
|
renderWarning(` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`);
|
|
46357
46710
|
}
|
|
46358
46711
|
}
|
|
46359
|
-
const isJetson = isArm && (
|
|
46712
|
+
const isJetson = isArm && (existsSync42("/etc/nv_tegra_release") || existsSync42("/usr/local/cuda/targets/aarch64-linux") || (process.env.JETSON_L4T_VERSION ?? "") !== "");
|
|
46360
46713
|
const installSteps = isArm ? [
|
|
46361
46714
|
// ARM: install individually so we get clear error messages per package.
|
|
46362
46715
|
// ALL are fatal because LuxTTS hard-imports them (no lazy/optional imports).
|
|
@@ -46426,14 +46779,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
46426
46779
|
}
|
|
46427
46780
|
/** Auto-detect an existing clone reference in the refs directory */
|
|
46428
46781
|
autoDetectCloneRef() {
|
|
46429
|
-
if (this.luxttsCloneRef &&
|
|
46782
|
+
if (this.luxttsCloneRef && existsSync42(this.luxttsCloneRef))
|
|
46430
46783
|
return;
|
|
46431
46784
|
const refsDir = luxttsCloneRefsDir();
|
|
46432
|
-
if (!
|
|
46785
|
+
if (!existsSync42(refsDir))
|
|
46433
46786
|
return;
|
|
46434
46787
|
for (const name of ["custom-clone.wav", "custom-clone.mp3", "glados-ref.wav", "overwatch-ref.wav"]) {
|
|
46435
|
-
const p =
|
|
46436
|
-
if (
|
|
46788
|
+
const p = join58(refsDir, name);
|
|
46789
|
+
if (existsSync42(p)) {
|
|
46437
46790
|
this.luxttsCloneRef = p;
|
|
46438
46791
|
return;
|
|
46439
46792
|
}
|
|
@@ -46533,15 +46886,15 @@ if __name__ == '__main__':
|
|
|
46533
46886
|
main()
|
|
46534
46887
|
`;
|
|
46535
46888
|
const scriptPath2 = luxttsInferScript();
|
|
46536
|
-
|
|
46537
|
-
|
|
46889
|
+
mkdirSync18(voiceDir(), { recursive: true });
|
|
46890
|
+
writeFileSync19(scriptPath2, script);
|
|
46538
46891
|
}
|
|
46539
46892
|
/** Ensure the LuxTTS daemon is running, spawn if needed */
|
|
46540
46893
|
async ensureLuxttsDaemon() {
|
|
46541
46894
|
if (this._luxttsDaemon && !this._luxttsDaemon.killed)
|
|
46542
46895
|
return true;
|
|
46543
46896
|
const venvPy = luxttsVenvPy();
|
|
46544
|
-
if (!
|
|
46897
|
+
if (!existsSync42(venvPy))
|
|
46545
46898
|
return false;
|
|
46546
46899
|
return new Promise((resolve36) => {
|
|
46547
46900
|
const env = { ...process.env, LUXTTS_REPO_PATH: luxttsRepoDir() };
|
|
@@ -46625,7 +46978,7 @@ if __name__ == '__main__':
|
|
|
46625
46978
|
* Used by drainQueue's pre-fetch pipeline for gapless back-to-back playback.
|
|
46626
46979
|
*/
|
|
46627
46980
|
async synthesizeLuxttsWav(text, speedFactor = 1) {
|
|
46628
|
-
if (!this.luxttsCloneRef || !
|
|
46981
|
+
if (!this.luxttsCloneRef || !existsSync42(this.luxttsCloneRef))
|
|
46629
46982
|
return null;
|
|
46630
46983
|
const cleaned = text.replace(/\*/g, "").trim();
|
|
46631
46984
|
if (!cleaned)
|
|
@@ -46633,7 +46986,7 @@ if __name__ == '__main__':
|
|
|
46633
46986
|
const ready = await this.ensureLuxttsDaemon();
|
|
46634
46987
|
if (!ready)
|
|
46635
46988
|
return null;
|
|
46636
|
-
const wavPath =
|
|
46989
|
+
const wavPath = join58(tmpdir9(), `oa-luxtts-${Date.now()}-${Math.random().toString(36).slice(2, 6)}.wav`);
|
|
46637
46990
|
try {
|
|
46638
46991
|
await this.luxttsRequest({
|
|
46639
46992
|
action: "synthesize",
|
|
@@ -46645,17 +46998,17 @@ if __name__ == '__main__':
|
|
|
46645
46998
|
} catch {
|
|
46646
46999
|
return null;
|
|
46647
47000
|
}
|
|
46648
|
-
return
|
|
47001
|
+
return existsSync42(wavPath) ? wavPath : null;
|
|
46649
47002
|
}
|
|
46650
47003
|
/**
|
|
46651
47004
|
* Post-process (fade-in, volume, pitch, stereo) and play a LuxTTS WAV file.
|
|
46652
47005
|
* Cleans up the WAV file after playback.
|
|
46653
47006
|
*/
|
|
46654
47007
|
async postProcessAndPlayLuxtts(wavPath, volume = 1, pitchFactor = 1, stereoDelayMs = 0.6) {
|
|
46655
|
-
if (!
|
|
47008
|
+
if (!existsSync42(wavPath))
|
|
46656
47009
|
return;
|
|
46657
47010
|
try {
|
|
46658
|
-
const wavData =
|
|
47011
|
+
const wavData = readFileSync31(wavPath);
|
|
46659
47012
|
if (wavData.length > 44) {
|
|
46660
47013
|
const sampleRate = wavData.readUInt32LE(24);
|
|
46661
47014
|
const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
|
|
@@ -46670,13 +47023,13 @@ if __name__ == '__main__':
|
|
|
46670
47023
|
}
|
|
46671
47024
|
const header = wavData.subarray(0, 44);
|
|
46672
47025
|
const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
|
|
46673
|
-
|
|
47026
|
+
writeFileSync19(wavPath, scaled);
|
|
46674
47027
|
}
|
|
46675
47028
|
} catch {
|
|
46676
47029
|
}
|
|
46677
47030
|
if (pitchFactor !== 1) {
|
|
46678
47031
|
try {
|
|
46679
|
-
const wavData =
|
|
47032
|
+
const wavData = readFileSync31(wavPath);
|
|
46680
47033
|
if (wavData.length > 44) {
|
|
46681
47034
|
const int16 = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
|
|
46682
47035
|
const float32 = new Float32Array(int16.length);
|
|
@@ -46691,7 +47044,7 @@ if __name__ == '__main__':
|
|
|
46691
47044
|
}
|
|
46692
47045
|
if (this.onPCMOutput) {
|
|
46693
47046
|
try {
|
|
46694
|
-
const wavData =
|
|
47047
|
+
const wavData = readFileSync31(wavPath);
|
|
46695
47048
|
if (wavData.length > 44) {
|
|
46696
47049
|
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
46697
47050
|
const sampleRate = wavData.readUInt32LE(24);
|
|
@@ -46702,7 +47055,7 @@ if __name__ == '__main__':
|
|
|
46702
47055
|
}
|
|
46703
47056
|
if (stereoDelayMs > 0) {
|
|
46704
47057
|
try {
|
|
46705
|
-
const wavData =
|
|
47058
|
+
const wavData = readFileSync31(wavPath);
|
|
46706
47059
|
if (wavData.length > 44) {
|
|
46707
47060
|
const sampleRate = wavData.readUInt32LE(24);
|
|
46708
47061
|
const numChannels = wavData.readUInt16LE(22);
|
|
@@ -46738,7 +47091,7 @@ if __name__ == '__main__':
|
|
|
46738
47091
|
* Used for Telegram voice messages and WebSocket streaming.
|
|
46739
47092
|
*/
|
|
46740
47093
|
async synthesizeLuxttsToBuffer(text) {
|
|
46741
|
-
if (!this.luxttsCloneRef || !
|
|
47094
|
+
if (!this.luxttsCloneRef || !existsSync42(this.luxttsCloneRef))
|
|
46742
47095
|
return null;
|
|
46743
47096
|
const cleaned = text.replace(/\*/g, "").trim();
|
|
46744
47097
|
if (!cleaned)
|
|
@@ -46746,7 +47099,7 @@ if __name__ == '__main__':
|
|
|
46746
47099
|
const ready = await this.ensureLuxttsDaemon();
|
|
46747
47100
|
if (!ready)
|
|
46748
47101
|
return null;
|
|
46749
|
-
const wavPath =
|
|
47102
|
+
const wavPath = join58(tmpdir9(), `oa-luxtts-buf-${Date.now()}.wav`);
|
|
46750
47103
|
try {
|
|
46751
47104
|
await this.luxttsRequest({
|
|
46752
47105
|
action: "synthesize",
|
|
@@ -46758,10 +47111,10 @@ if __name__ == '__main__':
|
|
|
46758
47111
|
} catch {
|
|
46759
47112
|
return null;
|
|
46760
47113
|
}
|
|
46761
|
-
if (!
|
|
47114
|
+
if (!existsSync42(wavPath))
|
|
46762
47115
|
return null;
|
|
46763
47116
|
try {
|
|
46764
|
-
const data =
|
|
47117
|
+
const data = readFileSync31(wavPath);
|
|
46765
47118
|
unlinkSync9(wavPath);
|
|
46766
47119
|
return data;
|
|
46767
47120
|
} catch {
|
|
@@ -46775,40 +47128,40 @@ if __name__ == '__main__':
|
|
|
46775
47128
|
if (this.ort)
|
|
46776
47129
|
return;
|
|
46777
47130
|
const arch2 = process.arch;
|
|
46778
|
-
|
|
46779
|
-
const pkgPath =
|
|
47131
|
+
mkdirSync18(voiceDir(), { recursive: true });
|
|
47132
|
+
const pkgPath = join58(voiceDir(), "package.json");
|
|
46780
47133
|
const expectedDeps = {
|
|
46781
47134
|
"onnxruntime-node": "^1.21.0",
|
|
46782
47135
|
"phonemizer": "^1.2.1"
|
|
46783
47136
|
};
|
|
46784
|
-
if (
|
|
47137
|
+
if (existsSync42(pkgPath)) {
|
|
46785
47138
|
try {
|
|
46786
|
-
const existing = JSON.parse(
|
|
47139
|
+
const existing = JSON.parse(readFileSync31(pkgPath, "utf8"));
|
|
46787
47140
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
46788
47141
|
existing.dependencies = { ...existing.dependencies, ...expectedDeps };
|
|
46789
|
-
|
|
47142
|
+
writeFileSync19(pkgPath, JSON.stringify(existing, null, 2));
|
|
46790
47143
|
}
|
|
46791
47144
|
} catch {
|
|
46792
47145
|
}
|
|
46793
47146
|
}
|
|
46794
|
-
if (!
|
|
46795
|
-
|
|
47147
|
+
if (!existsSync42(pkgPath)) {
|
|
47148
|
+
writeFileSync19(pkgPath, JSON.stringify({
|
|
46796
47149
|
name: "open-agents-voice",
|
|
46797
47150
|
private: true,
|
|
46798
47151
|
dependencies: expectedDeps
|
|
46799
47152
|
}, null, 2));
|
|
46800
47153
|
}
|
|
46801
|
-
const voiceRequire = createRequire(
|
|
47154
|
+
const voiceRequire = createRequire(join58(voiceDir(), "index.js"));
|
|
46802
47155
|
const probeOnnx = async () => {
|
|
46803
47156
|
try {
|
|
46804
|
-
const output = await this.asyncShell(`NODE_PATH="${
|
|
47157
|
+
const output = await this.asyncShell(`NODE_PATH="${join58(voiceDir(), "node_modules")}" node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, 15e3);
|
|
46805
47158
|
return output.trim() === "OK";
|
|
46806
47159
|
} catch {
|
|
46807
47160
|
return false;
|
|
46808
47161
|
}
|
|
46809
47162
|
};
|
|
46810
|
-
const onnxNodeModules =
|
|
46811
|
-
const onnxInstalled =
|
|
47163
|
+
const onnxNodeModules = join58(voiceDir(), "node_modules", "onnxruntime-node");
|
|
47164
|
+
const onnxInstalled = existsSync42(onnxNodeModules);
|
|
46812
47165
|
if (onnxInstalled && !await probeOnnx()) {
|
|
46813
47166
|
throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch2}). 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.`);
|
|
46814
47167
|
}
|
|
@@ -46858,18 +47211,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
46858
47211
|
const dir = modelDir(id);
|
|
46859
47212
|
const onnxPath = modelOnnxPath(id);
|
|
46860
47213
|
const configPath2 = modelConfigPath(id);
|
|
46861
|
-
if (
|
|
47214
|
+
if (existsSync42(onnxPath) && existsSync42(configPath2))
|
|
46862
47215
|
return;
|
|
46863
|
-
|
|
46864
|
-
if (!
|
|
47216
|
+
mkdirSync18(dir, { recursive: true });
|
|
47217
|
+
if (!existsSync42(configPath2)) {
|
|
46865
47218
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
46866
47219
|
const configResp = await fetch(model.configUrl);
|
|
46867
47220
|
if (!configResp.ok)
|
|
46868
47221
|
throw new Error(`Failed to download config: HTTP ${configResp.status}`);
|
|
46869
47222
|
const configText = await configResp.text();
|
|
46870
|
-
|
|
47223
|
+
writeFileSync19(configPath2, configText);
|
|
46871
47224
|
}
|
|
46872
|
-
if (!
|
|
47225
|
+
if (!existsSync42(onnxPath)) {
|
|
46873
47226
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
46874
47227
|
const onnxResp = await fetch(model.onnxUrl);
|
|
46875
47228
|
if (!onnxResp.ok)
|
|
@@ -46894,7 +47247,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
46894
47247
|
}
|
|
46895
47248
|
}
|
|
46896
47249
|
const fullBuffer = Buffer.concat(chunks);
|
|
46897
|
-
|
|
47250
|
+
writeFileSync19(onnxPath, fullBuffer);
|
|
46898
47251
|
renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
|
|
46899
47252
|
}
|
|
46900
47253
|
}
|
|
@@ -46906,10 +47259,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
46906
47259
|
throw new Error("ONNX runtime not loaded");
|
|
46907
47260
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
46908
47261
|
const configPath2 = modelConfigPath(this.modelId);
|
|
46909
|
-
if (!
|
|
47262
|
+
if (!existsSync42(onnxPath) || !existsSync42(configPath2)) {
|
|
46910
47263
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
46911
47264
|
}
|
|
46912
|
-
this.config = JSON.parse(
|
|
47265
|
+
this.config = JSON.parse(readFileSync31(configPath2, "utf8"));
|
|
46913
47266
|
this.session = await this.ort.InferenceSession.create(onnxPath, {
|
|
46914
47267
|
executionProviders: ["cpu"],
|
|
46915
47268
|
graphOptimizationLevel: "all"
|
|
@@ -46936,8 +47289,8 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
46936
47289
|
// packages/cli/dist/tui/commands.js
|
|
46937
47290
|
import * as nodeOs from "node:os";
|
|
46938
47291
|
import { execSync as nodeExecSync } from "node:child_process";
|
|
46939
|
-
import { existsSync as
|
|
46940
|
-
import { join as
|
|
47292
|
+
import { existsSync as existsSync43, readFileSync as readFileSync32, writeFileSync as writeFileSync20, mkdirSync as mkdirSync19, readdirSync as readdirSync12, statSync as statSync14, rmSync } from "node:fs";
|
|
47293
|
+
import { join as join59 } from "node:path";
|
|
46941
47294
|
function safeLog(text) {
|
|
46942
47295
|
if (isNeovimActive()) {
|
|
46943
47296
|
writeToNeovimOutput(text + "\n");
|
|
@@ -47356,9 +47709,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47356
47709
|
renderInfo("No wallet configured. Ask the agent to create one via the nexus tool.");
|
|
47357
47710
|
}
|
|
47358
47711
|
} else if (sub === "name") {
|
|
47359
|
-
const { homedir:
|
|
47712
|
+
const { homedir: homedir21 } = __require("node:os");
|
|
47360
47713
|
const { existsSync: ex, readFileSync: rf, writeFileSync: wf, mkdirSync: mkd } = __require("node:fs");
|
|
47361
|
-
const namePath = __require("node:path").join(
|
|
47714
|
+
const namePath = __require("node:path").join(homedir21(), ".open-agents", "agent-name");
|
|
47362
47715
|
if (rest2) {
|
|
47363
47716
|
const customName = rest2.replace(/[^a-zA-Z0-9_\-.\s]/g, "").trim().slice(0, 40);
|
|
47364
47717
|
if (!customName) {
|
|
@@ -47631,22 +47984,22 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47631
47984
|
let content = "";
|
|
47632
47985
|
let metadata = {};
|
|
47633
47986
|
if (shareType === "tool") {
|
|
47634
|
-
const toolDir =
|
|
47635
|
-
const toolFile =
|
|
47636
|
-
if (!
|
|
47987
|
+
const toolDir = join59(ctx.repoRoot, ".oa", "tools");
|
|
47988
|
+
const toolFile = join59(toolDir, shareName.endsWith(".json") ? shareName : `${shareName}.json`);
|
|
47989
|
+
if (!existsSync43(toolFile)) {
|
|
47637
47990
|
renderWarning(`Tool not found: ${toolFile}`);
|
|
47638
47991
|
return "handled";
|
|
47639
47992
|
}
|
|
47640
|
-
content =
|
|
47993
|
+
content = readFileSync32(toolFile, "utf8");
|
|
47641
47994
|
metadata = { type: "tool", name: shareName };
|
|
47642
47995
|
} else if (shareType === "skill") {
|
|
47643
|
-
const skillDir =
|
|
47644
|
-
const skillFile =
|
|
47645
|
-
if (!
|
|
47996
|
+
const skillDir = join59(ctx.repoRoot, ".oa", "skills", shareName);
|
|
47997
|
+
const skillFile = join59(skillDir, "SKILL.md");
|
|
47998
|
+
if (!existsSync43(skillFile)) {
|
|
47646
47999
|
renderWarning(`Skill not found: ${skillFile}`);
|
|
47647
48000
|
return "handled";
|
|
47648
48001
|
}
|
|
47649
|
-
content =
|
|
48002
|
+
content = readFileSync32(skillFile, "utf8");
|
|
47650
48003
|
metadata = { type: "skill", name: shareName };
|
|
47651
48004
|
} else {
|
|
47652
48005
|
renderWarning(`Unknown share type: ${shareType}. Use 'tool' or 'skill'.`);
|
|
@@ -47683,9 +48036,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47683
48036
|
try {
|
|
47684
48037
|
const nexus = new NexusTool(ctx.repoRoot);
|
|
47685
48038
|
await nexus.execute({ action: "ipfs_pin", cid: importCid, source: "import" });
|
|
47686
|
-
const regFile =
|
|
47687
|
-
if (
|
|
47688
|
-
const reg = JSON.parse(
|
|
48039
|
+
const regFile = join59(ctx.repoRoot, ".oa", "nexus", "ipfs", "cid-registry", "learning-cids.json");
|
|
48040
|
+
if (existsSync43(regFile)) {
|
|
48041
|
+
const reg = JSON.parse(readFileSync32(regFile, "utf8"));
|
|
47689
48042
|
const pinned = Object.values(reg).some((e) => e.cid === importCid && e.pinned);
|
|
47690
48043
|
if (pinned) {
|
|
47691
48044
|
renderInfo(`CID ${importCid.slice(0, 20)}... pinned successfully.`);
|
|
@@ -47737,33 +48090,33 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47737
48090
|
lines.push(`
|
|
47738
48091
|
${c2.bold("IPFS / Helia Status")}
|
|
47739
48092
|
`);
|
|
47740
|
-
const ipfsDir =
|
|
47741
|
-
const ipfsLocalDir =
|
|
48093
|
+
const ipfsDir = join59(ctx.repoRoot, ".oa", "ipfs");
|
|
48094
|
+
const ipfsLocalDir = join59(ipfsDir, "local");
|
|
47742
48095
|
let ipfsFiles = 0;
|
|
47743
48096
|
let ipfsBytes = 0;
|
|
47744
48097
|
let heliaBlocks = 0;
|
|
47745
48098
|
let heliaBytes = 0;
|
|
47746
48099
|
try {
|
|
47747
|
-
if (
|
|
48100
|
+
if (existsSync43(ipfsLocalDir)) {
|
|
47748
48101
|
const files = readdirSync12(ipfsLocalDir).filter((f) => f.endsWith(".json"));
|
|
47749
48102
|
ipfsFiles = files.length;
|
|
47750
48103
|
for (const f of files) {
|
|
47751
48104
|
try {
|
|
47752
|
-
ipfsBytes += statSync14(
|
|
48105
|
+
ipfsBytes += statSync14(join59(ipfsLocalDir, f)).size;
|
|
47753
48106
|
} catch {
|
|
47754
48107
|
}
|
|
47755
48108
|
}
|
|
47756
48109
|
}
|
|
47757
|
-
const heliaBlockDir =
|
|
47758
|
-
if (
|
|
48110
|
+
const heliaBlockDir = join59(ipfsDir, "blocks");
|
|
48111
|
+
if (existsSync43(heliaBlockDir)) {
|
|
47759
48112
|
const walkDir = (dir) => {
|
|
47760
48113
|
for (const entry of readdirSync12(dir, { withFileTypes: true })) {
|
|
47761
48114
|
if (entry.isDirectory())
|
|
47762
|
-
walkDir(
|
|
48115
|
+
walkDir(join59(dir, entry.name));
|
|
47763
48116
|
else {
|
|
47764
48117
|
heliaBlocks++;
|
|
47765
48118
|
try {
|
|
47766
|
-
heliaBytes += statSync14(
|
|
48119
|
+
heliaBytes += statSync14(join59(dir, entry.name)).size;
|
|
47767
48120
|
} catch {
|
|
47768
48121
|
}
|
|
47769
48122
|
}
|
|
@@ -47779,9 +48132,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47779
48132
|
lines.push(` Blocks: ${c2.bold(String(heliaBlocks))} Size: ${c2.bold(formatFileSize(heliaBytes))}`);
|
|
47780
48133
|
lines.push(` Backend: ${heliaBlocks > 0 ? c2.green("helia-ipfs") : c2.yellow("sha256-local (Helia not initialized)")}`);
|
|
47781
48134
|
try {
|
|
47782
|
-
const statusFile =
|
|
47783
|
-
if (
|
|
47784
|
-
const status = JSON.parse(
|
|
48135
|
+
const statusFile = join59(ctx.repoRoot, ".oa", "nexus", "status.json");
|
|
48136
|
+
if (existsSync43(statusFile)) {
|
|
48137
|
+
const status = JSON.parse(readFileSync32(statusFile, "utf8"));
|
|
47785
48138
|
if (status.peerId) {
|
|
47786
48139
|
lines.push(`
|
|
47787
48140
|
${c2.bold("Peer Info")}`);
|
|
@@ -47800,11 +48153,11 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47800
48153
|
${c2.dim("Commands: /ipfs pin <CID> /ipfs publish /ipfs cids")}`);
|
|
47801
48154
|
lines.push(`
|
|
47802
48155
|
${c2.bold("Identity Kernel")}`);
|
|
47803
|
-
const idDir =
|
|
48156
|
+
const idDir = join59(ctx.repoRoot, ".oa", "identity");
|
|
47804
48157
|
try {
|
|
47805
|
-
const stateFile =
|
|
47806
|
-
if (
|
|
47807
|
-
const state = JSON.parse(
|
|
48158
|
+
const stateFile = join59(idDir, "self-state.json");
|
|
48159
|
+
if (existsSync43(stateFile)) {
|
|
48160
|
+
const state = JSON.parse(readFileSync32(stateFile, "utf8"));
|
|
47808
48161
|
lines.push(` Version: ${c2.bold("v" + (state.version ?? "?"))} Sessions: ${c2.bold(String(state.session_count ?? 0))}`);
|
|
47809
48162
|
if (state.narrative_summary) {
|
|
47810
48163
|
lines.push(` Narrative: ${c2.dim(state.narrative_summary.slice(0, 60))}${state.narrative_summary.length > 60 ? "..." : ""}`);
|
|
@@ -47813,9 +48166,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47813
48166
|
const traits = typeof state.personality_traits === "object" ? Object.entries(state.personality_traits).map(([k, v]) => `${k}:${v}`).join(", ") : String(state.personality_traits);
|
|
47814
48167
|
lines.push(` Traits: ${c2.dim(traits.slice(0, 60))}`);
|
|
47815
48168
|
}
|
|
47816
|
-
const cidFile =
|
|
47817
|
-
if (
|
|
47818
|
-
const cids = JSON.parse(
|
|
48169
|
+
const cidFile = join59(idDir, "cids.json");
|
|
48170
|
+
if (existsSync43(cidFile)) {
|
|
48171
|
+
const cids = JSON.parse(readFileSync32(cidFile, "utf8"));
|
|
47819
48172
|
const lastCid = Array.isArray(cids) ? cids[cids.length - 1] : cids.latest;
|
|
47820
48173
|
if (lastCid)
|
|
47821
48174
|
lines.push(` Last CID: ${c2.dim(String(lastCid).slice(0, 50))}`);
|
|
@@ -47828,9 +48181,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47828
48181
|
lines.push(`
|
|
47829
48182
|
${c2.bold("Memory Sentiment")}`);
|
|
47830
48183
|
try {
|
|
47831
|
-
const metaFile =
|
|
47832
|
-
if (
|
|
47833
|
-
const store = JSON.parse(
|
|
48184
|
+
const metaFile = join59(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
48185
|
+
if (existsSync43(metaFile)) {
|
|
48186
|
+
const store = JSON.parse(readFileSync32(metaFile, "utf8"));
|
|
47834
48187
|
const active = store.filter((m) => m.type !== "quarantine");
|
|
47835
48188
|
const recoveries = active.filter((m) => m.content?.startsWith("[recovery]")).length;
|
|
47836
48189
|
const strategies = active.filter((m) => m.content?.startsWith("[strategy]")).length;
|
|
@@ -47848,8 +48201,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47848
48201
|
} catch {
|
|
47849
48202
|
}
|
|
47850
48203
|
try {
|
|
47851
|
-
const dbPath =
|
|
47852
|
-
if (
|
|
48204
|
+
const dbPath = join59(ctx.repoRoot, ".oa", "memory", "structured.db");
|
|
48205
|
+
if (existsSync43(dbPath)) {
|
|
47853
48206
|
const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
47854
48207
|
const db = initDb2(dbPath);
|
|
47855
48208
|
const memStore = new ProceduralMemoryStore2(db);
|
|
@@ -47870,8 +48223,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47870
48223
|
lines.push(`
|
|
47871
48224
|
${c2.bold("Storage Overview")}
|
|
47872
48225
|
`);
|
|
47873
|
-
const oaDir =
|
|
47874
|
-
if (!
|
|
48226
|
+
const oaDir = join59(ctx.repoRoot, ".oa");
|
|
48227
|
+
if (!existsSync43(oaDir)) {
|
|
47875
48228
|
lines.push(` ${c2.dim("No .oa/ directory found.")}`);
|
|
47876
48229
|
safeLog(lines.join("\n") + "\n");
|
|
47877
48230
|
return "handled";
|
|
@@ -47881,7 +48234,7 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47881
48234
|
const walkStorage = (dir, category) => {
|
|
47882
48235
|
try {
|
|
47883
48236
|
for (const entry of readdirSync12(dir, { withFileTypes: true })) {
|
|
47884
|
-
const full =
|
|
48237
|
+
const full = join59(dir, entry.name);
|
|
47885
48238
|
if (entry.isDirectory()) {
|
|
47886
48239
|
const subCat = category || entry.name;
|
|
47887
48240
|
walkStorage(full, subCat);
|
|
@@ -47917,10 +48270,10 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47917
48270
|
for (const entry of readdirSync12(dir, { withFileTypes: true })) {
|
|
47918
48271
|
const name = entry.name.toLowerCase();
|
|
47919
48272
|
if (sensitivePatterns.some((p) => name.includes(p))) {
|
|
47920
|
-
sensitiveFound.push(
|
|
48273
|
+
sensitiveFound.push(join59(dir, entry.name).replace(oaDir + "/", ""));
|
|
47921
48274
|
}
|
|
47922
48275
|
if (entry.isDirectory())
|
|
47923
|
-
checkSensitive(
|
|
48276
|
+
checkSensitive(join59(dir, entry.name));
|
|
47924
48277
|
}
|
|
47925
48278
|
} catch {
|
|
47926
48279
|
}
|
|
@@ -47948,8 +48301,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47948
48301
|
renderInfo("Supported: .wav .mp3 .flac .ogg (audio\u2192transcribe) | .pdf .txt .md (text\u2192chunk)");
|
|
47949
48302
|
return "handled";
|
|
47950
48303
|
}
|
|
47951
|
-
const resolvedPath =
|
|
47952
|
-
if (!
|
|
48304
|
+
const resolvedPath = join59(ctx.repoRoot, filePath);
|
|
48305
|
+
if (!existsSync43(resolvedPath)) {
|
|
47953
48306
|
renderWarning(`File not found: ${resolvedPath}`);
|
|
47954
48307
|
return "handled";
|
|
47955
48308
|
}
|
|
@@ -47965,9 +48318,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47965
48318
|
}
|
|
47966
48319
|
try {
|
|
47967
48320
|
const { initDb: initDb2, closeDb: cDb, ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
47968
|
-
const dbDir =
|
|
47969
|
-
|
|
47970
|
-
const db = initDb2(
|
|
48321
|
+
const dbDir = join59(ctx.repoRoot, ".oa", "memory");
|
|
48322
|
+
mkdirSync19(dbDir, { recursive: true });
|
|
48323
|
+
const db = initDb2(join59(dbDir, "structured.db"));
|
|
47971
48324
|
const memStore = new ProceduralMemoryStore2(db);
|
|
47972
48325
|
if (isAudio) {
|
|
47973
48326
|
renderInfo(`Transcribing: ${filePath}...`);
|
|
@@ -48008,7 +48361,7 @@ async function handleSlashCommand(input, ctx) {
|
|
|
48008
48361
|
return "handled";
|
|
48009
48362
|
}
|
|
48010
48363
|
} else {
|
|
48011
|
-
content =
|
|
48364
|
+
content = readFileSync32(resolvedPath, "utf8");
|
|
48012
48365
|
}
|
|
48013
48366
|
if (!content.trim()) {
|
|
48014
48367
|
renderWarning("No content extracted.");
|
|
@@ -48047,9 +48400,9 @@ async function handleSlashCommand(input, ctx) {
|
|
|
48047
48400
|
}
|
|
48048
48401
|
case "fortemi": {
|
|
48049
48402
|
const fortemiSubCmd = (arg || "").trim().toLowerCase();
|
|
48050
|
-
const fortemiDir =
|
|
48051
|
-
const altFortemiDir =
|
|
48052
|
-
const fDir =
|
|
48403
|
+
const fortemiDir = join59(ctx.repoRoot, "..", "fortemi-react");
|
|
48404
|
+
const altFortemiDir = join59(nodeOs.homedir(), "fortemi-react");
|
|
48405
|
+
const fDir = existsSync43(fortemiDir) ? fortemiDir : existsSync43(altFortemiDir) ? altFortemiDir : null;
|
|
48053
48406
|
if (fortemiSubCmd === "start" || fortemiSubCmd === "") {
|
|
48054
48407
|
if (!fDir) {
|
|
48055
48408
|
renderWarning("fortemi-react not found adjacent or in home directory.");
|
|
@@ -48064,14 +48417,14 @@ async function handleSlashCommand(input, ctx) {
|
|
|
48064
48417
|
// 24h
|
|
48065
48418
|
nonce: Math.random().toString(36).slice(2, 10)
|
|
48066
48419
|
};
|
|
48067
|
-
const jwtFile =
|
|
48068
|
-
|
|
48069
|
-
|
|
48420
|
+
const jwtFile = join59(ctx.repoRoot, ".oa", "fortemi-jwt.json");
|
|
48421
|
+
mkdirSync19(join59(ctx.repoRoot, ".oa"), { recursive: true });
|
|
48422
|
+
writeFileSync20(jwtFile, JSON.stringify(jwtPayload, null, 2));
|
|
48070
48423
|
renderInfo(`Launching fortemi-react from ${fDir}...`);
|
|
48071
48424
|
try {
|
|
48072
|
-
const { spawn:
|
|
48073
|
-
const child =
|
|
48074
|
-
cwd:
|
|
48425
|
+
const { spawn: spawn23 } = __require("node:child_process");
|
|
48426
|
+
const child = spawn23("npx", ["vite", "dev", "--host", "0.0.0.0", "--port", "3000"], {
|
|
48427
|
+
cwd: join59(fDir, "apps", "standalone"),
|
|
48075
48428
|
stdio: "ignore",
|
|
48076
48429
|
detached: true,
|
|
48077
48430
|
env: { ...process.env, OA_JWT: JSON.stringify(jwtPayload) }
|
|
@@ -48080,8 +48433,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
48080
48433
|
renderInfo("Fortemi-React starting on http://localhost:3000");
|
|
48081
48434
|
renderInfo(`JWT saved to ${jwtFile}`);
|
|
48082
48435
|
renderInfo("Memory operations will proxy to fortemi when available.");
|
|
48083
|
-
const bridgeFile =
|
|
48084
|
-
|
|
48436
|
+
const bridgeFile = join59(ctx.repoRoot, ".oa", "fortemi-bridge.json");
|
|
48437
|
+
writeFileSync20(bridgeFile, JSON.stringify({
|
|
48085
48438
|
url: "http://localhost:3000",
|
|
48086
48439
|
pid: child.pid,
|
|
48087
48440
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -48093,12 +48446,12 @@ async function handleSlashCommand(input, ctx) {
|
|
|
48093
48446
|
return "handled";
|
|
48094
48447
|
}
|
|
48095
48448
|
if (fortemiSubCmd === "status") {
|
|
48096
|
-
const bridgeFile =
|
|
48097
|
-
if (!
|
|
48449
|
+
const bridgeFile = join59(ctx.repoRoot, ".oa", "fortemi-bridge.json");
|
|
48450
|
+
if (!existsSync43(bridgeFile)) {
|
|
48098
48451
|
renderInfo("Fortemi bridge: not connected. Run /fortemi start");
|
|
48099
48452
|
return "handled";
|
|
48100
48453
|
}
|
|
48101
|
-
const bridge = JSON.parse(
|
|
48454
|
+
const bridge = JSON.parse(readFileSync32(bridgeFile, "utf8"));
|
|
48102
48455
|
let alive = false;
|
|
48103
48456
|
try {
|
|
48104
48457
|
process.kill(bridge.pid, 0);
|
|
@@ -48118,15 +48471,15 @@ async function handleSlashCommand(input, ctx) {
|
|
|
48118
48471
|
lines.push(` Process: ${alive ? c2.green("running") : c2.yellow("not running")} (PID ${bridge.pid})`);
|
|
48119
48472
|
lines.push(` HTTP: ${httpOk ? c2.green("connected") : c2.yellow("unreachable")}`);
|
|
48120
48473
|
lines.push(` Started: ${bridge.startedAt}`);
|
|
48121
|
-
lines.push(` JWT: ${
|
|
48474
|
+
lines.push(` JWT: ${existsSync43(bridge.jwtFile) ? c2.green("valid") : c2.yellow("missing")}`);
|
|
48122
48475
|
lines.push("");
|
|
48123
48476
|
safeLog(lines.join("\n"));
|
|
48124
48477
|
return "handled";
|
|
48125
48478
|
}
|
|
48126
48479
|
if (fortemiSubCmd === "stop") {
|
|
48127
|
-
const bridgeFile =
|
|
48128
|
-
if (
|
|
48129
|
-
const bridge = JSON.parse(
|
|
48480
|
+
const bridgeFile = join59(ctx.repoRoot, ".oa", "fortemi-bridge.json");
|
|
48481
|
+
if (existsSync43(bridgeFile)) {
|
|
48482
|
+
const bridge = JSON.parse(readFileSync32(bridgeFile, "utf8"));
|
|
48130
48483
|
try {
|
|
48131
48484
|
process.kill(bridge.pid, "SIGTERM");
|
|
48132
48485
|
} catch {
|
|
@@ -48183,6 +48536,37 @@ async function handleSlashCommand(input, ctx) {
|
|
|
48183
48536
|
ctx.saveSettings(settings);
|
|
48184
48537
|
};
|
|
48185
48538
|
if (arg) {
|
|
48539
|
+
if (arg === "personaplex" || arg === "pp") {
|
|
48540
|
+
const { detectPersonaPlexCapability: detectPersonaPlexCapability2, isPersonaPlexInstalled: isPersonaPlexInstalled2, installPersonaPlex: installPersonaPlex2, startPersonaPlexDaemon: startPersonaPlexDaemon2, stopPersonaPlex: stopPersonaPlex2, isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
|
|
48541
|
+
const caps = detectPersonaPlexCapability2();
|
|
48542
|
+
if (!caps.supported) {
|
|
48543
|
+
renderWarning(`PersonaPlex not available: ${caps.reason}`);
|
|
48544
|
+
renderInfo("Requirements: NVIDIA GPU with \u226516GB VRAM (RTX 3090/4090/A100+), CUDA 12.1+, PyTorch");
|
|
48545
|
+
return "handled";
|
|
48546
|
+
}
|
|
48547
|
+
renderInfo(`GPU: ${caps.gpuName} (${caps.vramGB.toFixed(0)}GB VRAM) \u2014 PersonaPlex compatible \u2713`);
|
|
48548
|
+
if (!isPersonaPlexInstalled2()) {
|
|
48549
|
+
renderInfo("Installing PersonaPlex-7B (~14GB download)...");
|
|
48550
|
+
const ok = await installPersonaPlex2((msg2) => renderInfo(msg2));
|
|
48551
|
+
if (!ok) {
|
|
48552
|
+
renderError("PersonaPlex installation failed.");
|
|
48553
|
+
return "handled";
|
|
48554
|
+
}
|
|
48555
|
+
}
|
|
48556
|
+
if (isPersonaPlexRunning2()) {
|
|
48557
|
+
renderInfo("PersonaPlex daemon is running.");
|
|
48558
|
+
renderInfo("Use /call to start a full-duplex voice session.");
|
|
48559
|
+
} else {
|
|
48560
|
+
const url = await startPersonaPlexDaemon2((msg2) => renderInfo(msg2));
|
|
48561
|
+
if (url) {
|
|
48562
|
+
renderInfo(`PersonaPlex ready at ${url}`);
|
|
48563
|
+
renderInfo("Use /call to start a full-duplex voice session with PersonaPlex.");
|
|
48564
|
+
} else {
|
|
48565
|
+
renderError("PersonaPlex daemon failed to start.");
|
|
48566
|
+
}
|
|
48567
|
+
}
|
|
48568
|
+
return "handled";
|
|
48569
|
+
}
|
|
48186
48570
|
if (arg === "enable" || arg === "on") {
|
|
48187
48571
|
const msg2 = await ctx.voiceToggle();
|
|
48188
48572
|
const isOn = msg2.toLowerCase().includes("enabled") || msg2.toLowerCase().includes("on");
|
|
@@ -48474,6 +48858,17 @@ async function handleSlashCommand(input, ctx) {
|
|
|
48474
48858
|
renderWarning("Call mode not available in this context.");
|
|
48475
48859
|
return "handled";
|
|
48476
48860
|
}
|
|
48861
|
+
try {
|
|
48862
|
+
const { isPersonaPlexRunning: isPersonaPlexRunning2, getPersonaPlexWSUrl: getPersonaPlexWSUrl2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
|
|
48863
|
+
if (isPersonaPlexRunning2()) {
|
|
48864
|
+
const ppUrl = getPersonaPlexWSUrl2();
|
|
48865
|
+
if (ppUrl) {
|
|
48866
|
+
renderInfo(`PersonaPlex active \u2014 full-duplex mode (${ppUrl})`);
|
|
48867
|
+
renderInfo("257ms response latency, concurrent listen+speak");
|
|
48868
|
+
}
|
|
48869
|
+
}
|
|
48870
|
+
} catch {
|
|
48871
|
+
}
|
|
48477
48872
|
if (arg === "stop" || arg === "off") {
|
|
48478
48873
|
if (ctx.isCallActive?.()) {
|
|
48479
48874
|
await ctx.callStop?.();
|
|
@@ -48707,10 +49102,10 @@ async function handleSlashCommand(input, ctx) {
|
|
|
48707
49102
|
let sponsorName = (config.header.message || "").replace(/^\/+/, "").trim();
|
|
48708
49103
|
if (!sponsorName || sponsorName.length < 2) {
|
|
48709
49104
|
try {
|
|
48710
|
-
const { homedir:
|
|
48711
|
-
const namePath = __require("path").join(
|
|
48712
|
-
if (
|
|
48713
|
-
sponsorName =
|
|
49105
|
+
const { homedir: homedir21 } = __require("os");
|
|
49106
|
+
const namePath = __require("path").join(homedir21(), ".open-agents", "agent-name");
|
|
49107
|
+
if (existsSync43(namePath))
|
|
49108
|
+
sponsorName = readFileSync32(namePath, "utf8").trim();
|
|
48714
49109
|
} catch {
|
|
48715
49110
|
}
|
|
48716
49111
|
if (!sponsorName)
|
|
@@ -49781,13 +50176,13 @@ async function showCohereDashboard(ctx) {
|
|
|
49781
50176
|
} else if (idResult.key === "view") {
|
|
49782
50177
|
await ik.execute({ operation: "hydrate" });
|
|
49783
50178
|
} else if (idResult.key === "history") {
|
|
49784
|
-
const snapDir =
|
|
49785
|
-
if (
|
|
50179
|
+
const snapDir = join59(ctx.repoRoot, ".oa", "identity", "snapshots");
|
|
50180
|
+
if (existsSync43(snapDir)) {
|
|
49786
50181
|
const snaps = readdirSync12(snapDir).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
49787
50182
|
const snapItems = snaps.slice(0, 20).map((f) => ({
|
|
49788
50183
|
key: f,
|
|
49789
50184
|
label: f.replace(".json", ""),
|
|
49790
|
-
detail: `${formatFileSize(statSync14(
|
|
50185
|
+
detail: `${formatFileSize(statSync14(join59(snapDir, f)).size)}`
|
|
49791
50186
|
}));
|
|
49792
50187
|
if (snapItems.length > 0) {
|
|
49793
50188
|
await tuiSelect({
|
|
@@ -50108,12 +50503,12 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
|
|
|
50108
50503
|
continue;
|
|
50109
50504
|
}
|
|
50110
50505
|
const { basename: basename18, join: pathJoin } = await import("node:path");
|
|
50111
|
-
const { copyFileSync: copyFileSync2, mkdirSync:
|
|
50112
|
-
const { homedir:
|
|
50506
|
+
const { copyFileSync: copyFileSync2, mkdirSync: mkdirSync31, existsSync: exists } = await import("node:fs");
|
|
50507
|
+
const { homedir: homedir21 } = await import("node:os");
|
|
50113
50508
|
const modelName = basename18(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
50114
|
-
const destDir = pathJoin(
|
|
50509
|
+
const destDir = pathJoin(homedir21(), ".open-agents", "voice", "models", modelName);
|
|
50115
50510
|
if (!exists(destDir))
|
|
50116
|
-
|
|
50511
|
+
mkdirSync31(destDir, { recursive: true });
|
|
50117
50512
|
copyFileSync2(onnxDrop.path, pathJoin(destDir, "model.onnx"));
|
|
50118
50513
|
copyFileSync2(jsonDrop.path, pathJoin(destDir, "config.json"));
|
|
50119
50514
|
const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
|
|
@@ -50740,11 +51135,11 @@ async function handleSponsoredEndpoint(ctx, local) {
|
|
|
50740
51135
|
}
|
|
50741
51136
|
} catch {
|
|
50742
51137
|
}
|
|
50743
|
-
const sponsorDir2 =
|
|
50744
|
-
const knownFile =
|
|
51138
|
+
const sponsorDir2 = join59(ctx.repoRoot ?? process.cwd(), ".oa", "sponsor");
|
|
51139
|
+
const knownFile = join59(sponsorDir2, "known-sponsors.json");
|
|
50745
51140
|
try {
|
|
50746
|
-
if (
|
|
50747
|
-
const saved = JSON.parse(
|
|
51141
|
+
if (existsSync43(knownFile)) {
|
|
51142
|
+
const saved = JSON.parse(readFileSync32(knownFile, "utf8"));
|
|
50748
51143
|
for (const s of saved) {
|
|
50749
51144
|
if (!sponsors.some((sp) => sp.url === s.url)) {
|
|
50750
51145
|
sponsors.push({ ...s, source: "saved" });
|
|
@@ -50879,11 +51274,11 @@ async function handleSponsoredEndpoint(ctx, local) {
|
|
|
50879
51274
|
}
|
|
50880
51275
|
const saveKey = selected.url || selected.peerId || selected.name;
|
|
50881
51276
|
try {
|
|
50882
|
-
|
|
50883
|
-
const existing =
|
|
51277
|
+
mkdirSync19(sponsorDir2, { recursive: true });
|
|
51278
|
+
const existing = existsSync43(knownFile) ? JSON.parse(readFileSync32(knownFile, "utf8")) : [];
|
|
50884
51279
|
const updated = existing.filter((s) => (s.url || s.peerId || s.name) !== saveKey);
|
|
50885
51280
|
updated.push(selected);
|
|
50886
|
-
|
|
51281
|
+
writeFileSync20(knownFile, JSON.stringify(updated, null, 2), "utf8");
|
|
50887
51282
|
} catch {
|
|
50888
51283
|
}
|
|
50889
51284
|
renderInfo(`Connected to sponsored endpoint: ${selected.name}`);
|
|
@@ -50952,11 +51347,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
|
|
|
50952
51347
|
const models = await fetchModels(peerUrl, authKey);
|
|
50953
51348
|
if (models.length > 0) {
|
|
50954
51349
|
try {
|
|
50955
|
-
const { writeFileSync:
|
|
50956
|
-
const { join:
|
|
50957
|
-
const cachePath =
|
|
50958
|
-
|
|
50959
|
-
|
|
51350
|
+
const { writeFileSync: writeFileSync30, mkdirSync: mkdirSync31 } = await import("node:fs");
|
|
51351
|
+
const { join: join77, dirname: dirname23 } = await import("node:path");
|
|
51352
|
+
const cachePath = join77(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
|
|
51353
|
+
mkdirSync31(dirname23(cachePath), { recursive: true });
|
|
51354
|
+
writeFileSync30(cachePath, JSON.stringify({
|
|
50960
51355
|
peerId,
|
|
50961
51356
|
cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
50962
51357
|
models: models.map((m) => ({ name: m.name, size: m.size, parameterSize: m.parameterSize }))
|
|
@@ -51005,7 +51400,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
|
|
|
51005
51400
|
}
|
|
51006
51401
|
}
|
|
51007
51402
|
async function handleParallel(arg, ctx) {
|
|
51008
|
-
const { execSync:
|
|
51403
|
+
const { execSync: execSync35 } = await import("node:child_process");
|
|
51009
51404
|
const baseUrl = ctx.config.backendUrl || "http://localhost:11434";
|
|
51010
51405
|
const isRemote = ctx.config.backendType === "nexus";
|
|
51011
51406
|
if (isRemote) {
|
|
@@ -51029,7 +51424,7 @@ async function handleParallel(arg, ctx) {
|
|
|
51029
51424
|
}
|
|
51030
51425
|
let systemdVal = "";
|
|
51031
51426
|
try {
|
|
51032
|
-
const out =
|
|
51427
|
+
const out = execSync35("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
|
|
51033
51428
|
const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
|
|
51034
51429
|
if (match)
|
|
51035
51430
|
systemdVal = match[1];
|
|
@@ -51058,7 +51453,7 @@ async function handleParallel(arg, ctx) {
|
|
|
51058
51453
|
}
|
|
51059
51454
|
const isSystemd = (() => {
|
|
51060
51455
|
try {
|
|
51061
|
-
const out =
|
|
51456
|
+
const out = execSync35("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
|
|
51062
51457
|
return out === "active" || out === "inactive";
|
|
51063
51458
|
} catch {
|
|
51064
51459
|
return false;
|
|
@@ -51072,10 +51467,10 @@ async function handleParallel(arg, ctx) {
|
|
|
51072
51467
|
const overrideContent = `[Service]
|
|
51073
51468
|
Environment="OLLAMA_NUM_PARALLEL=${n}"
|
|
51074
51469
|
`;
|
|
51075
|
-
|
|
51076
|
-
|
|
51077
|
-
|
|
51078
|
-
|
|
51470
|
+
execSync35(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
|
|
51471
|
+
execSync35(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
|
|
51472
|
+
execSync35("sudo systemctl daemon-reload", { stdio: "pipe" });
|
|
51473
|
+
execSync35("sudo systemctl restart ollama.service", { stdio: "pipe" });
|
|
51079
51474
|
let ready = false;
|
|
51080
51475
|
for (let i = 0; i < 30 && !ready; i++) {
|
|
51081
51476
|
await new Promise((r) => setTimeout(r, 500));
|
|
@@ -51102,13 +51497,13 @@ Environment="OLLAMA_NUM_PARALLEL=${n}"
|
|
|
51102
51497
|
renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n}...`);
|
|
51103
51498
|
try {
|
|
51104
51499
|
try {
|
|
51105
|
-
|
|
51500
|
+
execSync35("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
|
|
51106
51501
|
} catch {
|
|
51107
51502
|
}
|
|
51108
51503
|
await new Promise((r) => setTimeout(r, 1e3));
|
|
51109
51504
|
process.env.OLLAMA_NUM_PARALLEL = String(n);
|
|
51110
|
-
const { spawn:
|
|
51111
|
-
const child =
|
|
51505
|
+
const { spawn: spawn23 } = await import("node:child_process");
|
|
51506
|
+
const child = spawn23("ollama", ["serve"], {
|
|
51112
51507
|
stdio: "ignore",
|
|
51113
51508
|
detached: true,
|
|
51114
51509
|
env: { ...process.env, OLLAMA_NUM_PARALLEL: String(n) }
|
|
@@ -51155,17 +51550,17 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
51155
51550
|
try {
|
|
51156
51551
|
const { createRequire: createRequire6 } = await import("node:module");
|
|
51157
51552
|
const { fileURLToPath: fileURLToPath15 } = await import("node:url");
|
|
51158
|
-
const { dirname: dirname23, join:
|
|
51159
|
-
const { existsSync:
|
|
51553
|
+
const { dirname: dirname23, join: join77 } = await import("node:path");
|
|
51554
|
+
const { existsSync: existsSync57 } = await import("node:fs");
|
|
51160
51555
|
const req = createRequire6(import.meta.url);
|
|
51161
51556
|
const thisDir = dirname23(fileURLToPath15(import.meta.url));
|
|
51162
51557
|
const candidates = [
|
|
51163
|
-
|
|
51164
|
-
|
|
51165
|
-
|
|
51558
|
+
join77(thisDir, "..", "package.json"),
|
|
51559
|
+
join77(thisDir, "..", "..", "package.json"),
|
|
51560
|
+
join77(thisDir, "..", "..", "..", "package.json")
|
|
51166
51561
|
];
|
|
51167
51562
|
for (const pkgPath of candidates) {
|
|
51168
|
-
if (
|
|
51563
|
+
if (existsSync57(pkgPath)) {
|
|
51169
51564
|
const pkg = req(pkgPath);
|
|
51170
51565
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
51171
51566
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -51921,18 +52316,18 @@ async function showExposeDashboard(gateway, rl, ctx) {
|
|
|
51921
52316
|
const cmd = `/endpoint ${id} --auth ${gateway.authKey ?? ""}`;
|
|
51922
52317
|
let copied = false;
|
|
51923
52318
|
try {
|
|
51924
|
-
const { execSync:
|
|
52319
|
+
const { execSync: execSync35 } = __require("node:child_process");
|
|
51925
52320
|
const platform6 = process.platform;
|
|
51926
52321
|
if (platform6 === "darwin") {
|
|
51927
|
-
|
|
52322
|
+
execSync35("pbcopy", { input: cmd, timeout: 3e3 });
|
|
51928
52323
|
copied = true;
|
|
51929
52324
|
} else if (platform6 === "win32") {
|
|
51930
|
-
|
|
52325
|
+
execSync35("clip", { input: cmd, timeout: 3e3 });
|
|
51931
52326
|
copied = true;
|
|
51932
52327
|
} else {
|
|
51933
52328
|
for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
|
|
51934
52329
|
try {
|
|
51935
|
-
|
|
52330
|
+
execSync35(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
|
|
51936
52331
|
copied = true;
|
|
51937
52332
|
break;
|
|
51938
52333
|
} catch {
|
|
@@ -52019,10 +52414,10 @@ var init_commands = __esm({
|
|
|
52019
52414
|
});
|
|
52020
52415
|
|
|
52021
52416
|
// packages/cli/dist/tui/project-context.js
|
|
52022
|
-
import { existsSync as
|
|
52023
|
-
import { join as
|
|
52024
|
-
import { execSync as
|
|
52025
|
-
import { homedir as
|
|
52417
|
+
import { existsSync as existsSync44, readFileSync as readFileSync33, readdirSync as readdirSync13 } from "node:fs";
|
|
52418
|
+
import { join as join60, basename as basename12 } from "node:path";
|
|
52419
|
+
import { execSync as execSync31 } from "node:child_process";
|
|
52420
|
+
import { homedir as homedir17, platform as platform4, release } from "node:os";
|
|
52026
52421
|
function getModelTier(modelName) {
|
|
52027
52422
|
const m = modelName.toLowerCase();
|
|
52028
52423
|
const sizeMatch = m.match(/\b(\d+)b\b/);
|
|
@@ -52055,10 +52450,10 @@ function loadProjectMap(repoRoot) {
|
|
|
52055
52450
|
if (!hasOaDirectory(repoRoot)) {
|
|
52056
52451
|
initOaDirectory(repoRoot);
|
|
52057
52452
|
}
|
|
52058
|
-
const mapPath2 =
|
|
52059
|
-
if (
|
|
52453
|
+
const mapPath2 = join60(repoRoot, OA_DIR, "context", "project-map.md");
|
|
52454
|
+
if (existsSync44(mapPath2)) {
|
|
52060
52455
|
try {
|
|
52061
|
-
const content =
|
|
52456
|
+
const content = readFileSync33(mapPath2, "utf-8");
|
|
52062
52457
|
return content;
|
|
52063
52458
|
} catch {
|
|
52064
52459
|
}
|
|
@@ -52067,19 +52462,19 @@ function loadProjectMap(repoRoot) {
|
|
|
52067
52462
|
}
|
|
52068
52463
|
function getGitInfo(repoRoot) {
|
|
52069
52464
|
try {
|
|
52070
|
-
|
|
52465
|
+
execSync31("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
|
|
52071
52466
|
} catch {
|
|
52072
52467
|
return "";
|
|
52073
52468
|
}
|
|
52074
52469
|
const lines = [];
|
|
52075
52470
|
try {
|
|
52076
|
-
const branch =
|
|
52471
|
+
const branch = execSync31("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
52077
52472
|
if (branch)
|
|
52078
52473
|
lines.push(`Branch: ${branch}`);
|
|
52079
52474
|
} catch {
|
|
52080
52475
|
}
|
|
52081
52476
|
try {
|
|
52082
|
-
const status =
|
|
52477
|
+
const status = execSync31("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
52083
52478
|
if (status) {
|
|
52084
52479
|
const changed = status.split("\n").length;
|
|
52085
52480
|
lines.push(`Working tree: ${changed} changed file(s)`);
|
|
@@ -52089,7 +52484,7 @@ function getGitInfo(repoRoot) {
|
|
|
52089
52484
|
} catch {
|
|
52090
52485
|
}
|
|
52091
52486
|
try {
|
|
52092
|
-
const log =
|
|
52487
|
+
const log = execSync31("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
52093
52488
|
if (log)
|
|
52094
52489
|
lines.push(`Recent commits:
|
|
52095
52490
|
${log}`);
|
|
@@ -52099,31 +52494,31 @@ ${log}`);
|
|
|
52099
52494
|
}
|
|
52100
52495
|
function loadMemoryContext(repoRoot) {
|
|
52101
52496
|
const sections = [];
|
|
52102
|
-
const oaMemDir =
|
|
52497
|
+
const oaMemDir = join60(repoRoot, OA_DIR, "memory");
|
|
52103
52498
|
const oaEntries = loadMemoryDir(oaMemDir, "project");
|
|
52104
52499
|
if (oaEntries)
|
|
52105
52500
|
sections.push(oaEntries);
|
|
52106
|
-
const legacyMemDir =
|
|
52107
|
-
if (legacyMemDir !== oaMemDir &&
|
|
52501
|
+
const legacyMemDir = join60(repoRoot, ".open-agents", "memory");
|
|
52502
|
+
if (legacyMemDir !== oaMemDir && existsSync44(legacyMemDir)) {
|
|
52108
52503
|
const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
|
|
52109
52504
|
if (legacyEntries)
|
|
52110
52505
|
sections.push(legacyEntries);
|
|
52111
52506
|
}
|
|
52112
|
-
const globalMemDir =
|
|
52507
|
+
const globalMemDir = join60(homedir17(), ".open-agents", "memory");
|
|
52113
52508
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
52114
52509
|
if (globalEntries)
|
|
52115
52510
|
sections.push(globalEntries);
|
|
52116
52511
|
return sections.join("\n\n");
|
|
52117
52512
|
}
|
|
52118
52513
|
function loadMemoryDir(memDir, scope) {
|
|
52119
|
-
if (!
|
|
52514
|
+
if (!existsSync44(memDir))
|
|
52120
52515
|
return "";
|
|
52121
52516
|
const lines = [];
|
|
52122
52517
|
try {
|
|
52123
52518
|
const files = readdirSync13(memDir).filter((f) => f.endsWith(".json"));
|
|
52124
52519
|
for (const file of files.slice(0, 10)) {
|
|
52125
52520
|
try {
|
|
52126
|
-
const raw =
|
|
52521
|
+
const raw = readFileSync33(join60(memDir, file), "utf-8");
|
|
52127
52522
|
const entries = JSON.parse(raw);
|
|
52128
52523
|
const topic = basename12(file, ".json");
|
|
52129
52524
|
const keys = Object.keys(entries);
|
|
@@ -53263,8 +53658,8 @@ __export(banner_exports, {
|
|
|
53263
53658
|
saveBannerDesign: () => saveBannerDesign,
|
|
53264
53659
|
setGridText: () => setGridText
|
|
53265
53660
|
});
|
|
53266
|
-
import { existsSync as
|
|
53267
|
-
import { join as
|
|
53661
|
+
import { existsSync as existsSync45, readFileSync as readFileSync34, writeFileSync as writeFileSync21, mkdirSync as mkdirSync20 } from "node:fs";
|
|
53662
|
+
import { join as join61 } from "node:path";
|
|
53268
53663
|
function generateMnemonic(seed) {
|
|
53269
53664
|
let h = 2166136261;
|
|
53270
53665
|
for (let i = 0; i < seed.length; i++) {
|
|
@@ -53459,23 +53854,23 @@ function createSponsorBanner(sponsorName, tagline, primaryColor = 214, bgColor =
|
|
|
53459
53854
|
};
|
|
53460
53855
|
}
|
|
53461
53856
|
function saveBannerDesign(workDir, design) {
|
|
53462
|
-
const dir =
|
|
53463
|
-
|
|
53464
|
-
|
|
53857
|
+
const dir = join61(workDir, ".oa", "banners");
|
|
53858
|
+
mkdirSync20(dir, { recursive: true });
|
|
53859
|
+
writeFileSync21(join61(dir, `${design.id}.json`), JSON.stringify(design, null, 2), "utf8");
|
|
53465
53860
|
}
|
|
53466
53861
|
function loadBannerDesign(workDir, id) {
|
|
53467
|
-
const file =
|
|
53468
|
-
if (!
|
|
53862
|
+
const file = join61(workDir, ".oa", "banners", `${id}.json`);
|
|
53863
|
+
if (!existsSync45(file))
|
|
53469
53864
|
return null;
|
|
53470
53865
|
try {
|
|
53471
|
-
return JSON.parse(
|
|
53866
|
+
return JSON.parse(readFileSync34(file, "utf8"));
|
|
53472
53867
|
} catch {
|
|
53473
53868
|
return null;
|
|
53474
53869
|
}
|
|
53475
53870
|
}
|
|
53476
53871
|
function listBannerDesigns(workDir) {
|
|
53477
|
-
const dir =
|
|
53478
|
-
if (!
|
|
53872
|
+
const dir = join61(workDir, ".oa", "banners");
|
|
53873
|
+
if (!existsSync45(dir))
|
|
53479
53874
|
return [];
|
|
53480
53875
|
try {
|
|
53481
53876
|
const { readdirSync: readdirSync23 } = __require("node:fs");
|
|
@@ -53833,22 +54228,22 @@ var init_banner = __esm({
|
|
|
53833
54228
|
});
|
|
53834
54229
|
|
|
53835
54230
|
// packages/cli/dist/tui/carousel-descriptors.js
|
|
53836
|
-
import { existsSync as
|
|
53837
|
-
import { join as
|
|
54231
|
+
import { existsSync as existsSync46, readFileSync as readFileSync35, writeFileSync as writeFileSync22, mkdirSync as mkdirSync21, readdirSync as readdirSync14 } from "node:fs";
|
|
54232
|
+
import { join as join62, basename as basename13 } from "node:path";
|
|
53838
54233
|
function loadToolProfile(repoRoot) {
|
|
53839
|
-
const filePath =
|
|
54234
|
+
const filePath = join62(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
53840
54235
|
try {
|
|
53841
|
-
if (!
|
|
54236
|
+
if (!existsSync46(filePath))
|
|
53842
54237
|
return null;
|
|
53843
|
-
return JSON.parse(
|
|
54238
|
+
return JSON.parse(readFileSync35(filePath, "utf-8"));
|
|
53844
54239
|
} catch {
|
|
53845
54240
|
return null;
|
|
53846
54241
|
}
|
|
53847
54242
|
}
|
|
53848
54243
|
function saveToolProfile(repoRoot, profile) {
|
|
53849
|
-
const contextDir =
|
|
53850
|
-
|
|
53851
|
-
|
|
54244
|
+
const contextDir = join62(repoRoot, OA_DIR, "context");
|
|
54245
|
+
mkdirSync21(contextDir, { recursive: true });
|
|
54246
|
+
writeFileSync22(join62(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
|
|
53852
54247
|
}
|
|
53853
54248
|
function categorizeToolCall(toolName) {
|
|
53854
54249
|
for (const cat of TOOL_CATEGORIES) {
|
|
@@ -53906,25 +54301,25 @@ function weightedColor(profile) {
|
|
|
53906
54301
|
return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
|
|
53907
54302
|
}
|
|
53908
54303
|
function loadCachedDescriptors(repoRoot) {
|
|
53909
|
-
const filePath =
|
|
54304
|
+
const filePath = join62(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
|
|
53910
54305
|
try {
|
|
53911
|
-
if (!
|
|
54306
|
+
if (!existsSync46(filePath))
|
|
53912
54307
|
return null;
|
|
53913
|
-
const cached = JSON.parse(
|
|
54308
|
+
const cached = JSON.parse(readFileSync35(filePath, "utf-8"));
|
|
53914
54309
|
return cached.phrases.length > 0 ? cached.phrases : null;
|
|
53915
54310
|
} catch {
|
|
53916
54311
|
return null;
|
|
53917
54312
|
}
|
|
53918
54313
|
}
|
|
53919
54314
|
function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
|
|
53920
|
-
const contextDir =
|
|
53921
|
-
|
|
54315
|
+
const contextDir = join62(repoRoot, OA_DIR, "context");
|
|
54316
|
+
mkdirSync21(contextDir, { recursive: true });
|
|
53922
54317
|
const cached = {
|
|
53923
54318
|
phrases,
|
|
53924
54319
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
53925
54320
|
sourceHash
|
|
53926
54321
|
};
|
|
53927
|
-
|
|
54322
|
+
writeFileSync22(join62(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
|
|
53928
54323
|
}
|
|
53929
54324
|
function generateDescriptors(repoRoot) {
|
|
53930
54325
|
const profile = loadToolProfile(repoRoot);
|
|
@@ -53972,11 +54367,11 @@ function generateDescriptors(repoRoot) {
|
|
|
53972
54367
|
return phrases;
|
|
53973
54368
|
}
|
|
53974
54369
|
function extractFromPackageJson(repoRoot, tags) {
|
|
53975
|
-
const pkgPath =
|
|
54370
|
+
const pkgPath = join62(repoRoot, "package.json");
|
|
53976
54371
|
try {
|
|
53977
|
-
if (!
|
|
54372
|
+
if (!existsSync46(pkgPath))
|
|
53978
54373
|
return;
|
|
53979
|
-
const pkg = JSON.parse(
|
|
54374
|
+
const pkg = JSON.parse(readFileSync35(pkgPath, "utf-8"));
|
|
53980
54375
|
if (pkg.name && typeof pkg.name === "string") {
|
|
53981
54376
|
const parts = pkg.name.replace(/^@/, "").split("/");
|
|
53982
54377
|
for (const p of parts)
|
|
@@ -54020,7 +54415,7 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
54020
54415
|
{ file: ".github/workflows", tag: "ci/cd" }
|
|
54021
54416
|
];
|
|
54022
54417
|
for (const check of manifestChecks) {
|
|
54023
|
-
if (
|
|
54418
|
+
if (existsSync46(join62(repoRoot, check.file))) {
|
|
54024
54419
|
tags.push(check.tag);
|
|
54025
54420
|
}
|
|
54026
54421
|
}
|
|
@@ -54042,16 +54437,16 @@ function extractFromSessions(repoRoot, tags) {
|
|
|
54042
54437
|
}
|
|
54043
54438
|
}
|
|
54044
54439
|
function extractFromMemory(repoRoot, tags) {
|
|
54045
|
-
const memoryDir =
|
|
54440
|
+
const memoryDir = join62(repoRoot, OA_DIR, "memory");
|
|
54046
54441
|
try {
|
|
54047
|
-
if (!
|
|
54442
|
+
if (!existsSync46(memoryDir))
|
|
54048
54443
|
return;
|
|
54049
54444
|
const files = readdirSync14(memoryDir).filter((f) => f.endsWith(".json"));
|
|
54050
54445
|
for (const file of files) {
|
|
54051
54446
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
54052
54447
|
tags.push(topic);
|
|
54053
54448
|
try {
|
|
54054
|
-
const data = JSON.parse(
|
|
54449
|
+
const data = JSON.parse(readFileSync35(join62(memoryDir, file), "utf-8"));
|
|
54055
54450
|
if (data && typeof data === "object") {
|
|
54056
54451
|
const keys = Object.keys(data).slice(0, 3);
|
|
54057
54452
|
for (const key of keys) {
|
|
@@ -54722,13 +55117,13 @@ var init_stream_renderer = __esm({
|
|
|
54722
55117
|
});
|
|
54723
55118
|
|
|
54724
55119
|
// packages/cli/dist/tui/edit-history.js
|
|
54725
|
-
import { appendFileSync as appendFileSync3, mkdirSync as
|
|
54726
|
-
import { join as
|
|
55120
|
+
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync22 } from "node:fs";
|
|
55121
|
+
import { join as join63 } from "node:path";
|
|
54727
55122
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
54728
|
-
const historyDir =
|
|
54729
|
-
const logPath2 =
|
|
55123
|
+
const historyDir = join63(repoRoot, ".oa", "history");
|
|
55124
|
+
const logPath2 = join63(historyDir, "edits.jsonl");
|
|
54730
55125
|
try {
|
|
54731
|
-
|
|
55126
|
+
mkdirSync22(historyDir, { recursive: true });
|
|
54732
55127
|
} catch {
|
|
54733
55128
|
}
|
|
54734
55129
|
function logToolCall(toolName, toolArgs, success) {
|
|
@@ -54837,17 +55232,17 @@ var init_edit_history = __esm({
|
|
|
54837
55232
|
});
|
|
54838
55233
|
|
|
54839
55234
|
// packages/cli/dist/tui/promptLoader.js
|
|
54840
|
-
import { readFileSync as
|
|
54841
|
-
import { join as
|
|
55235
|
+
import { readFileSync as readFileSync36, existsSync as existsSync47 } from "node:fs";
|
|
55236
|
+
import { join as join64, dirname as dirname19 } from "node:path";
|
|
54842
55237
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
54843
55238
|
function loadPrompt3(promptPath, vars) {
|
|
54844
55239
|
let content = cache3.get(promptPath);
|
|
54845
55240
|
if (content === void 0) {
|
|
54846
|
-
const fullPath =
|
|
54847
|
-
if (!
|
|
55241
|
+
const fullPath = join64(PROMPTS_DIR3, promptPath);
|
|
55242
|
+
if (!existsSync47(fullPath)) {
|
|
54848
55243
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
54849
55244
|
}
|
|
54850
|
-
content =
|
|
55245
|
+
content = readFileSync36(fullPath, "utf-8");
|
|
54851
55246
|
cache3.set(promptPath, content);
|
|
54852
55247
|
}
|
|
54853
55248
|
if (!vars)
|
|
@@ -54860,23 +55255,23 @@ var init_promptLoader3 = __esm({
|
|
|
54860
55255
|
"use strict";
|
|
54861
55256
|
__filename3 = fileURLToPath11(import.meta.url);
|
|
54862
55257
|
__dirname6 = dirname19(__filename3);
|
|
54863
|
-
devPath2 =
|
|
54864
|
-
publishedPath2 =
|
|
54865
|
-
PROMPTS_DIR3 =
|
|
55258
|
+
devPath2 = join64(__dirname6, "..", "..", "prompts");
|
|
55259
|
+
publishedPath2 = join64(__dirname6, "..", "prompts");
|
|
55260
|
+
PROMPTS_DIR3 = existsSync47(devPath2) ? devPath2 : publishedPath2;
|
|
54866
55261
|
cache3 = /* @__PURE__ */ new Map();
|
|
54867
55262
|
}
|
|
54868
55263
|
});
|
|
54869
55264
|
|
|
54870
55265
|
// packages/cli/dist/tui/dream-engine.js
|
|
54871
|
-
import { mkdirSync as
|
|
54872
|
-
import { join as
|
|
54873
|
-
import { execSync as
|
|
55266
|
+
import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync23, readFileSync as readFileSync37, existsSync as existsSync48, cpSync, rmSync as rmSync2, readdirSync as readdirSync15 } from "node:fs";
|
|
55267
|
+
import { join as join65, basename as basename14 } from "node:path";
|
|
55268
|
+
import { execSync as execSync32 } from "node:child_process";
|
|
54874
55269
|
function loadAutoresearchMemory(repoRoot) {
|
|
54875
|
-
const memoryPath =
|
|
54876
|
-
if (!
|
|
55270
|
+
const memoryPath = join65(repoRoot, ".oa", "memory", "autoresearch.json");
|
|
55271
|
+
if (!existsSync48(memoryPath))
|
|
54877
55272
|
return "";
|
|
54878
55273
|
try {
|
|
54879
|
-
const raw =
|
|
55274
|
+
const raw = readFileSync37(memoryPath, "utf-8");
|
|
54880
55275
|
const data = JSON.parse(raw);
|
|
54881
55276
|
const sections = [];
|
|
54882
55277
|
for (const key of AUTORESEARCH_MEMORY_KEYS) {
|
|
@@ -55066,14 +55461,14 @@ var init_dream_engine = __esm({
|
|
|
55066
55461
|
const content = String(args["content"] ?? "");
|
|
55067
55462
|
if (!rawPath)
|
|
55068
55463
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
55069
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
55464
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join65(this.autoresearchDir, basename14(rawPath)) : join65(this.autoresearchDir, rawPath);
|
|
55070
55465
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
55071
55466
|
return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
|
|
55072
55467
|
}
|
|
55073
55468
|
try {
|
|
55074
|
-
const dir =
|
|
55075
|
-
|
|
55076
|
-
|
|
55469
|
+
const dir = join65(targetPath, "..");
|
|
55470
|
+
mkdirSync23(dir, { recursive: true });
|
|
55471
|
+
writeFileSync23(targetPath, content, "utf-8");
|
|
55077
55472
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
55078
55473
|
} catch (err) {
|
|
55079
55474
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -55101,20 +55496,20 @@ var init_dream_engine = __esm({
|
|
|
55101
55496
|
const rawPath = String(args["path"] ?? "");
|
|
55102
55497
|
const oldStr = String(args["old_string"] ?? "");
|
|
55103
55498
|
const newStr = String(args["new_string"] ?? "");
|
|
55104
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
55499
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join65(this.autoresearchDir, basename14(rawPath)) : join65(this.autoresearchDir, rawPath);
|
|
55105
55500
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
55106
55501
|
return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
|
|
55107
55502
|
}
|
|
55108
55503
|
try {
|
|
55109
|
-
if (!
|
|
55504
|
+
if (!existsSync48(targetPath)) {
|
|
55110
55505
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
55111
55506
|
}
|
|
55112
|
-
let content =
|
|
55507
|
+
let content = readFileSync37(targetPath, "utf-8");
|
|
55113
55508
|
if (!content.includes(oldStr)) {
|
|
55114
55509
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
55115
55510
|
}
|
|
55116
55511
|
content = content.replace(oldStr, newStr);
|
|
55117
|
-
|
|
55512
|
+
writeFileSync23(targetPath, content, "utf-8");
|
|
55118
55513
|
return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
|
|
55119
55514
|
} catch (err) {
|
|
55120
55515
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -55155,14 +55550,14 @@ var init_dream_engine = __esm({
|
|
|
55155
55550
|
const content = String(args["content"] ?? "");
|
|
55156
55551
|
if (!rawPath)
|
|
55157
55552
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
55158
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
55553
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join65(this.dreamsDir, basename14(rawPath)) : join65(this.dreamsDir, rawPath);
|
|
55159
55554
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
55160
55555
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
55161
55556
|
}
|
|
55162
55557
|
try {
|
|
55163
|
-
const dir =
|
|
55164
|
-
|
|
55165
|
-
|
|
55558
|
+
const dir = join65(targetPath, "..");
|
|
55559
|
+
mkdirSync23(dir, { recursive: true });
|
|
55560
|
+
writeFileSync23(targetPath, content, "utf-8");
|
|
55166
55561
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
55167
55562
|
} catch (err) {
|
|
55168
55563
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -55190,20 +55585,20 @@ var init_dream_engine = __esm({
|
|
|
55190
55585
|
const rawPath = String(args["path"] ?? "");
|
|
55191
55586
|
const oldStr = String(args["old_string"] ?? "");
|
|
55192
55587
|
const newStr = String(args["new_string"] ?? "");
|
|
55193
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
55588
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join65(this.dreamsDir, basename14(rawPath)) : join65(this.dreamsDir, rawPath);
|
|
55194
55589
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
55195
55590
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
55196
55591
|
}
|
|
55197
55592
|
try {
|
|
55198
|
-
if (!
|
|
55593
|
+
if (!existsSync48(targetPath)) {
|
|
55199
55594
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
55200
55595
|
}
|
|
55201
|
-
let content =
|
|
55596
|
+
let content = readFileSync37(targetPath, "utf-8");
|
|
55202
55597
|
if (!content.includes(oldStr)) {
|
|
55203
55598
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
55204
55599
|
}
|
|
55205
55600
|
content = content.replace(oldStr, newStr);
|
|
55206
|
-
|
|
55601
|
+
writeFileSync23(targetPath, content, "utf-8");
|
|
55207
55602
|
return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
|
|
55208
55603
|
} catch (err) {
|
|
55209
55604
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -55234,7 +55629,7 @@ var init_dream_engine = __esm({
|
|
|
55234
55629
|
}
|
|
55235
55630
|
}
|
|
55236
55631
|
try {
|
|
55237
|
-
const output =
|
|
55632
|
+
const output = execSync32(cmd, {
|
|
55238
55633
|
cwd: this.repoRoot,
|
|
55239
55634
|
timeout: 3e4,
|
|
55240
55635
|
encoding: "utf-8",
|
|
@@ -55257,7 +55652,7 @@ var init_dream_engine = __esm({
|
|
|
55257
55652
|
constructor(config, repoRoot) {
|
|
55258
55653
|
this.config = config;
|
|
55259
55654
|
this.repoRoot = repoRoot;
|
|
55260
|
-
this.dreamsDir =
|
|
55655
|
+
this.dreamsDir = join65(repoRoot, ".oa", "dreams");
|
|
55261
55656
|
this.state = {
|
|
55262
55657
|
mode: "default",
|
|
55263
55658
|
active: false,
|
|
@@ -55288,7 +55683,7 @@ var init_dream_engine = __esm({
|
|
|
55288
55683
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
55289
55684
|
results: []
|
|
55290
55685
|
};
|
|
55291
|
-
|
|
55686
|
+
mkdirSync23(this.dreamsDir, { recursive: true });
|
|
55292
55687
|
this.saveDreamState();
|
|
55293
55688
|
try {
|
|
55294
55689
|
for (let cycle = 1; cycle <= totalCycles; cycle++) {
|
|
@@ -55341,8 +55736,8 @@ ${result.summary}`;
|
|
|
55341
55736
|
if (mode !== "default" || cycle === totalCycles) {
|
|
55342
55737
|
renderDreamContraction(cycle);
|
|
55343
55738
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
55344
|
-
const summaryPath =
|
|
55345
|
-
|
|
55739
|
+
const summaryPath = join65(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
55740
|
+
writeFileSync23(summaryPath, cycleSummary, "utf-8");
|
|
55346
55741
|
}
|
|
55347
55742
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
55348
55743
|
this.saveVersionCheckpoint(cycle);
|
|
@@ -55554,7 +55949,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
|
|
|
55554
55949
|
}
|
|
55555
55950
|
/** Build role-specific tool sets for swarm agents */
|
|
55556
55951
|
buildSwarmTools(role, _workspace) {
|
|
55557
|
-
const autoresearchDir =
|
|
55952
|
+
const autoresearchDir = join65(this.repoRoot, ".oa", "autoresearch");
|
|
55558
55953
|
const taskComplete = this.createSwarmTaskCompleteTool(role);
|
|
55559
55954
|
switch (role) {
|
|
55560
55955
|
case "researcher": {
|
|
@@ -55918,7 +56313,7 @@ INSTRUCTIONS:
|
|
|
55918
56313
|
2. Summarize the key learnings and next steps
|
|
55919
56314
|
|
|
55920
56315
|
Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
|
|
55921
|
-
const reportPath =
|
|
56316
|
+
const reportPath = join65(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
|
|
55922
56317
|
const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
|
|
55923
56318
|
|
|
55924
56319
|
**Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -55940,8 +56335,8 @@ ${summaryResult}
|
|
|
55940
56335
|
*Generated by open-agents autoresearch swarm*
|
|
55941
56336
|
`;
|
|
55942
56337
|
try {
|
|
55943
|
-
|
|
55944
|
-
|
|
56338
|
+
mkdirSync23(this.dreamsDir, { recursive: true });
|
|
56339
|
+
writeFileSync23(reportPath, report, "utf-8");
|
|
55945
56340
|
} catch {
|
|
55946
56341
|
}
|
|
55947
56342
|
renderSwarmComplete(workspace);
|
|
@@ -56007,29 +56402,29 @@ ${summaryResult}
|
|
|
56007
56402
|
}
|
|
56008
56403
|
/** Save workspace backup for lucid mode */
|
|
56009
56404
|
saveVersionCheckpoint(cycle) {
|
|
56010
|
-
const checkpointDir =
|
|
56405
|
+
const checkpointDir = join65(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
56011
56406
|
try {
|
|
56012
|
-
|
|
56407
|
+
mkdirSync23(checkpointDir, { recursive: true });
|
|
56013
56408
|
try {
|
|
56014
|
-
const gitStatus =
|
|
56409
|
+
const gitStatus = execSync32("git status --porcelain", {
|
|
56015
56410
|
cwd: this.repoRoot,
|
|
56016
56411
|
encoding: "utf-8",
|
|
56017
56412
|
timeout: 1e4
|
|
56018
56413
|
});
|
|
56019
|
-
const gitDiff =
|
|
56414
|
+
const gitDiff = execSync32("git diff", {
|
|
56020
56415
|
cwd: this.repoRoot,
|
|
56021
56416
|
encoding: "utf-8",
|
|
56022
56417
|
timeout: 1e4
|
|
56023
56418
|
});
|
|
56024
|
-
const gitHash =
|
|
56419
|
+
const gitHash = execSync32("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
|
|
56025
56420
|
cwd: this.repoRoot,
|
|
56026
56421
|
encoding: "utf-8",
|
|
56027
56422
|
timeout: 5e3
|
|
56028
56423
|
}).trim();
|
|
56029
|
-
|
|
56030
|
-
|
|
56031
|
-
|
|
56032
|
-
|
|
56424
|
+
writeFileSync23(join65(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
|
|
56425
|
+
writeFileSync23(join65(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
|
|
56426
|
+
writeFileSync23(join65(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
|
|
56427
|
+
writeFileSync23(join65(checkpointDir, "checkpoint.json"), JSON.stringify({
|
|
56033
56428
|
cycle,
|
|
56034
56429
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
56035
56430
|
gitHash,
|
|
@@ -56037,7 +56432,7 @@ ${summaryResult}
|
|
|
56037
56432
|
}, null, 2), "utf-8");
|
|
56038
56433
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
56039
56434
|
} catch {
|
|
56040
|
-
|
|
56435
|
+
writeFileSync23(join65(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
|
|
56041
56436
|
renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
|
|
56042
56437
|
}
|
|
56043
56438
|
} catch (err) {
|
|
@@ -56095,14 +56490,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
|
|
|
56095
56490
|
---
|
|
56096
56491
|
*Auto-generated by open-agents dream engine*
|
|
56097
56492
|
`;
|
|
56098
|
-
|
|
56493
|
+
writeFileSync23(join65(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
56099
56494
|
} catch {
|
|
56100
56495
|
}
|
|
56101
56496
|
}
|
|
56102
56497
|
/** Save dream state for resume/inspection */
|
|
56103
56498
|
saveDreamState() {
|
|
56104
56499
|
try {
|
|
56105
|
-
|
|
56500
|
+
writeFileSync23(join65(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
56106
56501
|
} catch {
|
|
56107
56502
|
}
|
|
56108
56503
|
}
|
|
@@ -56476,8 +56871,8 @@ var init_bless_engine = __esm({
|
|
|
56476
56871
|
});
|
|
56477
56872
|
|
|
56478
56873
|
// packages/cli/dist/tui/dmn-engine.js
|
|
56479
|
-
import { existsSync as
|
|
56480
|
-
import { join as
|
|
56874
|
+
import { existsSync as existsSync49, readFileSync as readFileSync38, writeFileSync as writeFileSync24, mkdirSync as mkdirSync24, readdirSync as readdirSync16, unlinkSync as unlinkSync10 } from "node:fs";
|
|
56875
|
+
import { join as join66, basename as basename15 } from "node:path";
|
|
56481
56876
|
function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
|
|
56482
56877
|
const competenceReport = competence.length > 0 ? competence.map((c3) => {
|
|
56483
56878
|
const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
|
|
@@ -56597,9 +56992,9 @@ var init_dmn_engine = __esm({
|
|
|
56597
56992
|
constructor(config, repoRoot) {
|
|
56598
56993
|
this.config = config;
|
|
56599
56994
|
this.repoRoot = repoRoot;
|
|
56600
|
-
this.stateDir =
|
|
56601
|
-
this.historyDir =
|
|
56602
|
-
|
|
56995
|
+
this.stateDir = join66(repoRoot, ".oa", "dmn");
|
|
56996
|
+
this.historyDir = join66(repoRoot, ".oa", "dmn", "cycles");
|
|
56997
|
+
mkdirSync24(this.historyDir, { recursive: true });
|
|
56603
56998
|
this.loadState();
|
|
56604
56999
|
}
|
|
56605
57000
|
get stats() {
|
|
@@ -57188,11 +57583,11 @@ OUTPUT: Call task_complete with JSON:
|
|
|
57188
57583
|
async gatherMemoryTopics() {
|
|
57189
57584
|
const topics = [];
|
|
57190
57585
|
const dirs = [
|
|
57191
|
-
|
|
57192
|
-
|
|
57586
|
+
join66(this.repoRoot, ".oa", "memory"),
|
|
57587
|
+
join66(this.repoRoot, ".open-agents", "memory")
|
|
57193
57588
|
];
|
|
57194
57589
|
for (const dir of dirs) {
|
|
57195
|
-
if (!
|
|
57590
|
+
if (!existsSync49(dir))
|
|
57196
57591
|
continue;
|
|
57197
57592
|
try {
|
|
57198
57593
|
const files = readdirSync16(dir).filter((f) => f.endsWith(".json"));
|
|
@@ -57208,29 +57603,29 @@ OUTPUT: Call task_complete with JSON:
|
|
|
57208
57603
|
}
|
|
57209
57604
|
// ── State persistence ─────────────────────────────────────────────────
|
|
57210
57605
|
loadState() {
|
|
57211
|
-
const path =
|
|
57212
|
-
if (
|
|
57606
|
+
const path = join66(this.stateDir, "state.json");
|
|
57607
|
+
if (existsSync49(path)) {
|
|
57213
57608
|
try {
|
|
57214
|
-
this.state = JSON.parse(
|
|
57609
|
+
this.state = JSON.parse(readFileSync38(path, "utf-8"));
|
|
57215
57610
|
} catch {
|
|
57216
57611
|
}
|
|
57217
57612
|
}
|
|
57218
57613
|
}
|
|
57219
57614
|
saveState() {
|
|
57220
57615
|
try {
|
|
57221
|
-
|
|
57616
|
+
writeFileSync24(join66(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
57222
57617
|
} catch {
|
|
57223
57618
|
}
|
|
57224
57619
|
}
|
|
57225
57620
|
saveCycleResult(result) {
|
|
57226
57621
|
try {
|
|
57227
57622
|
const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
|
|
57228
|
-
|
|
57623
|
+
writeFileSync24(join66(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
|
|
57229
57624
|
const files = readdirSync16(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
|
|
57230
57625
|
if (files.length > 50) {
|
|
57231
57626
|
for (const old of files.slice(0, files.length - 50)) {
|
|
57232
57627
|
try {
|
|
57233
|
-
unlinkSync10(
|
|
57628
|
+
unlinkSync10(join66(this.historyDir, old));
|
|
57234
57629
|
} catch {
|
|
57235
57630
|
}
|
|
57236
57631
|
}
|
|
@@ -57243,8 +57638,8 @@ OUTPUT: Call task_complete with JSON:
|
|
|
57243
57638
|
});
|
|
57244
57639
|
|
|
57245
57640
|
// packages/cli/dist/tui/snr-engine.js
|
|
57246
|
-
import { existsSync as
|
|
57247
|
-
import { join as
|
|
57641
|
+
import { existsSync as existsSync50, readdirSync as readdirSync17, readFileSync as readFileSync39 } from "node:fs";
|
|
57642
|
+
import { join as join67, basename as basename16 } from "node:path";
|
|
57248
57643
|
function computeDPrime(signalScores, noiseScores) {
|
|
57249
57644
|
if (signalScores.length === 0 || noiseScores.length === 0)
|
|
57250
57645
|
return 0;
|
|
@@ -57484,11 +57879,11 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
57484
57879
|
loadMemoryEntries(topics) {
|
|
57485
57880
|
const entries = [];
|
|
57486
57881
|
const dirs = [
|
|
57487
|
-
|
|
57488
|
-
|
|
57882
|
+
join67(this.repoRoot, ".oa", "memory"),
|
|
57883
|
+
join67(this.repoRoot, ".open-agents", "memory")
|
|
57489
57884
|
];
|
|
57490
57885
|
for (const dir of dirs) {
|
|
57491
|
-
if (!
|
|
57886
|
+
if (!existsSync50(dir))
|
|
57492
57887
|
continue;
|
|
57493
57888
|
try {
|
|
57494
57889
|
const files = readdirSync17(dir).filter((f) => f.endsWith(".json"));
|
|
@@ -57497,7 +57892,7 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
57497
57892
|
if (topics.length > 0 && !topics.includes(topic))
|
|
57498
57893
|
continue;
|
|
57499
57894
|
try {
|
|
57500
|
-
const data = JSON.parse(
|
|
57895
|
+
const data = JSON.parse(readFileSync39(join67(dir, f), "utf-8"));
|
|
57501
57896
|
for (const [key, val] of Object.entries(data)) {
|
|
57502
57897
|
const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
57503
57898
|
entries.push({ topic, key, value });
|
|
@@ -58064,8 +58459,8 @@ var init_tool_policy = __esm({
|
|
|
58064
58459
|
});
|
|
58065
58460
|
|
|
58066
58461
|
// packages/cli/dist/tui/telegram-bridge.js
|
|
58067
|
-
import { mkdirSync as
|
|
58068
|
-
import { join as
|
|
58462
|
+
import { mkdirSync as mkdirSync25, existsSync as existsSync51, unlinkSync as unlinkSync11, readdirSync as readdirSync18, statSync as statSync15 } from "node:fs";
|
|
58463
|
+
import { join as join68, resolve as resolve30 } from "node:path";
|
|
58069
58464
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
58070
58465
|
function convertMarkdownToTelegramHTML(md) {
|
|
58071
58466
|
let html = md;
|
|
@@ -58393,7 +58788,7 @@ with summary "no_reply" to silently skip without responding.
|
|
|
58393
58788
|
this.polling = true;
|
|
58394
58789
|
this.abortController = new AbortController();
|
|
58395
58790
|
try {
|
|
58396
|
-
|
|
58791
|
+
mkdirSync25(this.mediaCacheDir, { recursive: true });
|
|
58397
58792
|
} catch {
|
|
58398
58793
|
}
|
|
58399
58794
|
this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
|
|
@@ -58830,7 +59225,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
|
|
|
58830
59225
|
return null;
|
|
58831
59226
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
58832
59227
|
const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
|
|
58833
|
-
const localPath =
|
|
59228
|
+
const localPath = join68(this.mediaCacheDir, fileName);
|
|
58834
59229
|
await writeFileAsync(localPath, buffer);
|
|
58835
59230
|
return localPath;
|
|
58836
59231
|
} catch {
|
|
@@ -59846,7 +60241,7 @@ __export(text_selection_exports, {
|
|
|
59846
60241
|
stripAnsi: () => stripAnsi3,
|
|
59847
60242
|
visibleLength: () => visibleLength
|
|
59848
60243
|
});
|
|
59849
|
-
import { execSync as
|
|
60244
|
+
import { execSync as execSync33 } from "node:child_process";
|
|
59850
60245
|
function stripAnsi3(s) {
|
|
59851
60246
|
return s.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\)/g, "");
|
|
59852
60247
|
}
|
|
@@ -59857,16 +60252,16 @@ function copyText(text) {
|
|
|
59857
60252
|
try {
|
|
59858
60253
|
const platform6 = process.platform;
|
|
59859
60254
|
if (platform6 === "darwin") {
|
|
59860
|
-
|
|
60255
|
+
execSync33("pbcopy", { input: text, timeout: 3e3 });
|
|
59861
60256
|
return true;
|
|
59862
60257
|
}
|
|
59863
60258
|
if (platform6 === "win32") {
|
|
59864
|
-
|
|
60259
|
+
execSync33("clip", { input: text, timeout: 3e3 });
|
|
59865
60260
|
return true;
|
|
59866
60261
|
}
|
|
59867
60262
|
for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
|
|
59868
60263
|
try {
|
|
59869
|
-
|
|
60264
|
+
execSync33(tool, { input: text, timeout: 3e3 });
|
|
59870
60265
|
return true;
|
|
59871
60266
|
} catch {
|
|
59872
60267
|
continue;
|
|
@@ -59875,10 +60270,10 @@ function copyText(text) {
|
|
|
59875
60270
|
if (!_clipboardAutoInstallAttempted) {
|
|
59876
60271
|
_clipboardAutoInstallAttempted = true;
|
|
59877
60272
|
try {
|
|
59878
|
-
|
|
60273
|
+
execSync33("which apt-get", { timeout: 2e3, stdio: "pipe" });
|
|
59879
60274
|
try {
|
|
59880
|
-
|
|
59881
|
-
|
|
60275
|
+
execSync33("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
|
|
60276
|
+
execSync33("xclip -selection clipboard", { input: text, timeout: 3e3 });
|
|
59882
60277
|
return true;
|
|
59883
60278
|
} catch {
|
|
59884
60279
|
}
|
|
@@ -60186,7 +60581,7 @@ var init_text_selection = __esm({
|
|
|
60186
60581
|
});
|
|
60187
60582
|
|
|
60188
60583
|
// packages/cli/dist/tui/status-bar.js
|
|
60189
|
-
import { readFileSync as
|
|
60584
|
+
import { readFileSync as readFileSync40 } from "node:fs";
|
|
60190
60585
|
function setTerminalTitle(task, version) {
|
|
60191
60586
|
if (!process.stdout.isTTY)
|
|
60192
60587
|
return;
|
|
@@ -60883,7 +61278,7 @@ var init_status_bar = __esm({
|
|
|
60883
61278
|
if (nexusDir) {
|
|
60884
61279
|
try {
|
|
60885
61280
|
const metricsPath = nexusDir + "/remote-metrics.json";
|
|
60886
|
-
const raw =
|
|
61281
|
+
const raw = readFileSync40(metricsPath, "utf8");
|
|
60887
61282
|
const cached = JSON.parse(raw);
|
|
60888
61283
|
if (cached && cached.ts && Date.now() - cached.ts < 6e4) {
|
|
60889
61284
|
const m = cached.data;
|
|
@@ -63176,24 +63571,24 @@ var init_direct_input = __esm({
|
|
|
63176
63571
|
});
|
|
63177
63572
|
|
|
63178
63573
|
// packages/cli/dist/api/profiles.js
|
|
63179
|
-
import { existsSync as
|
|
63180
|
-
import { join as
|
|
63181
|
-
import { homedir as
|
|
63574
|
+
import { existsSync as existsSync52, readFileSync as readFileSync41, writeFileSync as writeFileSync25, mkdirSync as mkdirSync26, readdirSync as readdirSync19, unlinkSync as unlinkSync12 } from "node:fs";
|
|
63575
|
+
import { join as join69 } from "node:path";
|
|
63576
|
+
import { homedir as homedir18 } from "node:os";
|
|
63182
63577
|
import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes15, scryptSync as scryptSync3, createHash as createHash5 } from "node:crypto";
|
|
63183
63578
|
function globalProfileDir() {
|
|
63184
|
-
return
|
|
63579
|
+
return join69(homedir18(), ".open-agents", "profiles");
|
|
63185
63580
|
}
|
|
63186
63581
|
function projectProfileDir(projectDir) {
|
|
63187
|
-
return
|
|
63582
|
+
return join69(projectDir || process.cwd(), ".oa", "profiles");
|
|
63188
63583
|
}
|
|
63189
63584
|
function listProfiles(projectDir) {
|
|
63190
63585
|
const result = [];
|
|
63191
63586
|
const seen = /* @__PURE__ */ new Set();
|
|
63192
63587
|
const projDir = projectProfileDir(projectDir);
|
|
63193
|
-
if (
|
|
63588
|
+
if (existsSync52(projDir)) {
|
|
63194
63589
|
for (const f of readdirSync19(projDir).filter((f2) => f2.endsWith(".json"))) {
|
|
63195
63590
|
try {
|
|
63196
|
-
const raw = JSON.parse(
|
|
63591
|
+
const raw = JSON.parse(readFileSync41(join69(projDir, f), "utf8"));
|
|
63197
63592
|
const name = f.replace(".json", "");
|
|
63198
63593
|
seen.add(name);
|
|
63199
63594
|
result.push({
|
|
@@ -63207,13 +63602,13 @@ function listProfiles(projectDir) {
|
|
|
63207
63602
|
}
|
|
63208
63603
|
}
|
|
63209
63604
|
const globDir = globalProfileDir();
|
|
63210
|
-
if (
|
|
63605
|
+
if (existsSync52(globDir)) {
|
|
63211
63606
|
for (const f of readdirSync19(globDir).filter((f2) => f2.endsWith(".json"))) {
|
|
63212
63607
|
const name = f.replace(".json", "");
|
|
63213
63608
|
if (seen.has(name))
|
|
63214
63609
|
continue;
|
|
63215
63610
|
try {
|
|
63216
|
-
const raw = JSON.parse(
|
|
63611
|
+
const raw = JSON.parse(readFileSync41(join69(globDir, f), "utf8"));
|
|
63217
63612
|
result.push({
|
|
63218
63613
|
name,
|
|
63219
63614
|
description: raw.description || "",
|
|
@@ -63228,12 +63623,12 @@ function listProfiles(projectDir) {
|
|
|
63228
63623
|
}
|
|
63229
63624
|
function loadProfile(name, password, projectDir) {
|
|
63230
63625
|
const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
63231
|
-
const projPath =
|
|
63232
|
-
const globPath =
|
|
63233
|
-
const filePath =
|
|
63626
|
+
const projPath = join69(projectProfileDir(projectDir), `${sanitized}.json`);
|
|
63627
|
+
const globPath = join69(globalProfileDir(), `${sanitized}.json`);
|
|
63628
|
+
const filePath = existsSync52(projPath) ? projPath : existsSync52(globPath) ? globPath : null;
|
|
63234
63629
|
if (!filePath)
|
|
63235
63630
|
return null;
|
|
63236
|
-
const raw = JSON.parse(
|
|
63631
|
+
const raw = JSON.parse(readFileSync41(filePath, "utf8"));
|
|
63237
63632
|
if (raw.encrypted === true) {
|
|
63238
63633
|
if (!password)
|
|
63239
63634
|
return null;
|
|
@@ -63243,23 +63638,23 @@ function loadProfile(name, password, projectDir) {
|
|
|
63243
63638
|
}
|
|
63244
63639
|
function saveProfile(profile, password, scope = "global", projectDir) {
|
|
63245
63640
|
const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
|
|
63246
|
-
|
|
63641
|
+
mkdirSync26(dir, { recursive: true });
|
|
63247
63642
|
const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
63248
|
-
const filePath =
|
|
63643
|
+
const filePath = join69(dir, `${sanitized}.json`);
|
|
63249
63644
|
profile.modified = (/* @__PURE__ */ new Date()).toISOString();
|
|
63250
63645
|
if (password) {
|
|
63251
63646
|
const encrypted = encryptProfile(profile, password);
|
|
63252
|
-
|
|
63647
|
+
writeFileSync25(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
63253
63648
|
} else {
|
|
63254
63649
|
profile.encrypted = false;
|
|
63255
|
-
|
|
63650
|
+
writeFileSync25(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
|
|
63256
63651
|
}
|
|
63257
63652
|
}
|
|
63258
63653
|
function deleteProfile(name, scope = "global", projectDir) {
|
|
63259
63654
|
const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
63260
63655
|
const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
|
|
63261
|
-
const filePath =
|
|
63262
|
-
if (
|
|
63656
|
+
const filePath = join69(dir, `${sanitized}.json`);
|
|
63657
|
+
if (existsSync52(filePath)) {
|
|
63263
63658
|
unlinkSync12(filePath);
|
|
63264
63659
|
return true;
|
|
63265
63660
|
}
|
|
@@ -63352,22 +63747,22 @@ import * as http from "node:http";
|
|
|
63352
63747
|
import * as https from "node:https";
|
|
63353
63748
|
import { createRequire as createRequire3 } from "node:module";
|
|
63354
63749
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
63355
|
-
import { dirname as dirname20, join as
|
|
63356
|
-
import { spawn as
|
|
63357
|
-
import { mkdirSync as
|
|
63750
|
+
import { dirname as dirname20, join as join70, resolve as resolve31 } from "node:path";
|
|
63751
|
+
import { spawn as spawn21 } from "node:child_process";
|
|
63752
|
+
import { mkdirSync as mkdirSync27, writeFileSync as writeFileSync26, readFileSync as readFileSync42, readdirSync as readdirSync20, existsSync as existsSync53 } from "node:fs";
|
|
63358
63753
|
import { randomBytes as randomBytes16 } from "node:crypto";
|
|
63359
63754
|
function getVersion3() {
|
|
63360
63755
|
try {
|
|
63361
63756
|
const require2 = createRequire3(import.meta.url);
|
|
63362
63757
|
const thisDir = dirname20(fileURLToPath12(import.meta.url));
|
|
63363
63758
|
const candidates = [
|
|
63364
|
-
|
|
63365
|
-
|
|
63366
|
-
|
|
63759
|
+
join70(thisDir, "..", "package.json"),
|
|
63760
|
+
join70(thisDir, "..", "..", "package.json"),
|
|
63761
|
+
join70(thisDir, "..", "..", "..", "package.json")
|
|
63367
63762
|
];
|
|
63368
63763
|
for (const pkgPath of candidates) {
|
|
63369
63764
|
try {
|
|
63370
|
-
if (!
|
|
63765
|
+
if (!existsSync53(pkgPath))
|
|
63371
63766
|
continue;
|
|
63372
63767
|
const pkg = require2(pkgPath);
|
|
63373
63768
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
|
|
@@ -63662,29 +64057,29 @@ function ollamaStream(ollamaUrl, path, method, body, onData, onEnd, onError) {
|
|
|
63662
64057
|
}
|
|
63663
64058
|
function jobsDir() {
|
|
63664
64059
|
const root = resolve31(process.cwd());
|
|
63665
|
-
const dir =
|
|
63666
|
-
|
|
64060
|
+
const dir = join70(root, ".oa", "jobs");
|
|
64061
|
+
mkdirSync27(dir, { recursive: true });
|
|
63667
64062
|
return dir;
|
|
63668
64063
|
}
|
|
63669
64064
|
function loadJob(id) {
|
|
63670
|
-
const file =
|
|
63671
|
-
if (!
|
|
64065
|
+
const file = join70(jobsDir(), `${id}.json`);
|
|
64066
|
+
if (!existsSync53(file))
|
|
63672
64067
|
return null;
|
|
63673
64068
|
try {
|
|
63674
|
-
return JSON.parse(
|
|
64069
|
+
return JSON.parse(readFileSync42(file, "utf-8"));
|
|
63675
64070
|
} catch {
|
|
63676
64071
|
return null;
|
|
63677
64072
|
}
|
|
63678
64073
|
}
|
|
63679
64074
|
function listJobs() {
|
|
63680
64075
|
const dir = jobsDir();
|
|
63681
|
-
if (!
|
|
64076
|
+
if (!existsSync53(dir))
|
|
63682
64077
|
return [];
|
|
63683
64078
|
const files = readdirSync20(dir).filter((f) => f.endsWith(".json")).sort();
|
|
63684
64079
|
const jobs = [];
|
|
63685
64080
|
for (const file of files) {
|
|
63686
64081
|
try {
|
|
63687
|
-
jobs.push(JSON.parse(
|
|
64082
|
+
jobs.push(JSON.parse(readFileSync42(join70(dir, file), "utf-8")));
|
|
63688
64083
|
} catch {
|
|
63689
64084
|
}
|
|
63690
64085
|
}
|
|
@@ -64077,8 +64472,8 @@ async function handleV1Run(req, res) {
|
|
|
64077
64472
|
if (workingDir) {
|
|
64078
64473
|
cwd4 = resolve31(workingDir);
|
|
64079
64474
|
} else if (isolate) {
|
|
64080
|
-
const wsDir =
|
|
64081
|
-
|
|
64475
|
+
const wsDir = join70(dir, "..", "workspaces", id);
|
|
64476
|
+
mkdirSync27(wsDir, { recursive: true });
|
|
64082
64477
|
cwd4 = wsDir;
|
|
64083
64478
|
} else {
|
|
64084
64479
|
cwd4 = resolve31(process.cwd());
|
|
@@ -64142,7 +64537,7 @@ async function handleV1Run(req, res) {
|
|
|
64142
64537
|
}
|
|
64143
64538
|
}
|
|
64144
64539
|
}
|
|
64145
|
-
const child =
|
|
64540
|
+
const child = spawn21("node", [oaBin, ...args], {
|
|
64146
64541
|
cwd: cwd4,
|
|
64147
64542
|
env: runEnv,
|
|
64148
64543
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -64150,7 +64545,7 @@ async function handleV1Run(req, res) {
|
|
|
64150
64545
|
});
|
|
64151
64546
|
child.unref();
|
|
64152
64547
|
job.pid = child.pid ?? 0;
|
|
64153
|
-
|
|
64548
|
+
writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
64154
64549
|
runningProcesses.set(id, child);
|
|
64155
64550
|
if (streamMode) {
|
|
64156
64551
|
res.writeHead(200, {
|
|
@@ -64180,7 +64575,7 @@ async function handleV1Run(req, res) {
|
|
|
64180
64575
|
job.status = code === 0 ? "completed" : "failed";
|
|
64181
64576
|
job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
64182
64577
|
try {
|
|
64183
|
-
|
|
64578
|
+
writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
64184
64579
|
} catch {
|
|
64185
64580
|
}
|
|
64186
64581
|
runningProcesses.delete(id);
|
|
@@ -64211,7 +64606,7 @@ async function handleV1Run(req, res) {
|
|
|
64211
64606
|
job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
64212
64607
|
}
|
|
64213
64608
|
try {
|
|
64214
|
-
|
|
64609
|
+
writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
64215
64610
|
} catch {
|
|
64216
64611
|
}
|
|
64217
64612
|
runningProcesses.delete(id);
|
|
@@ -64252,7 +64647,7 @@ function handleV1RunsDelete(res, id) {
|
|
|
64252
64647
|
job.error = "Aborted via API";
|
|
64253
64648
|
const dir = jobsDir();
|
|
64254
64649
|
try {
|
|
64255
|
-
|
|
64650
|
+
writeFileSync26(join70(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
64256
64651
|
} catch {
|
|
64257
64652
|
}
|
|
64258
64653
|
runningProcesses.delete(id);
|
|
@@ -64364,7 +64759,7 @@ async function handlePostCommand(res, cmd) {
|
|
|
64364
64759
|
return;
|
|
64365
64760
|
}
|
|
64366
64761
|
try {
|
|
64367
|
-
const child =
|
|
64762
|
+
const child = spawn21("node", [oaBin, "run", `/${cmd}`, "--json"], {
|
|
64368
64763
|
env: { ...process.env, __OPEN_AGENTS_NO_AUTO_RUN: "" },
|
|
64369
64764
|
stdio: ["ignore", "pipe", "pipe"],
|
|
64370
64765
|
timeout: 3e4
|
|
@@ -64777,13 +65172,13 @@ var init_serve = __esm({
|
|
|
64777
65172
|
|
|
64778
65173
|
// packages/cli/dist/tui/interactive.js
|
|
64779
65174
|
import { cwd } from "node:process";
|
|
64780
|
-
import { resolve as resolve32, join as
|
|
65175
|
+
import { resolve as resolve32, join as join71, dirname as dirname21, extname as extname11 } from "node:path";
|
|
64781
65176
|
import { createRequire as createRequire4 } from "node:module";
|
|
64782
65177
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
64783
|
-
import { readFileSync as
|
|
64784
|
-
import { existsSync as
|
|
64785
|
-
import { execSync as
|
|
64786
|
-
import { homedir as
|
|
65178
|
+
import { readFileSync as readFileSync43, writeFileSync as writeFileSync27, appendFileSync as appendFileSync4, rmSync as rmSync3, readdirSync as readdirSync21, mkdirSync as mkdirSync28 } from "node:fs";
|
|
65179
|
+
import { existsSync as existsSync54 } from "node:fs";
|
|
65180
|
+
import { execSync as execSync34 } from "node:child_process";
|
|
65181
|
+
import { homedir as homedir19 } from "node:os";
|
|
64787
65182
|
function formatTimeAgo(date) {
|
|
64788
65183
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
64789
65184
|
if (seconds < 60)
|
|
@@ -64802,12 +65197,12 @@ function getVersion4() {
|
|
|
64802
65197
|
const require2 = createRequire4(import.meta.url);
|
|
64803
65198
|
const thisDir = dirname21(fileURLToPath13(import.meta.url));
|
|
64804
65199
|
const candidates = [
|
|
64805
|
-
|
|
64806
|
-
|
|
64807
|
-
|
|
65200
|
+
join71(thisDir, "..", "package.json"),
|
|
65201
|
+
join71(thisDir, "..", "..", "package.json"),
|
|
65202
|
+
join71(thisDir, "..", "..", "..", "package.json")
|
|
64808
65203
|
];
|
|
64809
65204
|
for (const pkgPath of candidates) {
|
|
64810
|
-
if (
|
|
65205
|
+
if (existsSync54(pkgPath)) {
|
|
64811
65206
|
const pkg = require2(pkgPath);
|
|
64812
65207
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
|
|
64813
65208
|
return pkg.version ?? "0.0.0";
|
|
@@ -65043,15 +65438,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
|
|
|
65043
65438
|
function gatherMemorySnippets(root) {
|
|
65044
65439
|
const snippets = [];
|
|
65045
65440
|
const dirs = [
|
|
65046
|
-
|
|
65047
|
-
|
|
65441
|
+
join71(root, ".oa", "memory"),
|
|
65442
|
+
join71(root, ".open-agents", "memory")
|
|
65048
65443
|
];
|
|
65049
65444
|
for (const dir of dirs) {
|
|
65050
|
-
if (!
|
|
65445
|
+
if (!existsSync54(dir))
|
|
65051
65446
|
continue;
|
|
65052
65447
|
try {
|
|
65053
65448
|
for (const f of readdirSync21(dir).filter((f2) => f2.endsWith(".json"))) {
|
|
65054
|
-
const data = JSON.parse(
|
|
65449
|
+
const data = JSON.parse(readFileSync43(join71(dir, f), "utf-8"));
|
|
65055
65450
|
for (const val of Object.values(data)) {
|
|
65056
65451
|
const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
65057
65452
|
if (v.length > 10)
|
|
@@ -65208,9 +65603,9 @@ ${metabolismMemories}
|
|
|
65208
65603
|
} catch {
|
|
65209
65604
|
}
|
|
65210
65605
|
try {
|
|
65211
|
-
const archeFile =
|
|
65212
|
-
if (
|
|
65213
|
-
const variants = JSON.parse(
|
|
65606
|
+
const archeFile = join71(repoRoot, ".oa", "arche", "variants.json");
|
|
65607
|
+
if (existsSync54(archeFile)) {
|
|
65608
|
+
const variants = JSON.parse(readFileSync43(archeFile, "utf8"));
|
|
65214
65609
|
if (variants.length > 0) {
|
|
65215
65610
|
let filtered = variants;
|
|
65216
65611
|
if (taskType) {
|
|
@@ -65379,9 +65774,9 @@ RULES:
|
|
|
65379
65774
|
const compactionThreshold = modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
|
|
65380
65775
|
let identityInjection = "";
|
|
65381
65776
|
try {
|
|
65382
|
-
const ikStateFile =
|
|
65383
|
-
if (
|
|
65384
|
-
const selfState = JSON.parse(
|
|
65777
|
+
const ikStateFile = join71(repoRoot, ".oa", "identity", "self-state.json");
|
|
65778
|
+
if (existsSync54(ikStateFile)) {
|
|
65779
|
+
const selfState = JSON.parse(readFileSync43(ikStateFile, "utf8"));
|
|
65385
65780
|
const lines = [
|
|
65386
65781
|
`[Identity State v${selfState.version}]`,
|
|
65387
65782
|
`Self: ${selfState.narrative_summary}`,
|
|
@@ -66024,13 +66419,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
66024
66419
|
});
|
|
66025
66420
|
}
|
|
66026
66421
|
try {
|
|
66027
|
-
const ikDir =
|
|
66028
|
-
const ikFile =
|
|
66422
|
+
const ikDir = join71(repoRoot, ".oa", "identity");
|
|
66423
|
+
const ikFile = join71(ikDir, "self-state.json");
|
|
66029
66424
|
let ikState;
|
|
66030
|
-
if (
|
|
66031
|
-
ikState = JSON.parse(
|
|
66425
|
+
if (existsSync54(ikFile)) {
|
|
66426
|
+
ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
|
|
66032
66427
|
} else {
|
|
66033
|
-
|
|
66428
|
+
mkdirSync28(ikDir, { recursive: true });
|
|
66034
66429
|
const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
66035
66430
|
ikState = {
|
|
66036
66431
|
self_id: `oa-${machineId}`,
|
|
@@ -66056,7 +66451,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
66056
66451
|
}
|
|
66057
66452
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
66058
66453
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
66059
|
-
|
|
66454
|
+
writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
|
|
66060
66455
|
} catch (ikErr) {
|
|
66061
66456
|
try {
|
|
66062
66457
|
console.error("[IK-OBSERVE]", ikErr);
|
|
@@ -66071,14 +66466,14 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
66071
66466
|
} else {
|
|
66072
66467
|
renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
|
|
66073
66468
|
try {
|
|
66074
|
-
const ikFile =
|
|
66075
|
-
if (
|
|
66076
|
-
const ikState = JSON.parse(
|
|
66469
|
+
const ikFile = join71(repoRoot, ".oa", "identity", "self-state.json");
|
|
66470
|
+
if (existsSync54(ikFile)) {
|
|
66471
|
+
const ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
|
|
66077
66472
|
ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
|
|
66078
66473
|
ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
|
|
66079
66474
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
66080
66475
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
66081
|
-
|
|
66476
|
+
writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
|
|
66082
66477
|
}
|
|
66083
66478
|
} catch {
|
|
66084
66479
|
}
|
|
@@ -66175,10 +66570,10 @@ async function startInteractive(config, repoPath) {
|
|
|
66175
66570
|
process.stdin.pause();
|
|
66176
66571
|
}
|
|
66177
66572
|
try {
|
|
66178
|
-
const oaDir =
|
|
66179
|
-
const nexusPidFile =
|
|
66180
|
-
if (
|
|
66181
|
-
const pid = parseInt(
|
|
66573
|
+
const oaDir = join71(repoRoot, ".oa");
|
|
66574
|
+
const nexusPidFile = join71(oaDir, "nexus", "daemon.pid");
|
|
66575
|
+
if (existsSync54(nexusPidFile)) {
|
|
66576
|
+
const pid = parseInt(readFileSync43(nexusPidFile, "utf8").trim(), 10);
|
|
66182
66577
|
if (pid > 0) {
|
|
66183
66578
|
try {
|
|
66184
66579
|
process.kill(pid, 0);
|
|
@@ -66487,7 +66882,7 @@ Review its full output in the [${id}] tab or via full_sub_agent(action='output',
|
|
|
66487
66882
|
let p2pGateway = null;
|
|
66488
66883
|
let peerMesh = null;
|
|
66489
66884
|
let inferenceRouter = null;
|
|
66490
|
-
const secretVault = new SecretVault(
|
|
66885
|
+
const secretVault = new SecretVault(join71(repoRoot, ".oa", "vault.enc"));
|
|
66491
66886
|
let adminSessionKey = null;
|
|
66492
66887
|
const callSubAgents = /* @__PURE__ */ new Map();
|
|
66493
66888
|
const streamRenderer = new StreamRenderer();
|
|
@@ -66710,13 +67105,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
66710
67105
|
const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
|
|
66711
67106
|
return [hits, line];
|
|
66712
67107
|
}
|
|
66713
|
-
const HISTORY_DIR =
|
|
66714
|
-
const HISTORY_FILE =
|
|
67108
|
+
const HISTORY_DIR = join71(homedir19(), ".open-agents");
|
|
67109
|
+
const HISTORY_FILE = join71(HISTORY_DIR, "repl-history");
|
|
66715
67110
|
const MAX_HISTORY_LINES = 500;
|
|
66716
67111
|
let savedHistory = [];
|
|
66717
67112
|
try {
|
|
66718
|
-
if (
|
|
66719
|
-
const raw =
|
|
67113
|
+
if (existsSync54(HISTORY_FILE)) {
|
|
67114
|
+
const raw = readFileSync43(HISTORY_FILE, "utf8").trim();
|
|
66720
67115
|
if (raw)
|
|
66721
67116
|
savedHistory = raw.split("\n").reverse();
|
|
66722
67117
|
}
|
|
@@ -66819,12 +67214,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
66819
67214
|
if (!line.trim())
|
|
66820
67215
|
return;
|
|
66821
67216
|
try {
|
|
66822
|
-
|
|
67217
|
+
mkdirSync28(HISTORY_DIR, { recursive: true });
|
|
66823
67218
|
appendFileSync4(HISTORY_FILE, line + "\n", "utf8");
|
|
66824
67219
|
if (Math.random() < 0.02) {
|
|
66825
|
-
const all =
|
|
67220
|
+
const all = readFileSync43(HISTORY_FILE, "utf8").trim().split("\n");
|
|
66826
67221
|
if (all.length > MAX_HISTORY_LINES) {
|
|
66827
|
-
|
|
67222
|
+
writeFileSync27(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
|
|
66828
67223
|
}
|
|
66829
67224
|
}
|
|
66830
67225
|
} catch {
|
|
@@ -67008,7 +67403,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
67008
67403
|
} catch {
|
|
67009
67404
|
}
|
|
67010
67405
|
try {
|
|
67011
|
-
const oaDir =
|
|
67406
|
+
const oaDir = join71(repoRoot, ".oa");
|
|
67012
67407
|
const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
|
|
67013
67408
|
onInfo: (msg) => writeContent(() => renderInfo(msg)),
|
|
67014
67409
|
onError: (msg) => writeContent(() => renderWarning(msg))
|
|
@@ -67040,7 +67435,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
67040
67435
|
} catch {
|
|
67041
67436
|
}
|
|
67042
67437
|
try {
|
|
67043
|
-
const oaDir =
|
|
67438
|
+
const oaDir = join71(repoRoot, ".oa");
|
|
67044
67439
|
const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
|
|
67045
67440
|
onInfo: (msg) => writeContent(() => renderInfo(msg)),
|
|
67046
67441
|
onError: (msg) => writeContent(() => renderWarning(msg))
|
|
@@ -67081,11 +67476,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
67081
67476
|
}
|
|
67082
67477
|
try {
|
|
67083
67478
|
const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
|
|
67084
|
-
const globalNamePath =
|
|
67479
|
+
const globalNamePath = join71(_hd(), ".open-agents", "agent-name");
|
|
67085
67480
|
let agName = "";
|
|
67086
67481
|
try {
|
|
67087
|
-
if (
|
|
67088
|
-
agName =
|
|
67482
|
+
if (existsSync54(globalNamePath))
|
|
67483
|
+
agName = readFileSync43(globalNamePath, "utf8").trim();
|
|
67089
67484
|
} catch {
|
|
67090
67485
|
}
|
|
67091
67486
|
if (!agName) {
|
|
@@ -68050,7 +68445,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
68050
68445
|
kind,
|
|
68051
68446
|
targetUrl,
|
|
68052
68447
|
authKey,
|
|
68053
|
-
stateDir:
|
|
68448
|
+
stateDir: join71(repoRoot, ".oa"),
|
|
68054
68449
|
passthrough: passthrough ?? false,
|
|
68055
68450
|
loadbalance: loadbalance ?? false,
|
|
68056
68451
|
endpointAuth: passthrough ? currentConfig.apiKey : void 0,
|
|
@@ -68098,7 +68493,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
68098
68493
|
await tunnelGateway.stop();
|
|
68099
68494
|
tunnelGateway = null;
|
|
68100
68495
|
}
|
|
68101
|
-
const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir:
|
|
68496
|
+
const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join71(repoRoot, ".oa") });
|
|
68102
68497
|
newTunnel.on("stats", (stats) => {
|
|
68103
68498
|
statusBar.setExposeStatus({
|
|
68104
68499
|
status: stats.status,
|
|
@@ -68370,15 +68765,15 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
68370
68765
|
writeContent(() => renderInfo(`Killed ${bgKilled} background task(s).`));
|
|
68371
68766
|
}
|
|
68372
68767
|
try {
|
|
68373
|
-
const nexusDir =
|
|
68374
|
-
const pidFile =
|
|
68375
|
-
if (
|
|
68376
|
-
const pid = parseInt(
|
|
68768
|
+
const nexusDir = join71(repoRoot, OA_DIR, "nexus");
|
|
68769
|
+
const pidFile = join71(nexusDir, "daemon.pid");
|
|
68770
|
+
if (existsSync54(pidFile)) {
|
|
68771
|
+
const pid = parseInt(readFileSync43(pidFile, "utf8").trim(), 10);
|
|
68377
68772
|
if (pid > 0) {
|
|
68378
68773
|
try {
|
|
68379
68774
|
if (process.platform === "win32") {
|
|
68380
68775
|
try {
|
|
68381
|
-
|
|
68776
|
+
execSync34(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
|
|
68382
68777
|
} catch {
|
|
68383
68778
|
}
|
|
68384
68779
|
} else {
|
|
@@ -68395,17 +68790,17 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
68395
68790
|
} catch {
|
|
68396
68791
|
}
|
|
68397
68792
|
try {
|
|
68398
|
-
const voiceDir2 =
|
|
68793
|
+
const voiceDir2 = join71(homedir19(), ".open-agents", "voice");
|
|
68399
68794
|
const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
|
|
68400
68795
|
for (const pf of voicePidFiles) {
|
|
68401
|
-
const pidPath =
|
|
68402
|
-
if (
|
|
68796
|
+
const pidPath = join71(voiceDir2, pf);
|
|
68797
|
+
if (existsSync54(pidPath)) {
|
|
68403
68798
|
try {
|
|
68404
|
-
const pid = parseInt(
|
|
68799
|
+
const pid = parseInt(readFileSync43(pidPath, "utf8").trim(), 10);
|
|
68405
68800
|
if (pid > 0) {
|
|
68406
68801
|
if (process.platform === "win32") {
|
|
68407
68802
|
try {
|
|
68408
|
-
|
|
68803
|
+
execSync34(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
|
|
68409
68804
|
} catch {
|
|
68410
68805
|
}
|
|
68411
68806
|
} else {
|
|
@@ -68422,11 +68817,11 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
68422
68817
|
} catch {
|
|
68423
68818
|
}
|
|
68424
68819
|
try {
|
|
68425
|
-
|
|
68820
|
+
execSync34(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
|
|
68426
68821
|
} catch {
|
|
68427
68822
|
}
|
|
68428
|
-
const oaPath =
|
|
68429
|
-
if (
|
|
68823
|
+
const oaPath = join71(repoRoot, OA_DIR);
|
|
68824
|
+
if (existsSync54(oaPath)) {
|
|
68430
68825
|
let deleted = false;
|
|
68431
68826
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
68432
68827
|
try {
|
|
@@ -68436,14 +68831,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
68436
68831
|
} catch (err) {
|
|
68437
68832
|
if (attempt < 2) {
|
|
68438
68833
|
try {
|
|
68439
|
-
|
|
68834
|
+
execSync34(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
|
|
68440
68835
|
} catch {
|
|
68441
68836
|
}
|
|
68442
68837
|
} else {
|
|
68443
68838
|
writeContent(() => renderWarning(`Could not fully remove ${OA_DIR}/: ${err instanceof Error ? err.message : String(err)}`));
|
|
68444
68839
|
if (process.platform === "win32") {
|
|
68445
68840
|
try {
|
|
68446
|
-
|
|
68841
|
+
execSync34(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
|
|
68447
68842
|
deleted = true;
|
|
68448
68843
|
} catch {
|
|
68449
68844
|
}
|
|
@@ -68836,8 +69231,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
68836
69231
|
}
|
|
68837
69232
|
}
|
|
68838
69233
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
68839
|
-
const isImage = isImagePath(cleanPath) &&
|
|
68840
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
69234
|
+
const isImage = isImagePath(cleanPath) && existsSync54(resolve32(repoRoot, cleanPath));
|
|
69235
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync54(resolve32(repoRoot, cleanPath));
|
|
68841
69236
|
if (activeTask) {
|
|
68842
69237
|
if (activeTask.runner.isPaused) {
|
|
68843
69238
|
activeTask.runner.resume();
|
|
@@ -68846,7 +69241,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
68846
69241
|
if (isImage) {
|
|
68847
69242
|
try {
|
|
68848
69243
|
const imgPath = resolve32(repoRoot, cleanPath);
|
|
68849
|
-
const imgBuffer =
|
|
69244
|
+
const imgBuffer = readFileSync43(imgPath);
|
|
68850
69245
|
const base64 = imgBuffer.toString("base64");
|
|
68851
69246
|
const ext = extname11(cleanPath).toLowerCase();
|
|
68852
69247
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -69374,13 +69769,13 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
69374
69769
|
const handle = startTask(task, config, repoRoot);
|
|
69375
69770
|
await handle.promise;
|
|
69376
69771
|
try {
|
|
69377
|
-
const ikDir =
|
|
69378
|
-
const ikFile =
|
|
69772
|
+
const ikDir = join71(repoRoot, ".oa", "identity");
|
|
69773
|
+
const ikFile = join71(ikDir, "self-state.json");
|
|
69379
69774
|
let ikState;
|
|
69380
|
-
if (
|
|
69381
|
-
ikState = JSON.parse(
|
|
69775
|
+
if (existsSync54(ikFile)) {
|
|
69776
|
+
ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
|
|
69382
69777
|
} else {
|
|
69383
|
-
|
|
69778
|
+
mkdirSync28(ikDir, { recursive: true });
|
|
69384
69779
|
ikState = {
|
|
69385
69780
|
self_id: `oa-${Date.now().toString(36)}`,
|
|
69386
69781
|
version: 1,
|
|
@@ -69402,7 +69797,7 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
69402
69797
|
ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
|
|
69403
69798
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
69404
69799
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
69405
|
-
|
|
69800
|
+
writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
|
|
69406
69801
|
} catch (ikErr) {
|
|
69407
69802
|
}
|
|
69408
69803
|
try {
|
|
@@ -69411,12 +69806,12 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
69411
69806
|
ec.archiveVariantSync(`Task: ${task.slice(0, 200)}`, "success \u2014 completed", ["general"]);
|
|
69412
69807
|
} catch {
|
|
69413
69808
|
try {
|
|
69414
|
-
const archeDir =
|
|
69415
|
-
const archeFile =
|
|
69809
|
+
const archeDir = join71(repoRoot, ".oa", "arche");
|
|
69810
|
+
const archeFile = join71(archeDir, "variants.json");
|
|
69416
69811
|
let variants = [];
|
|
69417
69812
|
try {
|
|
69418
|
-
if (
|
|
69419
|
-
variants = JSON.parse(
|
|
69813
|
+
if (existsSync54(archeFile))
|
|
69814
|
+
variants = JSON.parse(readFileSync43(archeFile, "utf8"));
|
|
69420
69815
|
} catch {
|
|
69421
69816
|
}
|
|
69422
69817
|
variants.push({
|
|
@@ -69431,15 +69826,15 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
69431
69826
|
});
|
|
69432
69827
|
if (variants.length > 50)
|
|
69433
69828
|
variants = variants.slice(-50);
|
|
69434
|
-
|
|
69435
|
-
|
|
69829
|
+
mkdirSync28(archeDir, { recursive: true });
|
|
69830
|
+
writeFileSync27(archeFile, JSON.stringify(variants, null, 2));
|
|
69436
69831
|
} catch {
|
|
69437
69832
|
}
|
|
69438
69833
|
}
|
|
69439
69834
|
try {
|
|
69440
|
-
const metaFile =
|
|
69441
|
-
if (
|
|
69442
|
-
const store = JSON.parse(
|
|
69835
|
+
const metaFile = join71(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
69836
|
+
if (existsSync54(metaFile)) {
|
|
69837
|
+
const store = JSON.parse(readFileSync43(metaFile, "utf8"));
|
|
69443
69838
|
const surfaced = store.filter((m) => m.type !== "quarantine" && m.scores?.confidence > 0.15).sort((a, b) => b.scores.utility * b.scores.confidence - a.scores.utility * a.scores.confidence).slice(0, 5);
|
|
69444
69839
|
let updated = false;
|
|
69445
69840
|
for (const item of surfaced) {
|
|
@@ -69450,7 +69845,7 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
69450
69845
|
updated = true;
|
|
69451
69846
|
}
|
|
69452
69847
|
if (updated) {
|
|
69453
|
-
|
|
69848
|
+
writeFileSync27(metaFile, JSON.stringify(store, null, 2));
|
|
69454
69849
|
}
|
|
69455
69850
|
}
|
|
69456
69851
|
} catch {
|
|
@@ -69503,9 +69898,9 @@ Rules:
|
|
|
69503
69898
|
try {
|
|
69504
69899
|
const { initDb: initDb2 } = __require("@open-agents/memory");
|
|
69505
69900
|
const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
69506
|
-
const dbDir =
|
|
69507
|
-
|
|
69508
|
-
const db = initDb2(
|
|
69901
|
+
const dbDir = join71(repoRoot, ".oa", "memory");
|
|
69902
|
+
mkdirSync28(dbDir, { recursive: true });
|
|
69903
|
+
const db = initDb2(join71(dbDir, "structured.db"));
|
|
69509
69904
|
const memStore = new ProceduralMemoryStore2(db);
|
|
69510
69905
|
memStore.createWithEmbedding({
|
|
69511
69906
|
content: content.slice(0, 600),
|
|
@@ -69520,12 +69915,12 @@ Rules:
|
|
|
69520
69915
|
db.close();
|
|
69521
69916
|
} catch {
|
|
69522
69917
|
}
|
|
69523
|
-
const metaDir =
|
|
69524
|
-
const storeFile =
|
|
69918
|
+
const metaDir = join71(repoRoot, ".oa", "memory", "metabolism");
|
|
69919
|
+
const storeFile = join71(metaDir, "store.json");
|
|
69525
69920
|
let store = [];
|
|
69526
69921
|
try {
|
|
69527
|
-
if (
|
|
69528
|
-
store = JSON.parse(
|
|
69922
|
+
if (existsSync54(storeFile))
|
|
69923
|
+
store = JSON.parse(readFileSync43(storeFile, "utf8"));
|
|
69529
69924
|
} catch {
|
|
69530
69925
|
}
|
|
69531
69926
|
store.push({
|
|
@@ -69541,26 +69936,26 @@ Rules:
|
|
|
69541
69936
|
});
|
|
69542
69937
|
if (store.length > 100)
|
|
69543
69938
|
store = store.slice(-100);
|
|
69544
|
-
|
|
69545
|
-
|
|
69939
|
+
mkdirSync28(metaDir, { recursive: true });
|
|
69940
|
+
writeFileSync27(storeFile, JSON.stringify(store, null, 2));
|
|
69546
69941
|
}
|
|
69547
69942
|
}
|
|
69548
69943
|
} catch {
|
|
69549
69944
|
}
|
|
69550
69945
|
try {
|
|
69551
|
-
const cohereSettingsFile =
|
|
69946
|
+
const cohereSettingsFile = join71(repoRoot, ".oa", "settings.json");
|
|
69552
69947
|
let cohereActive = false;
|
|
69553
69948
|
try {
|
|
69554
|
-
if (
|
|
69555
|
-
const settings = JSON.parse(
|
|
69949
|
+
if (existsSync54(cohereSettingsFile)) {
|
|
69950
|
+
const settings = JSON.parse(readFileSync43(cohereSettingsFile, "utf8"));
|
|
69556
69951
|
cohereActive = settings.cohere === true;
|
|
69557
69952
|
}
|
|
69558
69953
|
} catch {
|
|
69559
69954
|
}
|
|
69560
69955
|
if (cohereActive) {
|
|
69561
|
-
const metaFile =
|
|
69562
|
-
if (
|
|
69563
|
-
const store = JSON.parse(
|
|
69956
|
+
const metaFile = join71(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
69957
|
+
if (existsSync54(metaFile)) {
|
|
69958
|
+
const store = JSON.parse(readFileSync43(metaFile, "utf8"));
|
|
69564
69959
|
const latest = store.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
|
|
69565
69960
|
if (latest && latest.scores?.confidence >= 0.6) {
|
|
69566
69961
|
try {
|
|
@@ -69585,18 +69980,18 @@ Rules:
|
|
|
69585
69980
|
}
|
|
69586
69981
|
} catch (err) {
|
|
69587
69982
|
try {
|
|
69588
|
-
const ikFile =
|
|
69589
|
-
if (
|
|
69590
|
-
const ikState = JSON.parse(
|
|
69983
|
+
const ikFile = join71(repoRoot, ".oa", "identity", "self-state.json");
|
|
69984
|
+
if (existsSync54(ikFile)) {
|
|
69985
|
+
const ikState = JSON.parse(readFileSync43(ikFile, "utf8"));
|
|
69591
69986
|
ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
|
|
69592
69987
|
ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
|
|
69593
69988
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
69594
69989
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
69595
|
-
|
|
69990
|
+
writeFileSync27(ikFile, JSON.stringify(ikState, null, 2));
|
|
69596
69991
|
}
|
|
69597
|
-
const metaFile =
|
|
69598
|
-
if (
|
|
69599
|
-
const store = JSON.parse(
|
|
69992
|
+
const metaFile = join71(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
69993
|
+
if (existsSync54(metaFile)) {
|
|
69994
|
+
const store = JSON.parse(readFileSync43(metaFile, "utf8"));
|
|
69600
69995
|
const surfaced = store.filter((m) => m.type !== "quarantine" && m.scores?.confidence > 0.15).sort((a, b) => b.scores.utility * b.scores.confidence - a.scores.utility * a.scores.confidence).slice(0, 5);
|
|
69601
69996
|
for (const item of surfaced) {
|
|
69602
69997
|
item.accessCount = (item.accessCount || 0) + 1;
|
|
@@ -69604,15 +69999,15 @@ Rules:
|
|
|
69604
69999
|
item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
|
|
69605
70000
|
item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
|
|
69606
70001
|
}
|
|
69607
|
-
|
|
70002
|
+
writeFileSync27(metaFile, JSON.stringify(store, null, 2));
|
|
69608
70003
|
}
|
|
69609
70004
|
try {
|
|
69610
|
-
const archeDir =
|
|
69611
|
-
const archeFile =
|
|
70005
|
+
const archeDir = join71(repoRoot, ".oa", "arche");
|
|
70006
|
+
const archeFile = join71(archeDir, "variants.json");
|
|
69612
70007
|
let variants = [];
|
|
69613
70008
|
try {
|
|
69614
|
-
if (
|
|
69615
|
-
variants = JSON.parse(
|
|
70009
|
+
if (existsSync54(archeFile))
|
|
70010
|
+
variants = JSON.parse(readFileSync43(archeFile, "utf8"));
|
|
69616
70011
|
} catch {
|
|
69617
70012
|
}
|
|
69618
70013
|
variants.push({
|
|
@@ -69627,8 +70022,8 @@ Rules:
|
|
|
69627
70022
|
});
|
|
69628
70023
|
if (variants.length > 50)
|
|
69629
70024
|
variants = variants.slice(-50);
|
|
69630
|
-
|
|
69631
|
-
|
|
70025
|
+
mkdirSync28(archeDir, { recursive: true });
|
|
70026
|
+
writeFileSync27(archeFile, JSON.stringify(variants, null, 2));
|
|
69632
70027
|
} catch {
|
|
69633
70028
|
}
|
|
69634
70029
|
} catch {
|
|
@@ -69694,14 +70089,14 @@ __export(run_exports, {
|
|
|
69694
70089
|
statusCommand: () => statusCommand
|
|
69695
70090
|
});
|
|
69696
70091
|
import { resolve as resolve33 } from "node:path";
|
|
69697
|
-
import { spawn as
|
|
69698
|
-
import { mkdirSync as
|
|
70092
|
+
import { spawn as spawn22 } from "node:child_process";
|
|
70093
|
+
import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync28, readFileSync as readFileSync44, readdirSync as readdirSync22, existsSync as existsSync55 } from "node:fs";
|
|
69699
70094
|
import { randomBytes as randomBytes17 } from "node:crypto";
|
|
69700
|
-
import { join as
|
|
70095
|
+
import { join as join72 } from "node:path";
|
|
69701
70096
|
function jobsDir2(repoPath) {
|
|
69702
70097
|
const root = resolve33(repoPath ?? process.cwd());
|
|
69703
|
-
const dir =
|
|
69704
|
-
|
|
70098
|
+
const dir = join72(root, ".oa", "jobs");
|
|
70099
|
+
mkdirSync29(dir, { recursive: true });
|
|
69705
70100
|
return dir;
|
|
69706
70101
|
}
|
|
69707
70102
|
async function runCommand(opts, config) {
|
|
@@ -69778,7 +70173,7 @@ async function runBackground(task, config, opts) {
|
|
|
69778
70173
|
const args = [task, "--json"];
|
|
69779
70174
|
if (config.model)
|
|
69780
70175
|
args.push("--model", config.model);
|
|
69781
|
-
const child =
|
|
70176
|
+
const child = spawn22("node", [oaBin, ...args], {
|
|
69782
70177
|
cwd: repoRoot,
|
|
69783
70178
|
env: { ...process.env, OA_JOB_ID: id },
|
|
69784
70179
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -69786,7 +70181,7 @@ async function runBackground(task, config, opts) {
|
|
|
69786
70181
|
});
|
|
69787
70182
|
child.unref();
|
|
69788
70183
|
job.pid = child.pid ?? 0;
|
|
69789
|
-
|
|
70184
|
+
writeFileSync28(join72(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
69790
70185
|
let output = "";
|
|
69791
70186
|
child.stdout?.on("data", (chunk) => {
|
|
69792
70187
|
output += chunk.toString();
|
|
@@ -69802,7 +70197,7 @@ async function runBackground(task, config, opts) {
|
|
|
69802
70197
|
job.summary = result.summary;
|
|
69803
70198
|
job.durationMs = result.durationMs;
|
|
69804
70199
|
job.error = result.error;
|
|
69805
|
-
|
|
70200
|
+
writeFileSync28(join72(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
69806
70201
|
} catch {
|
|
69807
70202
|
}
|
|
69808
70203
|
});
|
|
@@ -69818,13 +70213,13 @@ async function runBackground(task, config, opts) {
|
|
|
69818
70213
|
}
|
|
69819
70214
|
function statusCommand(jobId, repoPath) {
|
|
69820
70215
|
const dir = jobsDir2(repoPath);
|
|
69821
|
-
const file =
|
|
69822
|
-
if (!
|
|
70216
|
+
const file = join72(dir, `${jobId}.json`);
|
|
70217
|
+
if (!existsSync55(file)) {
|
|
69823
70218
|
console.error(`Job not found: ${jobId}`);
|
|
69824
70219
|
console.log(`Available jobs: oa jobs`);
|
|
69825
70220
|
process.exit(1);
|
|
69826
70221
|
}
|
|
69827
|
-
const job = JSON.parse(
|
|
70222
|
+
const job = JSON.parse(readFileSync44(file, "utf-8"));
|
|
69828
70223
|
const runtime = job.completedAt ? `${((new Date(job.completedAt).getTime() - new Date(job.startedAt).getTime()) / 1e3).toFixed(0)}s` : `${((Date.now() - new Date(job.startedAt).getTime()) / 1e3).toFixed(0)}s`;
|
|
69829
70224
|
const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
|
|
69830
70225
|
console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
|
|
@@ -69847,7 +70242,7 @@ function jobsCommand(repoPath) {
|
|
|
69847
70242
|
console.log("Jobs:");
|
|
69848
70243
|
for (const file of files) {
|
|
69849
70244
|
try {
|
|
69850
|
-
const job = JSON.parse(
|
|
70245
|
+
const job = JSON.parse(readFileSync44(join72(dir, file), "utf-8"));
|
|
69851
70246
|
const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
|
|
69852
70247
|
const runtime = job.completedAt ? `${((new Date(job.completedAt).getTime() - new Date(job.startedAt).getTime()) / 1e3).toFixed(0)}s` : `${((Date.now() - new Date(job.startedAt).getTime()) / 1e3).toFixed(0)}s`;
|
|
69853
70248
|
console.log(` ${icon} ${job.id} [${job.status}] ${runtime} \u2014 ${job.task.slice(0, 60)}`);
|
|
@@ -69867,7 +70262,7 @@ import { glob } from "glob";
|
|
|
69867
70262
|
import ignore from "ignore";
|
|
69868
70263
|
import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
|
|
69869
70264
|
import { createHash as createHash6 } from "node:crypto";
|
|
69870
|
-
import { join as
|
|
70265
|
+
import { join as join73, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
|
|
69871
70266
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
69872
70267
|
var init_codebase_indexer = __esm({
|
|
69873
70268
|
"packages/indexer/dist/codebase-indexer.js"() {
|
|
@@ -69911,7 +70306,7 @@ var init_codebase_indexer = __esm({
|
|
|
69911
70306
|
const ig = ignore.default();
|
|
69912
70307
|
if (this.config.respectGitignore) {
|
|
69913
70308
|
try {
|
|
69914
|
-
const gitignoreContent = await readFile23(
|
|
70309
|
+
const gitignoreContent = await readFile23(join73(this.config.rootDir, ".gitignore"), "utf-8");
|
|
69915
70310
|
ig.add(gitignoreContent);
|
|
69916
70311
|
} catch {
|
|
69917
70312
|
}
|
|
@@ -69926,7 +70321,7 @@ var init_codebase_indexer = __esm({
|
|
|
69926
70321
|
for (const relativePath of files) {
|
|
69927
70322
|
if (ig.ignores(relativePath))
|
|
69928
70323
|
continue;
|
|
69929
|
-
const fullPath =
|
|
70324
|
+
const fullPath = join73(this.config.rootDir, relativePath);
|
|
69930
70325
|
try {
|
|
69931
70326
|
const fileStat = await stat4(fullPath);
|
|
69932
70327
|
if (fileStat.size > this.config.maxFileSize)
|
|
@@ -69972,7 +70367,7 @@ var init_codebase_indexer = __esm({
|
|
|
69972
70367
|
if (!child) {
|
|
69973
70368
|
child = {
|
|
69974
70369
|
name: part,
|
|
69975
|
-
path:
|
|
70370
|
+
path: join73(current.path, part),
|
|
69976
70371
|
type: "directory",
|
|
69977
70372
|
children: []
|
|
69978
70373
|
};
|
|
@@ -70055,13 +70450,13 @@ __export(index_repo_exports, {
|
|
|
70055
70450
|
indexRepoCommand: () => indexRepoCommand
|
|
70056
70451
|
});
|
|
70057
70452
|
import { resolve as resolve34 } from "node:path";
|
|
70058
|
-
import { existsSync as
|
|
70453
|
+
import { existsSync as existsSync56, statSync as statSync16 } from "node:fs";
|
|
70059
70454
|
import { cwd as cwd2 } from "node:process";
|
|
70060
70455
|
async function indexRepoCommand(opts, _config) {
|
|
70061
70456
|
const repoRoot = resolve34(opts.repoPath ?? cwd2());
|
|
70062
70457
|
printHeader("Index Repository");
|
|
70063
70458
|
printInfo(`Indexing: ${repoRoot}`);
|
|
70064
|
-
if (!
|
|
70459
|
+
if (!existsSync56(repoRoot)) {
|
|
70065
70460
|
printError(`Path does not exist: ${repoRoot}`);
|
|
70066
70461
|
process.exit(1);
|
|
70067
70462
|
}
|
|
@@ -70313,8 +70708,8 @@ var config_exports2 = {};
|
|
|
70313
70708
|
__export(config_exports2, {
|
|
70314
70709
|
configCommand: () => configCommand
|
|
70315
70710
|
});
|
|
70316
|
-
import { join as
|
|
70317
|
-
import { homedir as
|
|
70711
|
+
import { join as join74, resolve as resolve35 } from "node:path";
|
|
70712
|
+
import { homedir as homedir20 } from "node:os";
|
|
70318
70713
|
import { cwd as cwd3 } from "node:process";
|
|
70319
70714
|
function redactIfSensitive(key, value) {
|
|
70320
70715
|
if (SENSITIVE_KEYS.has(key) && typeof value === "string" && value.length > 0) {
|
|
@@ -70396,7 +70791,7 @@ function handleShow(opts, config) {
|
|
|
70396
70791
|
}
|
|
70397
70792
|
}
|
|
70398
70793
|
printSection("Config File");
|
|
70399
|
-
printInfo(`~/.open-agents/config.json (${
|
|
70794
|
+
printInfo(`~/.open-agents/config.json (${join74(homedir20(), ".open-agents", "config.json")})`);
|
|
70400
70795
|
printSection("Priority Chain");
|
|
70401
70796
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
70402
70797
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -70435,7 +70830,7 @@ function handleSet(opts, _config) {
|
|
|
70435
70830
|
const coerced = coerceForSettings(key, value);
|
|
70436
70831
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
70437
70832
|
printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
|
|
70438
|
-
printInfo(`Saved to ${
|
|
70833
|
+
printInfo(`Saved to ${join74(repoRoot, ".oa", "settings.json")}`);
|
|
70439
70834
|
printInfo("This override applies only when running in this workspace.");
|
|
70440
70835
|
} catch (err) {
|
|
70441
70836
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -70578,8 +70973,8 @@ __export(eval_exports, {
|
|
|
70578
70973
|
evalCommand: () => evalCommand
|
|
70579
70974
|
});
|
|
70580
70975
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
70581
|
-
import { mkdirSync as
|
|
70582
|
-
import { join as
|
|
70976
|
+
import { mkdirSync as mkdirSync30, writeFileSync as writeFileSync29 } from "node:fs";
|
|
70977
|
+
import { join as join75 } from "node:path";
|
|
70583
70978
|
async function evalCommand(opts, config) {
|
|
70584
70979
|
const suiteName = opts.suite ?? "basic";
|
|
70585
70980
|
const suite = SUITES[suiteName];
|
|
@@ -70704,9 +71099,9 @@ async function evalCommand(opts, config) {
|
|
|
70704
71099
|
process.exit(failed > 0 ? 1 : 0);
|
|
70705
71100
|
}
|
|
70706
71101
|
function createTempEvalRepo() {
|
|
70707
|
-
const dir =
|
|
70708
|
-
|
|
70709
|
-
|
|
71102
|
+
const dir = join75(tmpdir10(), `open-agents-eval-${Date.now()}`);
|
|
71103
|
+
mkdirSync30(dir, { recursive: true });
|
|
71104
|
+
writeFileSync29(join75(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
70710
71105
|
return dir;
|
|
70711
71106
|
}
|
|
70712
71107
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -70766,7 +71161,7 @@ init_updater();
|
|
|
70766
71161
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
70767
71162
|
import { createRequire as createRequire5 } from "node:module";
|
|
70768
71163
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
70769
|
-
import { dirname as dirname22, join as
|
|
71164
|
+
import { dirname as dirname22, join as join76 } from "node:path";
|
|
70770
71165
|
|
|
70771
71166
|
// packages/cli/dist/cli.js
|
|
70772
71167
|
import { createInterface } from "node:readline";
|
|
@@ -70873,7 +71268,7 @@ init_output();
|
|
|
70873
71268
|
function getVersion5() {
|
|
70874
71269
|
try {
|
|
70875
71270
|
const require2 = createRequire5(import.meta.url);
|
|
70876
|
-
const pkgPath =
|
|
71271
|
+
const pkgPath = join76(dirname22(fileURLToPath14(import.meta.url)), "..", "package.json");
|
|
70877
71272
|
const pkg = require2(pkgPath);
|
|
70878
71273
|
return pkg.version;
|
|
70879
71274
|
} catch {
|
|
@@ -71148,12 +71543,12 @@ function crashLog(label, err) {
|
|
|
71148
71543
|
const logLine = `[${timestamp}] ${label}: ${msg}
|
|
71149
71544
|
`;
|
|
71150
71545
|
try {
|
|
71151
|
-
const { appendFileSync: appendFileSync5, mkdirSync:
|
|
71152
|
-
const { join:
|
|
71153
|
-
const { homedir:
|
|
71154
|
-
const logDir =
|
|
71155
|
-
|
|
71156
|
-
appendFileSync5(
|
|
71546
|
+
const { appendFileSync: appendFileSync5, mkdirSync: mkdirSync31 } = __require("node:fs");
|
|
71547
|
+
const { join: join77 } = __require("node:path");
|
|
71548
|
+
const { homedir: homedir21 } = __require("node:os");
|
|
71549
|
+
const logDir = join77(homedir21(), ".open-agents");
|
|
71550
|
+
mkdirSync31(logDir, { recursive: true });
|
|
71551
|
+
appendFileSync5(join77(logDir, "crash.log"), logLine);
|
|
71157
71552
|
} catch {
|
|
71158
71553
|
}
|
|
71159
71554
|
try {
|