open-agents-ai 0.185.77 → 0.185.79
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 +806 -425
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11957,8 +11957,8 @@ async function loadTranscribeCli() {
|
|
|
11957
11957
|
const nvmBase = join19(homedir7(), ".nvm", "versions", "node");
|
|
11958
11958
|
if (existsSync16(nvmBase)) {
|
|
11959
11959
|
try {
|
|
11960
|
-
const { readdirSync:
|
|
11961
|
-
for (const ver of
|
|
11960
|
+
const { readdirSync: readdirSync25 } = await import("node:fs");
|
|
11961
|
+
for (const ver of readdirSync25(nvmBase)) {
|
|
11962
11962
|
const tcPath = join19(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
11963
11963
|
if (existsSync16(join19(tcPath, "dist", "index.js"))) {
|
|
11964
11964
|
const { createRequire: createRequire6 } = await import("node:module");
|
|
@@ -13782,9 +13782,9 @@ print("${sentinel}")
|
|
|
13782
13782
|
if (!this.proc || this.proc.killed) {
|
|
13783
13783
|
return { success: false, path: "" };
|
|
13784
13784
|
}
|
|
13785
|
-
const { mkdirSync:
|
|
13785
|
+
const { mkdirSync: mkdirSync33, writeFileSync: writeFileSync31 } = await import("node:fs");
|
|
13786
13786
|
const sessionDir = join22(this.cwd, ".oa", "rlm");
|
|
13787
|
-
|
|
13787
|
+
mkdirSync33(sessionDir, { recursive: true });
|
|
13788
13788
|
const sessionPath = join22(sessionDir, "session.json");
|
|
13789
13789
|
try {
|
|
13790
13790
|
const inspectCode = `
|
|
@@ -13808,7 +13808,7 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
13808
13808
|
trajectoryCount: this.trajectory.length,
|
|
13809
13809
|
subCallCount: this.subCallCount
|
|
13810
13810
|
};
|
|
13811
|
-
|
|
13811
|
+
writeFileSync31(sessionPath, JSON.stringify(sessionData, null, 2), "utf8");
|
|
13812
13812
|
return { success: true, path: sessionPath };
|
|
13813
13813
|
}
|
|
13814
13814
|
} catch {
|
|
@@ -13820,11 +13820,11 @@ print("__SESSION__" + json.dumps(_session) + "__SESSION__")
|
|
|
13820
13820
|
* what was previously computed. */
|
|
13821
13821
|
async loadSessionInfo() {
|
|
13822
13822
|
try {
|
|
13823
|
-
const { readFileSync:
|
|
13823
|
+
const { readFileSync: readFileSync48, existsSync: existsSync60 } = await import("node:fs");
|
|
13824
13824
|
const sessionPath = join22(this.cwd, ".oa", "rlm", "session.json");
|
|
13825
|
-
if (!
|
|
13825
|
+
if (!existsSync60(sessionPath))
|
|
13826
13826
|
return null;
|
|
13827
|
-
return JSON.parse(
|
|
13827
|
+
return JSON.parse(readFileSync48(sessionPath, "utf8"));
|
|
13828
13828
|
} catch {
|
|
13829
13829
|
return null;
|
|
13830
13830
|
}
|
|
@@ -13971,9 +13971,9 @@ var init_memory_metabolism = __esm({
|
|
|
13971
13971
|
};
|
|
13972
13972
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
13973
13973
|
await mkdir6(metaDir, { recursive: true });
|
|
13974
|
-
const
|
|
13975
|
-
|
|
13976
|
-
await this.saveStore(metaDir,
|
|
13974
|
+
const store2 = await this.loadStore(metaDir);
|
|
13975
|
+
store2.push(item);
|
|
13976
|
+
await this.saveStore(metaDir, store2);
|
|
13977
13977
|
if (admitted && scope !== "private" && this.deltaPublisher) {
|
|
13978
13978
|
try {
|
|
13979
13979
|
this.deltaPublisher({
|
|
@@ -14001,10 +14001,10 @@ var init_memory_metabolism = __esm({
|
|
|
14001
14001
|
const trajDir = join23(this.cwd, ".oa", "rlm-trajectories");
|
|
14002
14002
|
let lessons = [];
|
|
14003
14003
|
try {
|
|
14004
|
-
const { readdirSync:
|
|
14005
|
-
const files =
|
|
14004
|
+
const { readdirSync: readdirSync25, readFileSync: readFileSync48 } = await import("node:fs");
|
|
14005
|
+
const files = readdirSync25(trajDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 3);
|
|
14006
14006
|
for (const file of files) {
|
|
14007
|
-
const lines =
|
|
14007
|
+
const lines = readFileSync48(join23(trajDir, file), "utf8").split("\n").filter((l) => l.trim());
|
|
14008
14008
|
for (const line of lines) {
|
|
14009
14009
|
try {
|
|
14010
14010
|
const entry = JSON.parse(line);
|
|
@@ -14032,9 +14032,9 @@ var init_memory_metabolism = __esm({
|
|
|
14032
14032
|
if (lessons.length > 0) {
|
|
14033
14033
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14034
14034
|
await mkdir6(metaDir, { recursive: true });
|
|
14035
|
-
const
|
|
14035
|
+
const store2 = await this.loadStore(metaDir);
|
|
14036
14036
|
for (const lesson of lessons.slice(0, 10)) {
|
|
14037
|
-
|
|
14037
|
+
store2.push({
|
|
14038
14038
|
id: `lesson-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`,
|
|
14039
14039
|
type: lesson.type === "recovery" ? "procedural" : "procedural",
|
|
14040
14040
|
content: `${lesson.description}
|
|
@@ -14047,7 +14047,7 @@ Context: ${lesson.context}`,
|
|
|
14047
14047
|
accessCount: 0
|
|
14048
14048
|
});
|
|
14049
14049
|
}
|
|
14050
|
-
await this.saveStore(metaDir,
|
|
14050
|
+
await this.saveStore(metaDir, store2);
|
|
14051
14051
|
}
|
|
14052
14052
|
return {
|
|
14053
14053
|
success: true,
|
|
@@ -14060,8 +14060,8 @@ Context: ${lesson.context}`,
|
|
|
14060
14060
|
async listMemories(args, start) {
|
|
14061
14061
|
const filterType = args.memory_type;
|
|
14062
14062
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14063
|
-
const
|
|
14064
|
-
const filtered = filterType ?
|
|
14063
|
+
const store2 = await this.loadStore(metaDir);
|
|
14064
|
+
const filtered = filterType ? store2.filter((m) => m.type === filterType) : store2;
|
|
14065
14065
|
if (filtered.length === 0) {
|
|
14066
14066
|
return { success: true, output: "No memories stored yet.", durationMs: performance.now() - start };
|
|
14067
14067
|
}
|
|
@@ -14082,15 +14082,15 @@ ${lines.join("\n")}`,
|
|
|
14082
14082
|
return { success: false, output: "id and memory_type required", durationMs: performance.now() - start };
|
|
14083
14083
|
}
|
|
14084
14084
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14085
|
-
const
|
|
14086
|
-
const item =
|
|
14085
|
+
const store2 = await this.loadStore(metaDir);
|
|
14086
|
+
const item = store2.find((m) => m.id === id);
|
|
14087
14087
|
if (!item) {
|
|
14088
14088
|
return { success: false, output: `Memory ${id} not found`, durationMs: performance.now() - start };
|
|
14089
14089
|
}
|
|
14090
14090
|
const oldType = item.type;
|
|
14091
14091
|
item.type = newType;
|
|
14092
14092
|
item.decision = { action: "promote", reason: `Promoted from ${oldType} to ${newType}` };
|
|
14093
|
-
await this.saveStore(metaDir,
|
|
14093
|
+
await this.saveStore(metaDir, store2);
|
|
14094
14094
|
return {
|
|
14095
14095
|
success: true,
|
|
14096
14096
|
output: `Promoted ${id}: ${oldType} \u2192 ${newType}`,
|
|
@@ -14104,13 +14104,13 @@ ${lines.join("\n")}`,
|
|
|
14104
14104
|
return { success: false, output: "id required", durationMs: performance.now() - start };
|
|
14105
14105
|
}
|
|
14106
14106
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14107
|
-
const
|
|
14108
|
-
const idx =
|
|
14107
|
+
const store2 = await this.loadStore(metaDir);
|
|
14108
|
+
const idx = store2.findIndex((m) => m.id === id);
|
|
14109
14109
|
if (idx === -1) {
|
|
14110
14110
|
return { success: false, output: `Memory ${id} not found`, durationMs: performance.now() - start };
|
|
14111
14111
|
}
|
|
14112
|
-
const removed =
|
|
14113
|
-
await this.saveStore(metaDir,
|
|
14112
|
+
const removed = store2.splice(idx, 1)[0];
|
|
14113
|
+
await this.saveStore(metaDir, store2);
|
|
14114
14114
|
return {
|
|
14115
14115
|
success: true,
|
|
14116
14116
|
output: `Forgotten: [${removed.id}] ${removed.content.slice(0, 60)}`,
|
|
@@ -14125,15 +14125,15 @@ ${lines.join("\n")}`,
|
|
|
14125
14125
|
*/
|
|
14126
14126
|
async repairMemories(start) {
|
|
14127
14127
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14128
|
-
const
|
|
14129
|
-
if (
|
|
14128
|
+
const store2 = await this.loadStore(metaDir);
|
|
14129
|
+
if (store2.length === 0) {
|
|
14130
14130
|
return { success: true, output: "No memories to repair.", durationMs: performance.now() - start };
|
|
14131
14131
|
}
|
|
14132
14132
|
let repaired = 0;
|
|
14133
14133
|
let quarantined = 0;
|
|
14134
14134
|
let expired = 0;
|
|
14135
14135
|
const issues = [];
|
|
14136
|
-
for (const item of
|
|
14136
|
+
for (const item of store2) {
|
|
14137
14137
|
if (item.type === "working") {
|
|
14138
14138
|
const ageMs = Date.now() - new Date(item.createdAt).getTime();
|
|
14139
14139
|
if (ageMs > 24 * 60 * 60 * 1e3) {
|
|
@@ -14142,7 +14142,7 @@ ${lines.join("\n")}`,
|
|
|
14142
14142
|
issues.push(`[${item.id}] Working memory expired \u2014 marked for cleanup`);
|
|
14143
14143
|
}
|
|
14144
14144
|
}
|
|
14145
|
-
const duplicates =
|
|
14145
|
+
const duplicates = store2.filter((m) => m.id !== item.id && m.content === item.content);
|
|
14146
14146
|
if (duplicates.length > 0) {
|
|
14147
14147
|
for (const dup of duplicates) {
|
|
14148
14148
|
const dupScore = (dup.scores.novelty + dup.scores.utility + dup.scores.confidence + dup.scores.identityRelevance) / 4;
|
|
@@ -14156,7 +14156,7 @@ ${lines.join("\n")}`,
|
|
|
14156
14156
|
}
|
|
14157
14157
|
}
|
|
14158
14158
|
if (item.type === "procedural" || item.type === "semantic") {
|
|
14159
|
-
const conflicts =
|
|
14159
|
+
const conflicts = store2.filter((m) => m.id !== item.id && m.type === item.type && m.decision.action !== "quarantine" && this.detectContradiction(item.content, m.content));
|
|
14160
14160
|
if (conflicts.length > 0) {
|
|
14161
14161
|
for (const conflict of conflicts) {
|
|
14162
14162
|
if (new Date(conflict.createdAt) < new Date(item.createdAt)) {
|
|
@@ -14176,12 +14176,12 @@ ${lines.join("\n")}`,
|
|
|
14176
14176
|
issues.push(`[${item.id}] Low confidence (${item.scores.confidence.toFixed(2)}) \u2014 quarantined`);
|
|
14177
14177
|
}
|
|
14178
14178
|
}
|
|
14179
|
-
const cleanedStore =
|
|
14179
|
+
const cleanedStore = store2.filter((m) => !(m.type === "working" && m.decision.action === "forget"));
|
|
14180
14180
|
await this.saveStore(metaDir, cleanedStore);
|
|
14181
14181
|
return {
|
|
14182
14182
|
success: true,
|
|
14183
14183
|
output: `Memory repair complete:
|
|
14184
|
-
Scanned: ${
|
|
14184
|
+
Scanned: ${store2.length} memories
|
|
14185
14185
|
Repaired contradictions: ${repaired}
|
|
14186
14186
|
Quarantined (duplicates/low-confidence): ${quarantined}
|
|
14187
14187
|
Expired working memories removed: ${expired}
|
|
@@ -14293,14 +14293,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14293
14293
|
// Memories below decay threshold get quarantined.
|
|
14294
14294
|
async decayMemories(start) {
|
|
14295
14295
|
const dir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14296
|
-
const
|
|
14297
|
-
if (
|
|
14296
|
+
const store2 = await this.loadStore(dir);
|
|
14297
|
+
if (store2.length === 0)
|
|
14298
14298
|
return { success: true, output: "No memories to decay", durationMs: performance.now() - start };
|
|
14299
14299
|
const now = Date.now();
|
|
14300
14300
|
const DECAY_RATE = 1e-3;
|
|
14301
14301
|
const QUARANTINE_THRESHOLD = 0.15;
|
|
14302
14302
|
let decayed = 0, quarantined = 0;
|
|
14303
|
-
for (const item of
|
|
14303
|
+
for (const item of store2) {
|
|
14304
14304
|
if (item.type === "quarantine")
|
|
14305
14305
|
continue;
|
|
14306
14306
|
const ageHours = (now - new Date(item.lastAccessedAt).getTime()) / (1e3 * 60 * 60);
|
|
@@ -14317,7 +14317,7 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14317
14317
|
quarantined++;
|
|
14318
14318
|
}
|
|
14319
14319
|
}
|
|
14320
|
-
await this.saveStore(dir,
|
|
14320
|
+
await this.saveStore(dir, store2);
|
|
14321
14321
|
return {
|
|
14322
14322
|
success: true,
|
|
14323
14323
|
output: `Decay sweep: ${decayed} memories updated, ${quarantined} quarantined (threshold: ${QUARANTINE_THRESHOLD})`,
|
|
@@ -14332,11 +14332,11 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14332
14332
|
// Any → procedural: if content matches action/strategy patterns
|
|
14333
14333
|
async autoLifecycle(start) {
|
|
14334
14334
|
const dir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14335
|
-
const
|
|
14336
|
-
if (
|
|
14335
|
+
const store2 = await this.loadStore(dir);
|
|
14336
|
+
if (store2.length === 0)
|
|
14337
14337
|
return { success: true, output: "No memories to process", durationMs: performance.now() - start };
|
|
14338
14338
|
let promoted = 0;
|
|
14339
|
-
for (const item of
|
|
14339
|
+
for (const item of store2) {
|
|
14340
14340
|
if (item.type === "quarantine")
|
|
14341
14341
|
continue;
|
|
14342
14342
|
if (item.type === "working" && item.accessCount >= 3) {
|
|
@@ -14358,18 +14358,18 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14358
14358
|
}
|
|
14359
14359
|
}
|
|
14360
14360
|
const decayResult = await this.decayMemories(start);
|
|
14361
|
-
await this.saveStore(dir,
|
|
14361
|
+
await this.saveStore(dir, store2);
|
|
14362
14362
|
try {
|
|
14363
14363
|
const { IdentityKernelTool: IdentityKernelTool2 } = await Promise.resolve().then(() => (init_identity_kernel(), identity_kernel_exports));
|
|
14364
14364
|
const ik = new IdentityKernelTool2(this.cwd);
|
|
14365
14365
|
const typeCounts = {};
|
|
14366
|
-
for (const item of
|
|
14366
|
+
for (const item of store2) {
|
|
14367
14367
|
typeCounts[item.type] = (typeCounts[item.type] || 0) + 1;
|
|
14368
14368
|
}
|
|
14369
14369
|
await ik.execute({
|
|
14370
14370
|
op: "observe",
|
|
14371
|
-
event: `Memory lifecycle: ${
|
|
14372
|
-
context: JSON.stringify({ total:
|
|
14371
|
+
event: `Memory lifecycle: ${store2.length} total, ${promoted} promoted. Types: ${JSON.stringify(typeCounts)}`,
|
|
14372
|
+
context: JSON.stringify({ total: store2.length, promoted, typeCounts })
|
|
14373
14373
|
});
|
|
14374
14374
|
} catch {
|
|
14375
14375
|
}
|
|
@@ -14388,18 +14388,18 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14388
14388
|
* Optionally filter by task type for phase-aware context (FSM paper insight).
|
|
14389
14389
|
*/
|
|
14390
14390
|
getTopMemoriesSync(k = 5, taskType) {
|
|
14391
|
-
const { readFileSync:
|
|
14391
|
+
const { readFileSync: readFileSync48, existsSync: existsSync60 } = __require("node:fs");
|
|
14392
14392
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14393
14393
|
const storeFile = join23(metaDir, "store.json");
|
|
14394
|
-
if (!
|
|
14394
|
+
if (!existsSync60(storeFile))
|
|
14395
14395
|
return "";
|
|
14396
|
-
let
|
|
14396
|
+
let store2 = [];
|
|
14397
14397
|
try {
|
|
14398
|
-
|
|
14398
|
+
store2 = JSON.parse(readFileSync48(storeFile, "utf8"));
|
|
14399
14399
|
} catch {
|
|
14400
14400
|
return "";
|
|
14401
14401
|
}
|
|
14402
|
-
let items =
|
|
14402
|
+
let items = store2.filter((m) => m.type !== "quarantine" && m.scores.confidence > 0.15);
|
|
14403
14403
|
if (taskType) {
|
|
14404
14404
|
const typeMatch = items.filter((m) => m.content.toLowerCase().includes(taskType.toLowerCase()) || m.sourceTrace.toLowerCase().includes(taskType.toLowerCase()));
|
|
14405
14405
|
if (typeMatch.length >= 2)
|
|
@@ -14417,14 +14417,14 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14417
14417
|
/** Update memory scores based on task outcome. Called after task completion.
|
|
14418
14418
|
* Memories used in successful tasks get boosted. Memories present during failures get decayed. */
|
|
14419
14419
|
updateFromOutcomeSync(surfacedMemoryText, succeeded) {
|
|
14420
|
-
const { readFileSync:
|
|
14420
|
+
const { readFileSync: readFileSync48, writeFileSync: writeFileSync31, existsSync: existsSync60, mkdirSync: mkdirSync33 } = __require("node:fs");
|
|
14421
14421
|
const metaDir = join23(this.cwd, ".oa", "memory", "metabolism");
|
|
14422
14422
|
const storeFile = join23(metaDir, "store.json");
|
|
14423
|
-
if (!
|
|
14423
|
+
if (!existsSync60(storeFile))
|
|
14424
14424
|
return;
|
|
14425
|
-
let
|
|
14425
|
+
let store2 = [];
|
|
14426
14426
|
try {
|
|
14427
|
-
|
|
14427
|
+
store2 = JSON.parse(readFileSync48(storeFile, "utf8"));
|
|
14428
14428
|
} catch {
|
|
14429
14429
|
return;
|
|
14430
14430
|
}
|
|
@@ -14433,7 +14433,7 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14433
14433
|
return;
|
|
14434
14434
|
const surfacedIds = new Set(idMatches.map((m) => m.slice(1, -1)));
|
|
14435
14435
|
let updated = false;
|
|
14436
|
-
for (const item of
|
|
14436
|
+
for (const item of store2) {
|
|
14437
14437
|
if (!surfacedIds.has(item.id))
|
|
14438
14438
|
continue;
|
|
14439
14439
|
item.accessCount++;
|
|
@@ -14448,8 +14448,8 @@ ${issues.map((i) => ` - ${i}`).join("\n")}` : " No issues found."),
|
|
|
14448
14448
|
updated = true;
|
|
14449
14449
|
}
|
|
14450
14450
|
if (updated) {
|
|
14451
|
-
|
|
14452
|
-
|
|
14451
|
+
mkdirSync33(metaDir, { recursive: true });
|
|
14452
|
+
writeFileSync31(storeFile, JSON.stringify(store2, null, 2));
|
|
14453
14453
|
}
|
|
14454
14454
|
}
|
|
14455
14455
|
// ── Storage ──────────────────────────────────────────────────────────
|
|
@@ -14871,13 +14871,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14871
14871
|
// Per EvoSkill (arXiv:2603.02766): retrieve relevant strategies from archive.
|
|
14872
14872
|
/** Retrieve top-K strategies for context injection. Returns "" if none. */
|
|
14873
14873
|
getRelevantStrategiesSync(k = 3, taskType) {
|
|
14874
|
-
const { readFileSync:
|
|
14874
|
+
const { readFileSync: readFileSync48, existsSync: existsSync60 } = __require("node:fs");
|
|
14875
14875
|
const archiveFile = join25(this.cwd, ".oa", "arche", "variants.json");
|
|
14876
|
-
if (!
|
|
14876
|
+
if (!existsSync60(archiveFile))
|
|
14877
14877
|
return "";
|
|
14878
14878
|
let variants = [];
|
|
14879
14879
|
try {
|
|
14880
|
-
variants = JSON.parse(
|
|
14880
|
+
variants = JSON.parse(readFileSync48(archiveFile, "utf8"));
|
|
14881
14881
|
} catch {
|
|
14882
14882
|
return "";
|
|
14883
14883
|
}
|
|
@@ -14895,13 +14895,13 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14895
14895
|
}
|
|
14896
14896
|
/** Archive a strategy variant synchronously (for task completion path) */
|
|
14897
14897
|
archiveVariantSync(strategy, outcome, tags = []) {
|
|
14898
|
-
const { readFileSync:
|
|
14898
|
+
const { readFileSync: readFileSync48, writeFileSync: writeFileSync31, existsSync: existsSync60, mkdirSync: mkdirSync33 } = __require("node:fs");
|
|
14899
14899
|
const dir = join25(this.cwd, ".oa", "arche");
|
|
14900
14900
|
const archiveFile = join25(dir, "variants.json");
|
|
14901
14901
|
let variants = [];
|
|
14902
14902
|
try {
|
|
14903
|
-
if (
|
|
14904
|
-
variants = JSON.parse(
|
|
14903
|
+
if (existsSync60(archiveFile))
|
|
14904
|
+
variants = JSON.parse(readFileSync48(archiveFile, "utf8"));
|
|
14905
14905
|
} catch {
|
|
14906
14906
|
}
|
|
14907
14907
|
variants.push({
|
|
@@ -14916,8 +14916,8 @@ Recommendation: Strategy ${scored[0].index + 1} scores highest.`;
|
|
|
14916
14916
|
});
|
|
14917
14917
|
if (variants.length > 50)
|
|
14918
14918
|
variants = variants.slice(-50);
|
|
14919
|
-
|
|
14920
|
-
|
|
14919
|
+
mkdirSync33(dir, { recursive: true });
|
|
14920
|
+
writeFileSync31(archiveFile, JSON.stringify(variants, null, 2));
|
|
14921
14921
|
}
|
|
14922
14922
|
async saveArchive(variants) {
|
|
14923
14923
|
const dir = join25(this.cwd, ".oa", "arche");
|
|
@@ -18168,12 +18168,12 @@ async function loadStore(workingDir) {
|
|
|
18168
18168
|
return { tasks: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
18169
18169
|
}
|
|
18170
18170
|
}
|
|
18171
|
-
async function saveStore(workingDir,
|
|
18171
|
+
async function saveStore(workingDir, store2) {
|
|
18172
18172
|
const dir = resolve23(workingDir, ".oa", "scheduled");
|
|
18173
18173
|
await mkdir11(dir, { recursive: true });
|
|
18174
18174
|
await mkdir11(join34(dir, "logs"), { recursive: true });
|
|
18175
|
-
|
|
18176
|
-
await writeFile15(join34(dir, "tasks.json"), JSON.stringify(
|
|
18175
|
+
store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
18176
|
+
await writeFile15(join34(dir, "tasks.json"), JSON.stringify(store2, null, 2), "utf-8");
|
|
18177
18177
|
}
|
|
18178
18178
|
function globalStoreDir() {
|
|
18179
18179
|
return join34(homedir9(), ".open-agents", "scheduled");
|
|
@@ -18186,12 +18186,12 @@ async function loadGlobalStore() {
|
|
|
18186
18186
|
return { tasks: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
18187
18187
|
}
|
|
18188
18188
|
}
|
|
18189
|
-
async function saveGlobalStore(
|
|
18189
|
+
async function saveGlobalStore(store2) {
|
|
18190
18190
|
const dir = globalStoreDir();
|
|
18191
18191
|
await mkdir11(dir, { recursive: true });
|
|
18192
18192
|
await mkdir11(join34(dir, "logs"), { recursive: true });
|
|
18193
|
-
|
|
18194
|
-
await writeFile15(join34(dir, "tasks.json"), JSON.stringify(
|
|
18193
|
+
store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
18194
|
+
await writeFile15(join34(dir, "tasks.json"), JSON.stringify(store2, null, 2), "utf-8");
|
|
18195
18195
|
}
|
|
18196
18196
|
async function loadAllStores(workingDir) {
|
|
18197
18197
|
const [local, global] = await Promise.all([
|
|
@@ -18332,13 +18332,13 @@ var init_scheduler = __esm({
|
|
|
18332
18332
|
projectDir: resolve23(this.workingDir)
|
|
18333
18333
|
};
|
|
18334
18334
|
if (scope === "global") {
|
|
18335
|
-
const
|
|
18336
|
-
|
|
18337
|
-
await saveGlobalStore(
|
|
18335
|
+
const store2 = await loadGlobalStore();
|
|
18336
|
+
store2.tasks.push(newTask);
|
|
18337
|
+
await saveGlobalStore(store2);
|
|
18338
18338
|
} else {
|
|
18339
|
-
const
|
|
18340
|
-
|
|
18341
|
-
await saveStore(this.workingDir,
|
|
18339
|
+
const store2 = await loadStore(this.workingDir);
|
|
18340
|
+
store2.tasks.push(newTask);
|
|
18341
|
+
await saveStore(this.workingDir, store2);
|
|
18342
18342
|
}
|
|
18343
18343
|
installCronJob(newTask, this.workingDir);
|
|
18344
18344
|
return {
|
|
@@ -18418,12 +18418,12 @@ var init_scheduler = __esm({
|
|
|
18418
18418
|
const id = String(args["id"] ?? "");
|
|
18419
18419
|
if (!id)
|
|
18420
18420
|
return { success: false, output: "", error: "id is required for cancel action", durationMs: performance.now() - start };
|
|
18421
|
-
const
|
|
18422
|
-
const idx =
|
|
18421
|
+
const store2 = await loadStore(this.workingDir);
|
|
18422
|
+
const idx = store2.tasks.findIndex((t) => t.id === id);
|
|
18423
18423
|
if (idx === -1)
|
|
18424
18424
|
return { success: false, output: "", error: `No task found with ID '${id}'`, durationMs: performance.now() - start };
|
|
18425
|
-
const removed =
|
|
18426
|
-
await saveStore(this.workingDir,
|
|
18425
|
+
const removed = store2.tasks.splice(idx, 1)[0];
|
|
18426
|
+
await saveStore(this.workingDir, store2);
|
|
18427
18427
|
removeCronJob(id);
|
|
18428
18428
|
return {
|
|
18429
18429
|
success: true,
|
|
@@ -18435,12 +18435,12 @@ var init_scheduler = __esm({
|
|
|
18435
18435
|
const id = String(args["id"] ?? "");
|
|
18436
18436
|
if (!id)
|
|
18437
18437
|
return { success: false, output: "", error: "id is required", durationMs: performance.now() - start };
|
|
18438
|
-
const
|
|
18439
|
-
const task =
|
|
18438
|
+
const store2 = await loadStore(this.workingDir);
|
|
18439
|
+
const task = store2.tasks.find((t) => t.id === id);
|
|
18440
18440
|
if (!task)
|
|
18441
18441
|
return { success: false, output: "", error: `No task found with ID '${id}'`, durationMs: performance.now() - start };
|
|
18442
18442
|
task.enabled = enable;
|
|
18443
|
-
await saveStore(this.workingDir,
|
|
18443
|
+
await saveStore(this.workingDir, store2);
|
|
18444
18444
|
if (enable) {
|
|
18445
18445
|
installCronJob(task, this.workingDir);
|
|
18446
18446
|
} else {
|
|
@@ -18535,15 +18535,15 @@ async function loadReminderStore(workingDir) {
|
|
|
18535
18535
|
return { reminders: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
18536
18536
|
}
|
|
18537
18537
|
}
|
|
18538
|
-
async function saveReminderStore(workingDir,
|
|
18538
|
+
async function saveReminderStore(workingDir, store2) {
|
|
18539
18539
|
const storePath = await getStorePath(workingDir);
|
|
18540
|
-
|
|
18541
|
-
await writeFile16(storePath, JSON.stringify(
|
|
18540
|
+
store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
18541
|
+
await writeFile16(storePath, JSON.stringify(store2, null, 2), "utf-8");
|
|
18542
18542
|
}
|
|
18543
18543
|
async function getDueReminders(workingDir) {
|
|
18544
|
-
const
|
|
18544
|
+
const store2 = await loadReminderStore(workingDir);
|
|
18545
18545
|
const now = /* @__PURE__ */ new Date();
|
|
18546
|
-
return
|
|
18546
|
+
return store2.reminders.filter((r) => {
|
|
18547
18547
|
if (r.status !== "pending")
|
|
18548
18548
|
return false;
|
|
18549
18549
|
if (!r.dueAt)
|
|
@@ -18552,15 +18552,15 @@ async function getDueReminders(workingDir) {
|
|
|
18552
18552
|
});
|
|
18553
18553
|
}
|
|
18554
18554
|
async function markRemindersSeen(workingDir, ids) {
|
|
18555
|
-
const
|
|
18555
|
+
const store2 = await loadReminderStore(workingDir);
|
|
18556
18556
|
const idSet = new Set(ids);
|
|
18557
|
-
for (const r of
|
|
18557
|
+
for (const r of store2.reminders) {
|
|
18558
18558
|
if (idSet.has(r.id) && r.status === "pending") {
|
|
18559
18559
|
r.status = "seen";
|
|
18560
18560
|
r.seenAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
18561
18561
|
}
|
|
18562
18562
|
}
|
|
18563
|
-
await saveReminderStore(workingDir,
|
|
18563
|
+
await saveReminderStore(workingDir, store2);
|
|
18564
18564
|
}
|
|
18565
18565
|
var STORE_FILE, ReminderTool;
|
|
18566
18566
|
var init_reminder = __esm({
|
|
@@ -18683,9 +18683,9 @@ var init_reminder = __esm({
|
|
|
18683
18683
|
context,
|
|
18684
18684
|
source: "agent"
|
|
18685
18685
|
};
|
|
18686
|
-
const
|
|
18687
|
-
|
|
18688
|
-
await saveReminderStore(this.workingDir,
|
|
18686
|
+
const store2 = await loadReminderStore(this.workingDir);
|
|
18687
|
+
store2.reminders.push(entry);
|
|
18688
|
+
await saveReminderStore(this.workingDir, store2);
|
|
18689
18689
|
return {
|
|
18690
18690
|
success: true,
|
|
18691
18691
|
output: [
|
|
@@ -18703,9 +18703,9 @@ var init_reminder = __esm({
|
|
|
18703
18703
|
};
|
|
18704
18704
|
}
|
|
18705
18705
|
async listReminders(args, start) {
|
|
18706
|
-
const
|
|
18706
|
+
const store2 = await loadReminderStore(this.workingDir);
|
|
18707
18707
|
const filter = String(args["filter"] ?? "pending");
|
|
18708
|
-
let filtered =
|
|
18708
|
+
let filtered = store2.reminders;
|
|
18709
18709
|
if (filter === "pending")
|
|
18710
18710
|
filtered = filtered.filter((r) => r.status === "pending" || r.status === "seen");
|
|
18711
18711
|
else if (filter !== "all")
|
|
@@ -18744,12 +18744,12 @@ var init_reminder = __esm({
|
|
|
18744
18744
|
const id = String(args["id"] ?? "");
|
|
18745
18745
|
if (!id)
|
|
18746
18746
|
return { success: false, output: "", error: "id is required", durationMs: performance.now() - start };
|
|
18747
|
-
const
|
|
18748
|
-
const reminder =
|
|
18747
|
+
const store2 = await loadReminderStore(this.workingDir);
|
|
18748
|
+
const reminder = store2.reminders.find((r) => r.id === id);
|
|
18749
18749
|
if (!reminder)
|
|
18750
18750
|
return { success: false, output: "", error: `No reminder found with ID '${id}'`, durationMs: performance.now() - start };
|
|
18751
18751
|
reminder.status = status;
|
|
18752
|
-
await saveReminderStore(this.workingDir,
|
|
18752
|
+
await saveReminderStore(this.workingDir, store2);
|
|
18753
18753
|
return {
|
|
18754
18754
|
success: true,
|
|
18755
18755
|
output: `Reminder '${id}' marked as ${status}: ${reminder.message.slice(0, 80)}`,
|
|
@@ -18764,15 +18764,15 @@ var init_reminder = __esm({
|
|
|
18764
18764
|
const parsed = parseDueTime(due);
|
|
18765
18765
|
if (!parsed)
|
|
18766
18766
|
return { success: false, output: "", error: `Cannot parse due time '${due}'`, durationMs: performance.now() - start };
|
|
18767
|
-
const
|
|
18768
|
-
const reminder =
|
|
18767
|
+
const store2 = await loadReminderStore(this.workingDir);
|
|
18768
|
+
const reminder = store2.reminders.find((r) => r.id === id);
|
|
18769
18769
|
if (!reminder)
|
|
18770
18770
|
return { success: false, output: "", error: `No reminder found with ID '${id}'`, durationMs: performance.now() - start };
|
|
18771
18771
|
reminder.status = "pending";
|
|
18772
18772
|
reminder.dueAt = parsed.isoDate;
|
|
18773
18773
|
reminder.dueDescription = parsed.description;
|
|
18774
18774
|
reminder.seenAt = void 0;
|
|
18775
|
-
await saveReminderStore(this.workingDir,
|
|
18775
|
+
await saveReminderStore(this.workingDir, store2);
|
|
18776
18776
|
return {
|
|
18777
18777
|
success: true,
|
|
18778
18778
|
output: `Reminder '${id}' snoozed until ${parsed.description}: ${reminder.message.slice(0, 80)}`,
|
|
@@ -18796,25 +18796,25 @@ async function loadAttentionStore(workingDir) {
|
|
|
18796
18796
|
return { items: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
18797
18797
|
}
|
|
18798
18798
|
}
|
|
18799
|
-
async function saveAttentionStore(workingDir,
|
|
18799
|
+
async function saveAttentionStore(workingDir, store2) {
|
|
18800
18800
|
const dir = resolve25(workingDir, ".oa", "scheduled");
|
|
18801
18801
|
await mkdir13(dir, { recursive: true });
|
|
18802
|
-
|
|
18803
|
-
await writeFile17(join36(dir, "attention.json"), JSON.stringify(
|
|
18802
|
+
store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
18803
|
+
await writeFile17(join36(dir, "attention.json"), JSON.stringify(store2, null, 2), "utf-8");
|
|
18804
18804
|
}
|
|
18805
18805
|
async function getActiveAttentionItems(workingDir) {
|
|
18806
|
-
const
|
|
18806
|
+
const store2 = await loadAttentionStore(workingDir);
|
|
18807
18807
|
const now = /* @__PURE__ */ new Date();
|
|
18808
18808
|
let changed = false;
|
|
18809
|
-
for (const item of
|
|
18809
|
+
for (const item of store2.items) {
|
|
18810
18810
|
if (item.status === "active" && item.expiresAt && new Date(item.expiresAt) <= now) {
|
|
18811
18811
|
item.status = "expired";
|
|
18812
18812
|
changed = true;
|
|
18813
18813
|
}
|
|
18814
18814
|
}
|
|
18815
18815
|
if (changed)
|
|
18816
|
-
await saveAttentionStore(workingDir,
|
|
18817
|
-
return
|
|
18816
|
+
await saveAttentionStore(workingDir, store2);
|
|
18817
|
+
return store2.items.filter((i) => i.status === "active");
|
|
18818
18818
|
}
|
|
18819
18819
|
var AgendaTool;
|
|
18820
18820
|
var init_agenda = __esm({
|
|
@@ -19002,9 +19002,9 @@ ${sections.join("\n")}`,
|
|
|
19002
19002
|
status: "active",
|
|
19003
19003
|
notes: notes2
|
|
19004
19004
|
};
|
|
19005
|
-
const
|
|
19006
|
-
|
|
19007
|
-
await saveAttentionStore(this.workingDir,
|
|
19005
|
+
const store2 = await loadAttentionStore(this.workingDir);
|
|
19006
|
+
store2.items.push(item);
|
|
19007
|
+
await saveAttentionStore(this.workingDir, store2);
|
|
19008
19008
|
return {
|
|
19009
19009
|
success: true,
|
|
19010
19010
|
output: [
|
|
@@ -19025,13 +19025,13 @@ ${sections.join("\n")}`,
|
|
|
19025
19025
|
const id = String(args["id"] ?? "");
|
|
19026
19026
|
if (!id)
|
|
19027
19027
|
return { success: false, output: "", error: "id is required for resolve", durationMs: performance.now() - start };
|
|
19028
|
-
const
|
|
19029
|
-
const item =
|
|
19028
|
+
const store2 = await loadAttentionStore(this.workingDir);
|
|
19029
|
+
const item = store2.items.find((i) => i.id === id);
|
|
19030
19030
|
if (!item)
|
|
19031
19031
|
return { success: false, output: "", error: `No attention item found with ID '${id}'`, durationMs: performance.now() - start };
|
|
19032
19032
|
item.status = "resolved";
|
|
19033
19033
|
item.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
19034
|
-
await saveAttentionStore(this.workingDir,
|
|
19034
|
+
await saveAttentionStore(this.workingDir, store2);
|
|
19035
19035
|
return {
|
|
19036
19036
|
success: true,
|
|
19037
19037
|
output: `Attention item '${id}' resolved: ${item.title}`,
|
|
@@ -19097,8 +19097,8 @@ ${sections.join("\n")}`,
|
|
|
19097
19097
|
try {
|
|
19098
19098
|
const storePath = resolve25(this.workingDir, ".oa", "scheduled", "tasks.json");
|
|
19099
19099
|
const raw = await readFile17(storePath, "utf-8");
|
|
19100
|
-
const
|
|
19101
|
-
return
|
|
19100
|
+
const store2 = JSON.parse(raw);
|
|
19101
|
+
return store2.tasks ?? [];
|
|
19102
19102
|
} catch {
|
|
19103
19103
|
return [];
|
|
19104
19104
|
}
|
|
@@ -19816,12 +19816,12 @@ async function loadStore2(workingDir) {
|
|
|
19816
19816
|
return { jobs: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
19817
19817
|
}
|
|
19818
19818
|
}
|
|
19819
|
-
async function saveStore2(workingDir,
|
|
19819
|
+
async function saveStore2(workingDir, store2) {
|
|
19820
19820
|
const dir = resolve27(workingDir, ".oa", "cron-agents");
|
|
19821
19821
|
await mkdir14(dir, { recursive: true });
|
|
19822
19822
|
await mkdir14(join39(dir, "logs"), { recursive: true });
|
|
19823
|
-
|
|
19824
|
-
await writeFile18(join39(dir, "store.json"), JSON.stringify(
|
|
19823
|
+
store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
19824
|
+
await writeFile18(join39(dir, "store.json"), JSON.stringify(store2, null, 2), "utf-8");
|
|
19825
19825
|
}
|
|
19826
19826
|
function globalCronDir() {
|
|
19827
19827
|
return join39(homedir10(), ".open-agents", "cron-agents");
|
|
@@ -19834,12 +19834,12 @@ async function loadGlobalCronStore() {
|
|
|
19834
19834
|
return { jobs: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
19835
19835
|
}
|
|
19836
19836
|
}
|
|
19837
|
-
async function saveGlobalCronStore(
|
|
19837
|
+
async function saveGlobalCronStore(store2) {
|
|
19838
19838
|
const dir = globalCronDir();
|
|
19839
19839
|
await mkdir14(dir, { recursive: true });
|
|
19840
19840
|
await mkdir14(join39(dir, "logs"), { recursive: true });
|
|
19841
|
-
|
|
19842
|
-
await writeFile18(join39(dir, "store.json"), JSON.stringify(
|
|
19841
|
+
store2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
19842
|
+
await writeFile18(join39(dir, "store.json"), JSON.stringify(store2, null, 2), "utf-8");
|
|
19843
19843
|
}
|
|
19844
19844
|
async function loadAllCronStores(workingDir) {
|
|
19845
19845
|
const [local, global] = await Promise.all([
|
|
@@ -20008,13 +20008,13 @@ var init_cron_agent = __esm({
|
|
|
20008
20008
|
projectDir: resolve27(this.workingDir)
|
|
20009
20009
|
};
|
|
20010
20010
|
if (scope === "global") {
|
|
20011
|
-
const
|
|
20012
|
-
|
|
20013
|
-
await saveGlobalCronStore(
|
|
20011
|
+
const store2 = await loadGlobalCronStore();
|
|
20012
|
+
store2.jobs.push(job);
|
|
20013
|
+
await saveGlobalCronStore(store2);
|
|
20014
20014
|
} else {
|
|
20015
|
-
const
|
|
20016
|
-
|
|
20017
|
-
await saveStore2(this.workingDir,
|
|
20015
|
+
const store2 = await loadStore2(this.workingDir);
|
|
20016
|
+
store2.jobs.push(job);
|
|
20017
|
+
await saveStore2(this.workingDir, store2);
|
|
20018
20018
|
}
|
|
20019
20019
|
installCronAgentJob(job, this.workingDir);
|
|
20020
20020
|
return {
|
|
@@ -20089,8 +20089,8 @@ var init_cron_agent = __esm({
|
|
|
20089
20089
|
const id = String(args["id"] ?? "");
|
|
20090
20090
|
if (!id)
|
|
20091
20091
|
return { success: false, output: "", error: "id is required", durationMs: performance.now() - start };
|
|
20092
|
-
const
|
|
20093
|
-
const job =
|
|
20092
|
+
const store2 = await loadStore2(this.workingDir);
|
|
20093
|
+
const job = store2.jobs.find((j) => j.id === id);
|
|
20094
20094
|
if (!job)
|
|
20095
20095
|
return { success: false, output: "", error: `No job found with ID '${id}'`, durationMs: performance.now() - start };
|
|
20096
20096
|
const lines = [
|
|
@@ -20124,12 +20124,12 @@ var init_cron_agent = __esm({
|
|
|
20124
20124
|
const id = String(args["id"] ?? "");
|
|
20125
20125
|
if (!id)
|
|
20126
20126
|
return { success: false, output: "", error: "id is required", durationMs: performance.now() - start };
|
|
20127
|
-
const
|
|
20128
|
-
const idx =
|
|
20127
|
+
const store2 = await loadStore2(this.workingDir);
|
|
20128
|
+
const idx = store2.jobs.findIndex((j) => j.id === id);
|
|
20129
20129
|
if (idx === -1)
|
|
20130
20130
|
return { success: false, output: "", error: `No job found with ID '${id}'`, durationMs: performance.now() - start };
|
|
20131
|
-
const removed =
|
|
20132
|
-
await saveStore2(this.workingDir,
|
|
20131
|
+
const removed = store2.jobs.splice(idx, 1)[0];
|
|
20132
|
+
await saveStore2(this.workingDir, store2);
|
|
20133
20133
|
removeCronAgentJob(id);
|
|
20134
20134
|
return {
|
|
20135
20135
|
success: true,
|
|
@@ -20155,8 +20155,8 @@ ${truncated}`, durationMs: performance.now() - start };
|
|
|
20155
20155
|
const id = String(args["id"] ?? "");
|
|
20156
20156
|
if (!id)
|
|
20157
20157
|
return { success: false, output: "", error: "id is required", durationMs: performance.now() - start };
|
|
20158
|
-
const
|
|
20159
|
-
const job =
|
|
20158
|
+
const store2 = await loadStore2(this.workingDir);
|
|
20159
|
+
const job = store2.jobs.find((j) => j.id === id);
|
|
20160
20160
|
if (!job)
|
|
20161
20161
|
return { success: false, output: "", error: `No job found with ID '${id}'`, durationMs: performance.now() - start };
|
|
20162
20162
|
const lines = [
|
|
@@ -20181,7 +20181,7 @@ ${truncated}`, durationMs: performance.now() - start };
|
|
|
20181
20181
|
lines.push(` cron_agent(action='cancel', id='${id}')`);
|
|
20182
20182
|
job.status = "completed";
|
|
20183
20183
|
removeCronAgentJob(id);
|
|
20184
|
-
await saveStore2(this.workingDir,
|
|
20184
|
+
await saveStore2(this.workingDir, store2);
|
|
20185
20185
|
lines.push(" Status automatically set to COMPLETED.");
|
|
20186
20186
|
} catch (err) {
|
|
20187
20187
|
const errMsg = err instanceof Error ? err.stderr?.toString() || err.message : String(err);
|
|
@@ -27422,10 +27422,10 @@ ${marker}` : marker);
|
|
|
27422
27422
|
if (!this._workingDirectory)
|
|
27423
27423
|
return;
|
|
27424
27424
|
try {
|
|
27425
|
-
const { mkdirSync:
|
|
27426
|
-
const { join:
|
|
27427
|
-
const sessionDir =
|
|
27428
|
-
|
|
27425
|
+
const { mkdirSync: mkdirSync33, writeFileSync: writeFileSync31 } = __require("node:fs");
|
|
27426
|
+
const { join: join80 } = __require("node:path");
|
|
27427
|
+
const sessionDir = join80(this._workingDirectory, ".oa", "session", this._sessionId);
|
|
27428
|
+
mkdirSync33(sessionDir, { recursive: true });
|
|
27429
27429
|
const checkpoint = {
|
|
27430
27430
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27431
27431
|
sessionId: this._sessionId,
|
|
@@ -27437,7 +27437,7 @@ ${marker}` : marker);
|
|
|
27437
27437
|
memexEntryCount: this._memexArchive.size,
|
|
27438
27438
|
fileRegistrySize: this._fileRegistry.size
|
|
27439
27439
|
};
|
|
27440
|
-
|
|
27440
|
+
writeFileSync31(join80(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
|
|
27441
27441
|
} catch {
|
|
27442
27442
|
}
|
|
27443
27443
|
}
|
|
@@ -28575,17 +28575,17 @@ ${transcript}`
|
|
|
28575
28575
|
let resizedBase64 = null;
|
|
28576
28576
|
try {
|
|
28577
28577
|
const { execSync: execSync36 } = await import("node:child_process");
|
|
28578
|
-
const { writeFileSync:
|
|
28579
|
-
const { join:
|
|
28578
|
+
const { writeFileSync: writeFileSync31, readFileSync: readFileSync48, unlinkSync: unlinkSync13 } = await import("node:fs");
|
|
28579
|
+
const { join: join80 } = await import("node:path");
|
|
28580
28580
|
const { tmpdir: tmpdir11 } = await import("node:os");
|
|
28581
|
-
const tmpIn =
|
|
28582
|
-
const tmpOut =
|
|
28583
|
-
|
|
28581
|
+
const tmpIn = join80(tmpdir11(), `oa_img_in_${Date.now()}.png`);
|
|
28582
|
+
const tmpOut = join80(tmpdir11(), `oa_img_out_${Date.now()}.jpg`);
|
|
28583
|
+
writeFileSync31(tmpIn, buffer);
|
|
28584
28584
|
const pyBin = process.platform === "win32" ? "python" : "python3";
|
|
28585
28585
|
const escapedIn = tmpIn.replace(/\\/g, "\\\\");
|
|
28586
28586
|
const escapedOut = tmpOut.replace(/\\/g, "\\\\");
|
|
28587
28587
|
execSync36(`${pyBin} -c "from PIL import Image; img = Image.open('${escapedIn}'); img.thumbnail((512, 512), Image.LANCZOS); img = img.convert('RGB'); img.save('${escapedOut}', 'JPEG', quality=75)"`, { timeout: 1e4, stdio: "pipe" });
|
|
28588
|
-
const resizedBuf =
|
|
28588
|
+
const resizedBuf = readFileSync48(tmpOut);
|
|
28589
28589
|
resizedBase64 = `data:image/jpeg;base64,${resizedBuf.toString("base64")}`;
|
|
28590
28590
|
try {
|
|
28591
28591
|
unlinkSync13(tmpIn);
|
|
@@ -30716,8 +30716,8 @@ var init_listen = __esm({
|
|
|
30716
30716
|
const nvmBase = join48(homedir11(), ".nvm", "versions", "node");
|
|
30717
30717
|
if (existsSync32(nvmBase)) {
|
|
30718
30718
|
try {
|
|
30719
|
-
const { readdirSync:
|
|
30720
|
-
for (const ver of
|
|
30719
|
+
const { readdirSync: readdirSync25 } = await import("node:fs");
|
|
30720
|
+
for (const ver of readdirSync25(nvmBase)) {
|
|
30721
30721
|
const tcPath = join48(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
30722
30722
|
if (existsSync32(join48(tcPath, "dist", "index.js"))) {
|
|
30723
30723
|
const { createRequire: createRequire6 } = await import("node:module");
|
|
@@ -39557,26 +39557,26 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
|
|
|
39557
39557
|
async function fetchPeerModels(peerId, authKey) {
|
|
39558
39558
|
try {
|
|
39559
39559
|
const { NexusTool: NexusTool2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
39560
|
-
const { existsSync:
|
|
39561
|
-
const { join:
|
|
39560
|
+
const { existsSync: existsSync60, readFileSync: readFileSync48 } = await import("node:fs");
|
|
39561
|
+
const { join: join80 } = await import("node:path");
|
|
39562
39562
|
const cwd4 = process.cwd();
|
|
39563
39563
|
const nexusTool = new NexusTool2(cwd4);
|
|
39564
39564
|
const nexusDir = nexusTool.getNexusDir();
|
|
39565
39565
|
let isLocalPeer = false;
|
|
39566
39566
|
try {
|
|
39567
|
-
const statusPath =
|
|
39568
|
-
if (
|
|
39569
|
-
const status = JSON.parse(
|
|
39567
|
+
const statusPath = join80(nexusDir, "status.json");
|
|
39568
|
+
if (existsSync60(statusPath)) {
|
|
39569
|
+
const status = JSON.parse(readFileSync48(statusPath, "utf8"));
|
|
39570
39570
|
if (status.peerId === peerId)
|
|
39571
39571
|
isLocalPeer = true;
|
|
39572
39572
|
}
|
|
39573
39573
|
} catch {
|
|
39574
39574
|
}
|
|
39575
39575
|
if (isLocalPeer) {
|
|
39576
|
-
const pricingPath =
|
|
39577
|
-
if (
|
|
39576
|
+
const pricingPath = join80(nexusDir, "pricing.json");
|
|
39577
|
+
if (existsSync60(pricingPath)) {
|
|
39578
39578
|
try {
|
|
39579
|
-
const pricing = JSON.parse(
|
|
39579
|
+
const pricing = JSON.parse(readFileSync48(pricingPath, "utf8"));
|
|
39580
39580
|
const localModels = (pricing.models || []).map((m) => ({
|
|
39581
39581
|
name: m.model || "unknown",
|
|
39582
39582
|
size: m.parameterSize || "",
|
|
@@ -39590,10 +39590,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
39590
39590
|
}
|
|
39591
39591
|
}
|
|
39592
39592
|
}
|
|
39593
|
-
const cachePath =
|
|
39594
|
-
if (
|
|
39593
|
+
const cachePath = join80(nexusDir, "peer-models-cache.json");
|
|
39594
|
+
if (existsSync60(cachePath)) {
|
|
39595
39595
|
try {
|
|
39596
|
-
const cache4 = JSON.parse(
|
|
39596
|
+
const cache4 = JSON.parse(readFileSync48(cachePath, "utf8"));
|
|
39597
39597
|
if (cache4.peerId === peerId && cache4.models?.length > 0) {
|
|
39598
39598
|
const age = Date.now() - new Date(cache4.cachedAt).getTime();
|
|
39599
39599
|
if (age < 5 * 60 * 1e3) {
|
|
@@ -39708,10 +39708,10 @@ async function fetchPeerModels(peerId, authKey) {
|
|
|
39708
39708
|
} catch {
|
|
39709
39709
|
}
|
|
39710
39710
|
if (isLocalPeer) {
|
|
39711
|
-
const pricingPath =
|
|
39712
|
-
if (
|
|
39711
|
+
const pricingPath = join80(nexusDir, "pricing.json");
|
|
39712
|
+
if (existsSync60(pricingPath)) {
|
|
39713
39713
|
try {
|
|
39714
|
-
const pricing = JSON.parse(
|
|
39714
|
+
const pricing = JSON.parse(readFileSync48(pricingPath, "utf8"));
|
|
39715
39715
|
return (pricing.models || []).map((m) => ({
|
|
39716
39716
|
name: m.model || "unknown",
|
|
39717
39717
|
size: m.parameterSize || "",
|
|
@@ -49671,8 +49671,8 @@ async function handleSlashCommand(input, ctx) {
|
|
|
49671
49671
|
try {
|
|
49672
49672
|
const metaFile = join59(ctx.repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
49673
49673
|
if (existsSync43(metaFile)) {
|
|
49674
|
-
const
|
|
49675
|
-
const active =
|
|
49674
|
+
const store2 = JSON.parse(readFileSync32(metaFile, "utf8"));
|
|
49675
|
+
const active = store2.filter((m) => m.type !== "quarantine");
|
|
49676
49676
|
const recoveries = active.filter((m) => m.content?.startsWith("[recovery]")).length;
|
|
49677
49677
|
const strategies = active.filter((m) => m.content?.startsWith("[strategy]")).length;
|
|
49678
49678
|
const optimizations = active.filter((m) => m.content?.startsWith("[optimization]")).length;
|
|
@@ -52121,12 +52121,12 @@ async function handleVoiceMenu(ctx, save, hasLocal) {
|
|
|
52121
52121
|
continue;
|
|
52122
52122
|
}
|
|
52123
52123
|
const { basename: basename18, join: pathJoin } = await import("node:path");
|
|
52124
|
-
const { copyFileSync: copyFileSync3, mkdirSync:
|
|
52124
|
+
const { copyFileSync: copyFileSync3, mkdirSync: mkdirSync33, existsSync: exists } = await import("node:fs");
|
|
52125
52125
|
const { homedir: homedir21 } = await import("node:os");
|
|
52126
52126
|
const modelName = basename18(onnxDrop.path, ".onnx").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
52127
52127
|
const destDir = pathJoin(homedir21(), ".open-agents", "voice", "models", modelName);
|
|
52128
52128
|
if (!exists(destDir))
|
|
52129
|
-
|
|
52129
|
+
mkdirSync33(destDir, { recursive: true });
|
|
52130
52130
|
copyFileSync3(onnxDrop.path, pathJoin(destDir, "model.onnx"));
|
|
52131
52131
|
copyFileSync3(jsonDrop.path, pathJoin(destDir, "config.json"));
|
|
52132
52132
|
const { registerCustomOnnxModel: registerCustomOnnxModel2 } = await Promise.resolve().then(() => (init_voice(), voice_exports));
|
|
@@ -52965,11 +52965,11 @@ async function handlePeerEndpoint(peerId, authKey, ctx, local) {
|
|
|
52965
52965
|
const models = await fetchModels(peerUrl, authKey);
|
|
52966
52966
|
if (models.length > 0) {
|
|
52967
52967
|
try {
|
|
52968
|
-
const { writeFileSync:
|
|
52969
|
-
const { join:
|
|
52970
|
-
const cachePath =
|
|
52971
|
-
|
|
52972
|
-
|
|
52968
|
+
const { writeFileSync: writeFileSync31, mkdirSync: mkdirSync33 } = await import("node:fs");
|
|
52969
|
+
const { join: join80, dirname: dirname24 } = await import("node:path");
|
|
52970
|
+
const cachePath = join80(ctx.repoRoot || process.cwd(), ".oa", "nexus", "peer-models-cache.json");
|
|
52971
|
+
mkdirSync33(dirname24(cachePath), { recursive: true });
|
|
52972
|
+
writeFileSync31(cachePath, JSON.stringify({
|
|
52973
52973
|
peerId,
|
|
52974
52974
|
cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
52975
52975
|
models: models.map((m) => ({ name: m.name, size: m.size, parameterSize: m.parameterSize }))
|
|
@@ -53168,17 +53168,17 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
53168
53168
|
try {
|
|
53169
53169
|
const { createRequire: createRequire6 } = await import("node:module");
|
|
53170
53170
|
const { fileURLToPath: fileURLToPath16 } = await import("node:url");
|
|
53171
|
-
const { dirname: dirname24, join:
|
|
53172
|
-
const { existsSync:
|
|
53171
|
+
const { dirname: dirname24, join: join80 } = await import("node:path");
|
|
53172
|
+
const { existsSync: existsSync60 } = await import("node:fs");
|
|
53173
53173
|
const req = createRequire6(import.meta.url);
|
|
53174
53174
|
const thisDir = dirname24(fileURLToPath16(import.meta.url));
|
|
53175
53175
|
const candidates = [
|
|
53176
|
-
|
|
53177
|
-
|
|
53178
|
-
|
|
53176
|
+
join80(thisDir, "..", "package.json"),
|
|
53177
|
+
join80(thisDir, "..", "..", "package.json"),
|
|
53178
|
+
join80(thisDir, "..", "..", "..", "package.json")
|
|
53179
53179
|
];
|
|
53180
53180
|
for (const pkgPath of candidates) {
|
|
53181
|
-
if (
|
|
53181
|
+
if (existsSync60(pkgPath)) {
|
|
53182
53182
|
const pkg = req(pkgPath);
|
|
53183
53183
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
53184
53184
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -54151,11 +54151,11 @@ function loadMemoryDir(memDir, scope) {
|
|
|
54151
54151
|
return lines.join("\n");
|
|
54152
54152
|
}
|
|
54153
54153
|
function loadSessionHistory(repoRoot) {
|
|
54154
|
-
const
|
|
54155
|
-
if (
|
|
54154
|
+
const sessions2 = loadRecentSessions(repoRoot, 5);
|
|
54155
|
+
if (sessions2.length === 0)
|
|
54156
54156
|
return "";
|
|
54157
54157
|
const lines = ["Recent tasks in this project:"];
|
|
54158
|
-
for (const s of
|
|
54158
|
+
for (const s of sessions2) {
|
|
54159
54159
|
if (!s.startedAt || !s.task)
|
|
54160
54160
|
continue;
|
|
54161
54161
|
const status = s.completed ? "completed" : "incomplete";
|
|
@@ -54176,11 +54176,11 @@ function getEnvironment(repoRoot) {
|
|
|
54176
54176
|
];
|
|
54177
54177
|
return lines.join("\n");
|
|
54178
54178
|
}
|
|
54179
|
-
function loadTaskMemories(repoRoot,
|
|
54179
|
+
function loadTaskMemories(repoRoot, store2) {
|
|
54180
54180
|
try {
|
|
54181
|
-
let tasks =
|
|
54181
|
+
let tasks = store2.listByRepo(repoRoot);
|
|
54182
54182
|
if (tasks.length === 0) {
|
|
54183
|
-
tasks =
|
|
54183
|
+
tasks = store2.recent(10);
|
|
54184
54184
|
}
|
|
54185
54185
|
if (tasks.length === 0)
|
|
54186
54186
|
return "";
|
|
@@ -54198,9 +54198,9 @@ function loadTaskMemories(repoRoot, store) {
|
|
|
54198
54198
|
return "";
|
|
54199
54199
|
}
|
|
54200
54200
|
}
|
|
54201
|
-
function loadFailurePatterns(
|
|
54201
|
+
function loadFailurePatterns(store2) {
|
|
54202
54202
|
try {
|
|
54203
|
-
const unresolved =
|
|
54203
|
+
const unresolved = store2.listUnresolved();
|
|
54204
54204
|
if (unresolved.length === 0)
|
|
54205
54205
|
return "";
|
|
54206
54206
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -54222,10 +54222,10 @@ function loadFailurePatterns(store) {
|
|
|
54222
54222
|
return "";
|
|
54223
54223
|
}
|
|
54224
54224
|
}
|
|
54225
|
-
function loadPatternSuggestions(repoRoot,
|
|
54225
|
+
function loadPatternSuggestions(repoRoot, store2) {
|
|
54226
54226
|
try {
|
|
54227
|
-
const projectPatterns =
|
|
54228
|
-
const globalPatterns =
|
|
54227
|
+
const projectPatterns = store2.detectPatterns({ repoRoot, minOccurrences: 3, minLen: 3 });
|
|
54228
|
+
const globalPatterns = store2.detectPatterns({ minOccurrences: 3, minLen: 3 });
|
|
54229
54229
|
const all = [...projectPatterns];
|
|
54230
54230
|
for (const gp of globalPatterns) {
|
|
54231
54231
|
const fp = gp.pattern.map((e) => e.tool).join("->");
|
|
@@ -55490,8 +55490,8 @@ function listBannerDesigns(workDir) {
|
|
|
55490
55490
|
if (!existsSync45(dir))
|
|
55491
55491
|
return [];
|
|
55492
55492
|
try {
|
|
55493
|
-
const { readdirSync:
|
|
55494
|
-
return
|
|
55493
|
+
const { readdirSync: readdirSync25 } = __require("node:fs");
|
|
55494
|
+
return readdirSync25(dir).filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", ""));
|
|
55495
55495
|
} catch {
|
|
55496
55496
|
return [];
|
|
55497
55497
|
}
|
|
@@ -56039,8 +56039,8 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
56039
56039
|
}
|
|
56040
56040
|
function extractFromSessions(repoRoot, tags) {
|
|
56041
56041
|
try {
|
|
56042
|
-
const
|
|
56043
|
-
for (const session of
|
|
56042
|
+
const sessions2 = loadRecentSessions(repoRoot, 10);
|
|
56043
|
+
for (const session of sessions2) {
|
|
56044
56044
|
if (session.task) {
|
|
56045
56045
|
const words = session.task.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 3 && !STOP_WORDS.has(w));
|
|
56046
56046
|
tags.push(...words.slice(0, 4));
|
|
@@ -65567,8 +65567,16 @@ body {
|
|
|
65567
65567
|
<select id="config-model-select" style="background:#2a2a30;border:1px solid #3a3a42;color:#b0b0b0;padding:4px 8px;border-radius:3px;font-family:inherit;font-size:0.7rem;flex:1"></select>
|
|
65568
65568
|
<button onclick="switchModel()" style="background:#2a2a30;border:1px solid #3a3a42;color:#b2920a;padding:4px 12px;border-radius:3px;font-family:inherit;font-size:0.7rem;cursor:pointer">switch</button>
|
|
65569
65569
|
</div>
|
|
65570
|
-
<h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">
|
|
65571
|
-
<div id="config-endpoint" style="font-size:0.78rem;color:#888"></div>
|
|
65570
|
+
<h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">Inference Provider</h3>
|
|
65571
|
+
<div id="config-endpoint" style="font-size:0.78rem;color:#888;margin-bottom:8px"></div>
|
|
65572
|
+
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:4px">
|
|
65573
|
+
<input id="config-ep-url" placeholder="https://api.example.com/v1" style="flex:1;min-width:200px;background:#2a2a30;border:1px solid #3a3a42;border-radius:3px;padding:4px 8px;color:#b0b0b0;font-family:inherit;font-size:0.7rem;outline:none">
|
|
65574
|
+
<input id="config-ep-key" placeholder="Bearer key (optional)" type="password" style="flex:1;min-width:150px;background:#2a2a30;border:1px solid #3a3a42;border-radius:3px;padding:4px 8px;color:#b0b0b0;font-family:inherit;font-size:0.7rem;outline:none">
|
|
65575
|
+
<select id="config-ep-type" style="background:#2a2a30;border:1px solid #3a3a42;color:#b0b0b0;padding:4px 8px;border-radius:3px;font-family:inherit;font-size:0.7rem">
|
|
65576
|
+
<option value="ollama">ollama</option><option value="vllm">vllm</option><option value="openai">openai</option>
|
|
65577
|
+
</select>
|
|
65578
|
+
<button onclick="switchEndpoint()" style="background:#2a2a30;border:1px solid #3a3a42;color:#b2920a;padding:4px 12px;border-radius:3px;font-family:inherit;font-size:0.7rem;cursor:pointer">set</button>
|
|
65579
|
+
</div>
|
|
65572
65580
|
<h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">Profiles</h3>
|
|
65573
65581
|
<div id="config-profiles" style="font-size:0.78rem"></div>
|
|
65574
65582
|
<h3 style="color:#b2920a;font-size:0.7rem;margin:16px 0 8px">Export Conversation</h3>
|
|
@@ -65609,6 +65617,7 @@ const statusEl = document.getElementById('status');
|
|
|
65609
65617
|
let apiKey = localStorage.getItem('oa-api-key') || '';
|
|
65610
65618
|
let streaming = false;
|
|
65611
65619
|
let messages = [];
|
|
65620
|
+
let chatSessionId = null; // stateful session for /v1/chat
|
|
65612
65621
|
|
|
65613
65622
|
// Auto-resize textarea
|
|
65614
65623
|
input.addEventListener('input', () => {
|
|
@@ -65714,22 +65723,25 @@ async function sendMessage() {
|
|
|
65714
65723
|
let fullContent = '';
|
|
65715
65724
|
|
|
65716
65725
|
try {
|
|
65726
|
+
// Use stateful /v1/chat endpoint (maintains OA identity + context)
|
|
65717
65727
|
const body = {
|
|
65728
|
+
session_id: chatSessionId,
|
|
65718
65729
|
model: modelSelect.value,
|
|
65719
|
-
|
|
65720
|
-
...(sysPrompt ? [{ role: 'system', content: sysPrompt }] : []),
|
|
65721
|
-
...messages,
|
|
65722
|
-
],
|
|
65730
|
+
message: text,
|
|
65723
65731
|
stream: true,
|
|
65724
65732
|
max_tokens: 4096,
|
|
65725
65733
|
};
|
|
65726
65734
|
|
|
65727
|
-
const response = await fetch('/v1/chat
|
|
65735
|
+
const response = await fetch('/v1/chat', {
|
|
65728
65736
|
method: 'POST',
|
|
65729
65737
|
headers: headers(),
|
|
65730
65738
|
body: JSON.stringify(body),
|
|
65731
65739
|
});
|
|
65732
65740
|
|
|
65741
|
+
// Capture session ID from response header
|
|
65742
|
+
const sid = response.headers.get('x-session-id');
|
|
65743
|
+
if (sid) chatSessionId = sid;
|
|
65744
|
+
|
|
65733
65745
|
const reader = response.body.getReader();
|
|
65734
65746
|
const decoder = new TextDecoder();
|
|
65735
65747
|
let buffer = '';
|
|
@@ -65867,6 +65879,21 @@ async function loadConfig() {
|
|
|
65867
65879
|
} catch {}
|
|
65868
65880
|
}
|
|
65869
65881
|
|
|
65882
|
+
async function switchEndpoint() {
|
|
65883
|
+
const url = document.getElementById('config-ep-url').value.trim();
|
|
65884
|
+
const auth = document.getElementById('config-ep-key').value.trim();
|
|
65885
|
+
const backendType = document.getElementById('config-ep-type').value;
|
|
65886
|
+
if (!url) return;
|
|
65887
|
+
try {
|
|
65888
|
+
await fetch('/v1/config/endpoint', {
|
|
65889
|
+
method: 'PUT', headers: headers(),
|
|
65890
|
+
body: JSON.stringify({ url, auth: auth ? 'Bearer ' + auth : '', backendType }),
|
|
65891
|
+
});
|
|
65892
|
+
loadConfig();
|
|
65893
|
+
loadModels(); // refresh model list from new endpoint
|
|
65894
|
+
} catch {}
|
|
65895
|
+
}
|
|
65896
|
+
|
|
65870
65897
|
async function switchModel() {
|
|
65871
65898
|
const model = document.getElementById('config-model-select').value;
|
|
65872
65899
|
if (!model) return;
|
|
@@ -66038,19 +66065,39 @@ async function loadDashboard() {
|
|
|
66038
66065
|
'<div style="color:#555;font-size:0.6rem">VERSION</div>' +
|
|
66039
66066
|
'<div style="color:#b0b0b0;font-size:0.8rem">' + d.version + '</div></div>';
|
|
66040
66067
|
} catch {}
|
|
66041
|
-
// Usage
|
|
66068
|
+
// Usage \u2014 per-provider breakdown with persistent totals
|
|
66042
66069
|
try {
|
|
66043
66070
|
const r = await fetch('/v1/usage', { headers: headers() });
|
|
66044
66071
|
const d = await r.json();
|
|
66072
|
+
const ps = d.persistent?.byProvider || {};
|
|
66073
|
+
let providerCards = '';
|
|
66074
|
+
for (const [label, stats] of Object.entries(ps)) {
|
|
66075
|
+
const s = stats;
|
|
66076
|
+
providerCards +=
|
|
66077
|
+
'<div style="background:#1e1e22;border-left:2px solid #b2920a;padding:8px 12px;margin:4px 0">' +
|
|
66078
|
+
'<div style="color:#b2920a;font-size:0.7rem;font-weight:bold">' + label + '</div>' +
|
|
66079
|
+
'<div style="display:flex;gap:16px;margin-top:4px">' +
|
|
66080
|
+
'<span style="color:#555;font-size:0.65rem">in: <span style="color:#b0b0b0">' + (s.tokensIn || 0).toLocaleString() + '</span></span>' +
|
|
66081
|
+
'<span style="color:#555;font-size:0.65rem">out: <span style="color:#b0b0b0">' + (s.tokensOut || 0).toLocaleString() + '</span></span>' +
|
|
66082
|
+
'<span style="color:#555;font-size:0.65rem">reqs: <span style="color:#b0b0b0">' + (s.requests || 0).toLocaleString() + '</span></span>' +
|
|
66083
|
+
'</div></div>';
|
|
66084
|
+
}
|
|
66085
|
+
const totalIn = d.persistent?.totalIn || d.totalTokensIn || 0;
|
|
66086
|
+
const totalOut = d.persistent?.totalOut || d.totalTokensOut || 0;
|
|
66045
66087
|
document.getElementById('dashboard-usage').innerHTML =
|
|
66046
|
-
'<
|
|
66088
|
+
'<h3 style="color:#b2920a;font-size:0.7rem;margin-bottom:8px">Token Usage by Provider (persistent)</h3>' +
|
|
66089
|
+
'<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:8px">' +
|
|
66047
66090
|
'<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:8px 12px;flex:1">' +
|
|
66048
|
-
'<div style="color:#555;font-size:0.6rem">
|
|
66049
|
-
'<div style="color:#b2920a;font-size:0.
|
|
66091
|
+
'<div style="color:#555;font-size:0.6rem">TOTAL IN</div>' +
|
|
66092
|
+
'<div style="color:#b2920a;font-size:0.9rem;font-weight:bold">' + totalIn.toLocaleString() + '</div></div>' +
|
|
66050
66093
|
'<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:8px 12px;flex:1">' +
|
|
66051
|
-
'<div style="color:#555;font-size:0.6rem">
|
|
66052
|
-
'<div style="color:#b2920a;font-size:0.
|
|
66053
|
-
'
|
|
66094
|
+
'<div style="color:#555;font-size:0.6rem">TOTAL OUT</div>' +
|
|
66095
|
+
'<div style="color:#b2920a;font-size:0.9rem;font-weight:bold">' + totalOut.toLocaleString() + '</div></div>' +
|
|
66096
|
+
'<div style="background:#1e1e22;border:1px solid #2a2a30;border-radius:3px;padding:8px 12px;flex:1">' +
|
|
66097
|
+
'<div style="color:#555;font-size:0.6rem">TOTAL REQUESTS</div>' +
|
|
66098
|
+
'<div style="color:#b2920a;font-size:0.9rem;font-weight:bold">' + (d.persistent?.totalRequests || 0).toLocaleString() + '</div></div>' +
|
|
66099
|
+
'</div>' +
|
|
66100
|
+
(providerCards || '<div style="color:#555;font-size:0.7rem">No provider usage recorded yet</div>');
|
|
66054
66101
|
} catch {}
|
|
66055
66102
|
}
|
|
66056
66103
|
|
|
@@ -66216,25 +66263,222 @@ var init_auth_oidc = __esm({
|
|
|
66216
66263
|
}
|
|
66217
66264
|
});
|
|
66218
66265
|
|
|
66219
|
-
// packages/cli/dist/api/
|
|
66220
|
-
import {
|
|
66266
|
+
// packages/cli/dist/api/chat-session.js
|
|
66267
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
66268
|
+
import { existsSync as existsSync53, readFileSync as readFileSync42, readdirSync as readdirSync20 } from "node:fs";
|
|
66221
66269
|
import { join as join70 } from "node:path";
|
|
66270
|
+
function buildSystemPrompt(cwd4) {
|
|
66271
|
+
const parts = [];
|
|
66272
|
+
parts.push("You are Open Agent (OA), an AI coding assistant running locally via Ollama. You have access to the user's workspace and can discuss code, files, and projects. Be helpful, concise, and technically precise. When asked about files or code, describe what you know from the conversation context.");
|
|
66273
|
+
parts.push(`\\nEnvironment: ${process.platform}, Node ${process.version}, CWD: ${cwd4}`);
|
|
66274
|
+
const diaryPath = join70(cwd4, ".oa", "context", "session-diary.md");
|
|
66275
|
+
if (existsSync53(diaryPath)) {
|
|
66276
|
+
try {
|
|
66277
|
+
const diary = readFileSync42(diaryPath, "utf-8").slice(0, 1e3);
|
|
66278
|
+
parts.push(`\\nPrevious session history:\\n${diary}`);
|
|
66279
|
+
} catch {
|
|
66280
|
+
}
|
|
66281
|
+
}
|
|
66282
|
+
const memDir = join70(cwd4, ".oa", "memory");
|
|
66283
|
+
if (existsSync53(memDir)) {
|
|
66284
|
+
try {
|
|
66285
|
+
const files = readdirSync20(memDir).filter((f) => f.endsWith(".json")).slice(0, 5);
|
|
66286
|
+
if (files.length > 0) {
|
|
66287
|
+
parts.push("\\nPersistent memory topics: " + files.map((f) => f.replace(".json", "")).join(", "));
|
|
66288
|
+
for (const f of files.slice(0, 3)) {
|
|
66289
|
+
try {
|
|
66290
|
+
const data = JSON.parse(readFileSync42(join70(memDir, f), "utf-8"));
|
|
66291
|
+
const entries = Object.entries(data).slice(0, 3);
|
|
66292
|
+
if (entries.length > 0) {
|
|
66293
|
+
parts.push(`\\nMemory [${f.replace(".json", "")}]: ` + entries.map(([k, v]) => `${k}: ${String(v.value ?? v).slice(0, 100)}`).join("; "));
|
|
66294
|
+
}
|
|
66295
|
+
} catch {
|
|
66296
|
+
}
|
|
66297
|
+
}
|
|
66298
|
+
}
|
|
66299
|
+
} catch {
|
|
66300
|
+
}
|
|
66301
|
+
}
|
|
66302
|
+
for (const name of ["AGENTS.md", "OA.md", ".open-agents.md"]) {
|
|
66303
|
+
const p = join70(cwd4, name);
|
|
66304
|
+
if (existsSync53(p)) {
|
|
66305
|
+
try {
|
|
66306
|
+
const content = readFileSync42(p, "utf-8").slice(0, 500);
|
|
66307
|
+
parts.push(`\\nProject instructions (${name}):\\n${content}`);
|
|
66308
|
+
} catch {
|
|
66309
|
+
}
|
|
66310
|
+
}
|
|
66311
|
+
}
|
|
66312
|
+
return parts.join("");
|
|
66313
|
+
}
|
|
66314
|
+
function getSession(sessionId, model, cwd4) {
|
|
66315
|
+
if (sessionId && sessions.has(sessionId)) {
|
|
66316
|
+
const s = sessions.get(sessionId);
|
|
66317
|
+
s.lastActivity = Date.now();
|
|
66318
|
+
return s;
|
|
66319
|
+
}
|
|
66320
|
+
const id = sessionId || randomUUID4();
|
|
66321
|
+
const systemPrompt = buildSystemPrompt(cwd4);
|
|
66322
|
+
const session = {
|
|
66323
|
+
id,
|
|
66324
|
+
messages: [{ role: "system", content: systemPrompt }],
|
|
66325
|
+
model,
|
|
66326
|
+
createdAt: Date.now(),
|
|
66327
|
+
lastActivity: Date.now(),
|
|
66328
|
+
tokensIn: 0,
|
|
66329
|
+
tokensOut: 0
|
|
66330
|
+
};
|
|
66331
|
+
sessions.set(id, session);
|
|
66332
|
+
return session;
|
|
66333
|
+
}
|
|
66334
|
+
function addUserMessage(session, content) {
|
|
66335
|
+
session.messages.push({ role: "user", content });
|
|
66336
|
+
session.lastActivity = Date.now();
|
|
66337
|
+
return [...session.messages];
|
|
66338
|
+
}
|
|
66339
|
+
function addAssistantMessage(session, content) {
|
|
66340
|
+
session.messages.push({ role: "assistant", content });
|
|
66341
|
+
session.lastActivity = Date.now();
|
|
66342
|
+
}
|
|
66343
|
+
function trackSessionTokens(session, tokensIn, tokensOut) {
|
|
66344
|
+
session.tokensIn += tokensIn;
|
|
66345
|
+
session.tokensOut += tokensOut;
|
|
66346
|
+
}
|
|
66347
|
+
function listSessions() {
|
|
66348
|
+
return Array.from(sessions.values()).map((s) => ({
|
|
66349
|
+
id: s.id,
|
|
66350
|
+
model: s.model,
|
|
66351
|
+
messages: s.messages.length - 1,
|
|
66352
|
+
// exclude system prompt
|
|
66353
|
+
tokensIn: s.tokensIn,
|
|
66354
|
+
tokensOut: s.tokensOut,
|
|
66355
|
+
lastActivity: new Date(s.lastActivity).toISOString()
|
|
66356
|
+
}));
|
|
66357
|
+
}
|
|
66358
|
+
function compactSession(session, maxMessages = 40) {
|
|
66359
|
+
if (session.messages.length <= maxMessages)
|
|
66360
|
+
return;
|
|
66361
|
+
const system = session.messages[0];
|
|
66362
|
+
const recent = session.messages.slice(-20);
|
|
66363
|
+
const middle = session.messages.slice(1, -20);
|
|
66364
|
+
const summary = `[Earlier conversation: ${middle.length} messages discussed ` + middle.filter((m) => m.role === "user").map((m) => m.content.slice(0, 50)).slice(0, 5).join(", ") + "...]";
|
|
66365
|
+
session.messages = [
|
|
66366
|
+
system,
|
|
66367
|
+
{ role: "system", content: summary },
|
|
66368
|
+
...recent
|
|
66369
|
+
];
|
|
66370
|
+
}
|
|
66371
|
+
var sessions, SESSION_TTL_MS;
|
|
66372
|
+
var init_chat_session = __esm({
|
|
66373
|
+
"packages/cli/dist/api/chat-session.js"() {
|
|
66374
|
+
"use strict";
|
|
66375
|
+
sessions = /* @__PURE__ */ new Map();
|
|
66376
|
+
SESSION_TTL_MS = 30 * 60 * 1e3;
|
|
66377
|
+
setInterval(() => {
|
|
66378
|
+
const now = Date.now();
|
|
66379
|
+
for (const [id, s] of sessions) {
|
|
66380
|
+
if (now - s.lastActivity > SESSION_TTL_MS)
|
|
66381
|
+
sessions.delete(id);
|
|
66382
|
+
}
|
|
66383
|
+
}, 5 * 60 * 1e3);
|
|
66384
|
+
}
|
|
66385
|
+
});
|
|
66386
|
+
|
|
66387
|
+
// packages/cli/dist/api/usage-tracker.js
|
|
66388
|
+
import { mkdirSync as mkdirSync27, readFileSync as readFileSync43, writeFileSync as writeFileSync25, existsSync as existsSync54 } from "node:fs";
|
|
66389
|
+
import { join as join71 } from "node:path";
|
|
66390
|
+
function initUsageTracker(oaDir) {
|
|
66391
|
+
const dir = join71(oaDir, "usage");
|
|
66392
|
+
mkdirSync27(dir, { recursive: true });
|
|
66393
|
+
usageFile = join71(dir, "token-usage.json");
|
|
66394
|
+
try {
|
|
66395
|
+
if (existsSync54(usageFile)) {
|
|
66396
|
+
store = JSON.parse(readFileSync43(usageFile, "utf-8"));
|
|
66397
|
+
}
|
|
66398
|
+
} catch {
|
|
66399
|
+
store = { providers: {}, lastSaved: "" };
|
|
66400
|
+
}
|
|
66401
|
+
initialized2 = true;
|
|
66402
|
+
setInterval(() => {
|
|
66403
|
+
if (dirty)
|
|
66404
|
+
flush();
|
|
66405
|
+
}, 3e4);
|
|
66406
|
+
}
|
|
66407
|
+
function ensureProvider(label) {
|
|
66408
|
+
if (!store.providers[label]) {
|
|
66409
|
+
store.providers[label] = { tokensIn: 0, tokensOut: 0, requests: 0, byDay: {} };
|
|
66410
|
+
}
|
|
66411
|
+
return store.providers[label];
|
|
66412
|
+
}
|
|
66413
|
+
function today() {
|
|
66414
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
66415
|
+
}
|
|
66416
|
+
function trackTokens(provider, tokensIn, tokensOut) {
|
|
66417
|
+
if (!initialized2)
|
|
66418
|
+
return;
|
|
66419
|
+
const p = ensureProvider(provider);
|
|
66420
|
+
p.tokensIn += tokensIn;
|
|
66421
|
+
p.tokensOut += tokensOut;
|
|
66422
|
+
p.requests++;
|
|
66423
|
+
const day = today();
|
|
66424
|
+
if (!p.byDay[day])
|
|
66425
|
+
p.byDay[day] = { in: 0, out: 0, reqs: 0 };
|
|
66426
|
+
p.byDay[day].in += tokensIn;
|
|
66427
|
+
p.byDay[day].out += tokensOut;
|
|
66428
|
+
p.byDay[day].reqs++;
|
|
66429
|
+
dirty = true;
|
|
66430
|
+
}
|
|
66431
|
+
function flush() {
|
|
66432
|
+
if (!initialized2 || !dirty)
|
|
66433
|
+
return;
|
|
66434
|
+
try {
|
|
66435
|
+
store.lastSaved = (/* @__PURE__ */ new Date()).toISOString();
|
|
66436
|
+
writeFileSync25(usageFile, JSON.stringify(store, null, 2), "utf-8");
|
|
66437
|
+
dirty = false;
|
|
66438
|
+
} catch {
|
|
66439
|
+
}
|
|
66440
|
+
}
|
|
66441
|
+
function getUsageSummary() {
|
|
66442
|
+
let totalIn = 0, totalOut = 0, totalRequests = 0;
|
|
66443
|
+
const byProvider = {};
|
|
66444
|
+
for (const [label, p] of Object.entries(store.providers)) {
|
|
66445
|
+
totalIn += p.tokensIn;
|
|
66446
|
+
totalOut += p.tokensOut;
|
|
66447
|
+
totalRequests += p.requests;
|
|
66448
|
+
byProvider[label] = { tokensIn: p.tokensIn, tokensOut: p.tokensOut, requests: p.requests };
|
|
66449
|
+
}
|
|
66450
|
+
return { totalIn, totalOut, totalRequests, byProvider };
|
|
66451
|
+
}
|
|
66452
|
+
var store, usageFile, dirty, initialized2;
|
|
66453
|
+
var init_usage_tracker = __esm({
|
|
66454
|
+
"packages/cli/dist/api/usage-tracker.js"() {
|
|
66455
|
+
"use strict";
|
|
66456
|
+
store = { providers: {}, lastSaved: "" };
|
|
66457
|
+
usageFile = "";
|
|
66458
|
+
dirty = false;
|
|
66459
|
+
initialized2 = false;
|
|
66460
|
+
}
|
|
66461
|
+
});
|
|
66462
|
+
|
|
66463
|
+
// packages/cli/dist/api/profiles.js
|
|
66464
|
+
import { existsSync as existsSync55, readFileSync as readFileSync44, writeFileSync as writeFileSync26, mkdirSync as mkdirSync28, readdirSync as readdirSync21, unlinkSync as unlinkSync12 } from "node:fs";
|
|
66465
|
+
import { join as join72 } from "node:path";
|
|
66222
66466
|
import { homedir as homedir18 } from "node:os";
|
|
66223
66467
|
import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes15, scryptSync as scryptSync3, createHash as createHash5 } from "node:crypto";
|
|
66224
66468
|
function globalProfileDir() {
|
|
66225
|
-
return
|
|
66469
|
+
return join72(homedir18(), ".open-agents", "profiles");
|
|
66226
66470
|
}
|
|
66227
66471
|
function projectProfileDir(projectDir) {
|
|
66228
|
-
return
|
|
66472
|
+
return join72(projectDir || process.cwd(), ".oa", "profiles");
|
|
66229
66473
|
}
|
|
66230
66474
|
function listProfiles(projectDir) {
|
|
66231
66475
|
const result = [];
|
|
66232
66476
|
const seen = /* @__PURE__ */ new Set();
|
|
66233
66477
|
const projDir = projectProfileDir(projectDir);
|
|
66234
|
-
if (
|
|
66235
|
-
for (const f of
|
|
66478
|
+
if (existsSync55(projDir)) {
|
|
66479
|
+
for (const f of readdirSync21(projDir).filter((f2) => f2.endsWith(".json"))) {
|
|
66236
66480
|
try {
|
|
66237
|
-
const raw = JSON.parse(
|
|
66481
|
+
const raw = JSON.parse(readFileSync44(join72(projDir, f), "utf8"));
|
|
66238
66482
|
const name = f.replace(".json", "");
|
|
66239
66483
|
seen.add(name);
|
|
66240
66484
|
result.push({
|
|
@@ -66248,13 +66492,13 @@ function listProfiles(projectDir) {
|
|
|
66248
66492
|
}
|
|
66249
66493
|
}
|
|
66250
66494
|
const globDir = globalProfileDir();
|
|
66251
|
-
if (
|
|
66252
|
-
for (const f of
|
|
66495
|
+
if (existsSync55(globDir)) {
|
|
66496
|
+
for (const f of readdirSync21(globDir).filter((f2) => f2.endsWith(".json"))) {
|
|
66253
66497
|
const name = f.replace(".json", "");
|
|
66254
66498
|
if (seen.has(name))
|
|
66255
66499
|
continue;
|
|
66256
66500
|
try {
|
|
66257
|
-
const raw = JSON.parse(
|
|
66501
|
+
const raw = JSON.parse(readFileSync44(join72(globDir, f), "utf8"));
|
|
66258
66502
|
result.push({
|
|
66259
66503
|
name,
|
|
66260
66504
|
description: raw.description || "",
|
|
@@ -66269,12 +66513,12 @@ function listProfiles(projectDir) {
|
|
|
66269
66513
|
}
|
|
66270
66514
|
function loadProfile(name, password, projectDir) {
|
|
66271
66515
|
const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
66272
|
-
const projPath =
|
|
66273
|
-
const globPath =
|
|
66274
|
-
const filePath =
|
|
66516
|
+
const projPath = join72(projectProfileDir(projectDir), `${sanitized}.json`);
|
|
66517
|
+
const globPath = join72(globalProfileDir(), `${sanitized}.json`);
|
|
66518
|
+
const filePath = existsSync55(projPath) ? projPath : existsSync55(globPath) ? globPath : null;
|
|
66275
66519
|
if (!filePath)
|
|
66276
66520
|
return null;
|
|
66277
|
-
const raw = JSON.parse(
|
|
66521
|
+
const raw = JSON.parse(readFileSync44(filePath, "utf8"));
|
|
66278
66522
|
if (raw.encrypted === true) {
|
|
66279
66523
|
if (!password)
|
|
66280
66524
|
return null;
|
|
@@ -66284,23 +66528,23 @@ function loadProfile(name, password, projectDir) {
|
|
|
66284
66528
|
}
|
|
66285
66529
|
function saveProfile(profile, password, scope = "global", projectDir) {
|
|
66286
66530
|
const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
|
|
66287
|
-
|
|
66531
|
+
mkdirSync28(dir, { recursive: true });
|
|
66288
66532
|
const sanitized = profile.name.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
66289
|
-
const filePath =
|
|
66533
|
+
const filePath = join72(dir, `${sanitized}.json`);
|
|
66290
66534
|
profile.modified = (/* @__PURE__ */ new Date()).toISOString();
|
|
66291
66535
|
if (password) {
|
|
66292
66536
|
const encrypted = encryptProfile(profile, password);
|
|
66293
|
-
|
|
66537
|
+
writeFileSync26(filePath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
66294
66538
|
} else {
|
|
66295
66539
|
profile.encrypted = false;
|
|
66296
|
-
|
|
66540
|
+
writeFileSync26(filePath, JSON.stringify(profile, null, 2), { mode: 420 });
|
|
66297
66541
|
}
|
|
66298
66542
|
}
|
|
66299
66543
|
function deleteProfile(name, scope = "global", projectDir) {
|
|
66300
66544
|
const sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
66301
66545
|
const dir = scope === "project" ? projectProfileDir(projectDir) : globalProfileDir();
|
|
66302
|
-
const filePath =
|
|
66303
|
-
if (
|
|
66546
|
+
const filePath = join72(dir, `${sanitized}.json`);
|
|
66547
|
+
if (existsSync55(filePath)) {
|
|
66304
66548
|
unlinkSync12(filePath);
|
|
66305
66549
|
return true;
|
|
66306
66550
|
}
|
|
@@ -66393,22 +66637,22 @@ import * as http from "node:http";
|
|
|
66393
66637
|
import * as https from "node:https";
|
|
66394
66638
|
import { createRequire as createRequire3 } from "node:module";
|
|
66395
66639
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
66396
|
-
import { dirname as dirname21, join as
|
|
66640
|
+
import { dirname as dirname21, join as join73, resolve as resolve31 } from "node:path";
|
|
66397
66641
|
import { spawn as spawn21 } from "node:child_process";
|
|
66398
|
-
import { mkdirSync as
|
|
66399
|
-
import { randomBytes as randomBytes16, randomUUID as
|
|
66642
|
+
import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync27, readFileSync as readFileSync45, readdirSync as readdirSync22, existsSync as existsSync56 } from "node:fs";
|
|
66643
|
+
import { randomBytes as randomBytes16, randomUUID as randomUUID5 } from "node:crypto";
|
|
66400
66644
|
function getVersion3() {
|
|
66401
66645
|
try {
|
|
66402
66646
|
const require2 = createRequire3(import.meta.url);
|
|
66403
66647
|
const thisDir = dirname21(fileURLToPath13(import.meta.url));
|
|
66404
66648
|
const candidates = [
|
|
66405
|
-
|
|
66406
|
-
|
|
66407
|
-
|
|
66649
|
+
join73(thisDir, "..", "package.json"),
|
|
66650
|
+
join73(thisDir, "..", "..", "package.json"),
|
|
66651
|
+
join73(thisDir, "..", "..", "..", "package.json")
|
|
66408
66652
|
];
|
|
66409
66653
|
for (const pkgPath of candidates) {
|
|
66410
66654
|
try {
|
|
66411
|
-
if (!
|
|
66655
|
+
if (!existsSync56(pkgPath))
|
|
66412
66656
|
continue;
|
|
66413
66657
|
const pkg = require2(pkgPath);
|
|
66414
66658
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
|
|
@@ -66424,14 +66668,14 @@ function getVersion3() {
|
|
|
66424
66668
|
}
|
|
66425
66669
|
function getEndpointUsage(label) {
|
|
66426
66670
|
let u = endpointUsage.get(label);
|
|
66427
|
-
const
|
|
66671
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
66428
66672
|
if (!u) {
|
|
66429
|
-
u = { requestTimestamps: [], tokensToday: 0, tokenDate:
|
|
66673
|
+
u = { requestTimestamps: [], tokensToday: 0, tokenDate: today2 };
|
|
66430
66674
|
endpointUsage.set(label, u);
|
|
66431
66675
|
}
|
|
66432
|
-
if (u.tokenDate !==
|
|
66676
|
+
if (u.tokenDate !== today2) {
|
|
66433
66677
|
u.tokensToday = 0;
|
|
66434
|
-
u.tokenDate =
|
|
66678
|
+
u.tokenDate = today2;
|
|
66435
66679
|
}
|
|
66436
66680
|
return u;
|
|
66437
66681
|
}
|
|
@@ -66709,29 +66953,29 @@ function ollamaStream(ollamaUrl, path, method, body, onData, onEnd, onError) {
|
|
|
66709
66953
|
}
|
|
66710
66954
|
function jobsDir() {
|
|
66711
66955
|
const root = resolve31(process.cwd());
|
|
66712
|
-
const dir =
|
|
66713
|
-
|
|
66956
|
+
const dir = join73(root, ".oa", "jobs");
|
|
66957
|
+
mkdirSync29(dir, { recursive: true });
|
|
66714
66958
|
return dir;
|
|
66715
66959
|
}
|
|
66716
66960
|
function loadJob(id) {
|
|
66717
|
-
const file =
|
|
66718
|
-
if (!
|
|
66961
|
+
const file = join73(jobsDir(), `${id}.json`);
|
|
66962
|
+
if (!existsSync56(file))
|
|
66719
66963
|
return null;
|
|
66720
66964
|
try {
|
|
66721
|
-
return JSON.parse(
|
|
66965
|
+
return JSON.parse(readFileSync45(file, "utf-8"));
|
|
66722
66966
|
} catch {
|
|
66723
66967
|
return null;
|
|
66724
66968
|
}
|
|
66725
66969
|
}
|
|
66726
66970
|
function listJobs() {
|
|
66727
66971
|
const dir = jobsDir();
|
|
66728
|
-
if (!
|
|
66972
|
+
if (!existsSync56(dir))
|
|
66729
66973
|
return [];
|
|
66730
|
-
const files =
|
|
66974
|
+
const files = readdirSync22(dir).filter((f) => f.endsWith(".json")).sort();
|
|
66731
66975
|
const jobs = [];
|
|
66732
66976
|
for (const file of files) {
|
|
66733
66977
|
try {
|
|
66734
|
-
jobs.push(JSON.parse(
|
|
66978
|
+
jobs.push(JSON.parse(readFileSync45(join73(dir, file), "utf-8")));
|
|
66735
66979
|
} catch {
|
|
66736
66980
|
}
|
|
66737
66981
|
}
|
|
@@ -66742,10 +66986,10 @@ function getKeyUsage(user) {
|
|
|
66742
66986
|
perKeyUsage.set(user, { requestTimestamps: [], tokensToday: 0, tokenDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), activeJobs: 0 });
|
|
66743
66987
|
}
|
|
66744
66988
|
const u = perKeyUsage.get(user);
|
|
66745
|
-
const
|
|
66746
|
-
if (u.tokenDate !==
|
|
66989
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
66990
|
+
if (u.tokenDate !== today2) {
|
|
66747
66991
|
u.tokensToday = 0;
|
|
66748
|
-
u.tokenDate =
|
|
66992
|
+
u.tokenDate = today2;
|
|
66749
66993
|
}
|
|
66750
66994
|
return u;
|
|
66751
66995
|
}
|
|
@@ -66924,8 +67168,11 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
|
66924
67168
|
const parsed = JSON.parse(result.body);
|
|
66925
67169
|
if (parsed.usage) {
|
|
66926
67170
|
const totalTok = (parsed.usage.prompt_tokens ?? 0) + (parsed.usage.completion_tokens ?? 0);
|
|
66927
|
-
|
|
66928
|
-
|
|
67171
|
+
const _pIn = parsed.usage.prompt_tokens ?? 0;
|
|
67172
|
+
const _pOut = parsed.usage.completion_tokens ?? 0;
|
|
67173
|
+
metrics.totalTokensIn += _pIn;
|
|
67174
|
+
metrics.totalTokensOut += _pOut;
|
|
67175
|
+
trackTokens(route?.endpoint?.label ?? "local", _pIn, _pOut);
|
|
66929
67176
|
if (route?.endpoint)
|
|
66930
67177
|
recordEndpointUsage(route.endpoint.label, totalTok);
|
|
66931
67178
|
}
|
|
@@ -66963,6 +67210,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
|
66963
67210
|
metrics.totalTokensOut += ollamaChunk.eval_count;
|
|
66964
67211
|
if (ollamaChunk.prompt_eval_count)
|
|
66965
67212
|
metrics.totalTokensIn += ollamaChunk.prompt_eval_count;
|
|
67213
|
+
trackTokens("local", ollamaChunk.prompt_eval_count ?? 0, ollamaChunk.eval_count ?? 0);
|
|
66966
67214
|
const doneEvent = {
|
|
66967
67215
|
id: chatId,
|
|
66968
67216
|
object: "chat.completion.chunk",
|
|
@@ -67013,6 +67261,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
|
67013
67261
|
metrics.totalTokensOut += ollamaChunk.eval_count;
|
|
67014
67262
|
if (ollamaChunk.prompt_eval_count)
|
|
67015
67263
|
metrics.totalTokensIn += ollamaChunk.prompt_eval_count;
|
|
67264
|
+
trackTokens("local", ollamaChunk.prompt_eval_count ?? 0, ollamaChunk.eval_count ?? 0);
|
|
67016
67265
|
res.write(`data: ${JSON.stringify({
|
|
67017
67266
|
id: chatId,
|
|
67018
67267
|
object: "chat.completion.chunk",
|
|
@@ -67052,6 +67301,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
|
67052
67301
|
metrics.totalTokensOut += ollamaResp.eval_count;
|
|
67053
67302
|
if (ollamaResp.prompt_eval_count)
|
|
67054
67303
|
metrics.totalTokensIn += ollamaResp.prompt_eval_count;
|
|
67304
|
+
trackTokens("local", ollamaResp.prompt_eval_count ?? 0, ollamaResp.eval_count ?? 0);
|
|
67055
67305
|
const chatId = `chatcmpl-${randomBytes16(12).toString("hex")}`;
|
|
67056
67306
|
const openaiResponse = {
|
|
67057
67307
|
id: chatId,
|
|
@@ -67173,8 +67423,8 @@ async function handleV1Run(req, res) {
|
|
|
67173
67423
|
if (workingDir) {
|
|
67174
67424
|
cwd4 = resolve31(workingDir);
|
|
67175
67425
|
} else if (isolate) {
|
|
67176
|
-
const wsDir =
|
|
67177
|
-
|
|
67426
|
+
const wsDir = join73(dir, "..", "workspaces", id);
|
|
67427
|
+
mkdirSync29(wsDir, { recursive: true });
|
|
67178
67428
|
cwd4 = wsDir;
|
|
67179
67429
|
} else {
|
|
67180
67430
|
cwd4 = resolve31(process.cwd());
|
|
@@ -67246,7 +67496,7 @@ async function handleV1Run(req, res) {
|
|
|
67246
67496
|
});
|
|
67247
67497
|
child.unref();
|
|
67248
67498
|
job.pid = child.pid ?? 0;
|
|
67249
|
-
|
|
67499
|
+
writeFileSync27(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
67250
67500
|
runningProcesses.set(id, child);
|
|
67251
67501
|
if (streamMode) {
|
|
67252
67502
|
res.writeHead(200, {
|
|
@@ -67273,7 +67523,7 @@ async function handleV1Run(req, res) {
|
|
|
67273
67523
|
job.status = code === 0 ? "completed" : "failed";
|
|
67274
67524
|
job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
67275
67525
|
try {
|
|
67276
|
-
|
|
67526
|
+
writeFileSync27(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
67277
67527
|
} catch {
|
|
67278
67528
|
}
|
|
67279
67529
|
runningProcesses.delete(id);
|
|
@@ -67304,7 +67554,7 @@ async function handleV1Run(req, res) {
|
|
|
67304
67554
|
job.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
67305
67555
|
}
|
|
67306
67556
|
try {
|
|
67307
|
-
|
|
67557
|
+
writeFileSync27(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
67308
67558
|
} catch {
|
|
67309
67559
|
}
|
|
67310
67560
|
runningProcesses.delete(id);
|
|
@@ -67353,7 +67603,7 @@ function handleV1RunsDelete(res, id) {
|
|
|
67353
67603
|
job.error = "Aborted via API";
|
|
67354
67604
|
const dir = jobsDir();
|
|
67355
67605
|
try {
|
|
67356
|
-
|
|
67606
|
+
writeFileSync27(join73(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
67357
67607
|
} catch {
|
|
67358
67608
|
}
|
|
67359
67609
|
runningProcesses.delete(id);
|
|
@@ -67498,7 +67748,7 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
|
|
|
67498
67748
|
const urlObj = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
67499
67749
|
const pathname = urlObj.pathname;
|
|
67500
67750
|
const startMs = performance.now();
|
|
67501
|
-
const requestId = req.headers["x-request-id"] ||
|
|
67751
|
+
const requestId = req.headers["x-request-id"] || randomUUID5();
|
|
67502
67752
|
res.setHeader("X-Request-ID", requestId);
|
|
67503
67753
|
if (method === "OPTIONS") {
|
|
67504
67754
|
if (!corsHeaders(req, res))
|
|
@@ -67573,6 +67823,127 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
|
|
|
67573
67823
|
return;
|
|
67574
67824
|
}
|
|
67575
67825
|
}
|
|
67826
|
+
if (pathname === "/v1/chat" && method === "POST") {
|
|
67827
|
+
if (!checkAuth(req, res, "run")) {
|
|
67828
|
+
status = 401;
|
|
67829
|
+
return;
|
|
67830
|
+
}
|
|
67831
|
+
const chatBody = await parseJsonBody(req);
|
|
67832
|
+
if (!chatBody?.message || typeof chatBody.message !== "string") {
|
|
67833
|
+
jsonResponse(res, 400, { error: "Missing required field: message" });
|
|
67834
|
+
return;
|
|
67835
|
+
}
|
|
67836
|
+
const sessionId = chatBody.session_id;
|
|
67837
|
+
const model = chatBody.model || loadConfig().model;
|
|
67838
|
+
const session = getSession(sessionId, model, resolve31(process.cwd()));
|
|
67839
|
+
const messages = addUserMessage(session, chatBody.message);
|
|
67840
|
+
compactSession(session);
|
|
67841
|
+
const streamMode = chatBody.stream !== false;
|
|
67842
|
+
const chatRequest = {
|
|
67843
|
+
model: session.model,
|
|
67844
|
+
messages,
|
|
67845
|
+
stream: streamMode,
|
|
67846
|
+
max_tokens: chatBody.max_tokens || 4096
|
|
67847
|
+
};
|
|
67848
|
+
const route = resolveModelEndpoint(session.model);
|
|
67849
|
+
const targetUrl = route?.endpoint?.url || loadConfig().backendUrl;
|
|
67850
|
+
if (streamMode) {
|
|
67851
|
+
res.writeHead(200, {
|
|
67852
|
+
"Content-Type": "text/event-stream",
|
|
67853
|
+
"Cache-Control": "no-cache",
|
|
67854
|
+
"Connection": "keep-alive",
|
|
67855
|
+
"X-Session-ID": session.id
|
|
67856
|
+
});
|
|
67857
|
+
let fullContent = "";
|
|
67858
|
+
try {
|
|
67859
|
+
const url = new URL("/api/chat", targetUrl);
|
|
67860
|
+
const isHttps = url.protocol === "https:";
|
|
67861
|
+
const transport = isHttps ? https : http;
|
|
67862
|
+
const reqBody = JSON.stringify({
|
|
67863
|
+
model: session.model.replace(/^local\//, ""),
|
|
67864
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
67865
|
+
stream: true
|
|
67866
|
+
});
|
|
67867
|
+
await new Promise((resolve36, reject) => {
|
|
67868
|
+
const proxyReq = transport.request({
|
|
67869
|
+
hostname: url.hostname,
|
|
67870
|
+
port: url.port || (isHttps ? 443 : 80),
|
|
67871
|
+
path: url.pathname,
|
|
67872
|
+
method: "POST",
|
|
67873
|
+
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(reqBody) }
|
|
67874
|
+
}, (proxyRes) => {
|
|
67875
|
+
let buffer = "";
|
|
67876
|
+
proxyRes.on("data", (chunk) => {
|
|
67877
|
+
buffer += chunk.toString();
|
|
67878
|
+
const lines = buffer.split("\n");
|
|
67879
|
+
buffer = lines.pop() || "";
|
|
67880
|
+
for (const line of lines) {
|
|
67881
|
+
if (!line.trim())
|
|
67882
|
+
continue;
|
|
67883
|
+
try {
|
|
67884
|
+
const parsed = JSON.parse(line);
|
|
67885
|
+
if (parsed.message?.content) {
|
|
67886
|
+
fullContent += parsed.message.content;
|
|
67887
|
+
const sseChunk = {
|
|
67888
|
+
id: `chatcmpl-${session.id.slice(0, 8)}`,
|
|
67889
|
+
object: "chat.completion.chunk",
|
|
67890
|
+
choices: [{ index: 0, delta: { content: parsed.message.content }, finish_reason: null }]
|
|
67891
|
+
};
|
|
67892
|
+
res.write("data: " + JSON.stringify(sseChunk) + "\n\n");
|
|
67893
|
+
}
|
|
67894
|
+
if (parsed.done) {
|
|
67895
|
+
trackSessionTokens(session, parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
|
|
67896
|
+
trackTokens("local", parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
|
|
67897
|
+
metrics.totalTokensIn += parsed.prompt_eval_count ?? 0;
|
|
67898
|
+
metrics.totalTokensOut += parsed.eval_count ?? 0;
|
|
67899
|
+
res.write("data: [DONE]\n\n");
|
|
67900
|
+
}
|
|
67901
|
+
} catch {
|
|
67902
|
+
}
|
|
67903
|
+
}
|
|
67904
|
+
});
|
|
67905
|
+
proxyRes.on("end", resolve36);
|
|
67906
|
+
proxyRes.on("error", reject);
|
|
67907
|
+
});
|
|
67908
|
+
proxyReq.setTimeout(12e4, () => proxyReq.destroy(new Error("Chat stream timeout")));
|
|
67909
|
+
proxyReq.on("error", reject);
|
|
67910
|
+
proxyReq.write(reqBody);
|
|
67911
|
+
proxyReq.end();
|
|
67912
|
+
});
|
|
67913
|
+
} catch (e) {
|
|
67914
|
+
res.write("data: " + JSON.stringify({ error: e.message }) + "\n\n");
|
|
67915
|
+
}
|
|
67916
|
+
addAssistantMessage(session, fullContent);
|
|
67917
|
+
res.end();
|
|
67918
|
+
} else {
|
|
67919
|
+
try {
|
|
67920
|
+
const result = await ollamaRequest(targetUrl, "/api/chat", "POST", JSON.stringify({
|
|
67921
|
+
model: session.model.replace(/^local\//, ""),
|
|
67922
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
67923
|
+
stream: false
|
|
67924
|
+
}));
|
|
67925
|
+
const parsed = JSON.parse(result.body);
|
|
67926
|
+
const content = parsed.message?.content ?? "";
|
|
67927
|
+
addAssistantMessage(session, content);
|
|
67928
|
+
trackSessionTokens(session, parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
|
|
67929
|
+
trackTokens("local", parsed.prompt_eval_count ?? 0, parsed.eval_count ?? 0);
|
|
67930
|
+
jsonResponse(res, 200, {
|
|
67931
|
+
session_id: session.id,
|
|
67932
|
+
message: { role: "assistant", content },
|
|
67933
|
+
usage: { prompt_tokens: parsed.prompt_eval_count ?? 0, completion_tokens: parsed.eval_count ?? 0 }
|
|
67934
|
+
});
|
|
67935
|
+
} catch (e) {
|
|
67936
|
+
jsonResponse(res, 500, { error: "Chat failed", message: e.message });
|
|
67937
|
+
}
|
|
67938
|
+
}
|
|
67939
|
+
return;
|
|
67940
|
+
}
|
|
67941
|
+
if (pathname === "/v1/chat/sessions" && method === "GET") {
|
|
67942
|
+
if (!checkAuth(req, res, "read"))
|
|
67943
|
+
return;
|
|
67944
|
+
jsonResponse(res, 200, { sessions: listSessions() });
|
|
67945
|
+
return;
|
|
67946
|
+
}
|
|
67576
67947
|
if (pathname === "/v1/models" && method === "GET") {
|
|
67577
67948
|
await handleV1Models(res, ollamaUrl);
|
|
67578
67949
|
return;
|
|
@@ -67639,7 +68010,14 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
|
|
|
67639
68010
|
limits: ep.limits ?? { maxRequestsPerMinute: "unlimited", maxTokensPerDay: "unlimited" }
|
|
67640
68011
|
};
|
|
67641
68012
|
}
|
|
67642
|
-
|
|
68013
|
+
const persistent = getUsageSummary();
|
|
68014
|
+
jsonResponse(res, 200, {
|
|
68015
|
+
usage: usageData,
|
|
68016
|
+
totalTokensIn: metrics.totalTokensIn,
|
|
68017
|
+
totalTokensOut: metrics.totalTokensOut,
|
|
68018
|
+
persistent
|
|
68019
|
+
// survives restarts
|
|
68020
|
+
});
|
|
67643
68021
|
return;
|
|
67644
68022
|
}
|
|
67645
68023
|
if (pathname === "/v1/commands" && method === "GET") {
|
|
@@ -67788,19 +68166,20 @@ function startApiServer(options = {}) {
|
|
|
67788
68166
|
const config = loadConfig();
|
|
67789
68167
|
const ollamaUrl = options.ollamaUrl ?? config.backendUrl;
|
|
67790
68168
|
const cwd4 = process.cwd();
|
|
67791
|
-
initAuditLog(
|
|
68169
|
+
initAuditLog(join73(cwd4, ".oa"));
|
|
68170
|
+
initUsageTracker(join73(cwd4, ".oa"));
|
|
67792
68171
|
const retentionDays = parseInt(process.env["OA_JOB_RETENTION_DAYS"] ?? "30", 10);
|
|
67793
68172
|
if (retentionDays > 0) {
|
|
67794
68173
|
try {
|
|
67795
|
-
const jobsDir3 =
|
|
67796
|
-
if (
|
|
68174
|
+
const jobsDir3 = join73(cwd4, ".oa", "jobs");
|
|
68175
|
+
if (existsSync56(jobsDir3)) {
|
|
67797
68176
|
const cutoff = Date.now() - retentionDays * 864e5;
|
|
67798
|
-
for (const f of
|
|
68177
|
+
for (const f of readdirSync22(jobsDir3)) {
|
|
67799
68178
|
if (!f.endsWith(".json"))
|
|
67800
68179
|
continue;
|
|
67801
68180
|
try {
|
|
67802
|
-
const jobPath =
|
|
67803
|
-
const job = JSON.parse(
|
|
68181
|
+
const jobPath = join73(jobsDir3, f);
|
|
68182
|
+
const job = JSON.parse(readFileSync45(jobPath, "utf-8"));
|
|
67804
68183
|
const jobTime = new Date(job.startedAt ?? job.completedAt ?? 0).getTime();
|
|
67805
68184
|
if (jobTime > 0 && jobTime < cutoff && job.status !== "running") {
|
|
67806
68185
|
const { unlinkSync: unlinkSync13 } = __require("node:fs");
|
|
@@ -67820,8 +68199,8 @@ function startApiServer(options = {}) {
|
|
|
67820
68199
|
if (useTls) {
|
|
67821
68200
|
try {
|
|
67822
68201
|
tlsOpts = {
|
|
67823
|
-
cert:
|
|
67824
|
-
key:
|
|
68202
|
+
cert: readFileSync45(resolve31(tlsCert)),
|
|
68203
|
+
key: readFileSync45(resolve31(tlsKey))
|
|
67825
68204
|
};
|
|
67826
68205
|
} catch (e) {
|
|
67827
68206
|
log2(`
|
|
@@ -67971,6 +68350,8 @@ var init_serve = __esm({
|
|
|
67971
68350
|
init_logger();
|
|
67972
68351
|
init_openapi();
|
|
67973
68352
|
init_auth_oidc();
|
|
68353
|
+
init_chat_session();
|
|
68354
|
+
init_usage_tracker();
|
|
67974
68355
|
init_oa_directory();
|
|
67975
68356
|
init_render();
|
|
67976
68357
|
init_profiles();
|
|
@@ -67993,11 +68374,11 @@ var init_serve = __esm({
|
|
|
67993
68374
|
|
|
67994
68375
|
// packages/cli/dist/tui/interactive.js
|
|
67995
68376
|
import { cwd } from "node:process";
|
|
67996
|
-
import { resolve as resolve32, join as
|
|
68377
|
+
import { resolve as resolve32, join as join74, dirname as dirname22, extname as extname11 } from "node:path";
|
|
67997
68378
|
import { createRequire as createRequire4 } from "node:module";
|
|
67998
68379
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
67999
|
-
import { readFileSync as
|
|
68000
|
-
import { existsSync as
|
|
68380
|
+
import { readFileSync as readFileSync46, writeFileSync as writeFileSync28, appendFileSync as appendFileSync5, rmSync as rmSync3, readdirSync as readdirSync23, mkdirSync as mkdirSync30 } from "node:fs";
|
|
68381
|
+
import { existsSync as existsSync57 } from "node:fs";
|
|
68001
68382
|
import { execSync as execSync35 } from "node:child_process";
|
|
68002
68383
|
import { homedir as homedir19 } from "node:os";
|
|
68003
68384
|
function formatTimeAgo(date) {
|
|
@@ -68018,12 +68399,12 @@ function getVersion4() {
|
|
|
68018
68399
|
const require2 = createRequire4(import.meta.url);
|
|
68019
68400
|
const thisDir = dirname22(fileURLToPath14(import.meta.url));
|
|
68020
68401
|
const candidates = [
|
|
68021
|
-
|
|
68022
|
-
|
|
68023
|
-
|
|
68402
|
+
join74(thisDir, "..", "package.json"),
|
|
68403
|
+
join74(thisDir, "..", "..", "package.json"),
|
|
68404
|
+
join74(thisDir, "..", "..", "..", "package.json")
|
|
68024
68405
|
];
|
|
68025
68406
|
for (const pkgPath of candidates) {
|
|
68026
|
-
if (
|
|
68407
|
+
if (existsSync57(pkgPath)) {
|
|
68027
68408
|
const pkg = require2(pkgPath);
|
|
68028
68409
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli" || pkg.name === "@open-agents/monorepo") {
|
|
68029
68410
|
return pkg.version ?? "0.0.0";
|
|
@@ -68262,15 +68643,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
|
|
|
68262
68643
|
function gatherMemorySnippets(root) {
|
|
68263
68644
|
const snippets = [];
|
|
68264
68645
|
const dirs = [
|
|
68265
|
-
|
|
68266
|
-
|
|
68646
|
+
join74(root, ".oa", "memory"),
|
|
68647
|
+
join74(root, ".open-agents", "memory")
|
|
68267
68648
|
];
|
|
68268
68649
|
for (const dir of dirs) {
|
|
68269
|
-
if (!
|
|
68650
|
+
if (!existsSync57(dir))
|
|
68270
68651
|
continue;
|
|
68271
68652
|
try {
|
|
68272
|
-
for (const f of
|
|
68273
|
-
const data = JSON.parse(
|
|
68653
|
+
for (const f of readdirSync23(dir).filter((f2) => f2.endsWith(".json"))) {
|
|
68654
|
+
const data = JSON.parse(readFileSync46(join74(dir, f), "utf-8"));
|
|
68274
68655
|
for (const val of Object.values(data)) {
|
|
68275
68656
|
const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
68276
68657
|
if (v.length > 10)
|
|
@@ -68427,9 +68808,9 @@ ${metabolismMemories}
|
|
|
68427
68808
|
} catch {
|
|
68428
68809
|
}
|
|
68429
68810
|
try {
|
|
68430
|
-
const archeFile =
|
|
68431
|
-
if (
|
|
68432
|
-
const variants = JSON.parse(
|
|
68811
|
+
const archeFile = join74(repoRoot, ".oa", "arche", "variants.json");
|
|
68812
|
+
if (existsSync57(archeFile)) {
|
|
68813
|
+
const variants = JSON.parse(readFileSync46(archeFile, "utf8"));
|
|
68433
68814
|
if (variants.length > 0) {
|
|
68434
68815
|
let filtered = variants;
|
|
68435
68816
|
if (taskType) {
|
|
@@ -68598,9 +68979,9 @@ RULES:
|
|
|
68598
68979
|
const compactionThreshold = modelTier === "small" ? 12e3 : modelTier === "medium" ? 24e3 : 4e4;
|
|
68599
68980
|
let identityInjection = "";
|
|
68600
68981
|
try {
|
|
68601
|
-
const ikStateFile =
|
|
68602
|
-
if (
|
|
68603
|
-
const selfState = JSON.parse(
|
|
68982
|
+
const ikStateFile = join74(repoRoot, ".oa", "identity", "self-state.json");
|
|
68983
|
+
if (existsSync57(ikStateFile)) {
|
|
68984
|
+
const selfState = JSON.parse(readFileSync46(ikStateFile, "utf8"));
|
|
68604
68985
|
const lines = [
|
|
68605
68986
|
`[Identity State v${selfState.version}]`,
|
|
68606
68987
|
`Self: ${selfState.narrative_summary}`,
|
|
@@ -69244,13 +69625,13 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
69244
69625
|
});
|
|
69245
69626
|
}
|
|
69246
69627
|
try {
|
|
69247
|
-
const ikDir =
|
|
69248
|
-
const ikFile =
|
|
69628
|
+
const ikDir = join74(repoRoot, ".oa", "identity");
|
|
69629
|
+
const ikFile = join74(ikDir, "self-state.json");
|
|
69249
69630
|
let ikState;
|
|
69250
|
-
if (
|
|
69251
|
-
ikState = JSON.parse(
|
|
69631
|
+
if (existsSync57(ikFile)) {
|
|
69632
|
+
ikState = JSON.parse(readFileSync46(ikFile, "utf8"));
|
|
69252
69633
|
} else {
|
|
69253
|
-
|
|
69634
|
+
mkdirSync30(ikDir, { recursive: true });
|
|
69254
69635
|
const machineId = Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
|
69255
69636
|
ikState = {
|
|
69256
69637
|
self_id: `oa-${machineId}`,
|
|
@@ -69276,7 +69657,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
69276
69657
|
}
|
|
69277
69658
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
69278
69659
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
69279
|
-
|
|
69660
|
+
writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
|
|
69280
69661
|
} catch (ikErr) {
|
|
69281
69662
|
try {
|
|
69282
69663
|
console.error("[IK-OBSERVE]", ikErr);
|
|
@@ -69291,14 +69672,14 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
69291
69672
|
} else {
|
|
69292
69673
|
renderTaskIncomplete(result.turns, result.toolCalls, result.durationMs, tokens);
|
|
69293
69674
|
try {
|
|
69294
|
-
const ikFile =
|
|
69295
|
-
if (
|
|
69296
|
-
const ikState = JSON.parse(
|
|
69675
|
+
const ikFile = join74(repoRoot, ".oa", "identity", "self-state.json");
|
|
69676
|
+
if (existsSync57(ikFile)) {
|
|
69677
|
+
const ikState = JSON.parse(readFileSync46(ikFile, "utf8"));
|
|
69297
69678
|
ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
|
|
69298
69679
|
ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
|
|
69299
69680
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
69300
69681
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
69301
|
-
|
|
69682
|
+
writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
|
|
69302
69683
|
}
|
|
69303
69684
|
} catch {
|
|
69304
69685
|
}
|
|
@@ -69395,10 +69776,10 @@ async function startInteractive(config, repoPath) {
|
|
|
69395
69776
|
process.stdin.pause();
|
|
69396
69777
|
}
|
|
69397
69778
|
try {
|
|
69398
|
-
const oaDir =
|
|
69399
|
-
const nexusPidFile =
|
|
69400
|
-
if (
|
|
69401
|
-
const pid = parseInt(
|
|
69779
|
+
const oaDir = join74(repoRoot, ".oa");
|
|
69780
|
+
const nexusPidFile = join74(oaDir, "nexus", "daemon.pid");
|
|
69781
|
+
if (existsSync57(nexusPidFile)) {
|
|
69782
|
+
const pid = parseInt(readFileSync46(nexusPidFile, "utf8").trim(), 10);
|
|
69402
69783
|
if (pid > 0) {
|
|
69403
69784
|
try {
|
|
69404
69785
|
process.kill(pid, 0);
|
|
@@ -69735,7 +70116,7 @@ Review its full output in the [${id}] tab or via full_sub_agent(action='output',
|
|
|
69735
70116
|
let p2pGateway = null;
|
|
69736
70117
|
let peerMesh = null;
|
|
69737
70118
|
let inferenceRouter = null;
|
|
69738
|
-
const secretVault = new SecretVault(
|
|
70119
|
+
const secretVault = new SecretVault(join74(repoRoot, ".oa", "vault.enc"));
|
|
69739
70120
|
let adminSessionKey = null;
|
|
69740
70121
|
const callSubAgents = /* @__PURE__ */ new Map();
|
|
69741
70122
|
const streamRenderer = new StreamRenderer();
|
|
@@ -69958,13 +70339,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
69958
70339
|
const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
|
|
69959
70340
|
return [hits, line];
|
|
69960
70341
|
}
|
|
69961
|
-
const HISTORY_DIR =
|
|
69962
|
-
const HISTORY_FILE =
|
|
70342
|
+
const HISTORY_DIR = join74(homedir19(), ".open-agents");
|
|
70343
|
+
const HISTORY_FILE = join74(HISTORY_DIR, "repl-history");
|
|
69963
70344
|
const MAX_HISTORY_LINES = 500;
|
|
69964
70345
|
let savedHistory = [];
|
|
69965
70346
|
try {
|
|
69966
|
-
if (
|
|
69967
|
-
const raw =
|
|
70347
|
+
if (existsSync57(HISTORY_FILE)) {
|
|
70348
|
+
const raw = readFileSync46(HISTORY_FILE, "utf8").trim();
|
|
69968
70349
|
if (raw)
|
|
69969
70350
|
savedHistory = raw.split("\n").reverse();
|
|
69970
70351
|
}
|
|
@@ -70067,12 +70448,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
70067
70448
|
if (!line.trim())
|
|
70068
70449
|
return;
|
|
70069
70450
|
try {
|
|
70070
|
-
|
|
70451
|
+
mkdirSync30(HISTORY_DIR, { recursive: true });
|
|
70071
70452
|
appendFileSync5(HISTORY_FILE, line + "\n", "utf8");
|
|
70072
70453
|
if (Math.random() < 0.02) {
|
|
70073
|
-
const all =
|
|
70454
|
+
const all = readFileSync46(HISTORY_FILE, "utf8").trim().split("\n");
|
|
70074
70455
|
if (all.length > MAX_HISTORY_LINES) {
|
|
70075
|
-
|
|
70456
|
+
writeFileSync28(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
|
|
70076
70457
|
}
|
|
70077
70458
|
}
|
|
70078
70459
|
} catch {
|
|
@@ -70256,7 +70637,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
70256
70637
|
} catch {
|
|
70257
70638
|
}
|
|
70258
70639
|
try {
|
|
70259
|
-
const oaDir =
|
|
70640
|
+
const oaDir = join74(repoRoot, ".oa");
|
|
70260
70641
|
const reconnected = await ExposeGateway.checkAndReconnect(oaDir, {
|
|
70261
70642
|
onInfo: (msg) => writeContent(() => renderInfo(msg)),
|
|
70262
70643
|
onError: (msg) => writeContent(() => renderWarning(msg))
|
|
@@ -70288,7 +70669,7 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
70288
70669
|
} catch {
|
|
70289
70670
|
}
|
|
70290
70671
|
try {
|
|
70291
|
-
const oaDir =
|
|
70672
|
+
const oaDir = join74(repoRoot, ".oa");
|
|
70292
70673
|
const reconnectedP2P = await ExposeP2PGateway.checkAndReconnect(oaDir, new NexusTool(repoRoot), {
|
|
70293
70674
|
onInfo: (msg) => writeContent(() => renderInfo(msg)),
|
|
70294
70675
|
onError: (msg) => writeContent(() => renderWarning(msg))
|
|
@@ -70329,11 +70710,11 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
70329
70710
|
}
|
|
70330
70711
|
try {
|
|
70331
70712
|
const { homedir: _hd, hostname: _hn, userInfo: _ui } = await import("node:os");
|
|
70332
|
-
const globalNamePath =
|
|
70713
|
+
const globalNamePath = join74(_hd(), ".open-agents", "agent-name");
|
|
70333
70714
|
let agName = "";
|
|
70334
70715
|
try {
|
|
70335
|
-
if (
|
|
70336
|
-
agName =
|
|
70716
|
+
if (existsSync57(globalNamePath))
|
|
70717
|
+
agName = readFileSync46(globalNamePath, "utf8").trim();
|
|
70337
70718
|
} catch {
|
|
70338
70719
|
}
|
|
70339
70720
|
if (!agName) {
|
|
@@ -71309,7 +71690,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
71309
71690
|
kind,
|
|
71310
71691
|
targetUrl,
|
|
71311
71692
|
authKey,
|
|
71312
|
-
stateDir:
|
|
71693
|
+
stateDir: join74(repoRoot, ".oa"),
|
|
71313
71694
|
passthrough: passthrough ?? false,
|
|
71314
71695
|
loadbalance: loadbalance ?? false,
|
|
71315
71696
|
endpointAuth: passthrough ? currentConfig.apiKey : void 0,
|
|
@@ -71355,7 +71736,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
71355
71736
|
await tunnelGateway.stop();
|
|
71356
71737
|
tunnelGateway = null;
|
|
71357
71738
|
}
|
|
71358
|
-
const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir:
|
|
71739
|
+
const newTunnel = new ExposeGateway({ kind, targetUrl, authKey, fullAccess, stateDir: join74(repoRoot, ".oa") });
|
|
71359
71740
|
newTunnel.on("stats", (stats) => {
|
|
71360
71741
|
statusBar.setExposeStatus({
|
|
71361
71742
|
status: stats.status,
|
|
@@ -71444,9 +71825,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
71444
71825
|
if (!result.success)
|
|
71445
71826
|
throw new Error(result.error || "Connect failed");
|
|
71446
71827
|
try {
|
|
71447
|
-
const nexusPidFile =
|
|
71448
|
-
if (
|
|
71449
|
-
const pid = parseInt(
|
|
71828
|
+
const nexusPidFile = join74(repoRoot, ".oa", "nexus", "daemon.pid");
|
|
71829
|
+
if (existsSync57(nexusPidFile)) {
|
|
71830
|
+
const pid = parseInt(readFileSync46(nexusPidFile, "utf8").trim(), 10);
|
|
71450
71831
|
if (pid > 0) {
|
|
71451
71832
|
registry.register({
|
|
71452
71833
|
name: "Nexus",
|
|
@@ -71642,10 +72023,10 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
71642
72023
|
writeContent(() => renderInfo(`Killed ${bgKilled} background task(s).`));
|
|
71643
72024
|
}
|
|
71644
72025
|
try {
|
|
71645
|
-
const nexusDir =
|
|
71646
|
-
const pidFile =
|
|
71647
|
-
if (
|
|
71648
|
-
const pid = parseInt(
|
|
72026
|
+
const nexusDir = join74(repoRoot, OA_DIR, "nexus");
|
|
72027
|
+
const pidFile = join74(nexusDir, "daemon.pid");
|
|
72028
|
+
if (existsSync57(pidFile)) {
|
|
72029
|
+
const pid = parseInt(readFileSync46(pidFile, "utf8").trim(), 10);
|
|
71649
72030
|
if (pid > 0) {
|
|
71650
72031
|
try {
|
|
71651
72032
|
if (process.platform === "win32") {
|
|
@@ -71667,13 +72048,13 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
71667
72048
|
} catch {
|
|
71668
72049
|
}
|
|
71669
72050
|
try {
|
|
71670
|
-
const voiceDir2 =
|
|
72051
|
+
const voiceDir2 = join74(homedir19(), ".open-agents", "voice");
|
|
71671
72052
|
const voicePidFiles = ["luxtts-daemon.pid", "piper-daemon.pid"];
|
|
71672
72053
|
for (const pf of voicePidFiles) {
|
|
71673
|
-
const pidPath =
|
|
71674
|
-
if (
|
|
72054
|
+
const pidPath = join74(voiceDir2, pf);
|
|
72055
|
+
if (existsSync57(pidPath)) {
|
|
71675
72056
|
try {
|
|
71676
|
-
const pid = parseInt(
|
|
72057
|
+
const pid = parseInt(readFileSync46(pidPath, "utf8").trim(), 10);
|
|
71677
72058
|
if (pid > 0) {
|
|
71678
72059
|
if (process.platform === "win32") {
|
|
71679
72060
|
try {
|
|
@@ -71697,8 +72078,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
71697
72078
|
execSync35(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
|
|
71698
72079
|
} catch {
|
|
71699
72080
|
}
|
|
71700
|
-
const oaPath =
|
|
71701
|
-
if (
|
|
72081
|
+
const oaPath = join74(repoRoot, OA_DIR);
|
|
72082
|
+
if (existsSync57(oaPath)) {
|
|
71702
72083
|
let deleted = false;
|
|
71703
72084
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
71704
72085
|
try {
|
|
@@ -71781,19 +72162,19 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
71781
72162
|
try {
|
|
71782
72163
|
const { isPersonaPlexRunning: isPersonaPlexRunning2 } = await Promise.resolve().then(() => (init_personaplex(), personaplex_exports));
|
|
71783
72164
|
if (isPersonaPlexRunning2()) {
|
|
71784
|
-
const ppPidFile =
|
|
71785
|
-
const ppPortFile =
|
|
71786
|
-
if (
|
|
71787
|
-
const ppPid = parseInt(
|
|
71788
|
-
const ppPort =
|
|
72165
|
+
const ppPidFile = join74(homedir19(), ".open-agents", "voice", "personaplex", "daemon.pid");
|
|
72166
|
+
const ppPortFile = join74(homedir19(), ".open-agents", "voice", "personaplex", "daemon.port");
|
|
72167
|
+
if (existsSync57(ppPidFile)) {
|
|
72168
|
+
const ppPid = parseInt(readFileSync46(ppPidFile, "utf8").trim(), 10);
|
|
72169
|
+
const ppPort = existsSync57(ppPortFile) ? parseInt(readFileSync46(ppPortFile, "utf8").trim(), 10) : void 0;
|
|
71789
72170
|
if (ppPid > 0 && !registry.daemons.has("PersonaPlex")) {
|
|
71790
72171
|
registry.register({ name: "PersonaPlex", pid: ppPid, port: ppPort, startedAt: Date.now(), status: "running" });
|
|
71791
72172
|
}
|
|
71792
72173
|
}
|
|
71793
72174
|
}
|
|
71794
|
-
const nexusPidFile =
|
|
71795
|
-
if (
|
|
71796
|
-
const nPid = parseInt(
|
|
72175
|
+
const nexusPidFile = join74(repoRoot, ".oa", "nexus", "daemon.pid");
|
|
72176
|
+
if (existsSync57(nexusPidFile)) {
|
|
72177
|
+
const nPid = parseInt(readFileSync46(nexusPidFile, "utf8").trim(), 10);
|
|
71797
72178
|
if (nPid > 0 && !registry.daemons.has("Nexus")) {
|
|
71798
72179
|
try {
|
|
71799
72180
|
process.kill(nPid, 0);
|
|
@@ -72135,8 +72516,8 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
72135
72516
|
}
|
|
72136
72517
|
}
|
|
72137
72518
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
72138
|
-
const isImage = isImagePath(cleanPath) &&
|
|
72139
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
72519
|
+
const isImage = isImagePath(cleanPath) && existsSync57(resolve32(repoRoot, cleanPath));
|
|
72520
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync57(resolve32(repoRoot, cleanPath));
|
|
72140
72521
|
if (activeTask) {
|
|
72141
72522
|
if (activeTask.runner.isPaused) {
|
|
72142
72523
|
activeTask.runner.resume();
|
|
@@ -72145,7 +72526,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
72145
72526
|
if (isImage) {
|
|
72146
72527
|
try {
|
|
72147
72528
|
const imgPath = resolve32(repoRoot, cleanPath);
|
|
72148
|
-
const imgBuffer =
|
|
72529
|
+
const imgBuffer = readFileSync46(imgPath);
|
|
72149
72530
|
const base64 = imgBuffer.toString("base64");
|
|
72150
72531
|
const ext = extname11(cleanPath).toLowerCase();
|
|
72151
72532
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -72360,7 +72741,7 @@ Summarize or analyze this transcription as appropriate.`;
|
|
|
72360
72741
|
|
|
72361
72742
|
NEW TASK: ${fullInput}`;
|
|
72362
72743
|
restoredSessionContext = null;
|
|
72363
|
-
} else if (
|
|
72744
|
+
} else if (existsSync57(join74(repoRoot, ".oa", "context", "session-diary.md"))) {
|
|
72364
72745
|
taskInput = `[Previous sessions exist \u2014 file_read(".oa/context/session-diary.md") to recall]
|
|
72365
72746
|
|
|
72366
72747
|
${fullInput}`;
|
|
@@ -72677,13 +73058,13 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
72677
73058
|
const handle = startTask(task, config, repoRoot);
|
|
72678
73059
|
await handle.promise;
|
|
72679
73060
|
try {
|
|
72680
|
-
const ikDir =
|
|
72681
|
-
const ikFile =
|
|
73061
|
+
const ikDir = join74(repoRoot, ".oa", "identity");
|
|
73062
|
+
const ikFile = join74(ikDir, "self-state.json");
|
|
72682
73063
|
let ikState;
|
|
72683
|
-
if (
|
|
72684
|
-
ikState = JSON.parse(
|
|
73064
|
+
if (existsSync57(ikFile)) {
|
|
73065
|
+
ikState = JSON.parse(readFileSync46(ikFile, "utf8"));
|
|
72685
73066
|
} else {
|
|
72686
|
-
|
|
73067
|
+
mkdirSync30(ikDir, { recursive: true });
|
|
72687
73068
|
ikState = {
|
|
72688
73069
|
self_id: `oa-${Date.now().toString(36)}`,
|
|
72689
73070
|
version: 1,
|
|
@@ -72705,7 +73086,7 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
72705
73086
|
ikState.homeostasis.coherence = Math.min(1, ikState.homeostasis.coherence + 0.05);
|
|
72706
73087
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
72707
73088
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
72708
|
-
|
|
73089
|
+
writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
|
|
72709
73090
|
} catch (ikErr) {
|
|
72710
73091
|
}
|
|
72711
73092
|
try {
|
|
@@ -72714,12 +73095,12 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
72714
73095
|
ec.archiveVariantSync(`Task: ${task.slice(0, 200)}`, "success \u2014 completed", ["general"]);
|
|
72715
73096
|
} catch {
|
|
72716
73097
|
try {
|
|
72717
|
-
const archeDir =
|
|
72718
|
-
const archeFile =
|
|
73098
|
+
const archeDir = join74(repoRoot, ".oa", "arche");
|
|
73099
|
+
const archeFile = join74(archeDir, "variants.json");
|
|
72719
73100
|
let variants = [];
|
|
72720
73101
|
try {
|
|
72721
|
-
if (
|
|
72722
|
-
variants = JSON.parse(
|
|
73102
|
+
if (existsSync57(archeFile))
|
|
73103
|
+
variants = JSON.parse(readFileSync46(archeFile, "utf8"));
|
|
72723
73104
|
} catch {
|
|
72724
73105
|
}
|
|
72725
73106
|
variants.push({
|
|
@@ -72734,16 +73115,16 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
72734
73115
|
});
|
|
72735
73116
|
if (variants.length > 50)
|
|
72736
73117
|
variants = variants.slice(-50);
|
|
72737
|
-
|
|
72738
|
-
|
|
73118
|
+
mkdirSync30(archeDir, { recursive: true });
|
|
73119
|
+
writeFileSync28(archeFile, JSON.stringify(variants, null, 2));
|
|
72739
73120
|
} catch {
|
|
72740
73121
|
}
|
|
72741
73122
|
}
|
|
72742
73123
|
try {
|
|
72743
|
-
const metaFile =
|
|
72744
|
-
if (
|
|
72745
|
-
const
|
|
72746
|
-
const surfaced =
|
|
73124
|
+
const metaFile = join74(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
73125
|
+
if (existsSync57(metaFile)) {
|
|
73126
|
+
const store2 = JSON.parse(readFileSync46(metaFile, "utf8"));
|
|
73127
|
+
const surfaced = store2.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);
|
|
72747
73128
|
let updated = false;
|
|
72748
73129
|
for (const item of surfaced) {
|
|
72749
73130
|
item.accessCount = (item.accessCount || 0) + 1;
|
|
@@ -72753,7 +73134,7 @@ async function runWithTUI(task, config, repoPath) {
|
|
|
72753
73134
|
updated = true;
|
|
72754
73135
|
}
|
|
72755
73136
|
if (updated) {
|
|
72756
|
-
|
|
73137
|
+
writeFileSync28(metaFile, JSON.stringify(store2, null, 2));
|
|
72757
73138
|
}
|
|
72758
73139
|
}
|
|
72759
73140
|
} catch {
|
|
@@ -72806,9 +73187,9 @@ Rules:
|
|
|
72806
73187
|
try {
|
|
72807
73188
|
const { initDb: initDb2 } = __require("@open-agents/memory");
|
|
72808
73189
|
const { ProceduralMemoryStore: ProceduralMemoryStore2 } = __require("@open-agents/memory");
|
|
72809
|
-
const dbDir =
|
|
72810
|
-
|
|
72811
|
-
const db = initDb2(
|
|
73190
|
+
const dbDir = join74(repoRoot, ".oa", "memory");
|
|
73191
|
+
mkdirSync30(dbDir, { recursive: true });
|
|
73192
|
+
const db = initDb2(join74(dbDir, "structured.db"));
|
|
72812
73193
|
const memStore = new ProceduralMemoryStore2(db);
|
|
72813
73194
|
memStore.createWithEmbedding({
|
|
72814
73195
|
content: content.slice(0, 600),
|
|
@@ -72823,15 +73204,15 @@ Rules:
|
|
|
72823
73204
|
db.close();
|
|
72824
73205
|
} catch {
|
|
72825
73206
|
}
|
|
72826
|
-
const metaDir =
|
|
72827
|
-
const storeFile =
|
|
72828
|
-
let
|
|
73207
|
+
const metaDir = join74(repoRoot, ".oa", "memory", "metabolism");
|
|
73208
|
+
const storeFile = join74(metaDir, "store.json");
|
|
73209
|
+
let store2 = [];
|
|
72829
73210
|
try {
|
|
72830
|
-
if (
|
|
72831
|
-
|
|
73211
|
+
if (existsSync57(storeFile))
|
|
73212
|
+
store2 = JSON.parse(readFileSync46(storeFile, "utf8"));
|
|
72832
73213
|
} catch {
|
|
72833
73214
|
}
|
|
72834
|
-
|
|
73215
|
+
store2.push({
|
|
72835
73216
|
id: `mem-traj-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`,
|
|
72836
73217
|
type: "procedural",
|
|
72837
73218
|
content: content.slice(0, 600),
|
|
@@ -72842,29 +73223,29 @@ Rules:
|
|
|
72842
73223
|
lastAccessedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
72843
73224
|
accessCount: 0
|
|
72844
73225
|
});
|
|
72845
|
-
if (
|
|
72846
|
-
|
|
72847
|
-
|
|
72848
|
-
|
|
73226
|
+
if (store2.length > 100)
|
|
73227
|
+
store2 = store2.slice(-100);
|
|
73228
|
+
mkdirSync30(metaDir, { recursive: true });
|
|
73229
|
+
writeFileSync28(storeFile, JSON.stringify(store2, null, 2));
|
|
72849
73230
|
}
|
|
72850
73231
|
}
|
|
72851
73232
|
} catch {
|
|
72852
73233
|
}
|
|
72853
73234
|
try {
|
|
72854
|
-
const cohereSettingsFile =
|
|
73235
|
+
const cohereSettingsFile = join74(repoRoot, ".oa", "settings.json");
|
|
72855
73236
|
let cohereActive = false;
|
|
72856
73237
|
try {
|
|
72857
|
-
if (
|
|
72858
|
-
const settings = JSON.parse(
|
|
73238
|
+
if (existsSync57(cohereSettingsFile)) {
|
|
73239
|
+
const settings = JSON.parse(readFileSync46(cohereSettingsFile, "utf8"));
|
|
72859
73240
|
cohereActive = settings.cohere === true;
|
|
72860
73241
|
}
|
|
72861
73242
|
} catch {
|
|
72862
73243
|
}
|
|
72863
73244
|
if (cohereActive) {
|
|
72864
|
-
const metaFile =
|
|
72865
|
-
if (
|
|
72866
|
-
const
|
|
72867
|
-
const latest =
|
|
73245
|
+
const metaFile = join74(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
73246
|
+
if (existsSync57(metaFile)) {
|
|
73247
|
+
const store2 = JSON.parse(readFileSync46(metaFile, "utf8"));
|
|
73248
|
+
const latest = store2.filter((m) => m.sourceTrace === "trajectory-extraction" || m.sourceTrace === "llm-trajectory-extraction").slice(-1)[0];
|
|
72868
73249
|
if (latest && latest.scores?.confidence >= 0.6) {
|
|
72869
73250
|
try {
|
|
72870
73251
|
const { NexusTool: NexusTool2 } = __require("@open-agents/execution");
|
|
@@ -72888,34 +73269,34 @@ Rules:
|
|
|
72888
73269
|
}
|
|
72889
73270
|
} catch (err) {
|
|
72890
73271
|
try {
|
|
72891
|
-
const ikFile =
|
|
72892
|
-
if (
|
|
72893
|
-
const ikState = JSON.parse(
|
|
73272
|
+
const ikFile = join74(repoRoot, ".oa", "identity", "self-state.json");
|
|
73273
|
+
if (existsSync57(ikFile)) {
|
|
73274
|
+
const ikState = JSON.parse(readFileSync46(ikFile, "utf8"));
|
|
72894
73275
|
ikState.homeostasis.uncertainty = Math.min(1, ikState.homeostasis.uncertainty + 0.1);
|
|
72895
73276
|
ikState.homeostasis.coherence = Math.max(0, ikState.homeostasis.coherence - 0.05);
|
|
72896
73277
|
ikState.session_count = (ikState.session_count || 0) + 1;
|
|
72897
73278
|
ikState.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
72898
|
-
|
|
73279
|
+
writeFileSync28(ikFile, JSON.stringify(ikState, null, 2));
|
|
72899
73280
|
}
|
|
72900
|
-
const metaFile =
|
|
72901
|
-
if (
|
|
72902
|
-
const
|
|
72903
|
-
const surfaced =
|
|
73281
|
+
const metaFile = join74(repoRoot, ".oa", "memory", "metabolism", "store.json");
|
|
73282
|
+
if (existsSync57(metaFile)) {
|
|
73283
|
+
const store2 = JSON.parse(readFileSync46(metaFile, "utf8"));
|
|
73284
|
+
const surfaced = store2.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);
|
|
72904
73285
|
for (const item of surfaced) {
|
|
72905
73286
|
item.accessCount = (item.accessCount || 0) + 1;
|
|
72906
73287
|
item.lastAccessedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
72907
73288
|
item.scores.utility = Math.max(0, (item.scores.utility || 0.5) - 0.05);
|
|
72908
73289
|
item.scores.confidence = Math.max(0, (item.scores.confidence || 0.5) - 0.02);
|
|
72909
73290
|
}
|
|
72910
|
-
|
|
73291
|
+
writeFileSync28(metaFile, JSON.stringify(store2, null, 2));
|
|
72911
73292
|
}
|
|
72912
73293
|
try {
|
|
72913
|
-
const archeDir =
|
|
72914
|
-
const archeFile =
|
|
73294
|
+
const archeDir = join74(repoRoot, ".oa", "arche");
|
|
73295
|
+
const archeFile = join74(archeDir, "variants.json");
|
|
72915
73296
|
let variants = [];
|
|
72916
73297
|
try {
|
|
72917
|
-
if (
|
|
72918
|
-
variants = JSON.parse(
|
|
73298
|
+
if (existsSync57(archeFile))
|
|
73299
|
+
variants = JSON.parse(readFileSync46(archeFile, "utf8"));
|
|
72919
73300
|
} catch {
|
|
72920
73301
|
}
|
|
72921
73302
|
variants.push({
|
|
@@ -72930,8 +73311,8 @@ Rules:
|
|
|
72930
73311
|
});
|
|
72931
73312
|
if (variants.length > 50)
|
|
72932
73313
|
variants = variants.slice(-50);
|
|
72933
|
-
|
|
72934
|
-
|
|
73314
|
+
mkdirSync30(archeDir, { recursive: true });
|
|
73315
|
+
writeFileSync28(archeFile, JSON.stringify(variants, null, 2));
|
|
72935
73316
|
} catch {
|
|
72936
73317
|
}
|
|
72937
73318
|
} catch {
|
|
@@ -73001,13 +73382,13 @@ __export(run_exports, {
|
|
|
73001
73382
|
});
|
|
73002
73383
|
import { resolve as resolve33 } from "node:path";
|
|
73003
73384
|
import { spawn as spawn22 } from "node:child_process";
|
|
73004
|
-
import { mkdirSync as
|
|
73385
|
+
import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync29, readFileSync as readFileSync47, readdirSync as readdirSync24, existsSync as existsSync58 } from "node:fs";
|
|
73005
73386
|
import { randomBytes as randomBytes17 } from "node:crypto";
|
|
73006
|
-
import { join as
|
|
73387
|
+
import { join as join75 } from "node:path";
|
|
73007
73388
|
function jobsDir2(repoPath) {
|
|
73008
73389
|
const root = resolve33(repoPath ?? process.cwd());
|
|
73009
|
-
const dir =
|
|
73010
|
-
|
|
73390
|
+
const dir = join75(root, ".oa", "jobs");
|
|
73391
|
+
mkdirSync31(dir, { recursive: true });
|
|
73011
73392
|
return dir;
|
|
73012
73393
|
}
|
|
73013
73394
|
async function runCommand(opts, config) {
|
|
@@ -73092,7 +73473,7 @@ async function runBackground(task, config, opts) {
|
|
|
73092
73473
|
});
|
|
73093
73474
|
child.unref();
|
|
73094
73475
|
job.pid = child.pid ?? 0;
|
|
73095
|
-
|
|
73476
|
+
writeFileSync29(join75(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
73096
73477
|
let output = "";
|
|
73097
73478
|
child.stdout?.on("data", (chunk) => {
|
|
73098
73479
|
output += chunk.toString();
|
|
@@ -73108,7 +73489,7 @@ async function runBackground(task, config, opts) {
|
|
|
73108
73489
|
job.summary = result.summary;
|
|
73109
73490
|
job.durationMs = result.durationMs;
|
|
73110
73491
|
job.error = result.error;
|
|
73111
|
-
|
|
73492
|
+
writeFileSync29(join75(dir, `${id}.json`), JSON.stringify(job, null, 2));
|
|
73112
73493
|
} catch {
|
|
73113
73494
|
}
|
|
73114
73495
|
});
|
|
@@ -73124,13 +73505,13 @@ async function runBackground(task, config, opts) {
|
|
|
73124
73505
|
}
|
|
73125
73506
|
function statusCommand(jobId, repoPath) {
|
|
73126
73507
|
const dir = jobsDir2(repoPath);
|
|
73127
|
-
const file =
|
|
73128
|
-
if (!
|
|
73508
|
+
const file = join75(dir, `${jobId}.json`);
|
|
73509
|
+
if (!existsSync58(file)) {
|
|
73129
73510
|
console.error(`Job not found: ${jobId}`);
|
|
73130
73511
|
console.log(`Available jobs: oa jobs`);
|
|
73131
73512
|
process.exit(1);
|
|
73132
73513
|
}
|
|
73133
|
-
const job = JSON.parse(
|
|
73514
|
+
const job = JSON.parse(readFileSync47(file, "utf-8"));
|
|
73134
73515
|
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`;
|
|
73135
73516
|
const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
|
|
73136
73517
|
console.log(`${icon} ${job.id} [${job.status}] ${runtime}`);
|
|
@@ -73145,7 +73526,7 @@ function statusCommand(jobId, repoPath) {
|
|
|
73145
73526
|
}
|
|
73146
73527
|
function jobsCommand(repoPath) {
|
|
73147
73528
|
const dir = jobsDir2(repoPath);
|
|
73148
|
-
const files =
|
|
73529
|
+
const files = readdirSync24(dir).filter((f) => f.endsWith(".json")).sort();
|
|
73149
73530
|
if (files.length === 0) {
|
|
73150
73531
|
console.log("No jobs found.");
|
|
73151
73532
|
return;
|
|
@@ -73153,7 +73534,7 @@ function jobsCommand(repoPath) {
|
|
|
73153
73534
|
console.log("Jobs:");
|
|
73154
73535
|
for (const file of files) {
|
|
73155
73536
|
try {
|
|
73156
|
-
const job = JSON.parse(
|
|
73537
|
+
const job = JSON.parse(readFileSync47(join75(dir, file), "utf-8"));
|
|
73157
73538
|
const icon = job.status === "completed" ? "\u2713" : job.status === "failed" ? "\u2717" : "\u25CF";
|
|
73158
73539
|
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`;
|
|
73159
73540
|
console.log(` ${icon} ${job.id} [${job.status}] ${runtime} \u2014 ${job.task.slice(0, 60)}`);
|
|
@@ -73173,7 +73554,7 @@ import { glob } from "glob";
|
|
|
73173
73554
|
import ignore from "ignore";
|
|
73174
73555
|
import { readFile as readFile23, stat as stat4 } from "node:fs/promises";
|
|
73175
73556
|
import { createHash as createHash6 } from "node:crypto";
|
|
73176
|
-
import { join as
|
|
73557
|
+
import { join as join76, relative as relative4, extname as extname12, basename as basename17 } from "node:path";
|
|
73177
73558
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
73178
73559
|
var init_codebase_indexer = __esm({
|
|
73179
73560
|
"packages/indexer/dist/codebase-indexer.js"() {
|
|
@@ -73217,7 +73598,7 @@ var init_codebase_indexer = __esm({
|
|
|
73217
73598
|
const ig = ignore.default();
|
|
73218
73599
|
if (this.config.respectGitignore) {
|
|
73219
73600
|
try {
|
|
73220
|
-
const gitignoreContent = await readFile23(
|
|
73601
|
+
const gitignoreContent = await readFile23(join76(this.config.rootDir, ".gitignore"), "utf-8");
|
|
73221
73602
|
ig.add(gitignoreContent);
|
|
73222
73603
|
} catch {
|
|
73223
73604
|
}
|
|
@@ -73232,7 +73613,7 @@ var init_codebase_indexer = __esm({
|
|
|
73232
73613
|
for (const relativePath of files) {
|
|
73233
73614
|
if (ig.ignores(relativePath))
|
|
73234
73615
|
continue;
|
|
73235
|
-
const fullPath =
|
|
73616
|
+
const fullPath = join76(this.config.rootDir, relativePath);
|
|
73236
73617
|
try {
|
|
73237
73618
|
const fileStat = await stat4(fullPath);
|
|
73238
73619
|
if (fileStat.size > this.config.maxFileSize)
|
|
@@ -73278,7 +73659,7 @@ var init_codebase_indexer = __esm({
|
|
|
73278
73659
|
if (!child) {
|
|
73279
73660
|
child = {
|
|
73280
73661
|
name: part,
|
|
73281
|
-
path:
|
|
73662
|
+
path: join76(current.path, part),
|
|
73282
73663
|
type: "directory",
|
|
73283
73664
|
children: []
|
|
73284
73665
|
};
|
|
@@ -73361,13 +73742,13 @@ __export(index_repo_exports, {
|
|
|
73361
73742
|
indexRepoCommand: () => indexRepoCommand
|
|
73362
73743
|
});
|
|
73363
73744
|
import { resolve as resolve34 } from "node:path";
|
|
73364
|
-
import { existsSync as
|
|
73745
|
+
import { existsSync as existsSync59, statSync as statSync17 } from "node:fs";
|
|
73365
73746
|
import { cwd as cwd2 } from "node:process";
|
|
73366
73747
|
async function indexRepoCommand(opts, _config) {
|
|
73367
73748
|
const repoRoot = resolve34(opts.repoPath ?? cwd2());
|
|
73368
73749
|
printHeader("Index Repository");
|
|
73369
73750
|
printInfo(`Indexing: ${repoRoot}`);
|
|
73370
|
-
if (!
|
|
73751
|
+
if (!existsSync59(repoRoot)) {
|
|
73371
73752
|
printError(`Path does not exist: ${repoRoot}`);
|
|
73372
73753
|
process.exit(1);
|
|
73373
73754
|
}
|
|
@@ -73619,7 +74000,7 @@ var config_exports2 = {};
|
|
|
73619
74000
|
__export(config_exports2, {
|
|
73620
74001
|
configCommand: () => configCommand
|
|
73621
74002
|
});
|
|
73622
|
-
import { join as
|
|
74003
|
+
import { join as join77, resolve as resolve35 } from "node:path";
|
|
73623
74004
|
import { homedir as homedir20 } from "node:os";
|
|
73624
74005
|
import { cwd as cwd3 } from "node:process";
|
|
73625
74006
|
function redactIfSensitive(key, value) {
|
|
@@ -73702,7 +74083,7 @@ function handleShow(opts, config) {
|
|
|
73702
74083
|
}
|
|
73703
74084
|
}
|
|
73704
74085
|
printSection("Config File");
|
|
73705
|
-
printInfo(`~/.open-agents/config.json (${
|
|
74086
|
+
printInfo(`~/.open-agents/config.json (${join77(homedir20(), ".open-agents", "config.json")})`);
|
|
73706
74087
|
printSection("Priority Chain");
|
|
73707
74088
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
73708
74089
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -73741,7 +74122,7 @@ function handleSet(opts, _config) {
|
|
|
73741
74122
|
const coerced = coerceForSettings(key, value);
|
|
73742
74123
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
73743
74124
|
printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
|
|
73744
|
-
printInfo(`Saved to ${
|
|
74125
|
+
printInfo(`Saved to ${join77(repoRoot, ".oa", "settings.json")}`);
|
|
73745
74126
|
printInfo("This override applies only when running in this workspace.");
|
|
73746
74127
|
} catch (err) {
|
|
73747
74128
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -73884,8 +74265,8 @@ __export(eval_exports, {
|
|
|
73884
74265
|
evalCommand: () => evalCommand
|
|
73885
74266
|
});
|
|
73886
74267
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
73887
|
-
import { mkdirSync as
|
|
73888
|
-
import { join as
|
|
74268
|
+
import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync30 } from "node:fs";
|
|
74269
|
+
import { join as join78 } from "node:path";
|
|
73889
74270
|
async function evalCommand(opts, config) {
|
|
73890
74271
|
const suiteName = opts.suite ?? "basic";
|
|
73891
74272
|
const suite = SUITES[suiteName];
|
|
@@ -74010,9 +74391,9 @@ async function evalCommand(opts, config) {
|
|
|
74010
74391
|
process.exit(failed > 0 ? 1 : 0);
|
|
74011
74392
|
}
|
|
74012
74393
|
function createTempEvalRepo() {
|
|
74013
|
-
const dir =
|
|
74014
|
-
|
|
74015
|
-
|
|
74394
|
+
const dir = join78(tmpdir10(), `open-agents-eval-${Date.now()}`);
|
|
74395
|
+
mkdirSync32(dir, { recursive: true });
|
|
74396
|
+
writeFileSync30(join78(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
74016
74397
|
return dir;
|
|
74017
74398
|
}
|
|
74018
74399
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -74072,7 +74453,7 @@ init_updater();
|
|
|
74072
74453
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
74073
74454
|
import { createRequire as createRequire5 } from "node:module";
|
|
74074
74455
|
import { fileURLToPath as fileURLToPath15 } from "node:url";
|
|
74075
|
-
import { dirname as dirname23, join as
|
|
74456
|
+
import { dirname as dirname23, join as join79 } from "node:path";
|
|
74076
74457
|
|
|
74077
74458
|
// packages/cli/dist/cli.js
|
|
74078
74459
|
import { createInterface } from "node:readline";
|
|
@@ -74179,7 +74560,7 @@ init_output();
|
|
|
74179
74560
|
function getVersion5() {
|
|
74180
74561
|
try {
|
|
74181
74562
|
const require2 = createRequire5(import.meta.url);
|
|
74182
|
-
const pkgPath =
|
|
74563
|
+
const pkgPath = join79(dirname23(fileURLToPath15(import.meta.url)), "..", "package.json");
|
|
74183
74564
|
const pkg = require2(pkgPath);
|
|
74184
74565
|
return pkg.version;
|
|
74185
74566
|
} catch {
|
|
@@ -74454,12 +74835,12 @@ function crashLog(label, err) {
|
|
|
74454
74835
|
const logLine = `[${timestamp}] ${label}: ${msg}
|
|
74455
74836
|
`;
|
|
74456
74837
|
try {
|
|
74457
|
-
const { appendFileSync: appendFileSync6, mkdirSync:
|
|
74458
|
-
const { join:
|
|
74838
|
+
const { appendFileSync: appendFileSync6, mkdirSync: mkdirSync33 } = __require("node:fs");
|
|
74839
|
+
const { join: join80 } = __require("node:path");
|
|
74459
74840
|
const { homedir: homedir21 } = __require("node:os");
|
|
74460
|
-
const logDir =
|
|
74461
|
-
|
|
74462
|
-
appendFileSync6(
|
|
74841
|
+
const logDir = join80(homedir21(), ".open-agents");
|
|
74842
|
+
mkdirSync33(logDir, { recursive: true });
|
|
74843
|
+
appendFileSync6(join80(logDir, "crash.log"), logLine);
|
|
74463
74844
|
} catch {
|
|
74464
74845
|
}
|
|
74465
74846
|
try {
|