open-agents-ai 0.97.0 → 0.100.0
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/README.md +43 -11
- package/dist/index.js +1069 -557
- package/package.json +2 -1
- package/prompts/agentic/system-large.md +30 -1
- package/prompts/agentic/system-medium.md +6 -1
- package/prompts/agentic/system-small.md +3 -0
- package/prompts/skill-builder/seed-analysis.md +30 -0
- package/prompts/skill-builder/skill-expansion.md +76 -0
- package/prompts/skill-builder/skill-validation.md +31 -0
package/dist/index.js
CHANGED
|
@@ -6047,7 +6047,8 @@ function loadSkillsFromDir(dir, source, out) {
|
|
|
6047
6047
|
description: manifestEntry?.description ?? parseDescription(skillMd),
|
|
6048
6048
|
triggers: manifestEntry?.triggers ?? parseTriggers(skillMd),
|
|
6049
6049
|
source,
|
|
6050
|
-
filePath: skillMd
|
|
6050
|
+
filePath: skillMd,
|
|
6051
|
+
compactionStrategy: parseCompactionStrategy(skillMd)
|
|
6051
6052
|
};
|
|
6052
6053
|
out.set(entry, info);
|
|
6053
6054
|
}
|
|
@@ -6134,6 +6135,25 @@ function parseDescription(filePath) {
|
|
|
6134
6135
|
}
|
|
6135
6136
|
return "";
|
|
6136
6137
|
}
|
|
6138
|
+
function parseCompactionStrategy(filePath) {
|
|
6139
|
+
try {
|
|
6140
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
6141
|
+
if (!content.startsWith("---"))
|
|
6142
|
+
return void 0;
|
|
6143
|
+
const endIdx = content.indexOf("---", 3);
|
|
6144
|
+
if (endIdx === -1)
|
|
6145
|
+
return void 0;
|
|
6146
|
+
const frontmatter = content.slice(3, endIdx);
|
|
6147
|
+
const match = frontmatter.match(/^compaction_strategy:\s*(.+)$/m);
|
|
6148
|
+
if (!match)
|
|
6149
|
+
return void 0;
|
|
6150
|
+
const val = match[1].trim().toLowerCase();
|
|
6151
|
+
const valid = ["default", "aggressive", "decisions", "errors", "summary", "structured"];
|
|
6152
|
+
return valid.includes(val) ? val : void 0;
|
|
6153
|
+
} catch {
|
|
6154
|
+
return void 0;
|
|
6155
|
+
}
|
|
6156
|
+
}
|
|
6137
6157
|
function parseTriggers(filePath) {
|
|
6138
6158
|
const triggers = [];
|
|
6139
6159
|
try {
|
|
@@ -6269,10 +6289,12 @@ Did you mean: ${fuzzy.map((s) => s.name).join(", ")}?` : "\nUse skill_list to se
|
|
|
6269
6289
|
durationMs: performance.now() - start
|
|
6270
6290
|
};
|
|
6271
6291
|
}
|
|
6292
|
+
const compactionHint = skill.compactionStrategy ? `
|
|
6293
|
+
Compaction strategy: ${skill.compactionStrategy}` : "";
|
|
6272
6294
|
return {
|
|
6273
6295
|
success: true,
|
|
6274
6296
|
output: `# Skill: ${skill.name}
|
|
6275
|
-
Source: ${skill.source}
|
|
6297
|
+
Source: ${skill.source}${compactionHint}
|
|
6276
6298
|
|
|
6277
6299
|
${content}`,
|
|
6278
6300
|
durationMs: performance.now() - start
|
|
@@ -6282,9 +6304,254 @@ ${content}`,
|
|
|
6282
6304
|
}
|
|
6283
6305
|
});
|
|
6284
6306
|
|
|
6307
|
+
// packages/execution/dist/tools/skill-builder.js
|
|
6308
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync4 } from "node:fs";
|
|
6309
|
+
import { join as join15, dirname as dirname4 } from "node:path";
|
|
6310
|
+
function loadBuilderPrompt(name, vars) {
|
|
6311
|
+
const candidates = [
|
|
6312
|
+
// Dev layout: execution/dist/tools/ → orchestrator/prompts/
|
|
6313
|
+
join15(dirname4(dirname4(dirname4(__dirname))), "orchestrator", "prompts", "skill-builder", name),
|
|
6314
|
+
// Published layout: publish/dist/ → publish/prompts/
|
|
6315
|
+
join15(dirname4(dirname4(__dirname)), "prompts", "skill-builder", name),
|
|
6316
|
+
// Monorepo root fallback
|
|
6317
|
+
join15(dirname4(dirname4(dirname4(dirname4(__dirname)))), "packages", "orchestrator", "prompts", "skill-builder", name)
|
|
6318
|
+
];
|
|
6319
|
+
let content;
|
|
6320
|
+
for (const p of candidates) {
|
|
6321
|
+
try {
|
|
6322
|
+
content = readFileSync9(p, "utf-8");
|
|
6323
|
+
break;
|
|
6324
|
+
} catch {
|
|
6325
|
+
}
|
|
6326
|
+
}
|
|
6327
|
+
if (!content) {
|
|
6328
|
+
throw new Error(`Skill builder prompt not found: ${name} (searched: ${candidates.join(", ")})`);
|
|
6329
|
+
}
|
|
6330
|
+
if (!vars)
|
|
6331
|
+
return content;
|
|
6332
|
+
return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
|
|
6333
|
+
}
|
|
6334
|
+
function extractJSON(text) {
|
|
6335
|
+
const codeBlockMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
|
|
6336
|
+
if (codeBlockMatch)
|
|
6337
|
+
return codeBlockMatch[1].trim();
|
|
6338
|
+
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
6339
|
+
if (jsonMatch)
|
|
6340
|
+
return jsonMatch[0];
|
|
6341
|
+
throw new Error("No JSON found in LLM response");
|
|
6342
|
+
}
|
|
6343
|
+
var SkillBuildTool;
|
|
6344
|
+
var init_skill_builder = __esm({
|
|
6345
|
+
"packages/execution/dist/tools/skill-builder.js"() {
|
|
6346
|
+
"use strict";
|
|
6347
|
+
SkillBuildTool = class {
|
|
6348
|
+
name = "skill_build";
|
|
6349
|
+
description = "Generate a comprehensive SKILL.md from a simple skill request. Takes a natural language description (e.g. 'learn to write pytest fixtures') and expands it into a structured skill definition with triggers, behaviors, verification steps, and compaction hints. The skill is saved to .oa/skills/ for immediate use with skill_execute.";
|
|
6350
|
+
parameters = {
|
|
6351
|
+
type: "object",
|
|
6352
|
+
properties: {
|
|
6353
|
+
skill_request: {
|
|
6354
|
+
type: "string",
|
|
6355
|
+
description: "Natural language description of the skill to build (e.g. 'write Rust unit tests', 'debug Kubernetes pods', 'optimize SQL queries')"
|
|
6356
|
+
},
|
|
6357
|
+
target_dir: {
|
|
6358
|
+
type: "string",
|
|
6359
|
+
description: "Optional: directory to save the skill. Defaults to .oa/skills/ in the project root. Can also be .aiwg/skills/ for AIWG-compatible deployment."
|
|
6360
|
+
},
|
|
6361
|
+
validate: {
|
|
6362
|
+
type: "boolean",
|
|
6363
|
+
description: "Whether to run the validation phase (default: true). Validation scores the generated skill and suggests improvements."
|
|
6364
|
+
}
|
|
6365
|
+
},
|
|
6366
|
+
required: ["skill_request"]
|
|
6367
|
+
};
|
|
6368
|
+
repoRoot;
|
|
6369
|
+
llmCall;
|
|
6370
|
+
constructor(repoRoot, llmCall) {
|
|
6371
|
+
this.repoRoot = repoRoot;
|
|
6372
|
+
this.llmCall = llmCall;
|
|
6373
|
+
}
|
|
6374
|
+
async execute(args) {
|
|
6375
|
+
const start = performance.now();
|
|
6376
|
+
const skillRequest = String(args["skill_request"] ?? "").trim();
|
|
6377
|
+
const targetDir = String(args["target_dir"] ?? join15(this.repoRoot, ".oa", "skills"));
|
|
6378
|
+
const shouldValidate = args["validate"] !== false;
|
|
6379
|
+
if (!skillRequest) {
|
|
6380
|
+
return {
|
|
6381
|
+
success: false,
|
|
6382
|
+
output: "",
|
|
6383
|
+
error: "skill_request is required. Describe the skill you want to build.",
|
|
6384
|
+
durationMs: performance.now() - start
|
|
6385
|
+
};
|
|
6386
|
+
}
|
|
6387
|
+
try {
|
|
6388
|
+
const seed = await this.analyzeSeed(skillRequest);
|
|
6389
|
+
let skillContent = await this.expandSkill(seed);
|
|
6390
|
+
let validationInfo = "";
|
|
6391
|
+
if (shouldValidate) {
|
|
6392
|
+
const validation = await this.validateSkill(skillContent);
|
|
6393
|
+
validationInfo = `
|
|
6394
|
+
Validation: ${validation.pass ? "PASS" : "NEEDS IMPROVEMENT"} (${validation.overall.toFixed(1)}/5.0)`;
|
|
6395
|
+
if (validation.fixes.length > 0) {
|
|
6396
|
+
validationInfo += `
|
|
6397
|
+
Suggestions: ${validation.fixes.join("; ")}`;
|
|
6398
|
+
}
|
|
6399
|
+
if (!validation.pass && validation.fixes.length > 0) {
|
|
6400
|
+
skillContent = await this.refineSkill(skillContent, validation.fixes);
|
|
6401
|
+
validationInfo += "\n Applied refinement pass.";
|
|
6402
|
+
}
|
|
6403
|
+
}
|
|
6404
|
+
const skillDir = join15(targetDir, seed.name);
|
|
6405
|
+
const skillPath = join15(skillDir, "SKILL.md");
|
|
6406
|
+
if (!existsSync12(skillDir)) {
|
|
6407
|
+
mkdirSync4(skillDir, { recursive: true });
|
|
6408
|
+
}
|
|
6409
|
+
writeFileSync4(skillPath, skillContent, "utf-8");
|
|
6410
|
+
const output = [
|
|
6411
|
+
`Skill "${seed.name}" built successfully.`,
|
|
6412
|
+
` Domain: ${seed.domain}`,
|
|
6413
|
+
` Scope: ${seed.scope}`,
|
|
6414
|
+
` Capabilities: ${seed.capabilities.length}`,
|
|
6415
|
+
` Triggers: ${seed.triggers.length}`,
|
|
6416
|
+
` Compaction: ${seed.compaction_strategy}`,
|
|
6417
|
+
` Saved to: ${skillPath}`,
|
|
6418
|
+
validationInfo,
|
|
6419
|
+
"",
|
|
6420
|
+
'Use `skill_execute` with name "' + seed.name + '" to load the skill.'
|
|
6421
|
+
].join("\n");
|
|
6422
|
+
return {
|
|
6423
|
+
success: true,
|
|
6424
|
+
output,
|
|
6425
|
+
durationMs: performance.now() - start
|
|
6426
|
+
};
|
|
6427
|
+
} catch (err) {
|
|
6428
|
+
return {
|
|
6429
|
+
success: false,
|
|
6430
|
+
output: "",
|
|
6431
|
+
error: `Skill build failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
6432
|
+
durationMs: performance.now() - start
|
|
6433
|
+
};
|
|
6434
|
+
}
|
|
6435
|
+
}
|
|
6436
|
+
// -------------------------------------------------------------------------
|
|
6437
|
+
// Phase 1: Seed Analysis
|
|
6438
|
+
// -------------------------------------------------------------------------
|
|
6439
|
+
async analyzeSeed(request) {
|
|
6440
|
+
const prompt = loadBuilderPrompt("seed-analysis.md", {
|
|
6441
|
+
skill_request: request
|
|
6442
|
+
});
|
|
6443
|
+
const response = await this.llmCall([
|
|
6444
|
+
{ role: "system", content: prompt },
|
|
6445
|
+
{ role: "user", content: `Analyze this skill request: "${request}"` }
|
|
6446
|
+
]);
|
|
6447
|
+
const jsonStr = extractJSON(response);
|
|
6448
|
+
const seed = JSON.parse(jsonStr);
|
|
6449
|
+
if (!seed.name || !seed.description || !seed.capabilities?.length) {
|
|
6450
|
+
throw new Error("Seed analysis produced incomplete result \u2014 missing name, description, or capabilities");
|
|
6451
|
+
}
|
|
6452
|
+
seed.name = seed.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
6453
|
+
return seed;
|
|
6454
|
+
}
|
|
6455
|
+
// -------------------------------------------------------------------------
|
|
6456
|
+
// Phase 2: Skill Expansion
|
|
6457
|
+
// -------------------------------------------------------------------------
|
|
6458
|
+
async expandSkill(seed) {
|
|
6459
|
+
const prompt = loadBuilderPrompt("skill-expansion.md", {
|
|
6460
|
+
seed_json: JSON.stringify(seed, null, 2)
|
|
6461
|
+
});
|
|
6462
|
+
const response = await this.llmCall([
|
|
6463
|
+
{ role: "system", content: prompt },
|
|
6464
|
+
{
|
|
6465
|
+
role: "user",
|
|
6466
|
+
content: `Generate the complete SKILL.md for the "${seed.name}" skill.`
|
|
6467
|
+
}
|
|
6468
|
+
]);
|
|
6469
|
+
let content = response.trim();
|
|
6470
|
+
if (content.startsWith("```markdown")) {
|
|
6471
|
+
content = content.slice("```markdown".length).trim();
|
|
6472
|
+
} else if (content.startsWith("```")) {
|
|
6473
|
+
content = content.slice(3).trim();
|
|
6474
|
+
}
|
|
6475
|
+
if (content.endsWith("```")) {
|
|
6476
|
+
content = content.slice(0, -3).trim();
|
|
6477
|
+
}
|
|
6478
|
+
if (!content.startsWith("---")) {
|
|
6479
|
+
const frontmatter = [
|
|
6480
|
+
"---",
|
|
6481
|
+
`name: ${seed.name}`,
|
|
6482
|
+
`description: ${seed.description}`,
|
|
6483
|
+
`compaction_strategy: ${seed.compaction_strategy}`,
|
|
6484
|
+
"triggers:",
|
|
6485
|
+
...seed.triggers.map((t) => ` - "${t}"`),
|
|
6486
|
+
"---",
|
|
6487
|
+
""
|
|
6488
|
+
].join("\n");
|
|
6489
|
+
content = frontmatter + content;
|
|
6490
|
+
}
|
|
6491
|
+
return content;
|
|
6492
|
+
}
|
|
6493
|
+
// -------------------------------------------------------------------------
|
|
6494
|
+
// Phase 3: Validation
|
|
6495
|
+
// -------------------------------------------------------------------------
|
|
6496
|
+
async validateSkill(content) {
|
|
6497
|
+
const prompt = loadBuilderPrompt("skill-validation.md", {
|
|
6498
|
+
skill_content: content
|
|
6499
|
+
});
|
|
6500
|
+
try {
|
|
6501
|
+
const response = await this.llmCall([
|
|
6502
|
+
{ role: "system", content: prompt },
|
|
6503
|
+
{ role: "user", content: "Validate this SKILL.md." }
|
|
6504
|
+
]);
|
|
6505
|
+
const jsonStr = extractJSON(response);
|
|
6506
|
+
return JSON.parse(jsonStr);
|
|
6507
|
+
} catch {
|
|
6508
|
+
return {
|
|
6509
|
+
scores: { structure: 3, actionability: 3, completeness: 3, verification: 3, conciseness: 3 },
|
|
6510
|
+
overall: 3,
|
|
6511
|
+
pass: true,
|
|
6512
|
+
fixes: []
|
|
6513
|
+
};
|
|
6514
|
+
}
|
|
6515
|
+
}
|
|
6516
|
+
// -------------------------------------------------------------------------
|
|
6517
|
+
// Phase 3b: Refinement (if validation fails)
|
|
6518
|
+
// -------------------------------------------------------------------------
|
|
6519
|
+
async refineSkill(content, fixes) {
|
|
6520
|
+
const fixList = fixes.map((f, i) => `${i + 1}. ${f}`).join("\n");
|
|
6521
|
+
const response = await this.llmCall([
|
|
6522
|
+
{
|
|
6523
|
+
role: "system",
|
|
6524
|
+
content: "You are a skill definition editor. Apply the requested fixes to the SKILL.md content. Output ONLY the corrected SKILL.md content (starting with --- frontmatter). Do not explain changes or add commentary."
|
|
6525
|
+
},
|
|
6526
|
+
{
|
|
6527
|
+
role: "user",
|
|
6528
|
+
content: `Apply these fixes to the SKILL.md:
|
|
6529
|
+
|
|
6530
|
+
${fixList}
|
|
6531
|
+
|
|
6532
|
+
---
|
|
6533
|
+
|
|
6534
|
+
Current SKILL.md:
|
|
6535
|
+
|
|
6536
|
+
${content}`
|
|
6537
|
+
}
|
|
6538
|
+
]);
|
|
6539
|
+
let refined = response.trim();
|
|
6540
|
+
if (refined.startsWith("```markdown"))
|
|
6541
|
+
refined = refined.slice("```markdown".length).trim();
|
|
6542
|
+
else if (refined.startsWith("```"))
|
|
6543
|
+
refined = refined.slice(3).trim();
|
|
6544
|
+
if (refined.endsWith("```"))
|
|
6545
|
+
refined = refined.slice(0, -3).trim();
|
|
6546
|
+
return refined.startsWith("---") ? refined : content;
|
|
6547
|
+
}
|
|
6548
|
+
};
|
|
6549
|
+
}
|
|
6550
|
+
});
|
|
6551
|
+
|
|
6285
6552
|
// packages/execution/dist/tools/transcribe-tool.js
|
|
6286
|
-
import { existsSync as
|
|
6287
|
-
import { join as
|
|
6553
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readFileSync as readFileSync10, unlinkSync } from "node:fs";
|
|
6554
|
+
import { join as join16, basename as basename4, extname as extname3, resolve as resolve13 } from "node:path";
|
|
6288
6555
|
import { homedir as homedir6 } from "node:os";
|
|
6289
6556
|
import { execSync as execSync10, spawn as spawn4 } from "node:child_process";
|
|
6290
6557
|
function isTranscribable(path) {
|
|
@@ -6301,25 +6568,25 @@ async function loadTranscribeCli() {
|
|
|
6301
6568
|
timeout: 5e3,
|
|
6302
6569
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6303
6570
|
}).trim();
|
|
6304
|
-
const tcPath =
|
|
6305
|
-
if (
|
|
6571
|
+
const tcPath = join16(globalRoot, "transcribe-cli");
|
|
6572
|
+
if (existsSync13(join16(tcPath, "dist", "index.js"))) {
|
|
6306
6573
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
6307
6574
|
const req = createRequire4(import.meta.url);
|
|
6308
|
-
_tcModule = req(
|
|
6575
|
+
_tcModule = req(join16(tcPath, "dist", "index.js"));
|
|
6309
6576
|
return _tcModule;
|
|
6310
6577
|
}
|
|
6311
6578
|
} catch {
|
|
6312
6579
|
}
|
|
6313
|
-
const nvmBase =
|
|
6314
|
-
if (
|
|
6580
|
+
const nvmBase = join16(homedir6(), ".nvm", "versions", "node");
|
|
6581
|
+
if (existsSync13(nvmBase)) {
|
|
6315
6582
|
try {
|
|
6316
6583
|
const { readdirSync: readdirSync15 } = await import("node:fs");
|
|
6317
6584
|
for (const ver of readdirSync15(nvmBase)) {
|
|
6318
|
-
const tcPath =
|
|
6319
|
-
if (
|
|
6585
|
+
const tcPath = join16(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
6586
|
+
if (existsSync13(join16(tcPath, "dist", "index.js"))) {
|
|
6320
6587
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
6321
6588
|
const req = createRequire4(import.meta.url);
|
|
6322
|
-
_tcModule = req(
|
|
6589
|
+
_tcModule = req(join16(tcPath, "dist", "index.js"));
|
|
6323
6590
|
return _tcModule;
|
|
6324
6591
|
}
|
|
6325
6592
|
}
|
|
@@ -6391,7 +6658,7 @@ var init_transcribe_tool = __esm({
|
|
|
6391
6658
|
const filePath = resolve13(this.workingDir, String(args["path"] ?? ""));
|
|
6392
6659
|
const model = String(args["model"] ?? "base");
|
|
6393
6660
|
const diarize = Boolean(args["diarize"] ?? false);
|
|
6394
|
-
if (!
|
|
6661
|
+
if (!existsSync13(filePath)) {
|
|
6395
6662
|
return {
|
|
6396
6663
|
success: false,
|
|
6397
6664
|
output: "",
|
|
@@ -6418,10 +6685,10 @@ var init_transcribe_tool = __esm({
|
|
|
6418
6685
|
diarize,
|
|
6419
6686
|
wordTimestamps: false
|
|
6420
6687
|
});
|
|
6421
|
-
const transcriptDir =
|
|
6422
|
-
|
|
6423
|
-
const outFile =
|
|
6424
|
-
|
|
6688
|
+
const transcriptDir = join16(this.workingDir, ".oa", "transcripts");
|
|
6689
|
+
mkdirSync5(transcriptDir, { recursive: true });
|
|
6690
|
+
const outFile = join16(transcriptDir, `${basename4(filePath)}.txt`);
|
|
6691
|
+
writeFileSync5(outFile, result.text, "utf-8");
|
|
6425
6692
|
const lines = [
|
|
6426
6693
|
`Transcription of: ${basename4(filePath)}`,
|
|
6427
6694
|
`Model: ${model} | Language: ${result.language} | Duration: ${result.duration ? `${result.duration.toFixed(1)}s` : "unknown"}`,
|
|
@@ -6518,14 +6785,14 @@ var init_transcribe_tool = __esm({
|
|
|
6518
6785
|
durationMs: performance.now() - start
|
|
6519
6786
|
};
|
|
6520
6787
|
}
|
|
6521
|
-
const tmpDir =
|
|
6522
|
-
|
|
6788
|
+
const tmpDir = join16(this.workingDir, ".oa", "tmp");
|
|
6789
|
+
mkdirSync5(tmpDir, { recursive: true });
|
|
6523
6790
|
const urlPath = new URL(url).pathname;
|
|
6524
6791
|
let ext = extname3(urlPath).toLowerCase();
|
|
6525
6792
|
if (!ext || !AUDIO_EXTS.has(ext) && !VIDEO_EXTS.has(ext)) {
|
|
6526
6793
|
ext = ".mp3";
|
|
6527
6794
|
}
|
|
6528
|
-
const tmpFile =
|
|
6795
|
+
const tmpFile = join16(tmpDir, `download-${Date.now()}${ext}`);
|
|
6529
6796
|
try {
|
|
6530
6797
|
try {
|
|
6531
6798
|
execSync10(`curl -sL -o "${tmpFile}" "${url}"`, {
|
|
@@ -6538,7 +6805,7 @@ var init_transcribe_tool = __esm({
|
|
|
6538
6805
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6539
6806
|
});
|
|
6540
6807
|
}
|
|
6541
|
-
if (!
|
|
6808
|
+
if (!existsSync13(tmpFile)) {
|
|
6542
6809
|
return {
|
|
6543
6810
|
success: false,
|
|
6544
6811
|
output: "",
|
|
@@ -6578,7 +6845,7 @@ ${result.output}`,
|
|
|
6578
6845
|
|
|
6579
6846
|
// packages/execution/dist/tools/structured-file.js
|
|
6580
6847
|
import { writeFile as writeFile6, mkdir as mkdir3 } from "node:fs/promises";
|
|
6581
|
-
import { resolve as resolve14, dirname as
|
|
6848
|
+
import { resolve as resolve14, dirname as dirname5, extname as extname4 } from "node:path";
|
|
6582
6849
|
function jsonToCSV(data, separator = ",") {
|
|
6583
6850
|
if (!Array.isArray(data) || data.length === 0)
|
|
6584
6851
|
return "";
|
|
@@ -6693,7 +6960,7 @@ var init_structured_file = __esm({
|
|
|
6693
6960
|
}
|
|
6694
6961
|
try {
|
|
6695
6962
|
const fullPath = resolve14(this.workingDir, filePath);
|
|
6696
|
-
await mkdir3(
|
|
6963
|
+
await mkdir3(dirname5(fullPath), { recursive: true });
|
|
6697
6964
|
let content;
|
|
6698
6965
|
let byteInfo = "";
|
|
6699
6966
|
switch (format) {
|
|
@@ -6759,7 +7026,7 @@ var init_structured_file = __esm({
|
|
|
6759
7026
|
// packages/execution/dist/tools/code-sandbox.js
|
|
6760
7027
|
import { spawn as spawn5 } from "node:child_process";
|
|
6761
7028
|
import { writeFile as writeFile7, mkdtemp, rm, readdir as readdir2, stat } from "node:fs/promises";
|
|
6762
|
-
import { join as
|
|
7029
|
+
import { join as join17 } from "node:path";
|
|
6763
7030
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
6764
7031
|
function runProcess(cmd, args, options) {
|
|
6765
7032
|
return new Promise((resolve31) => {
|
|
@@ -6825,7 +7092,7 @@ async function listCreatedFiles(dir) {
|
|
|
6825
7092
|
for (const entry of entries) {
|
|
6826
7093
|
if (entry.startsWith("_sandbox_script"))
|
|
6827
7094
|
continue;
|
|
6828
|
-
const fullPath =
|
|
7095
|
+
const fullPath = join17(dir, entry);
|
|
6829
7096
|
const s = await stat(fullPath);
|
|
6830
7097
|
if (s.isFile()) {
|
|
6831
7098
|
files.push(entry);
|
|
@@ -6945,9 +7212,9 @@ ${result.filesCreated.join("\n")}`);
|
|
|
6945
7212
|
// Subprocess mode — temp directory + separate process
|
|
6946
7213
|
// -------------------------------------------------------------------------
|
|
6947
7214
|
async #runSubprocess(code, langConfig, timeoutMs, stdin) {
|
|
6948
|
-
const sandboxDir = await mkdtemp(
|
|
7215
|
+
const sandboxDir = await mkdtemp(join17(tmpdir2(), "oa-sandbox-"));
|
|
6949
7216
|
try {
|
|
6950
|
-
const scriptFile =
|
|
7217
|
+
const scriptFile = join17(sandboxDir, `_sandbox_script${langConfig.ext}`);
|
|
6951
7218
|
await writeFile7(scriptFile, code, "utf-8");
|
|
6952
7219
|
const result = await runProcess(langConfig.cmd, langConfig.args(scriptFile), {
|
|
6953
7220
|
cwd: sandboxDir,
|
|
@@ -6972,10 +7239,10 @@ ${result.filesCreated.join("\n")}`);
|
|
|
6972
7239
|
bash: "bash:5"
|
|
6973
7240
|
};
|
|
6974
7241
|
const image = images[language] ?? "node:22-slim";
|
|
6975
|
-
const sandboxDir = await mkdtemp(
|
|
7242
|
+
const sandboxDir = await mkdtemp(join17(tmpdir2(), "oa-docker-sandbox-"));
|
|
6976
7243
|
try {
|
|
6977
7244
|
const scriptFile = `_sandbox_script${langConfig.ext}`;
|
|
6978
|
-
await writeFile7(
|
|
7245
|
+
await writeFile7(join17(sandboxDir, scriptFile), code, "utf-8");
|
|
6979
7246
|
const dockerArgs = [
|
|
6980
7247
|
"run",
|
|
6981
7248
|
"--rm",
|
|
@@ -7345,9 +7612,9 @@ ${parts.join("\n\n")}`,
|
|
|
7345
7612
|
});
|
|
7346
7613
|
|
|
7347
7614
|
// packages/execution/dist/tools/vision.js
|
|
7348
|
-
import { readFileSync as
|
|
7615
|
+
import { readFileSync as readFileSync11, existsSync as existsSync14, statSync as statSync5 } from "node:fs";
|
|
7349
7616
|
import { execSync as execSync11, spawn as spawn6 } from "node:child_process";
|
|
7350
|
-
import { resolve as resolve16, extname as extname6, basename as basename5, dirname as
|
|
7617
|
+
import { resolve as resolve16, extname as extname6, basename as basename5, dirname as dirname6, join as join18 } from "node:path";
|
|
7351
7618
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7352
7619
|
async function probeStation(endpoint) {
|
|
7353
7620
|
try {
|
|
@@ -7362,24 +7629,24 @@ async function probeStation(endpoint) {
|
|
|
7362
7629
|
}
|
|
7363
7630
|
}
|
|
7364
7631
|
function findStationBinary() {
|
|
7365
|
-
const oaVenvPython =
|
|
7366
|
-
if (
|
|
7632
|
+
const oaVenvPython = join18(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "python");
|
|
7633
|
+
if (existsSync14(oaVenvPython)) {
|
|
7367
7634
|
try {
|
|
7368
7635
|
execSync11(`${JSON.stringify(oaVenvPython)} -c "import moondream_station"`, { stdio: "pipe", timeout: 5e3 });
|
|
7369
7636
|
return oaVenvPython;
|
|
7370
7637
|
} catch {
|
|
7371
7638
|
}
|
|
7372
7639
|
}
|
|
7373
|
-
const oaVenvBin =
|
|
7374
|
-
if (
|
|
7640
|
+
const oaVenvBin = join18(process.env["HOME"] || "/root", ".open-agents", "venv", "bin", "moondream-station");
|
|
7641
|
+
if (existsSync14(oaVenvBin))
|
|
7375
7642
|
return oaVenvBin;
|
|
7376
|
-
const thisDir =
|
|
7643
|
+
const thisDir = dirname6(fileURLToPath2(import.meta.url));
|
|
7377
7644
|
const localVenvPaths = [
|
|
7378
7645
|
resolve16(thisDir, "../../../../.moondream-venv/bin/python"),
|
|
7379
7646
|
resolve16(thisDir, "../../../.moondream-venv/bin/python")
|
|
7380
7647
|
];
|
|
7381
7648
|
for (const p of localVenvPaths) {
|
|
7382
|
-
if (
|
|
7649
|
+
if (existsSync14(p)) {
|
|
7383
7650
|
try {
|
|
7384
7651
|
execSync11(`${JSON.stringify(p)} -c "import moondream_station"`, { stdio: "pipe", timeout: 5e3 });
|
|
7385
7652
|
return p;
|
|
@@ -7399,9 +7666,9 @@ async function autoLaunchStation(port = 2020) {
|
|
|
7399
7666
|
const pythonBin = findStationBinary();
|
|
7400
7667
|
if (!pythonBin)
|
|
7401
7668
|
return false;
|
|
7402
|
-
const thisDir =
|
|
7669
|
+
const thisDir = dirname6(fileURLToPath2(import.meta.url));
|
|
7403
7670
|
const launcherScript = resolve16(thisDir, "../../scripts/start-moondream.py");
|
|
7404
|
-
if (!
|
|
7671
|
+
if (!existsSync14(launcherScript))
|
|
7405
7672
|
return false;
|
|
7406
7673
|
return new Promise((resolvePromise) => {
|
|
7407
7674
|
const child = spawn6(pythonBin, [launcherScript, "--port", String(port)], {
|
|
@@ -7476,7 +7743,7 @@ Details: ${err.message}` : "");
|
|
|
7476
7743
|
}
|
|
7477
7744
|
function loadImageBuffer(workingDir, rawPath) {
|
|
7478
7745
|
const fullPath = resolve16(workingDir, rawPath);
|
|
7479
|
-
if (!
|
|
7746
|
+
if (!existsSync14(fullPath)) {
|
|
7480
7747
|
throw new Error(`File not found: ${rawPath}`);
|
|
7481
7748
|
}
|
|
7482
7749
|
const stat5 = statSync5(fullPath);
|
|
@@ -7487,7 +7754,7 @@ function loadImageBuffer(workingDir, rawPath) {
|
|
|
7487
7754
|
if (!IMAGE_EXTENSIONS2.has(ext)) {
|
|
7488
7755
|
throw new Error(`Not a supported image format: ${ext}. Supported: ${[...IMAGE_EXTENSIONS2].join(", ")}`);
|
|
7489
7756
|
}
|
|
7490
|
-
return { buffer:
|
|
7757
|
+
return { buffer: readFileSync11(fullPath), fullPath };
|
|
7491
7758
|
}
|
|
7492
7759
|
var moondreamClient, moondreamError, stationProcess, IMAGE_EXTENSIONS2, VisionTool;
|
|
7493
7760
|
var init_vision = __esm({
|
|
@@ -7715,10 +7982,10 @@ ${response}`, durationMs: performance.now() - start };
|
|
|
7715
7982
|
});
|
|
7716
7983
|
|
|
7717
7984
|
// packages/execution/dist/tools/desktop-click.js
|
|
7718
|
-
import { readFileSync as
|
|
7985
|
+
import { readFileSync as readFileSync12, existsSync as existsSync15 } from "node:fs";
|
|
7719
7986
|
import { execSync as execSync12 } from "node:child_process";
|
|
7720
7987
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
7721
|
-
import { join as
|
|
7988
|
+
import { join as join19, dirname as dirname7 } from "node:path";
|
|
7722
7989
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
7723
7990
|
function hasCommand2(cmd) {
|
|
7724
7991
|
try {
|
|
@@ -7780,7 +8047,7 @@ function captureScreenshot(outputPath) {
|
|
|
7780
8047
|
} else {
|
|
7781
8048
|
try {
|
|
7782
8049
|
execSync12(`DISPLAY=:0 python3 -c "from PIL import ImageGrab; ImageGrab.grab().save(${JSON.stringify(outputPath)})"`, { stdio: "pipe", timeout: 1e4 });
|
|
7783
|
-
if (
|
|
8050
|
+
if (existsSync15(outputPath))
|
|
7784
8051
|
return;
|
|
7785
8052
|
} catch {
|
|
7786
8053
|
}
|
|
@@ -7791,7 +8058,7 @@ function captureScreenshot(outputPath) {
|
|
|
7791
8058
|
throw new Error("No screenshot tool found. Auto-install failed. Try manually: sudo apt install scrot");
|
|
7792
8059
|
}
|
|
7793
8060
|
execSync12(cmd, { stdio: "pipe", timeout: 1e4 });
|
|
7794
|
-
if (!
|
|
8061
|
+
if (!existsSync15(outputPath)) {
|
|
7795
8062
|
throw new Error("Screenshot file was not created");
|
|
7796
8063
|
}
|
|
7797
8064
|
}
|
|
@@ -7842,7 +8109,7 @@ for i in range(${clicks}):
|
|
|
7842
8109
|
} catch {
|
|
7843
8110
|
}
|
|
7844
8111
|
try {
|
|
7845
|
-
const venvPy =
|
|
8112
|
+
const venvPy = join19(__dirname2, "../../../../.moondream-venv/bin/python");
|
|
7846
8113
|
execSync12(`DISPLAY=:0 ${JSON.stringify(venvPy)} -c "${pyScript}"`, { stdio: "pipe", timeout: 5e3 });
|
|
7847
8114
|
return;
|
|
7848
8115
|
} catch {
|
|
@@ -7865,12 +8132,12 @@ for i in range(${clicks}):
|
|
|
7865
8132
|
throw new Error(`Desktop click not supported on platform: ${plat}`);
|
|
7866
8133
|
}
|
|
7867
8134
|
}
|
|
7868
|
-
var
|
|
8135
|
+
var __dirname2, DesktopClickTool, DesktopDescribeTool;
|
|
7869
8136
|
var init_desktop_click = __esm({
|
|
7870
8137
|
"packages/execution/dist/tools/desktop-click.js"() {
|
|
7871
8138
|
"use strict";
|
|
7872
8139
|
init_system_deps();
|
|
7873
|
-
|
|
8140
|
+
__dirname2 = dirname7(fileURLToPath3(import.meta.url));
|
|
7874
8141
|
DesktopClickTool = class {
|
|
7875
8142
|
workingDir;
|
|
7876
8143
|
name = "desktop_click";
|
|
@@ -7934,7 +8201,7 @@ var init_desktop_click = __esm({
|
|
|
7934
8201
|
if (delayMs > 0) {
|
|
7935
8202
|
await new Promise((r) => setTimeout(r, delayMs));
|
|
7936
8203
|
}
|
|
7937
|
-
const screenshotPath =
|
|
8204
|
+
const screenshotPath = join19(tmpdir3(), `oa-desktop-click-${Date.now()}.png`);
|
|
7938
8205
|
captureScreenshot(screenshotPath);
|
|
7939
8206
|
const dims = getImageDimensions2(screenshotPath);
|
|
7940
8207
|
if (!dims) {
|
|
@@ -7959,7 +8226,7 @@ var init_desktop_click = __esm({
|
|
|
7959
8226
|
} else {
|
|
7960
8227
|
client = new vl({ endpoint: "http://localhost:2020/v1" });
|
|
7961
8228
|
}
|
|
7962
|
-
const imageBuffer =
|
|
8229
|
+
const imageBuffer = readFileSync12(screenshotPath);
|
|
7963
8230
|
const pointResult = await client.point({ image: imageBuffer, object: target });
|
|
7964
8231
|
points = pointResult.points ?? [];
|
|
7965
8232
|
visionWorked = true;
|
|
@@ -7970,7 +8237,7 @@ var init_desktop_click = __esm({
|
|
|
7970
8237
|
const ollamaHost = process.env["OLLAMA_HOST"] || "http://127.0.0.1:11434";
|
|
7971
8238
|
const envModel = process.env["OLLAMA_VISION_MODEL"];
|
|
7972
8239
|
const ollamaModel = envModel || (this._activeModelHasVision && this._activeModel ? this._activeModel : "moondream");
|
|
7973
|
-
const imageBase64 =
|
|
8240
|
+
const imageBase64 = readFileSync12(screenshotPath).toString("base64");
|
|
7974
8241
|
const res = await fetch(`${ollamaHost}/api/generate`, {
|
|
7975
8242
|
method: "POST",
|
|
7976
8243
|
headers: { "Content-Type": "application/json" },
|
|
@@ -8109,10 +8376,10 @@ Screenshot: ${screenshotPath}`,
|
|
|
8109
8376
|
if (delayMs > 0) {
|
|
8110
8377
|
await new Promise((r) => setTimeout(r, delayMs));
|
|
8111
8378
|
}
|
|
8112
|
-
const screenshotPath =
|
|
8379
|
+
const screenshotPath = join19(tmpdir3(), `oa-desktop-describe-${Date.now()}.png`);
|
|
8113
8380
|
captureScreenshot(screenshotPath);
|
|
8114
8381
|
const dims = getImageDimensions2(screenshotPath);
|
|
8115
|
-
const imageBuffer =
|
|
8382
|
+
const imageBuffer = readFileSync12(screenshotPath);
|
|
8116
8383
|
const parts = [];
|
|
8117
8384
|
let visionWorked = false;
|
|
8118
8385
|
try {
|
|
@@ -8224,7 +8491,7 @@ Screen: ${dims.width}x${dims.height}`);
|
|
|
8224
8491
|
});
|
|
8225
8492
|
|
|
8226
8493
|
// packages/execution/dist/tools/ocr-pdf.js
|
|
8227
|
-
import { existsSync as
|
|
8494
|
+
import { existsSync as existsSync16, statSync as statSync6 } from "node:fs";
|
|
8228
8495
|
import { resolve as resolve17, basename as basename6 } from "node:path";
|
|
8229
8496
|
import { execSync as execSync13 } from "node:child_process";
|
|
8230
8497
|
var OcrPdfTool;
|
|
@@ -8276,7 +8543,7 @@ var init_ocr_pdf = __esm({
|
|
|
8276
8543
|
return { success: false, output: "", error: "input path is required", durationMs: 0 };
|
|
8277
8544
|
}
|
|
8278
8545
|
const inputPath = resolve17(this.workingDir, rawInput);
|
|
8279
|
-
if (!
|
|
8546
|
+
if (!existsSync16(inputPath)) {
|
|
8280
8547
|
return { success: false, output: "", error: `File not found: ${rawInput}`, durationMs: performance.now() - start };
|
|
8281
8548
|
}
|
|
8282
8549
|
const stat5 = statSync6(inputPath);
|
|
@@ -8347,8 +8614,8 @@ Language: ${language}
|
|
|
8347
8614
|
});
|
|
8348
8615
|
|
|
8349
8616
|
// packages/execution/dist/tools/pdf-to-text.js
|
|
8350
|
-
import { existsSync as
|
|
8351
|
-
import { resolve as resolve18, basename as basename7, join as
|
|
8617
|
+
import { existsSync as existsSync17, statSync as statSync7, readFileSync as readFileSync13, unlinkSync as unlinkSync2 } from "node:fs";
|
|
8618
|
+
import { resolve as resolve18, basename as basename7, join as join20 } from "node:path";
|
|
8352
8619
|
import { execSync as execSync14 } from "node:child_process";
|
|
8353
8620
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
8354
8621
|
var PdfToTextTool;
|
|
@@ -8400,7 +8667,7 @@ var init_pdf_to_text = __esm({
|
|
|
8400
8667
|
return { success: false, output: "", error: "path is required", durationMs: 0 };
|
|
8401
8668
|
}
|
|
8402
8669
|
const fullPath = resolve18(this.workingDir, rawPath);
|
|
8403
|
-
if (!
|
|
8670
|
+
if (!existsSync17(fullPath)) {
|
|
8404
8671
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: performance.now() - start };
|
|
8405
8672
|
}
|
|
8406
8673
|
const fileStat = statSync7(fullPath);
|
|
@@ -8502,7 +8769,7 @@ ${text}`,
|
|
|
8502
8769
|
if (!ocrCheck.available || !tesCheck.available || !gsCheck.available) {
|
|
8503
8770
|
return null;
|
|
8504
8771
|
}
|
|
8505
|
-
const tmpPdf =
|
|
8772
|
+
const tmpPdf = join20(tmpdir4(), `oa-ocr-${Date.now()}.pdf`);
|
|
8506
8773
|
try {
|
|
8507
8774
|
const ocrCmd = `ocrmypdf -l ${language} --skip-text ${JSON.stringify(inputPath)} ${JSON.stringify(tmpPdf)}`;
|
|
8508
8775
|
execSync14(ocrCmd, { stdio: "pipe", timeout: 6e5 });
|
|
@@ -8532,27 +8799,27 @@ ${text}`,
|
|
|
8532
8799
|
});
|
|
8533
8800
|
|
|
8534
8801
|
// packages/execution/dist/tools/ocr-image-advanced.js
|
|
8535
|
-
import { existsSync as
|
|
8536
|
-
import { resolve as resolve19, basename as basename8, dirname as
|
|
8802
|
+
import { existsSync as existsSync18, statSync as statSync8 } from "node:fs";
|
|
8803
|
+
import { resolve as resolve19, basename as basename8, dirname as dirname8, join as join21 } from "node:path";
|
|
8537
8804
|
import { execSync as execSync15 } from "node:child_process";
|
|
8538
8805
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
8539
8806
|
import { homedir as homedir7, tmpdir as tmpdir5 } from "node:os";
|
|
8540
8807
|
function findOcrScript() {
|
|
8541
|
-
const thisDir =
|
|
8808
|
+
const thisDir = dirname8(fileURLToPath4(import.meta.url));
|
|
8542
8809
|
const devPath3 = resolve19(thisDir, "../../scripts/ocr-advanced.py");
|
|
8543
|
-
if (
|
|
8810
|
+
if (existsSync18(devPath3))
|
|
8544
8811
|
return devPath3;
|
|
8545
8812
|
const bundledPath = resolve19(thisDir, "../scripts/ocr-advanced.py");
|
|
8546
|
-
if (
|
|
8813
|
+
if (existsSync18(bundledPath))
|
|
8547
8814
|
return bundledPath;
|
|
8548
8815
|
const sameDirPath = resolve19(thisDir, "ocr-advanced.py");
|
|
8549
|
-
if (
|
|
8816
|
+
if (existsSync18(sameDirPath))
|
|
8550
8817
|
return sameDirPath;
|
|
8551
8818
|
return null;
|
|
8552
8819
|
}
|
|
8553
8820
|
function findPython() {
|
|
8554
|
-
const venvPython =
|
|
8555
|
-
if (
|
|
8821
|
+
const venvPython = join21(homedir7(), ".open-agents", "venv", "bin", "python");
|
|
8822
|
+
if (existsSync18(venvPython)) {
|
|
8556
8823
|
try {
|
|
8557
8824
|
execSync15(`${JSON.stringify(venvPython)} -c "import cv2, pytesseract, numpy, PIL"`, {
|
|
8558
8825
|
stdio: "pipe",
|
|
@@ -8636,7 +8903,7 @@ var init_ocr_image_advanced = __esm({
|
|
|
8636
8903
|
return { success: false, output: "", error: "image path is required", durationMs: 0 };
|
|
8637
8904
|
}
|
|
8638
8905
|
const fullPath = resolve19(this.workingDir, rawPath);
|
|
8639
|
-
if (!
|
|
8906
|
+
if (!existsSync18(fullPath)) {
|
|
8640
8907
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: performance.now() - start };
|
|
8641
8908
|
}
|
|
8642
8909
|
if (!batch) {
|
|
@@ -8697,7 +8964,7 @@ var init_ocr_image_advanced = __esm({
|
|
|
8697
8964
|
cmdParts.push("--output-dir", JSON.stringify(resolve19(this.workingDir, outputDir)));
|
|
8698
8965
|
let debugDir;
|
|
8699
8966
|
if (debug) {
|
|
8700
|
-
debugDir =
|
|
8967
|
+
debugDir = join21(tmpdir5(), `oa-ocr-debug-${Date.now()}`);
|
|
8701
8968
|
cmdParts.push("--debug-dir", debugDir);
|
|
8702
8969
|
}
|
|
8703
8970
|
try {
|
|
@@ -8796,7 +9063,7 @@ var init_ocr_image_advanced = __esm({
|
|
|
8796
9063
|
if (region) {
|
|
8797
9064
|
try {
|
|
8798
9065
|
const [x, y, w, h] = region.split(",").map(Number);
|
|
8799
|
-
const croppedPath =
|
|
9066
|
+
const croppedPath = join21(tmpdir5(), `oa-ocr-crop-${Date.now()}.png`);
|
|
8800
9067
|
execSync15(`convert ${JSON.stringify(imagePath)} -crop ${w}x${h}+${x}+${y} +repage ${JSON.stringify(croppedPath)}`, { stdio: "pipe", timeout: 1e4 });
|
|
8801
9068
|
inputPath = croppedPath;
|
|
8802
9069
|
} catch {
|
|
@@ -8836,8 +9103,8 @@ Note: Advanced Python pipeline not available \u2014 install pytesseract, opencv-
|
|
|
8836
9103
|
|
|
8837
9104
|
// packages/execution/dist/tools/browser-action.js
|
|
8838
9105
|
import { execSync as execSync16, spawn as spawn7 } from "node:child_process";
|
|
8839
|
-
import { existsSync as
|
|
8840
|
-
import { join as
|
|
9106
|
+
import { existsSync as existsSync19, readFileSync as readFileSync14 } from "node:fs";
|
|
9107
|
+
import { join as join22, dirname as dirname9 } from "node:path";
|
|
8841
9108
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
8842
9109
|
async function probeService() {
|
|
8843
9110
|
try {
|
|
@@ -8867,7 +9134,7 @@ async function launchService() {
|
|
|
8867
9134
|
const python = findPython2();
|
|
8868
9135
|
if (!python)
|
|
8869
9136
|
return "Python 3 not found. Install Python 3.9+ to use browser automation.";
|
|
8870
|
-
if (!
|
|
9137
|
+
if (!existsSync19(SCRAPE_SCRIPT)) {
|
|
8871
9138
|
return `Scrape service script not found at ${SCRAPE_SCRIPT}`;
|
|
8872
9139
|
}
|
|
8873
9140
|
serviceProcess = spawn7(python, [SCRAPE_SCRIPT], {
|
|
@@ -8924,12 +9191,12 @@ async function apiCall(endpoint, method = "POST", body) {
|
|
|
8924
9191
|
const res = await fetch(url, options);
|
|
8925
9192
|
return await res.json();
|
|
8926
9193
|
}
|
|
8927
|
-
var
|
|
9194
|
+
var __dirname3, SCRAPE_SCRIPT, DEFAULT_PORT, BASE_URL, serviceProcess, activeSessionId, BrowserActionTool;
|
|
8928
9195
|
var init_browser_action = __esm({
|
|
8929
9196
|
"packages/execution/dist/tools/browser-action.js"() {
|
|
8930
9197
|
"use strict";
|
|
8931
|
-
|
|
8932
|
-
SCRAPE_SCRIPT =
|
|
9198
|
+
__dirname3 = dirname9(fileURLToPath5(import.meta.url));
|
|
9199
|
+
SCRAPE_SCRIPT = join22(__dirname3, "..", "..", "scripts", "web_scrape.py");
|
|
8933
9200
|
DEFAULT_PORT = 8130;
|
|
8934
9201
|
BASE_URL = `http://localhost:${DEFAULT_PORT}`;
|
|
8935
9202
|
serviceProcess = null;
|
|
@@ -9089,19 +9356,19 @@ var init_browser_action = __esm({
|
|
|
9089
9356
|
|
|
9090
9357
|
// packages/execution/dist/tools/autoresearch.js
|
|
9091
9358
|
import { execSync as execSync17, spawn as spawn8 } from "node:child_process";
|
|
9092
|
-
import { existsSync as
|
|
9093
|
-
import { join as
|
|
9359
|
+
import { existsSync as existsSync20, readFileSync as readFileSync15, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, appendFileSync, copyFileSync } from "node:fs";
|
|
9360
|
+
import { join as join23, resolve as resolve20, dirname as dirname10 } from "node:path";
|
|
9094
9361
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
9095
9362
|
function findAutoresearchScript(scriptName) {
|
|
9096
|
-
const thisDir =
|
|
9363
|
+
const thisDir = dirname10(fileURLToPath6(import.meta.url));
|
|
9097
9364
|
const devPath3 = resolve20(thisDir, "../../scripts", scriptName);
|
|
9098
|
-
if (
|
|
9365
|
+
if (existsSync20(devPath3))
|
|
9099
9366
|
return devPath3;
|
|
9100
9367
|
const bundledPath = resolve20(thisDir, "../scripts", scriptName);
|
|
9101
|
-
if (
|
|
9368
|
+
if (existsSync20(bundledPath))
|
|
9102
9369
|
return bundledPath;
|
|
9103
9370
|
const sameDirPath = resolve20(thisDir, scriptName);
|
|
9104
|
-
if (
|
|
9371
|
+
if (existsSync20(sameDirPath))
|
|
9105
9372
|
return sameDirPath;
|
|
9106
9373
|
return null;
|
|
9107
9374
|
}
|
|
@@ -9192,7 +9459,7 @@ Requires: NVIDIA GPU, Python 3.10+, uv (astral.sh package manager).`;
|
|
|
9192
9459
|
async execute(args) {
|
|
9193
9460
|
const start = Date.now();
|
|
9194
9461
|
const action = String(args["action"] ?? "status");
|
|
9195
|
-
const workspacePath = String(args["workspace"] ??
|
|
9462
|
+
const workspacePath = String(args["workspace"] ?? join23(this.repoRoot, ".oa", "autoresearch"));
|
|
9196
9463
|
try {
|
|
9197
9464
|
switch (action) {
|
|
9198
9465
|
case "setup":
|
|
@@ -9229,17 +9496,17 @@ Requires: NVIDIA GPU, Python 3.10+, uv (astral.sh package manager).`;
|
|
|
9229
9496
|
} catch {
|
|
9230
9497
|
output.push("GPU: detection failed (nvidia-smi not available)");
|
|
9231
9498
|
}
|
|
9232
|
-
|
|
9499
|
+
mkdirSync6(workspace, { recursive: true });
|
|
9233
9500
|
const prepareScript = findAutoresearchScript("autoresearch-prepare.py");
|
|
9234
9501
|
const trainScript = findAutoresearchScript("autoresearch-train.py");
|
|
9235
9502
|
if (prepareScript) {
|
|
9236
|
-
copyFileSync(prepareScript,
|
|
9503
|
+
copyFileSync(prepareScript, join23(workspace, "prepare.py"));
|
|
9237
9504
|
output.push("Copied prepare.py template");
|
|
9238
9505
|
} else {
|
|
9239
9506
|
return { success: false, output: output.join("\n"), error: "autoresearch-prepare.py template not found in distribution", durationMs: Date.now() - start };
|
|
9240
9507
|
}
|
|
9241
9508
|
if (trainScript) {
|
|
9242
|
-
copyFileSync(trainScript,
|
|
9509
|
+
copyFileSync(trainScript, join23(workspace, "train.py"));
|
|
9243
9510
|
output.push("Copied train.py template");
|
|
9244
9511
|
} else {
|
|
9245
9512
|
return { success: false, output: output.join("\n"), error: "autoresearch-train.py template not found in distribution", durationMs: Date.now() - start };
|
|
@@ -9271,7 +9538,7 @@ name = "pytorch-cu128"
|
|
|
9271
9538
|
url = "https://download.pytorch.org/whl/cu128"
|
|
9272
9539
|
explicit = true
|
|
9273
9540
|
`;
|
|
9274
|
-
|
|
9541
|
+
writeFileSync6(join23(workspace, "pyproject.toml"), pyprojectContent, "utf-8");
|
|
9275
9542
|
output.push("Created pyproject.toml");
|
|
9276
9543
|
try {
|
|
9277
9544
|
execSync17("git rev-parse --git-dir", { cwd: workspace, encoding: "utf-8", timeout: 5e3 });
|
|
@@ -9313,9 +9580,9 @@ explicit = true
|
|
|
9313
9580
|
const e = err;
|
|
9314
9581
|
output.push(`Data prep warning: ${(e.stderr ?? e.stdout ?? "failed").slice(0, 500)}`);
|
|
9315
9582
|
}
|
|
9316
|
-
const tsvPath =
|
|
9317
|
-
if (!
|
|
9318
|
-
|
|
9583
|
+
const tsvPath = join23(workspace, "results.tsv");
|
|
9584
|
+
if (!existsSync20(tsvPath)) {
|
|
9585
|
+
writeFileSync6(tsvPath, "commit val_bpb memory_gb status description\n", "utf-8");
|
|
9319
9586
|
output.push("Created results.tsv");
|
|
9320
9587
|
}
|
|
9321
9588
|
return {
|
|
@@ -9335,10 +9602,10 @@ Next steps:
|
|
|
9335
9602
|
}
|
|
9336
9603
|
// ── Run experiment ─────────────────────────────────────────────────────
|
|
9337
9604
|
async run(workspace, args, start) {
|
|
9338
|
-
if (!
|
|
9605
|
+
if (!existsSync20(join23(workspace, "train.py"))) {
|
|
9339
9606
|
return { success: false, output: "", error: `No train.py found in ${workspace}. Run autoresearch(action="setup") first.`, durationMs: Date.now() - start };
|
|
9340
9607
|
}
|
|
9341
|
-
if (!
|
|
9608
|
+
if (!existsSync20(join23(workspace, ".venv")) && existsSync20(join23(workspace, "pyproject.toml"))) {
|
|
9342
9609
|
try {
|
|
9343
9610
|
execSync17("uv sync 2>&1", { cwd: workspace, encoding: "utf-8", timeout: 3e5 });
|
|
9344
9611
|
} catch {
|
|
@@ -9346,7 +9613,7 @@ Next steps:
|
|
|
9346
9613
|
}
|
|
9347
9614
|
const timeoutMin = Number(args["timeout_minutes"] ?? 10);
|
|
9348
9615
|
const timeoutMs = timeoutMin * 60 * 1e3;
|
|
9349
|
-
const logPath =
|
|
9616
|
+
const logPath = join23(workspace, "run.log");
|
|
9350
9617
|
return new Promise((resolveResult) => {
|
|
9351
9618
|
const proc = spawn8("uv", ["run", "train.py"], {
|
|
9352
9619
|
cwd: workspace,
|
|
@@ -9377,7 +9644,7 @@ Next steps:
|
|
|
9377
9644
|
clearTimeout(timer);
|
|
9378
9645
|
const fullLog = stdout + "\n" + stderr;
|
|
9379
9646
|
try {
|
|
9380
|
-
|
|
9647
|
+
writeFileSync6(logPath, fullLog, "utf-8");
|
|
9381
9648
|
} catch {
|
|
9382
9649
|
}
|
|
9383
9650
|
if (timedOut) {
|
|
@@ -9417,7 +9684,7 @@ ${fullLog.slice(-2e3)}`,
|
|
|
9417
9684
|
return;
|
|
9418
9685
|
}
|
|
9419
9686
|
try {
|
|
9420
|
-
|
|
9687
|
+
writeFileSync6(join23(workspace, ".last-result.json"), JSON.stringify(result, null, 2), "utf-8");
|
|
9421
9688
|
} catch {
|
|
9422
9689
|
}
|
|
9423
9690
|
const memGB = (result.peak_vram_mb / 1024).toFixed(1);
|
|
@@ -9453,11 +9720,11 @@ ${fullLog.slice(-2e3)}`,
|
|
|
9453
9720
|
}
|
|
9454
9721
|
// ── Results ────────────────────────────────────────────────────────────
|
|
9455
9722
|
getResults(workspace, start) {
|
|
9456
|
-
const tsvPath =
|
|
9457
|
-
if (!
|
|
9723
|
+
const tsvPath = join23(workspace, "results.tsv");
|
|
9724
|
+
if (!existsSync20(tsvPath)) {
|
|
9458
9725
|
return { success: false, output: "", error: `No results.tsv found. Run autoresearch(action="setup") first.`, durationMs: Date.now() - start };
|
|
9459
9726
|
}
|
|
9460
|
-
const content =
|
|
9727
|
+
const content = readFileSync15(tsvPath, "utf-8");
|
|
9461
9728
|
const lines = content.trim().split("\n");
|
|
9462
9729
|
if (lines.length <= 1) {
|
|
9463
9730
|
return { success: true, output: 'No experiments recorded yet. Run autoresearch(action="run") to start.', durationMs: Date.now() - start };
|
|
@@ -9480,7 +9747,7 @@ ${fullLog.slice(-2e3)}`,
|
|
|
9480
9747
|
// ── Status ─────────────────────────────────────────────────────────────
|
|
9481
9748
|
getStatus(workspace, start) {
|
|
9482
9749
|
const output = [];
|
|
9483
|
-
if (!
|
|
9750
|
+
if (!existsSync20(join23(workspace, "train.py"))) {
|
|
9484
9751
|
return {
|
|
9485
9752
|
success: true,
|
|
9486
9753
|
output: `Autoresearch workspace not initialized at ${workspace}.
|
|
@@ -9503,33 +9770,33 @@ Run autoresearch(action="setup") to begin.`,
|
|
|
9503
9770
|
} catch {
|
|
9504
9771
|
output.push("GPU: not detected");
|
|
9505
9772
|
}
|
|
9506
|
-
const lastResultPath =
|
|
9507
|
-
if (
|
|
9773
|
+
const lastResultPath = join23(workspace, ".last-result.json");
|
|
9774
|
+
if (existsSync20(lastResultPath)) {
|
|
9508
9775
|
try {
|
|
9509
|
-
const last = JSON.parse(
|
|
9776
|
+
const last = JSON.parse(readFileSync15(lastResultPath, "utf-8"));
|
|
9510
9777
|
output.push(`Last experiment: val_bpb=${last.val_bpb.toFixed(6)}, ${(last.peak_vram_mb / 1024).toFixed(1)}GB VRAM, ${last.num_params_M.toFixed(1)}M params`);
|
|
9511
9778
|
} catch {
|
|
9512
9779
|
}
|
|
9513
9780
|
}
|
|
9514
|
-
const tsvPath =
|
|
9515
|
-
if (
|
|
9516
|
-
const lines =
|
|
9781
|
+
const tsvPath = join23(workspace, "results.tsv");
|
|
9782
|
+
if (existsSync20(tsvPath)) {
|
|
9783
|
+
const lines = readFileSync15(tsvPath, "utf-8").trim().split("\n");
|
|
9517
9784
|
output.push(`Experiments recorded: ${lines.length - 1}`);
|
|
9518
9785
|
}
|
|
9519
|
-
const cacheDir =
|
|
9520
|
-
output.push(`Data cache: ${
|
|
9786
|
+
const cacheDir = join23(process.env["HOME"] ?? "~", ".cache", "autoresearch");
|
|
9787
|
+
output.push(`Data cache: ${existsSync20(cacheDir) ? "present" : "not found"} (${cacheDir})`);
|
|
9521
9788
|
return { success: true, output: output.join("\n"), durationMs: Date.now() - start };
|
|
9522
9789
|
}
|
|
9523
9790
|
// ── Keep / Discard ─────────────────────────────────────────────────────
|
|
9524
9791
|
keepExperiment(workspace, args, start) {
|
|
9525
9792
|
const desc = String(args["description"] ?? "experiment");
|
|
9526
|
-
const tsvPath =
|
|
9527
|
-
const lastResultPath =
|
|
9793
|
+
const tsvPath = join23(workspace, "results.tsv");
|
|
9794
|
+
const lastResultPath = join23(workspace, ".last-result.json");
|
|
9528
9795
|
let valBpb = args["val_bpb"];
|
|
9529
9796
|
let memGb = args["memory_gb"];
|
|
9530
|
-
if ((valBpb === void 0 || memGb === void 0) &&
|
|
9797
|
+
if ((valBpb === void 0 || memGb === void 0) && existsSync20(lastResultPath)) {
|
|
9531
9798
|
try {
|
|
9532
|
-
const last = JSON.parse(
|
|
9799
|
+
const last = JSON.parse(readFileSync15(lastResultPath, "utf-8"));
|
|
9533
9800
|
if (valBpb === void 0)
|
|
9534
9801
|
valBpb = last.val_bpb;
|
|
9535
9802
|
if (memGb === void 0)
|
|
@@ -9562,13 +9829,13 @@ Branch advanced. Ready for next experiment.`,
|
|
|
9562
9829
|
}
|
|
9563
9830
|
discardExperiment(workspace, args, start) {
|
|
9564
9831
|
const desc = String(args["description"] ?? "experiment");
|
|
9565
|
-
const tsvPath =
|
|
9566
|
-
const lastResultPath =
|
|
9832
|
+
const tsvPath = join23(workspace, "results.tsv");
|
|
9833
|
+
const lastResultPath = join23(workspace, ".last-result.json");
|
|
9567
9834
|
let valBpb = args["val_bpb"];
|
|
9568
9835
|
let memGb = args["memory_gb"];
|
|
9569
|
-
if ((valBpb === void 0 || memGb === void 0) &&
|
|
9836
|
+
if ((valBpb === void 0 || memGb === void 0) && existsSync20(lastResultPath)) {
|
|
9570
9837
|
try {
|
|
9571
|
-
const last = JSON.parse(
|
|
9838
|
+
const last = JSON.parse(readFileSync15(lastResultPath, "utf-8"));
|
|
9572
9839
|
if (valBpb === void 0)
|
|
9573
9840
|
valBpb = last.val_bpb;
|
|
9574
9841
|
if (memGb === void 0)
|
|
@@ -9610,7 +9877,7 @@ train.py reverted to last kept state. Ready for next experiment.`,
|
|
|
9610
9877
|
// packages/execution/dist/tools/scheduler.js
|
|
9611
9878
|
import { execSync as execSync18, exec as execCb } from "node:child_process";
|
|
9612
9879
|
import { readFile as readFile9, writeFile as writeFile8, mkdir as mkdir4 } from "node:fs/promises";
|
|
9613
|
-
import { resolve as resolve21, join as
|
|
9880
|
+
import { resolve as resolve21, join as join24 } from "node:path";
|
|
9614
9881
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
9615
9882
|
function isValidCron(expr) {
|
|
9616
9883
|
const parts = expr.trim().split(/\s+/);
|
|
@@ -9694,7 +9961,7 @@ function installCronJob(task, workingDir) {
|
|
|
9694
9961
|
const lines = getCurrentCrontab();
|
|
9695
9962
|
const oaBin = findOaBinary();
|
|
9696
9963
|
const logDir = resolve21(workingDir, ".oa", "scheduled", "logs");
|
|
9697
|
-
const logFile =
|
|
9964
|
+
const logFile = join24(logDir, `${task.id}.log`);
|
|
9698
9965
|
const storeFile = resolve21(workingDir, ".oa", "scheduled", "tasks.json");
|
|
9699
9966
|
const taskEscaped = task.task.replace(/'/g, "'\\''");
|
|
9700
9967
|
const taskId = task.id;
|
|
@@ -9736,9 +10003,9 @@ async function loadStore(workingDir) {
|
|
|
9736
10003
|
async function saveStore(workingDir, store) {
|
|
9737
10004
|
const dir = resolve21(workingDir, ".oa", "scheduled");
|
|
9738
10005
|
await mkdir4(dir, { recursive: true });
|
|
9739
|
-
await mkdir4(
|
|
10006
|
+
await mkdir4(join24(dir, "logs"), { recursive: true });
|
|
9740
10007
|
store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9741
|
-
await writeFile8(
|
|
10008
|
+
await writeFile8(join24(dir, "tasks.json"), JSON.stringify(store, null, 2), "utf-8");
|
|
9742
10009
|
}
|
|
9743
10010
|
var SCHEDULE_PRESETS, CRON_MARKER, SchedulerTool;
|
|
9744
10011
|
var init_scheduler = __esm({
|
|
@@ -9972,7 +10239,7 @@ ${truncated}`, durationMs: performance.now() - start };
|
|
|
9972
10239
|
|
|
9973
10240
|
// packages/execution/dist/tools/reminder.js
|
|
9974
10241
|
import { readFile as readFile10, writeFile as writeFile9, mkdir as mkdir5 } from "node:fs/promises";
|
|
9975
|
-
import { resolve as resolve22, join as
|
|
10242
|
+
import { resolve as resolve22, join as join25 } from "node:path";
|
|
9976
10243
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
9977
10244
|
function parseDueTime(due) {
|
|
9978
10245
|
const lower = due.toLowerCase().trim();
|
|
@@ -10024,7 +10291,7 @@ function parseDueTime(due) {
|
|
|
10024
10291
|
async function getStorePath(workingDir) {
|
|
10025
10292
|
const dir = resolve22(workingDir, ".oa", "scheduled");
|
|
10026
10293
|
await mkdir5(dir, { recursive: true });
|
|
10027
|
-
return
|
|
10294
|
+
return join25(dir, STORE_FILE);
|
|
10028
10295
|
}
|
|
10029
10296
|
async function loadReminderStore(workingDir) {
|
|
10030
10297
|
const storePath = await getStorePath(workingDir);
|
|
@@ -10285,7 +10552,7 @@ var init_reminder = __esm({
|
|
|
10285
10552
|
|
|
10286
10553
|
// packages/execution/dist/tools/agenda.js
|
|
10287
10554
|
import { readFile as readFile11, writeFile as writeFile10, mkdir as mkdir6 } from "node:fs/promises";
|
|
10288
|
-
import { resolve as resolve23, join as
|
|
10555
|
+
import { resolve as resolve23, join as join26 } from "node:path";
|
|
10289
10556
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
10290
10557
|
async function loadAttentionStore(workingDir) {
|
|
10291
10558
|
const storePath = resolve23(workingDir, ".oa", "scheduled", "attention.json");
|
|
@@ -10300,7 +10567,7 @@ async function saveAttentionStore(workingDir, store) {
|
|
|
10300
10567
|
const dir = resolve23(workingDir, ".oa", "scheduled");
|
|
10301
10568
|
await mkdir6(dir, { recursive: true });
|
|
10302
10569
|
store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
10303
|
-
await writeFile10(
|
|
10570
|
+
await writeFile10(join26(dir, "attention.json"), JSON.stringify(store, null, 2), "utf-8");
|
|
10304
10571
|
}
|
|
10305
10572
|
async function getActiveAttentionItems(workingDir) {
|
|
10306
10573
|
const store = await loadAttentionStore(workingDir);
|
|
@@ -10609,8 +10876,8 @@ ${sections.join("\n")}`,
|
|
|
10609
10876
|
|
|
10610
10877
|
// packages/execution/dist/tools/opencode.js
|
|
10611
10878
|
import { execSync as execSync19, spawn as spawn9 } from "node:child_process";
|
|
10612
|
-
import { existsSync as
|
|
10613
|
-
import { join as
|
|
10879
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
10880
|
+
import { join as join27, resolve as resolve24 } from "node:path";
|
|
10614
10881
|
function findOpencode() {
|
|
10615
10882
|
for (const cmd of ["opencode"]) {
|
|
10616
10883
|
try {
|
|
@@ -10622,12 +10889,12 @@ function findOpencode() {
|
|
|
10622
10889
|
}
|
|
10623
10890
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
10624
10891
|
const candidates = [
|
|
10625
|
-
|
|
10626
|
-
|
|
10892
|
+
join27(homeDir, ".opencode", "bin", "opencode"),
|
|
10893
|
+
join27(homeDir, "bin", "opencode"),
|
|
10627
10894
|
"/usr/local/bin/opencode"
|
|
10628
10895
|
];
|
|
10629
10896
|
for (const p of candidates) {
|
|
10630
|
-
if (
|
|
10897
|
+
if (existsSync21(p))
|
|
10631
10898
|
return p;
|
|
10632
10899
|
}
|
|
10633
10900
|
return null;
|
|
@@ -10883,8 +11150,8 @@ var init_opencode = __esm({
|
|
|
10883
11150
|
|
|
10884
11151
|
// packages/execution/dist/tools/factory.js
|
|
10885
11152
|
import { execSync as execSync20, spawn as spawn10 } from "node:child_process";
|
|
10886
|
-
import { existsSync as
|
|
10887
|
-
import { join as
|
|
11153
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
11154
|
+
import { join as join28 } from "node:path";
|
|
10888
11155
|
function findDroid() {
|
|
10889
11156
|
for (const cmd of ["droid"]) {
|
|
10890
11157
|
try {
|
|
@@ -10896,12 +11163,12 @@ function findDroid() {
|
|
|
10896
11163
|
}
|
|
10897
11164
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
10898
11165
|
const candidates = [
|
|
10899
|
-
|
|
10900
|
-
|
|
11166
|
+
join28(homeDir, ".factory", "bin", "droid"),
|
|
11167
|
+
join28(homeDir, "bin", "droid"),
|
|
10901
11168
|
"/usr/local/bin/droid"
|
|
10902
11169
|
];
|
|
10903
11170
|
for (const p of candidates) {
|
|
10904
|
-
if (
|
|
11171
|
+
if (existsSync22(p))
|
|
10905
11172
|
return p;
|
|
10906
11173
|
}
|
|
10907
11174
|
return null;
|
|
@@ -11193,7 +11460,7 @@ var init_factory = __esm({
|
|
|
11193
11460
|
// packages/execution/dist/tools/cron-agent.js
|
|
11194
11461
|
import { execSync as execSync21 } from "node:child_process";
|
|
11195
11462
|
import { readFile as readFile12, writeFile as writeFile11, mkdir as mkdir7 } from "node:fs/promises";
|
|
11196
|
-
import { resolve as resolve25, join as
|
|
11463
|
+
import { resolve as resolve25, join as join29 } from "node:path";
|
|
11197
11464
|
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
11198
11465
|
function isValidCron2(expr) {
|
|
11199
11466
|
const parts = expr.trim().split(/\s+/);
|
|
@@ -11279,7 +11546,7 @@ function installCronAgentJob(job, workingDir) {
|
|
|
11279
11546
|
const lines = getCurrentCrontab2();
|
|
11280
11547
|
const oaBin = findOaBinary2();
|
|
11281
11548
|
const logDir = resolve25(workingDir, ".oa", "cron-agents", "logs");
|
|
11282
|
-
const logFile =
|
|
11549
|
+
const logFile = join29(logDir, `${job.id}.log`);
|
|
11283
11550
|
const storeFile = resolve25(workingDir, ".oa", "cron-agents", "store.json");
|
|
11284
11551
|
const taskEscaped = job.task.replace(/'/g, "'\\''");
|
|
11285
11552
|
const jobId = job.id;
|
|
@@ -11318,9 +11585,9 @@ async function loadStore2(workingDir) {
|
|
|
11318
11585
|
async function saveStore2(workingDir, store) {
|
|
11319
11586
|
const dir = resolve25(workingDir, ".oa", "cron-agents");
|
|
11320
11587
|
await mkdir7(dir, { recursive: true });
|
|
11321
|
-
await mkdir7(
|
|
11588
|
+
await mkdir7(join29(dir, "logs"), { recursive: true });
|
|
11322
11589
|
store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
11323
|
-
await writeFile11(
|
|
11590
|
+
await writeFile11(join29(dir, "store.json"), JSON.stringify(store, null, 2), "utf-8");
|
|
11324
11591
|
}
|
|
11325
11592
|
var LONG_HORIZON_PRESETS, CRON_AGENT_MARKER, CronAgentTool;
|
|
11326
11593
|
var init_cron_agent = __esm({
|
|
@@ -11657,8 +11924,8 @@ ${truncated}`, durationMs: performance.now() - start };
|
|
|
11657
11924
|
|
|
11658
11925
|
// packages/execution/dist/tools/nexus.js
|
|
11659
11926
|
import { readFile as readFile13, writeFile as writeFile12, mkdir as mkdir8, chmod, unlink, readdir as readdir3, open as fsOpen } from "node:fs/promises";
|
|
11660
|
-
import { existsSync as
|
|
11661
|
-
import { resolve as resolve26, join as
|
|
11927
|
+
import { existsSync as existsSync23, readFileSync as readFileSync16 } from "node:fs";
|
|
11928
|
+
import { resolve as resolve26, join as join30 } from "node:path";
|
|
11662
11929
|
import { randomBytes as randomBytes6, createCipheriv, createDecipheriv, scryptSync, createHash } from "node:crypto";
|
|
11663
11930
|
import { execSync as execSync22, spawn as spawn11 } from "node:child_process";
|
|
11664
11931
|
import { hostname, userInfo } from "node:os";
|
|
@@ -12694,7 +12961,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12694
12961
|
this.nexusDir = resolve26(repoRoot, ".oa", "nexus");
|
|
12695
12962
|
}
|
|
12696
12963
|
async ensureDir() {
|
|
12697
|
-
if (!
|
|
12964
|
+
if (!existsSync23(this.nexusDir)) {
|
|
12698
12965
|
await mkdir8(this.nexusDir, { recursive: true });
|
|
12699
12966
|
}
|
|
12700
12967
|
}
|
|
@@ -12809,11 +13076,11 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12809
13076
|
// Daemon management
|
|
12810
13077
|
// =========================================================================
|
|
12811
13078
|
getDaemonPid() {
|
|
12812
|
-
const pidFile =
|
|
12813
|
-
if (!
|
|
13079
|
+
const pidFile = join30(this.nexusDir, "daemon.pid");
|
|
13080
|
+
if (!existsSync23(pidFile))
|
|
12814
13081
|
return null;
|
|
12815
13082
|
try {
|
|
12816
|
-
const pid = parseInt(
|
|
13083
|
+
const pid = parseInt(readFileSync16(pidFile, "utf8").trim(), 10);
|
|
12817
13084
|
process.kill(pid, 0);
|
|
12818
13085
|
return pid;
|
|
12819
13086
|
} catch {
|
|
@@ -12825,16 +13092,16 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12825
13092
|
if (!pid)
|
|
12826
13093
|
throw new Error("Nexus daemon not running. Use action 'connect' first.");
|
|
12827
13094
|
const cmdId = randomBytes6(8).toString("hex");
|
|
12828
|
-
const cmdFile =
|
|
12829
|
-
const respFile =
|
|
12830
|
-
if (
|
|
13095
|
+
const cmdFile = join30(this.nexusDir, "cmd.json");
|
|
13096
|
+
const respFile = join30(this.nexusDir, "resp.json");
|
|
13097
|
+
if (existsSync23(respFile))
|
|
12831
13098
|
await unlink(respFile).catch(() => {
|
|
12832
13099
|
});
|
|
12833
13100
|
await writeFile12(cmdFile, JSON.stringify({ id: cmdId, action, args }, null, 2));
|
|
12834
13101
|
const polls = Math.ceil(timeoutMs / 500);
|
|
12835
13102
|
for (let i = 0; i < polls; i++) {
|
|
12836
13103
|
await new Promise((r) => setTimeout(r, 500));
|
|
12837
|
-
if (!
|
|
13104
|
+
if (!existsSync23(respFile))
|
|
12838
13105
|
continue;
|
|
12839
13106
|
try {
|
|
12840
13107
|
const resp = JSON.parse(await readFile13(respFile, "utf8"));
|
|
@@ -12861,8 +13128,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12861
13128
|
await this.ensureDir();
|
|
12862
13129
|
const existingPid = this.getDaemonPid();
|
|
12863
13130
|
if (existingPid) {
|
|
12864
|
-
const statusFile2 =
|
|
12865
|
-
if (
|
|
13131
|
+
const statusFile2 = join30(this.nexusDir, "status.json");
|
|
13132
|
+
if (existsSync23(statusFile2)) {
|
|
12866
13133
|
try {
|
|
12867
13134
|
const status = JSON.parse(await readFile13(statusFile2, "utf8"));
|
|
12868
13135
|
if (status.connected && status.peerId) {
|
|
@@ -12878,8 +13145,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12878
13145
|
await new Promise((r) => setTimeout(r, 500));
|
|
12879
13146
|
}
|
|
12880
13147
|
for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
|
|
12881
|
-
const p =
|
|
12882
|
-
if (
|
|
13148
|
+
const p = join30(this.nexusDir, f);
|
|
13149
|
+
if (existsSync23(p))
|
|
12883
13150
|
await unlink(p).catch(() => {
|
|
12884
13151
|
});
|
|
12885
13152
|
}
|
|
@@ -12887,21 +13154,21 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12887
13154
|
let nexusResolved = false;
|
|
12888
13155
|
let installedVersion = "";
|
|
12889
13156
|
try {
|
|
12890
|
-
const nexusPkg =
|
|
12891
|
-
if (
|
|
13157
|
+
const nexusPkg = join30(nodeModulesDir, "open-agents-nexus", "package.json");
|
|
13158
|
+
if (existsSync23(nexusPkg)) {
|
|
12892
13159
|
nexusResolved = true;
|
|
12893
13160
|
try {
|
|
12894
|
-
const pkg = JSON.parse(
|
|
13161
|
+
const pkg = JSON.parse(readFileSync16(nexusPkg, "utf8"));
|
|
12895
13162
|
installedVersion = pkg.version || "";
|
|
12896
13163
|
} catch {
|
|
12897
13164
|
}
|
|
12898
13165
|
} else {
|
|
12899
13166
|
const globalDir = execSync22("npm root -g", { encoding: "utf8", timeout: 5e3 }).trim();
|
|
12900
|
-
const globalPkg =
|
|
12901
|
-
if (
|
|
13167
|
+
const globalPkg = join30(globalDir, "open-agents-nexus", "package.json");
|
|
13168
|
+
if (existsSync23(globalPkg)) {
|
|
12902
13169
|
nexusResolved = true;
|
|
12903
13170
|
try {
|
|
12904
|
-
const pkg = JSON.parse(
|
|
13171
|
+
const pkg = JSON.parse(readFileSync16(globalPkg, "utf8"));
|
|
12905
13172
|
installedVersion = pkg.version || "";
|
|
12906
13173
|
} catch {
|
|
12907
13174
|
}
|
|
@@ -12944,7 +13211,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12944
13211
|
}
|
|
12945
13212
|
}
|
|
12946
13213
|
}
|
|
12947
|
-
const daemonPath =
|
|
13214
|
+
const daemonPath = join30(this.nexusDir, "nexus-daemon.mjs");
|
|
12948
13215
|
await writeFile12(daemonPath, DAEMON_SCRIPT);
|
|
12949
13216
|
const agentName = args.agent_name || "open-agents-node";
|
|
12950
13217
|
const agentType = args.agent_type || "general";
|
|
@@ -12969,10 +13236,10 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12969
13236
|
child.stderr?.on("data", (d) => {
|
|
12970
13237
|
earlyError += d.toString();
|
|
12971
13238
|
});
|
|
12972
|
-
const statusFile =
|
|
13239
|
+
const statusFile = join30(this.nexusDir, "status.json");
|
|
12973
13240
|
for (let i = 0; i < 40; i++) {
|
|
12974
13241
|
await new Promise((r) => setTimeout(r, 500));
|
|
12975
|
-
if (
|
|
13242
|
+
if (existsSync23(statusFile)) {
|
|
12976
13243
|
try {
|
|
12977
13244
|
const status = JSON.parse(await readFile13(statusFile, "utf8"));
|
|
12978
13245
|
if (status.error) {
|
|
@@ -13013,8 +13280,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13013
13280
|
} catch {
|
|
13014
13281
|
}
|
|
13015
13282
|
for (const f of ["daemon.pid", "status.json", "cmd.json", "resp.json"]) {
|
|
13016
|
-
const p =
|
|
13017
|
-
if (
|
|
13283
|
+
const p = join30(this.nexusDir, f);
|
|
13284
|
+
if (existsSync23(p))
|
|
13018
13285
|
await unlink(p).catch(() => {
|
|
13019
13286
|
});
|
|
13020
13287
|
}
|
|
@@ -13024,8 +13291,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13024
13291
|
const pid = this.getDaemonPid();
|
|
13025
13292
|
if (!pid)
|
|
13026
13293
|
return "Nexus daemon not running. Use action 'connect' to start.";
|
|
13027
|
-
const statusFile =
|
|
13028
|
-
if (!
|
|
13294
|
+
const statusFile = join30(this.nexusDir, "status.json");
|
|
13295
|
+
if (!existsSync23(statusFile))
|
|
13029
13296
|
return `Daemon running (pid: ${pid}) but no status yet.`;
|
|
13030
13297
|
try {
|
|
13031
13298
|
const status = JSON.parse(await readFile13(statusFile, "utf8"));
|
|
@@ -13039,8 +13306,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13039
13306
|
` Capabilities: ${(status.capabilities || []).length ? (status.capabilities || []).join(", ") : "none"}`,
|
|
13040
13307
|
` Blocked peers: ${(status.blockedPeers || []).length || 0}`
|
|
13041
13308
|
];
|
|
13042
|
-
const walletPath =
|
|
13043
|
-
if (
|
|
13309
|
+
const walletPath = join30(this.nexusDir, "wallet.enc");
|
|
13310
|
+
if (existsSync23(walletPath)) {
|
|
13044
13311
|
try {
|
|
13045
13312
|
const w = JSON.parse(await readFile13(walletPath, "utf8"));
|
|
13046
13313
|
lines.push(` Wallet: ${w.address}`);
|
|
@@ -13050,14 +13317,14 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13050
13317
|
} else {
|
|
13051
13318
|
lines.push(` Wallet: not configured`);
|
|
13052
13319
|
}
|
|
13053
|
-
const inboxDir =
|
|
13054
|
-
if (
|
|
13320
|
+
const inboxDir = join30(this.nexusDir, "inbox");
|
|
13321
|
+
if (existsSync23(inboxDir)) {
|
|
13055
13322
|
try {
|
|
13056
13323
|
const roomDirs = await readdir3(inboxDir);
|
|
13057
13324
|
let totalMsgs = 0;
|
|
13058
13325
|
for (const rd of roomDirs) {
|
|
13059
13326
|
try {
|
|
13060
|
-
totalMsgs += (await readdir3(
|
|
13327
|
+
totalMsgs += (await readdir3(join30(inboxDir, rd))).length;
|
|
13061
13328
|
} catch {
|
|
13062
13329
|
}
|
|
13063
13330
|
}
|
|
@@ -13104,10 +13371,10 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13104
13371
|
}
|
|
13105
13372
|
async doReadMessages(args) {
|
|
13106
13373
|
const roomId = args.room_id;
|
|
13107
|
-
const inboxDir =
|
|
13374
|
+
const inboxDir = join30(this.nexusDir, "inbox");
|
|
13108
13375
|
if (roomId) {
|
|
13109
|
-
const roomInbox =
|
|
13110
|
-
if (!
|
|
13376
|
+
const roomInbox = join30(inboxDir, roomId);
|
|
13377
|
+
if (!existsSync23(roomInbox))
|
|
13111
13378
|
return `No messages in room: ${roomId}`;
|
|
13112
13379
|
const files = (await readdir3(roomInbox)).sort().slice(-20);
|
|
13113
13380
|
if (files.length === 0)
|
|
@@ -13115,7 +13382,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13115
13382
|
const messages = [`Messages in ${roomId} (last ${files.length}):`];
|
|
13116
13383
|
for (const f of files) {
|
|
13117
13384
|
try {
|
|
13118
|
-
const msg = JSON.parse(await readFile13(
|
|
13385
|
+
const msg = JSON.parse(await readFile13(join30(roomInbox, f), "utf8"));
|
|
13119
13386
|
const sender = (msg.sender || "unknown").slice(0, 12);
|
|
13120
13387
|
messages.push(` [${new Date(msg.timestamp).toLocaleTimeString()}] ${sender}...: ${msg.content}`);
|
|
13121
13388
|
} catch {
|
|
@@ -13123,7 +13390,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13123
13390
|
}
|
|
13124
13391
|
return messages.join("\n");
|
|
13125
13392
|
}
|
|
13126
|
-
if (!
|
|
13393
|
+
if (!existsSync23(inboxDir))
|
|
13127
13394
|
return "No messages received yet.";
|
|
13128
13395
|
const roomDirs = await readdir3(inboxDir);
|
|
13129
13396
|
if (roomDirs.length === 0)
|
|
@@ -13131,7 +13398,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13131
13398
|
const lines = ["Inbox:"];
|
|
13132
13399
|
for (const rd of roomDirs) {
|
|
13133
13400
|
try {
|
|
13134
|
-
const count = (await readdir3(
|
|
13401
|
+
const count = (await readdir3(join30(inboxDir, rd))).length;
|
|
13135
13402
|
lines.push(` ${rd}: ${count} message(s)`);
|
|
13136
13403
|
} catch {
|
|
13137
13404
|
}
|
|
@@ -13143,8 +13410,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13143
13410
|
// ---------------------------------------------------------------------------
|
|
13144
13411
|
async doWalletStatus() {
|
|
13145
13412
|
await this.ensureDir();
|
|
13146
|
-
const walletPath =
|
|
13147
|
-
if (!
|
|
13413
|
+
const walletPath = join30(this.nexusDir, "wallet.enc");
|
|
13414
|
+
if (!existsSync23(walletPath)) {
|
|
13148
13415
|
return "No wallet configured. Use wallet_create to set one up.";
|
|
13149
13416
|
}
|
|
13150
13417
|
try {
|
|
@@ -13182,8 +13449,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13182
13449
|
}
|
|
13183
13450
|
async doWalletCreate(args) {
|
|
13184
13451
|
await this.ensureDir();
|
|
13185
|
-
const walletPath =
|
|
13186
|
-
if (
|
|
13452
|
+
const walletPath = join30(this.nexusDir, "wallet.enc");
|
|
13453
|
+
if (existsSync23(walletPath))
|
|
13187
13454
|
return "Wallet already exists. Delete wallet.enc to create a new one.";
|
|
13188
13455
|
const userAddress = args.wallet_address;
|
|
13189
13456
|
if (userAddress) {
|
|
@@ -13228,7 +13495,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13228
13495
|
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
13229
13496
|
let enc = cipher.update(privKeyHex, "utf8", "hex");
|
|
13230
13497
|
enc += cipher.final("hex");
|
|
13231
|
-
const x402KeyPath =
|
|
13498
|
+
const x402KeyPath = join30(this.nexusDir, "x402-wallet.key");
|
|
13232
13499
|
const x402Fh = await fsOpen(x402KeyPath, "w", 384);
|
|
13233
13500
|
await x402Fh.writeFile("0x" + privKeyHex);
|
|
13234
13501
|
await x402Fh.close();
|
|
@@ -13299,8 +13566,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13299
13566
|
// ---------------------------------------------------------------------------
|
|
13300
13567
|
async doLedgerStatus() {
|
|
13301
13568
|
await this.ensureDir();
|
|
13302
|
-
const ledgerPath =
|
|
13303
|
-
if (!
|
|
13569
|
+
const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
|
|
13570
|
+
if (!existsSync23(ledgerPath)) {
|
|
13304
13571
|
return "No ledger entries. Earnings and spending will be tracked here after x402 transactions.";
|
|
13305
13572
|
}
|
|
13306
13573
|
try {
|
|
@@ -13341,8 +13608,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13341
13608
|
}
|
|
13342
13609
|
}
|
|
13343
13610
|
async getLedgerSummary() {
|
|
13344
|
-
const ledgerPath =
|
|
13345
|
-
if (!
|
|
13611
|
+
const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
|
|
13612
|
+
if (!existsSync23(ledgerPath))
|
|
13346
13613
|
return null;
|
|
13347
13614
|
try {
|
|
13348
13615
|
const raw = await readFile13(ledgerPath, "utf8");
|
|
@@ -13366,16 +13633,16 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13366
13633
|
}
|
|
13367
13634
|
async appendLedger(entry) {
|
|
13368
13635
|
await this.ensureDir();
|
|
13369
|
-
const ledgerPath =
|
|
13636
|
+
const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
|
|
13370
13637
|
const line = JSON.stringify(entry) + "\n";
|
|
13371
|
-
await writeFile12(ledgerPath,
|
|
13638
|
+
await writeFile12(ledgerPath, existsSync23(ledgerPath) ? await readFile13(ledgerPath, "utf8") + line : line);
|
|
13372
13639
|
}
|
|
13373
13640
|
// ---------------------------------------------------------------------------
|
|
13374
13641
|
// Step 4: Budget Policy — Spending limits and auto-approve thresholds
|
|
13375
13642
|
// ---------------------------------------------------------------------------
|
|
13376
13643
|
async loadBudget() {
|
|
13377
|
-
const budgetPath =
|
|
13378
|
-
if (!
|
|
13644
|
+
const budgetPath = join30(this.nexusDir, "budget.json");
|
|
13645
|
+
if (!existsSync23(budgetPath))
|
|
13379
13646
|
return null;
|
|
13380
13647
|
try {
|
|
13381
13648
|
return JSON.parse(await readFile13(budgetPath, "utf8"));
|
|
@@ -13384,8 +13651,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13384
13651
|
}
|
|
13385
13652
|
}
|
|
13386
13653
|
async ensureDefaultBudget() {
|
|
13387
|
-
const budgetPath =
|
|
13388
|
-
if (
|
|
13654
|
+
const budgetPath = join30(this.nexusDir, "budget.json");
|
|
13655
|
+
if (existsSync23(budgetPath))
|
|
13389
13656
|
return;
|
|
13390
13657
|
const defaultBudget = {
|
|
13391
13658
|
version: 1,
|
|
@@ -13454,13 +13721,13 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13454
13721
|
if (changes.length === 0) {
|
|
13455
13722
|
return "No budget parameters provided. Use daily_limit, per_invoke_max, or auto_approve_below.";
|
|
13456
13723
|
}
|
|
13457
|
-
const budgetPath =
|
|
13724
|
+
const budgetPath = join30(this.nexusDir, "budget.json");
|
|
13458
13725
|
await writeFile12(budgetPath, JSON.stringify(budget, null, 2));
|
|
13459
13726
|
return `Budget updated: ${changes.join(", ")}`;
|
|
13460
13727
|
}
|
|
13461
13728
|
async getTodaySpending() {
|
|
13462
|
-
const ledgerPath =
|
|
13463
|
-
if (!
|
|
13729
|
+
const ledgerPath = join30(this.nexusDir, "ledger.jsonl");
|
|
13730
|
+
if (!existsSync23(ledgerPath))
|
|
13464
13731
|
return 0;
|
|
13465
13732
|
try {
|
|
13466
13733
|
const todayPrefix = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -13503,8 +13770,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13503
13770
|
if (todaySpent + amountUsdc > budget.dailyLimitUsdc) {
|
|
13504
13771
|
return { allowed: false, reason: `Would exceed daily limit ($${((todaySpent + amountUsdc) / 1e6).toFixed(6)} > $${(budget.dailyLimitUsdc / 1e6).toFixed(6)})` };
|
|
13505
13772
|
}
|
|
13506
|
-
const walletPath =
|
|
13507
|
-
if (
|
|
13773
|
+
const walletPath = join30(this.nexusDir, "wallet.enc");
|
|
13774
|
+
if (existsSync23(walletPath)) {
|
|
13508
13775
|
try {
|
|
13509
13776
|
const w = JSON.parse(await readFile13(walletPath, "utf8"));
|
|
13510
13777
|
if (w.version === 2 && w.address) {
|
|
@@ -13534,8 +13801,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13534
13801
|
const budgetResult = await this.checkBudget(amountSmallest, "transfer:direct", targetAddress);
|
|
13535
13802
|
if (!budgetResult.allowed)
|
|
13536
13803
|
return `BLOCKED by budget policy: ${budgetResult.reason}`;
|
|
13537
|
-
const walletPath =
|
|
13538
|
-
if (!
|
|
13804
|
+
const walletPath = join30(this.nexusDir, "wallet.enc");
|
|
13805
|
+
if (!existsSync23(walletPath))
|
|
13539
13806
|
throw new Error("No wallet. Use wallet_create first.");
|
|
13540
13807
|
const w = JSON.parse(await readFile13(walletPath, "utf8"));
|
|
13541
13808
|
if (!w.encryptedKey)
|
|
@@ -13595,7 +13862,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13595
13862
|
capability: "transfer:direct",
|
|
13596
13863
|
note: "signed, awaiting submission"
|
|
13597
13864
|
});
|
|
13598
|
-
const proofFile =
|
|
13865
|
+
const proofFile = join30(this.nexusDir, "pending-transfer.json");
|
|
13599
13866
|
const proof = {
|
|
13600
13867
|
from: account.address,
|
|
13601
13868
|
to: targetAddress,
|
|
@@ -13637,8 +13904,8 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13637
13904
|
throw new Error("prompt is required");
|
|
13638
13905
|
const estimatedTokens = Math.ceil(prompt.length / 4) + 1e3;
|
|
13639
13906
|
let estimatedCostSmallest = 0;
|
|
13640
|
-
const pricingPath =
|
|
13641
|
-
if (
|
|
13907
|
+
const pricingPath = join30(this.nexusDir, "pricing.json");
|
|
13908
|
+
if (existsSync23(pricingPath)) {
|
|
13642
13909
|
try {
|
|
13643
13910
|
const pricing = JSON.parse(await readFile13(pricingPath, "utf8"));
|
|
13644
13911
|
const modelPricing = (pricing.models || []).find((m) => m.model === model || m.model.startsWith(model.split(":")[0]));
|
|
@@ -13757,7 +14024,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13757
14024
|
const bar = (s) => "\u2588".repeat(Math.round(s / 5)) + "\u2591".repeat(20 - Math.round(s / 5));
|
|
13758
14025
|
const mem = vramMb > 24e3 ? 95 : vramMb > 16e3 ? 80 : vramMb > 8e3 ? 60 : vramMb > 0 ? 40 : 20;
|
|
13759
14026
|
await this.ensureDir();
|
|
13760
|
-
await writeFile12(
|
|
14027
|
+
await writeFile12(join30(this.nexusDir, "inference-proof.json"), JSON.stringify({
|
|
13761
14028
|
modelName,
|
|
13762
14029
|
gpuName,
|
|
13763
14030
|
vramMb,
|
|
@@ -13885,6 +14152,7 @@ var init_dist2 = __esm({
|
|
|
13885
14152
|
init_custom_tool();
|
|
13886
14153
|
init_tool_creator();
|
|
13887
14154
|
init_skill_tools();
|
|
14155
|
+
init_skill_builder();
|
|
13888
14156
|
init_transcribe_tool();
|
|
13889
14157
|
init_structured_file();
|
|
13890
14158
|
init_code_sandbox();
|
|
@@ -14587,30 +14855,30 @@ var init_dist3 = __esm({
|
|
|
14587
14855
|
});
|
|
14588
14856
|
|
|
14589
14857
|
// packages/orchestrator/dist/promptLoader.js
|
|
14590
|
-
import { readFileSync as
|
|
14591
|
-
import { join as
|
|
14858
|
+
import { readFileSync as readFileSync17, existsSync as existsSync24 } from "node:fs";
|
|
14859
|
+
import { join as join31, dirname as dirname11 } from "node:path";
|
|
14592
14860
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
14593
14861
|
function loadPrompt(promptPath, vars) {
|
|
14594
14862
|
let content = cache.get(promptPath);
|
|
14595
14863
|
if (content === void 0) {
|
|
14596
|
-
const fullPath =
|
|
14597
|
-
if (!
|
|
14864
|
+
const fullPath = join31(PROMPTS_DIR, promptPath);
|
|
14865
|
+
if (!existsSync24(fullPath)) {
|
|
14598
14866
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
14599
14867
|
}
|
|
14600
|
-
content =
|
|
14868
|
+
content = readFileSync17(fullPath, "utf-8");
|
|
14601
14869
|
cache.set(promptPath, content);
|
|
14602
14870
|
}
|
|
14603
14871
|
if (!vars)
|
|
14604
14872
|
return content;
|
|
14605
14873
|
return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
|
|
14606
14874
|
}
|
|
14607
|
-
var __filename,
|
|
14875
|
+
var __filename, __dirname4, PROMPTS_DIR, cache;
|
|
14608
14876
|
var init_promptLoader = __esm({
|
|
14609
14877
|
"packages/orchestrator/dist/promptLoader.js"() {
|
|
14610
14878
|
"use strict";
|
|
14611
14879
|
__filename = fileURLToPath7(import.meta.url);
|
|
14612
|
-
|
|
14613
|
-
PROMPTS_DIR =
|
|
14880
|
+
__dirname4 = dirname11(__filename);
|
|
14881
|
+
PROMPTS_DIR = join31(__dirname4, "..", "prompts");
|
|
14614
14882
|
cache = /* @__PURE__ */ new Map();
|
|
14615
14883
|
}
|
|
14616
14884
|
});
|
|
@@ -14990,7 +15258,7 @@ var init_code_retriever = __esm({
|
|
|
14990
15258
|
import { execFile as execFile5 } from "node:child_process";
|
|
14991
15259
|
import { promisify as promisify4 } from "node:util";
|
|
14992
15260
|
import { readFile as readFile14, readdir as readdir4, stat as stat3 } from "node:fs/promises";
|
|
14993
|
-
import { join as
|
|
15261
|
+
import { join as join32, extname as extname7 } from "node:path";
|
|
14994
15262
|
async function searchByPath(pathPattern, options) {
|
|
14995
15263
|
const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
|
|
14996
15264
|
const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
|
|
@@ -15132,7 +15400,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
|
|
|
15132
15400
|
continue;
|
|
15133
15401
|
if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
|
|
15134
15402
|
continue;
|
|
15135
|
-
const absPath =
|
|
15403
|
+
const absPath = join32(dir, entry.name);
|
|
15136
15404
|
if (entry.isDirectory()) {
|
|
15137
15405
|
await walkForFiles(rootDir, absPath, excludeGlobs, results);
|
|
15138
15406
|
} else if (entry.isFile()) {
|
|
@@ -15439,7 +15707,7 @@ var init_graphExpand = __esm({
|
|
|
15439
15707
|
|
|
15440
15708
|
// packages/retrieval/dist/snippetPacker.js
|
|
15441
15709
|
import { readFile as readFile15 } from "node:fs/promises";
|
|
15442
|
-
import { join as
|
|
15710
|
+
import { join as join33 } from "node:path";
|
|
15443
15711
|
async function packSnippets(requests, opts = {}) {
|
|
15444
15712
|
const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
15445
15713
|
const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
|
|
@@ -15465,7 +15733,7 @@ async function packSnippets(requests, opts = {}) {
|
|
|
15465
15733
|
return { packed, dropped, totalTokens };
|
|
15466
15734
|
}
|
|
15467
15735
|
async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
|
|
15468
|
-
const absPath = req.filePath.startsWith("/") ? req.filePath :
|
|
15736
|
+
const absPath = req.filePath.startsWith("/") ? req.filePath : join33(repoRoot, req.filePath);
|
|
15469
15737
|
let content;
|
|
15470
15738
|
try {
|
|
15471
15739
|
content = await readFile15(absPath, "utf-8");
|
|
@@ -16646,6 +16914,7 @@ var init_agenticRunner = __esm({
|
|
|
16646
16914
|
_sudoPassword = null;
|
|
16647
16915
|
_sudoResolve = null;
|
|
16648
16916
|
_pendingCompaction = null;
|
|
16917
|
+
_skillCompactionStrategy = null;
|
|
16649
16918
|
// -- Task State Tracking (Priority 3) --
|
|
16650
16919
|
_taskState = {
|
|
16651
16920
|
goal: "",
|
|
@@ -16713,6 +16982,54 @@ var init_agenticRunner = __esm({
|
|
|
16713
16982
|
}));
|
|
16714
16983
|
}
|
|
16715
16984
|
// -------------------------------------------------------------------------
|
|
16985
|
+
// Structured Context Assembly — C = A(c_instr, c_know, c_tools, c_mem, c_state, c_query)
|
|
16986
|
+
// Reference: "A Survey of Context Engineering for LLMs" (arXiv:2507.xxxxx)
|
|
16987
|
+
// -------------------------------------------------------------------------
|
|
16988
|
+
/**
|
|
16989
|
+
* Assemble context from multiple sources into a structured system prompt.
|
|
16990
|
+
* Each section is labeled with its role in the context engineering equation
|
|
16991
|
+
* and tracked for token budget analysis.
|
|
16992
|
+
*
|
|
16993
|
+
* Instruction hierarchy (arXiv:2404.13208):
|
|
16994
|
+
* - Priority 0: c_instr (system instructions — immutable rules)
|
|
16995
|
+
* - Priority 10: c_state (personality, project context)
|
|
16996
|
+
* - Priority 20: c_know (retrieved knowledge, dynamic context)
|
|
16997
|
+
* - Priority 30: c_tools (tool definitions — handled separately by API)
|
|
16998
|
+
*/
|
|
16999
|
+
assembleContext(task, context) {
|
|
17000
|
+
const sections = [];
|
|
17001
|
+
const basePrompt = getSystemPromptForTier(this.options.modelTier);
|
|
17002
|
+
sections.push({
|
|
17003
|
+
label: "c_instr",
|
|
17004
|
+
content: basePrompt,
|
|
17005
|
+
tokenEstimate: Math.ceil(basePrompt.length / 4)
|
|
17006
|
+
});
|
|
17007
|
+
const personalitySuffix = this.options.personality ? compilePersonalityPrompt(this.options.personality) : "";
|
|
17008
|
+
if (personalitySuffix) {
|
|
17009
|
+
sections.push({
|
|
17010
|
+
label: "c_state",
|
|
17011
|
+
content: personalitySuffix,
|
|
17012
|
+
tokenEstimate: Math.ceil(personalitySuffix.length / 4)
|
|
17013
|
+
});
|
|
17014
|
+
}
|
|
17015
|
+
if (this.options.dynamicContext) {
|
|
17016
|
+
sections.push({
|
|
17017
|
+
label: "c_know",
|
|
17018
|
+
content: `
|
|
17019
|
+
|
|
17020
|
+
${this.options.dynamicContext}`,
|
|
17021
|
+
tokenEstimate: Math.ceil(this.options.dynamicContext.length / 4)
|
|
17022
|
+
});
|
|
17023
|
+
}
|
|
17024
|
+
const assembled = sections.map((s) => s.content).join("");
|
|
17025
|
+
const totalTokenEstimate = sections.reduce((sum, s) => sum + s.tokenEstimate, 0);
|
|
17026
|
+
return {
|
|
17027
|
+
assembled,
|
|
17028
|
+
sections: sections.map((s) => ({ label: s.label, tokenEstimate: s.tokenEstimate })),
|
|
17029
|
+
totalTokenEstimate
|
|
17030
|
+
};
|
|
17031
|
+
}
|
|
17032
|
+
// -------------------------------------------------------------------------
|
|
16716
17033
|
// Context-aware limits — all dynamic values derived from contextWindowSize
|
|
16717
17034
|
// and modelTier. Call this instead of using hardcoded magic numbers.
|
|
16718
17035
|
// -------------------------------------------------------------------------
|
|
@@ -16844,6 +17161,14 @@ var init_agenticRunner = __esm({
|
|
|
16844
17161
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
16845
17162
|
});
|
|
16846
17163
|
}
|
|
17164
|
+
/**
|
|
17165
|
+
* Set the active skill's preferred compaction strategy.
|
|
17166
|
+
* When set, auto-compaction uses this strategy instead of "default".
|
|
17167
|
+
* Called by the CLI when a skill is loaded via skill_execute.
|
|
17168
|
+
*/
|
|
17169
|
+
setSkillCompactionStrategy(strategy) {
|
|
17170
|
+
this._skillCompactionStrategy = strategy;
|
|
17171
|
+
}
|
|
16847
17172
|
/**
|
|
16848
17173
|
* If paused, block until resume() or abort() is called.
|
|
16849
17174
|
* Returns true if the loop should continue, false if aborted while paused.
|
|
@@ -16921,12 +17246,13 @@ Respond with your assessment, then take action.`;
|
|
|
16921
17246
|
this._fileRegistry.clear();
|
|
16922
17247
|
this._memexArchive.clear();
|
|
16923
17248
|
this._sessionId = `session-${Date.now()}`;
|
|
16924
|
-
const
|
|
16925
|
-
const
|
|
16926
|
-
|
|
16927
|
-
|
|
16928
|
-
|
|
16929
|
-
|
|
17249
|
+
const contextComposition = this.assembleContext(task, context);
|
|
17250
|
+
const systemPrompt = contextComposition.assembled;
|
|
17251
|
+
this.emit({
|
|
17252
|
+
type: "status",
|
|
17253
|
+
content: `Context assembled: ${contextComposition.sections.map((s) => `${s.label}(${s.tokenEstimate}t)`).join(" + ")} = ~${contextComposition.totalTokenEstimate}t`,
|
|
17254
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17255
|
+
});
|
|
16930
17256
|
const messages = [
|
|
16931
17257
|
{ role: "system", content: systemPrompt },
|
|
16932
17258
|
{ role: "user", content: context ? `${context}
|
|
@@ -17294,7 +17620,7 @@ You have used ${totalTurns} turns and ${toolCallCount} tool calls so far. The ta
|
|
|
17294
17620
|
|
|
17295
17621
|
You have ${this.options.maxTurns} more turns. Continue making progress. Call task_complete when the task is fully done.`
|
|
17296
17622
|
});
|
|
17297
|
-
const compacted = await this.compactMessages(messages);
|
|
17623
|
+
const compacted = await this.compactMessages(messages, this._skillCompactionStrategy ?? "default");
|
|
17298
17624
|
if (compacted !== messages) {
|
|
17299
17625
|
messages.length = 0;
|
|
17300
17626
|
messages.push(...compacted);
|
|
@@ -17358,7 +17684,7 @@ Integrate this guidance into your current approach. Continue working on the task
|
|
|
17358
17684
|
this._pendingCompaction = null;
|
|
17359
17685
|
compactedMsgs = await this.compactMessages(messages, strategy, true);
|
|
17360
17686
|
} else {
|
|
17361
|
-
compactedMsgs = await this.compactMessages(messages);
|
|
17687
|
+
compactedMsgs = await this.compactMessages(messages, this._skillCompactionStrategy ?? "default");
|
|
17362
17688
|
}
|
|
17363
17689
|
const chatRequest = { messages: compactedMsgs, tools: toolDefs, temperature: this.options.temperature, maxTokens: this.options.maxTokens, timeoutMs: this.options.requestTimeoutMs };
|
|
17364
17690
|
let response;
|
|
@@ -17636,10 +17962,10 @@ ${marker}` : marker);
|
|
|
17636
17962
|
if (!this._workingDirectory)
|
|
17637
17963
|
return;
|
|
17638
17964
|
try {
|
|
17639
|
-
const { mkdirSync:
|
|
17640
|
-
const { join:
|
|
17641
|
-
const sessionDir =
|
|
17642
|
-
|
|
17965
|
+
const { mkdirSync: mkdirSync19, writeFileSync: writeFileSync17 } = __require("node:fs");
|
|
17966
|
+
const { join: join54 } = __require("node:path");
|
|
17967
|
+
const sessionDir = join54(this._workingDirectory, ".oa", "session", this._sessionId);
|
|
17968
|
+
mkdirSync19(sessionDir, { recursive: true });
|
|
17643
17969
|
const checkpoint = {
|
|
17644
17970
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17645
17971
|
sessionId: this._sessionId,
|
|
@@ -17651,7 +17977,7 @@ ${marker}` : marker);
|
|
|
17651
17977
|
memexEntryCount: this._memexArchive.size,
|
|
17652
17978
|
fileRegistrySize: this._fileRegistry.size
|
|
17653
17979
|
};
|
|
17654
|
-
|
|
17980
|
+
writeFileSync17(join54(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
|
|
17655
17981
|
} catch {
|
|
17656
17982
|
}
|
|
17657
17983
|
}
|
|
@@ -17943,6 +18269,7 @@ ${newerSummary}` : newerSummary;
|
|
|
17943
18269
|
const commandResults = [];
|
|
17944
18270
|
const searchFindings = [];
|
|
17945
18271
|
const errors = [];
|
|
18272
|
+
let skillResults;
|
|
17946
18273
|
let toolCallCount = 0;
|
|
17947
18274
|
for (const msg of messages) {
|
|
17948
18275
|
if (msg.role === "assistant" && typeof msg.content === "string" && msg.content.trim()) {
|
|
@@ -18036,6 +18363,19 @@ ${newerSummary}` : newerSummary;
|
|
|
18036
18363
|
searchFindings.push(`find "${pattern}": ${files.length} files \u2014 ${files.slice(0, 5).join(", ")}`);
|
|
18037
18364
|
break;
|
|
18038
18365
|
}
|
|
18366
|
+
case "skill_build":
|
|
18367
|
+
case "skill_execute":
|
|
18368
|
+
case "skill_list":
|
|
18369
|
+
case "memory_write":
|
|
18370
|
+
case "memory_read": {
|
|
18371
|
+
const summary = content.length > 300 ? content.slice(0, 300) + "..." : content;
|
|
18372
|
+
if (!skillResults)
|
|
18373
|
+
skillResults = [];
|
|
18374
|
+
skillResults.push(`${tc.name}: ${summary}`);
|
|
18375
|
+
if (content.startsWith("Error:"))
|
|
18376
|
+
errors.push(`${tc.name}: ${content.slice(0, 200)}`);
|
|
18377
|
+
break;
|
|
18378
|
+
}
|
|
18039
18379
|
default: {
|
|
18040
18380
|
if (content.startsWith("Error:"))
|
|
18041
18381
|
errors.push(`${tc.name}: ${content.slice(0, 200)}`);
|
|
@@ -18084,6 +18424,13 @@ ${newerSummary}` : newerSummary;
|
|
|
18084
18424
|
}
|
|
18085
18425
|
parts.push("");
|
|
18086
18426
|
}
|
|
18427
|
+
if (skillResults && skillResults.length > 0) {
|
|
18428
|
+
parts.push("### Skill/Memory Context");
|
|
18429
|
+
for (const sr of skillResults.slice(0, 5)) {
|
|
18430
|
+
parts.push(`- ${sr}`);
|
|
18431
|
+
}
|
|
18432
|
+
parts.push("");
|
|
18433
|
+
}
|
|
18087
18434
|
if (errors.length > 0) {
|
|
18088
18435
|
parts.push("### Errors Encountered");
|
|
18089
18436
|
for (const error of errors.slice(0, 5)) {
|
|
@@ -18261,11 +18608,24 @@ ${newerSummary}` : newerSummary;
|
|
|
18261
18608
|
context: action,
|
|
18262
18609
|
error: content.slice(0, 300)
|
|
18263
18610
|
});
|
|
18611
|
+
} else if (tc.name === "skill_build" || tc.name === "skill_execute" || tc.name === "memory_read") {
|
|
18612
|
+
successes.push(`${action}: ${content.slice(0, 200)}`);
|
|
18264
18613
|
} else {
|
|
18265
18614
|
successes.push(`${action} \u2192 ok`);
|
|
18266
18615
|
}
|
|
18267
18616
|
}
|
|
18268
18617
|
}
|
|
18618
|
+
const decisions = [];
|
|
18619
|
+
for (const msg of messages) {
|
|
18620
|
+
if (msg.role === "assistant" && typeof msg.content === "string" && msg.content.trim().length > 30) {
|
|
18621
|
+
const decisionPatterns = /(?:I (?:will|need to|should|decided|chose|'ll)|Let me|The (?:fix|solution|approach|issue))[^.!?\n]{10,120}[.!?]/gi;
|
|
18622
|
+
const matches = msg.content.match(decisionPatterns);
|
|
18623
|
+
if (matches) {
|
|
18624
|
+
for (const m of matches.slice(0, 2))
|
|
18625
|
+
decisions.push(m.trim());
|
|
18626
|
+
}
|
|
18627
|
+
}
|
|
18628
|
+
}
|
|
18269
18629
|
const parts = [];
|
|
18270
18630
|
parts.push(`## Error-Focused Compact
|
|
18271
18631
|
`);
|
|
@@ -18279,6 +18639,12 @@ ${newerSummary}` : newerSummary;
|
|
|
18279
18639
|
}
|
|
18280
18640
|
parts.push("");
|
|
18281
18641
|
}
|
|
18642
|
+
if (decisions.length > 0) {
|
|
18643
|
+
parts.push("### Key Decisions");
|
|
18644
|
+
for (const d of decisions.slice(0, 5))
|
|
18645
|
+
parts.push(`- ${d}`);
|
|
18646
|
+
parts.push("");
|
|
18647
|
+
}
|
|
18282
18648
|
if (successes.length > 0) {
|
|
18283
18649
|
parts.push(`### Successful Operations (${successes.length} total)`);
|
|
18284
18650
|
for (const s of successes.slice(0, 10))
|
|
@@ -19429,8 +19795,8 @@ __export(listen_exports, {
|
|
|
19429
19795
|
waitForTranscribeCli: () => waitForTranscribeCli
|
|
19430
19796
|
});
|
|
19431
19797
|
import { spawn as spawn12, execSync as execSync23 } from "node:child_process";
|
|
19432
|
-
import { existsSync as
|
|
19433
|
-
import { join as
|
|
19798
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7, readdirSync as readdirSync6 } from "node:fs";
|
|
19799
|
+
import { join as join34, dirname as dirname12 } from "node:path";
|
|
19434
19800
|
import { homedir as homedir8 } from "node:os";
|
|
19435
19801
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
19436
19802
|
import { EventEmitter } from "node:events";
|
|
@@ -19514,17 +19880,17 @@ function findMicCaptureCommand() {
|
|
|
19514
19880
|
return null;
|
|
19515
19881
|
}
|
|
19516
19882
|
function findLiveWhisperScript() {
|
|
19517
|
-
const thisDir =
|
|
19883
|
+
const thisDir = dirname12(fileURLToPath8(import.meta.url));
|
|
19518
19884
|
const candidates = [
|
|
19519
|
-
|
|
19520
|
-
|
|
19521
|
-
|
|
19885
|
+
join34(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
|
|
19886
|
+
join34(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
|
|
19887
|
+
join34(thisDir, "../../execution/scripts/live-whisper.py"),
|
|
19522
19888
|
// npm install layout — scripts bundled alongside dist
|
|
19523
|
-
|
|
19524
|
-
|
|
19889
|
+
join34(thisDir, "../scripts/live-whisper.py"),
|
|
19890
|
+
join34(thisDir, "../../scripts/live-whisper.py")
|
|
19525
19891
|
];
|
|
19526
19892
|
for (const p of candidates) {
|
|
19527
|
-
if (
|
|
19893
|
+
if (existsSync25(p))
|
|
19528
19894
|
return p;
|
|
19529
19895
|
}
|
|
19530
19896
|
try {
|
|
@@ -19534,21 +19900,21 @@ function findLiveWhisperScript() {
|
|
|
19534
19900
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19535
19901
|
}).trim();
|
|
19536
19902
|
const candidates2 = [
|
|
19537
|
-
|
|
19538
|
-
|
|
19903
|
+
join34(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
|
|
19904
|
+
join34(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
|
|
19539
19905
|
];
|
|
19540
19906
|
for (const p of candidates2) {
|
|
19541
|
-
if (
|
|
19907
|
+
if (existsSync25(p))
|
|
19542
19908
|
return p;
|
|
19543
19909
|
}
|
|
19544
19910
|
} catch {
|
|
19545
19911
|
}
|
|
19546
|
-
const nvmBase =
|
|
19547
|
-
if (
|
|
19912
|
+
const nvmBase = join34(homedir8(), ".nvm", "versions", "node");
|
|
19913
|
+
if (existsSync25(nvmBase)) {
|
|
19548
19914
|
try {
|
|
19549
19915
|
for (const ver of readdirSync6(nvmBase)) {
|
|
19550
|
-
const p =
|
|
19551
|
-
if (
|
|
19916
|
+
const p = join34(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
|
|
19917
|
+
if (existsSync25(p))
|
|
19552
19918
|
return p;
|
|
19553
19919
|
}
|
|
19554
19920
|
} catch {
|
|
@@ -19566,7 +19932,7 @@ function ensureTranscribeCliBackground() {
|
|
|
19566
19932
|
timeout: 5e3,
|
|
19567
19933
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19568
19934
|
}).trim();
|
|
19569
|
-
if (
|
|
19935
|
+
if (existsSync25(join34(globalRoot, "transcribe-cli", "dist", "index.js"))) {
|
|
19570
19936
|
return true;
|
|
19571
19937
|
}
|
|
19572
19938
|
} catch {
|
|
@@ -19789,24 +20155,24 @@ var init_listen = __esm({
|
|
|
19789
20155
|
timeout: 5e3,
|
|
19790
20156
|
stdio: ["pipe", "pipe", "pipe"]
|
|
19791
20157
|
}).trim();
|
|
19792
|
-
const tcPath =
|
|
19793
|
-
if (
|
|
20158
|
+
const tcPath = join34(globalRoot, "transcribe-cli");
|
|
20159
|
+
if (existsSync25(join34(tcPath, "dist", "index.js"))) {
|
|
19794
20160
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
19795
20161
|
const req = createRequire4(import.meta.url);
|
|
19796
|
-
return req(
|
|
20162
|
+
return req(join34(tcPath, "dist", "index.js"));
|
|
19797
20163
|
}
|
|
19798
20164
|
} catch {
|
|
19799
20165
|
}
|
|
19800
|
-
const nvmBase =
|
|
19801
|
-
if (
|
|
20166
|
+
const nvmBase = join34(homedir8(), ".nvm", "versions", "node");
|
|
20167
|
+
if (existsSync25(nvmBase)) {
|
|
19802
20168
|
try {
|
|
19803
20169
|
const { readdirSync: readdirSync15 } = await import("node:fs");
|
|
19804
20170
|
for (const ver of readdirSync15(nvmBase)) {
|
|
19805
|
-
const tcPath =
|
|
19806
|
-
if (
|
|
20171
|
+
const tcPath = join34(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
20172
|
+
if (existsSync25(join34(tcPath, "dist", "index.js"))) {
|
|
19807
20173
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
19808
20174
|
const req = createRequire4(import.meta.url);
|
|
19809
|
-
return req(
|
|
20175
|
+
return req(join34(tcPath, "dist", "index.js"));
|
|
19810
20176
|
}
|
|
19811
20177
|
}
|
|
19812
20178
|
} catch {
|
|
@@ -20088,10 +20454,10 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
20088
20454
|
});
|
|
20089
20455
|
if (outputDir) {
|
|
20090
20456
|
const { basename: basename16 } = await import("node:path");
|
|
20091
|
-
const transcriptDir =
|
|
20092
|
-
|
|
20093
|
-
const outFile =
|
|
20094
|
-
|
|
20457
|
+
const transcriptDir = join34(outputDir, ".oa", "transcripts");
|
|
20458
|
+
mkdirSync7(transcriptDir, { recursive: true });
|
|
20459
|
+
const outFile = join34(transcriptDir, `${basename16(filePath)}.txt`);
|
|
20460
|
+
writeFileSync7(outFile, result.text, "utf-8");
|
|
20095
20461
|
}
|
|
20096
20462
|
return {
|
|
20097
20463
|
text: result.text,
|
|
@@ -24302,6 +24668,8 @@ function renderSlashHelp() {
|
|
|
24302
24668
|
["/nexus wallet", "Show wallet address and x402 payment status"],
|
|
24303
24669
|
["/style", "Show current response style"],
|
|
24304
24670
|
["/style <preset>", "Set style: concise, balanced, verbose, pedagogical"],
|
|
24671
|
+
["/commands auto", "Allow agent to invoke slash commands as tools"],
|
|
24672
|
+
["/commands manual", "Slash commands are user-only (default)"],
|
|
24305
24673
|
["/verbose", "Toggle verbose mode"],
|
|
24306
24674
|
["/clear", "Clear the screen"],
|
|
24307
24675
|
["/help", "Show this help"],
|
|
@@ -25689,8 +26057,8 @@ var init_types = __esm({
|
|
|
25689
26057
|
|
|
25690
26058
|
// packages/cli/dist/tui/p2p/secret-vault.js
|
|
25691
26059
|
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes8, scryptSync as scryptSync2, createHash as createHash2 } from "node:crypto";
|
|
25692
|
-
import { readFileSync as
|
|
25693
|
-
import { join as
|
|
26060
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync8, existsSync as existsSync26, mkdirSync as mkdirSync8 } from "node:fs";
|
|
26061
|
+
import { join as join35, dirname as dirname13 } from "node:path";
|
|
25694
26062
|
var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
|
|
25695
26063
|
var init_secret_vault = __esm({
|
|
25696
26064
|
"packages/cli/dist/tui/p2p/secret-vault.js"() {
|
|
@@ -25901,19 +26269,19 @@ var init_secret_vault = __esm({
|
|
|
25901
26269
|
const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
|
|
25902
26270
|
const tag = cipher.getAuthTag();
|
|
25903
26271
|
const blob = Buffer.concat([salt, iv, tag, encrypted]);
|
|
25904
|
-
const dir =
|
|
25905
|
-
if (!
|
|
25906
|
-
|
|
25907
|
-
|
|
26272
|
+
const dir = dirname13(this.storePath);
|
|
26273
|
+
if (!existsSync26(dir))
|
|
26274
|
+
mkdirSync8(dir, { recursive: true });
|
|
26275
|
+
writeFileSync8(this.storePath, blob, { mode: 384 });
|
|
25908
26276
|
}
|
|
25909
26277
|
/**
|
|
25910
26278
|
* Load vault from disk, decrypting with the given passphrase.
|
|
25911
26279
|
* Returns the number of secrets loaded.
|
|
25912
26280
|
*/
|
|
25913
26281
|
load(passphrase) {
|
|
25914
|
-
if (!this.storePath || !
|
|
26282
|
+
if (!this.storePath || !existsSync26(this.storePath))
|
|
25915
26283
|
return 0;
|
|
25916
|
-
const blob =
|
|
26284
|
+
const blob = readFileSync18(this.storePath);
|
|
25917
26285
|
if (blob.length < SALT_LEN + IV_LEN + 16) {
|
|
25918
26286
|
throw new Error("Vault file is corrupted (too small)");
|
|
25919
26287
|
}
|
|
@@ -27133,32 +27501,32 @@ var init_render2 = __esm({
|
|
|
27133
27501
|
});
|
|
27134
27502
|
|
|
27135
27503
|
// packages/prompts/dist/promptLoader.js
|
|
27136
|
-
import { readFileSync as
|
|
27137
|
-
import { join as
|
|
27504
|
+
import { readFileSync as readFileSync19, existsSync as existsSync27 } from "node:fs";
|
|
27505
|
+
import { join as join36, dirname as dirname14 } from "node:path";
|
|
27138
27506
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
27139
27507
|
function loadPrompt2(promptPath, vars) {
|
|
27140
27508
|
let content = cache2.get(promptPath);
|
|
27141
27509
|
if (content === void 0) {
|
|
27142
|
-
const fullPath =
|
|
27143
|
-
if (!
|
|
27510
|
+
const fullPath = join36(PROMPTS_DIR2, promptPath);
|
|
27511
|
+
if (!existsSync27(fullPath)) {
|
|
27144
27512
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
27145
27513
|
}
|
|
27146
|
-
content =
|
|
27514
|
+
content = readFileSync19(fullPath, "utf-8");
|
|
27147
27515
|
cache2.set(promptPath, content);
|
|
27148
27516
|
}
|
|
27149
27517
|
if (!vars)
|
|
27150
27518
|
return content;
|
|
27151
27519
|
return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
|
|
27152
27520
|
}
|
|
27153
|
-
var __filename2,
|
|
27521
|
+
var __filename2, __dirname5, devPath, publishedPath, PROMPTS_DIR2, cache2;
|
|
27154
27522
|
var init_promptLoader2 = __esm({
|
|
27155
27523
|
"packages/prompts/dist/promptLoader.js"() {
|
|
27156
27524
|
"use strict";
|
|
27157
27525
|
__filename2 = fileURLToPath9(import.meta.url);
|
|
27158
|
-
|
|
27159
|
-
devPath =
|
|
27160
|
-
publishedPath =
|
|
27161
|
-
PROMPTS_DIR2 =
|
|
27526
|
+
__dirname5 = dirname14(__filename2);
|
|
27527
|
+
devPath = join36(__dirname5, "..", "templates");
|
|
27528
|
+
publishedPath = join36(__dirname5, "..", "prompts", "templates");
|
|
27529
|
+
PROMPTS_DIR2 = existsSync27(devPath) ? devPath : publishedPath;
|
|
27162
27530
|
cache2 = /* @__PURE__ */ new Map();
|
|
27163
27531
|
}
|
|
27164
27532
|
});
|
|
@@ -27269,7 +27637,7 @@ var init_task_templates = __esm({
|
|
|
27269
27637
|
});
|
|
27270
27638
|
|
|
27271
27639
|
// packages/prompts/dist/index.js
|
|
27272
|
-
import { join as
|
|
27640
|
+
import { join as join37, dirname as dirname15 } from "node:path";
|
|
27273
27641
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
27274
27642
|
var _dir, _packageRoot;
|
|
27275
27643
|
var init_dist6 = __esm({
|
|
@@ -27279,27 +27647,27 @@ var init_dist6 = __esm({
|
|
|
27279
27647
|
init_render2();
|
|
27280
27648
|
init_task_templates();
|
|
27281
27649
|
init_render2();
|
|
27282
|
-
_dir =
|
|
27283
|
-
_packageRoot =
|
|
27650
|
+
_dir = dirname15(fileURLToPath10(import.meta.url));
|
|
27651
|
+
_packageRoot = join37(_dir, "..");
|
|
27284
27652
|
}
|
|
27285
27653
|
});
|
|
27286
27654
|
|
|
27287
27655
|
// packages/cli/dist/tui/oa-directory.js
|
|
27288
|
-
import { existsSync as
|
|
27289
|
-
import { join as
|
|
27656
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync9, readFileSync as readFileSync20, writeFileSync as writeFileSync9, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
|
|
27657
|
+
import { join as join38, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
|
|
27290
27658
|
import { homedir as homedir9 } from "node:os";
|
|
27291
27659
|
function initOaDirectory(repoRoot) {
|
|
27292
|
-
const oaPath =
|
|
27660
|
+
const oaPath = join38(repoRoot, OA_DIR);
|
|
27293
27661
|
for (const sub of SUBDIRS) {
|
|
27294
|
-
|
|
27662
|
+
mkdirSync9(join38(oaPath, sub), { recursive: true });
|
|
27295
27663
|
}
|
|
27296
27664
|
try {
|
|
27297
|
-
const gitignorePath =
|
|
27665
|
+
const gitignorePath = join38(repoRoot, ".gitignore");
|
|
27298
27666
|
const settingsPattern = ".oa/settings.json";
|
|
27299
|
-
if (
|
|
27300
|
-
const content =
|
|
27667
|
+
if (existsSync28(gitignorePath)) {
|
|
27668
|
+
const content = readFileSync20(gitignorePath, "utf-8");
|
|
27301
27669
|
if (!content.includes(settingsPattern)) {
|
|
27302
|
-
|
|
27670
|
+
writeFileSync9(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
|
|
27303
27671
|
}
|
|
27304
27672
|
}
|
|
27305
27673
|
} catch {
|
|
@@ -27307,41 +27675,41 @@ function initOaDirectory(repoRoot) {
|
|
|
27307
27675
|
return oaPath;
|
|
27308
27676
|
}
|
|
27309
27677
|
function hasOaDirectory(repoRoot) {
|
|
27310
|
-
return
|
|
27678
|
+
return existsSync28(join38(repoRoot, OA_DIR, "index"));
|
|
27311
27679
|
}
|
|
27312
27680
|
function loadProjectSettings(repoRoot) {
|
|
27313
|
-
const settingsPath =
|
|
27681
|
+
const settingsPath = join38(repoRoot, OA_DIR, "settings.json");
|
|
27314
27682
|
try {
|
|
27315
|
-
if (
|
|
27316
|
-
return JSON.parse(
|
|
27683
|
+
if (existsSync28(settingsPath)) {
|
|
27684
|
+
return JSON.parse(readFileSync20(settingsPath, "utf-8"));
|
|
27317
27685
|
}
|
|
27318
27686
|
} catch {
|
|
27319
27687
|
}
|
|
27320
27688
|
return {};
|
|
27321
27689
|
}
|
|
27322
27690
|
function saveProjectSettings(repoRoot, settings) {
|
|
27323
|
-
const oaPath =
|
|
27324
|
-
|
|
27691
|
+
const oaPath = join38(repoRoot, OA_DIR);
|
|
27692
|
+
mkdirSync9(oaPath, { recursive: true });
|
|
27325
27693
|
const existing = loadProjectSettings(repoRoot);
|
|
27326
27694
|
const merged = { ...existing, ...settings };
|
|
27327
|
-
|
|
27695
|
+
writeFileSync9(join38(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
27328
27696
|
}
|
|
27329
27697
|
function loadGlobalSettings() {
|
|
27330
|
-
const settingsPath =
|
|
27698
|
+
const settingsPath = join38(homedir9(), ".open-agents", "settings.json");
|
|
27331
27699
|
try {
|
|
27332
|
-
if (
|
|
27333
|
-
return JSON.parse(
|
|
27700
|
+
if (existsSync28(settingsPath)) {
|
|
27701
|
+
return JSON.parse(readFileSync20(settingsPath, "utf-8"));
|
|
27334
27702
|
}
|
|
27335
27703
|
} catch {
|
|
27336
27704
|
}
|
|
27337
27705
|
return {};
|
|
27338
27706
|
}
|
|
27339
27707
|
function saveGlobalSettings(settings) {
|
|
27340
|
-
const dir =
|
|
27341
|
-
|
|
27708
|
+
const dir = join38(homedir9(), ".open-agents");
|
|
27709
|
+
mkdirSync9(dir, { recursive: true });
|
|
27342
27710
|
const existing = loadGlobalSettings();
|
|
27343
27711
|
const merged = { ...existing, ...settings };
|
|
27344
|
-
|
|
27712
|
+
writeFileSync9(join38(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
27345
27713
|
}
|
|
27346
27714
|
function resolveSettings(repoRoot) {
|
|
27347
27715
|
const global = loadGlobalSettings();
|
|
@@ -27356,12 +27724,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
27356
27724
|
while (dir && !visited.has(dir)) {
|
|
27357
27725
|
visited.add(dir);
|
|
27358
27726
|
for (const name of CONTEXT_FILES) {
|
|
27359
|
-
const filePath =
|
|
27727
|
+
const filePath = join38(dir, name);
|
|
27360
27728
|
const normalizedName = name.toLowerCase();
|
|
27361
|
-
if (
|
|
27729
|
+
if (existsSync28(filePath) && !seen.has(filePath)) {
|
|
27362
27730
|
seen.add(filePath);
|
|
27363
27731
|
try {
|
|
27364
|
-
let content =
|
|
27732
|
+
let content = readFileSync20(filePath, "utf-8");
|
|
27365
27733
|
if (content.length > maxContentLen) {
|
|
27366
27734
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
27367
27735
|
}
|
|
@@ -27375,11 +27743,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
27375
27743
|
}
|
|
27376
27744
|
}
|
|
27377
27745
|
}
|
|
27378
|
-
const projectMap =
|
|
27379
|
-
if (
|
|
27746
|
+
const projectMap = join38(dir, OA_DIR, "context", "project-map.md");
|
|
27747
|
+
if (existsSync28(projectMap) && !seen.has(projectMap)) {
|
|
27380
27748
|
seen.add(projectMap);
|
|
27381
27749
|
try {
|
|
27382
|
-
let content =
|
|
27750
|
+
let content = readFileSync20(projectMap, "utf-8");
|
|
27383
27751
|
if (content.length > maxContentLen) {
|
|
27384
27752
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
27385
27753
|
}
|
|
@@ -27391,7 +27759,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
27391
27759
|
} catch {
|
|
27392
27760
|
}
|
|
27393
27761
|
}
|
|
27394
|
-
const parent =
|
|
27762
|
+
const parent = join38(dir, "..");
|
|
27395
27763
|
if (parent === dir)
|
|
27396
27764
|
break;
|
|
27397
27765
|
dir = parent;
|
|
@@ -27409,9 +27777,9 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
27409
27777
|
return found;
|
|
27410
27778
|
}
|
|
27411
27779
|
function readIndexMeta(repoRoot) {
|
|
27412
|
-
const metaPath =
|
|
27780
|
+
const metaPath = join38(repoRoot, OA_DIR, "index", "meta.json");
|
|
27413
27781
|
try {
|
|
27414
|
-
return JSON.parse(
|
|
27782
|
+
return JSON.parse(readFileSync20(metaPath, "utf-8"));
|
|
27415
27783
|
} catch {
|
|
27416
27784
|
return null;
|
|
27417
27785
|
}
|
|
@@ -27462,28 +27830,28 @@ ${tree}\`\`\`
|
|
|
27462
27830
|
sections.push("");
|
|
27463
27831
|
}
|
|
27464
27832
|
const content = sections.join("\n");
|
|
27465
|
-
const contextDir =
|
|
27466
|
-
|
|
27467
|
-
|
|
27833
|
+
const contextDir = join38(repoRoot, OA_DIR, "context");
|
|
27834
|
+
mkdirSync9(contextDir, { recursive: true });
|
|
27835
|
+
writeFileSync9(join38(contextDir, "project-map.md"), content, "utf-8");
|
|
27468
27836
|
return content;
|
|
27469
27837
|
}
|
|
27470
27838
|
function saveSession(repoRoot, session) {
|
|
27471
|
-
const historyDir =
|
|
27472
|
-
|
|
27473
|
-
|
|
27839
|
+
const historyDir = join38(repoRoot, OA_DIR, "history");
|
|
27840
|
+
mkdirSync9(historyDir, { recursive: true });
|
|
27841
|
+
writeFileSync9(join38(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
|
|
27474
27842
|
}
|
|
27475
27843
|
function loadRecentSessions(repoRoot, limit = 5) {
|
|
27476
|
-
const historyDir =
|
|
27477
|
-
if (!
|
|
27844
|
+
const historyDir = join38(repoRoot, OA_DIR, "history");
|
|
27845
|
+
if (!existsSync28(historyDir))
|
|
27478
27846
|
return [];
|
|
27479
27847
|
try {
|
|
27480
27848
|
const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
|
|
27481
|
-
const stat5 = statSync9(
|
|
27849
|
+
const stat5 = statSync9(join38(historyDir, f));
|
|
27482
27850
|
return { file: f, mtime: stat5.mtimeMs };
|
|
27483
27851
|
}).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
|
|
27484
27852
|
return files.map((f) => {
|
|
27485
27853
|
try {
|
|
27486
|
-
return JSON.parse(
|
|
27854
|
+
return JSON.parse(readFileSync20(join38(historyDir, f.file), "utf-8"));
|
|
27487
27855
|
} catch {
|
|
27488
27856
|
return null;
|
|
27489
27857
|
}
|
|
@@ -27493,16 +27861,16 @@ function loadRecentSessions(repoRoot, limit = 5) {
|
|
|
27493
27861
|
}
|
|
27494
27862
|
}
|
|
27495
27863
|
function savePendingTask(repoRoot, task) {
|
|
27496
|
-
const historyDir =
|
|
27497
|
-
|
|
27498
|
-
|
|
27864
|
+
const historyDir = join38(repoRoot, OA_DIR, "history");
|
|
27865
|
+
mkdirSync9(historyDir, { recursive: true });
|
|
27866
|
+
writeFileSync9(join38(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
|
|
27499
27867
|
}
|
|
27500
27868
|
function loadPendingTask(repoRoot) {
|
|
27501
|
-
const filePath =
|
|
27869
|
+
const filePath = join38(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
|
|
27502
27870
|
try {
|
|
27503
|
-
if (!
|
|
27871
|
+
if (!existsSync28(filePath))
|
|
27504
27872
|
return null;
|
|
27505
|
-
const data = JSON.parse(
|
|
27873
|
+
const data = JSON.parse(readFileSync20(filePath, "utf-8"));
|
|
27506
27874
|
try {
|
|
27507
27875
|
unlinkSync3(filePath);
|
|
27508
27876
|
} catch {
|
|
@@ -27513,13 +27881,13 @@ function loadPendingTask(repoRoot) {
|
|
|
27513
27881
|
}
|
|
27514
27882
|
}
|
|
27515
27883
|
function saveSessionContext(repoRoot, entry) {
|
|
27516
|
-
const contextDir =
|
|
27517
|
-
|
|
27518
|
-
const filePath =
|
|
27884
|
+
const contextDir = join38(repoRoot, OA_DIR, "context");
|
|
27885
|
+
mkdirSync9(contextDir, { recursive: true });
|
|
27886
|
+
const filePath = join38(contextDir, CONTEXT_SAVE_FILE);
|
|
27519
27887
|
let ctx;
|
|
27520
27888
|
try {
|
|
27521
|
-
if (
|
|
27522
|
-
ctx = JSON.parse(
|
|
27889
|
+
if (existsSync28(filePath)) {
|
|
27890
|
+
ctx = JSON.parse(readFileSync20(filePath, "utf-8"));
|
|
27523
27891
|
} else {
|
|
27524
27892
|
ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
|
|
27525
27893
|
}
|
|
@@ -27531,14 +27899,14 @@ function saveSessionContext(repoRoot, entry) {
|
|
|
27531
27899
|
ctx.entries = ctx.entries.slice(-ctx.maxEntries);
|
|
27532
27900
|
}
|
|
27533
27901
|
ctx.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
27534
|
-
|
|
27902
|
+
writeFileSync9(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
|
|
27535
27903
|
}
|
|
27536
27904
|
function loadSessionContext(repoRoot) {
|
|
27537
|
-
const filePath =
|
|
27905
|
+
const filePath = join38(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
|
|
27538
27906
|
try {
|
|
27539
|
-
if (!
|
|
27907
|
+
if (!existsSync28(filePath))
|
|
27540
27908
|
return null;
|
|
27541
|
-
return JSON.parse(
|
|
27909
|
+
return JSON.parse(readFileSync20(filePath, "utf-8"));
|
|
27542
27910
|
} catch {
|
|
27543
27911
|
return null;
|
|
27544
27912
|
}
|
|
@@ -27585,12 +27953,12 @@ function detectManifests(repoRoot) {
|
|
|
27585
27953
|
{ file: "docker-compose.yaml", type: "Docker Compose" }
|
|
27586
27954
|
];
|
|
27587
27955
|
for (const check of checks) {
|
|
27588
|
-
const filePath =
|
|
27589
|
-
if (
|
|
27956
|
+
const filePath = join38(repoRoot, check.file);
|
|
27957
|
+
if (existsSync28(filePath)) {
|
|
27590
27958
|
let name;
|
|
27591
27959
|
if (check.nameField) {
|
|
27592
27960
|
try {
|
|
27593
|
-
const data = JSON.parse(
|
|
27961
|
+
const data = JSON.parse(readFileSync20(filePath, "utf-8"));
|
|
27594
27962
|
name = data[check.nameField];
|
|
27595
27963
|
} catch {
|
|
27596
27964
|
}
|
|
@@ -27619,7 +27987,7 @@ function findKeyFiles(repoRoot) {
|
|
|
27619
27987
|
{ pattern: "CLAUDE.md", description: "Claude Code context" }
|
|
27620
27988
|
];
|
|
27621
27989
|
for (const check of checks) {
|
|
27622
|
-
if (
|
|
27990
|
+
if (existsSync28(join38(repoRoot, check.pattern))) {
|
|
27623
27991
|
keyFiles.push({ path: check.pattern, description: check.description });
|
|
27624
27992
|
}
|
|
27625
27993
|
}
|
|
@@ -27645,12 +28013,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
27645
28013
|
if (entry.isDirectory()) {
|
|
27646
28014
|
let fileCount = 0;
|
|
27647
28015
|
try {
|
|
27648
|
-
fileCount = readdirSync7(
|
|
28016
|
+
fileCount = readdirSync7(join38(root, entry.name)).filter((f) => !f.startsWith(".")).length;
|
|
27649
28017
|
} catch {
|
|
27650
28018
|
}
|
|
27651
28019
|
result += `${prefix}${connector}${entry.name}/ (${fileCount})
|
|
27652
28020
|
`;
|
|
27653
|
-
result += buildDirTree(
|
|
28021
|
+
result += buildDirTree(join38(root, entry.name), maxDepth, childPrefix, depth + 1);
|
|
27654
28022
|
} else if (depth < maxDepth) {
|
|
27655
28023
|
result += `${prefix}${connector}${entry.name}
|
|
27656
28024
|
`;
|
|
@@ -27704,8 +28072,8 @@ var init_oa_directory = __esm({
|
|
|
27704
28072
|
// packages/cli/dist/tui/setup.js
|
|
27705
28073
|
import * as readline from "node:readline";
|
|
27706
28074
|
import { execSync as execSync25, spawn as spawn15 } from "node:child_process";
|
|
27707
|
-
import { existsSync as
|
|
27708
|
-
import { join as
|
|
28075
|
+
import { existsSync as existsSync29, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
|
|
28076
|
+
import { join as join39 } from "node:path";
|
|
27709
28077
|
import { homedir as homedir10, platform } from "node:os";
|
|
27710
28078
|
function detectSystemSpecs() {
|
|
27711
28079
|
let totalRamGB = 0;
|
|
@@ -27938,7 +28306,7 @@ async function installOllamaMac(_rl) {
|
|
|
27938
28306
|
execSync25('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
|
|
27939
28307
|
if (!hasCmd("brew")) {
|
|
27940
28308
|
try {
|
|
27941
|
-
const brewPrefix =
|
|
28309
|
+
const brewPrefix = existsSync29("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
|
|
27942
28310
|
process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
|
|
27943
28311
|
} catch {
|
|
27944
28312
|
}
|
|
@@ -28692,10 +29060,10 @@ async function doSetup(config, rl) {
|
|
|
28692
29060
|
`PARAMETER num_predict ${numPredict}`,
|
|
28693
29061
|
`PARAMETER stop "<|endoftext|>"`
|
|
28694
29062
|
].join("\n");
|
|
28695
|
-
const modelDir2 =
|
|
28696
|
-
|
|
28697
|
-
const modelfilePath =
|
|
28698
|
-
|
|
29063
|
+
const modelDir2 = join39(homedir10(), ".open-agents", "models");
|
|
29064
|
+
mkdirSync10(modelDir2, { recursive: true });
|
|
29065
|
+
const modelfilePath = join39(modelDir2, `Modelfile.${customName}`);
|
|
29066
|
+
writeFileSync10(modelfilePath, modelfileContent + "\n", "utf8");
|
|
28699
29067
|
process.stdout.write(` ${c2.dim("Creating model...")} `);
|
|
28700
29068
|
execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
28701
29069
|
stdio: "pipe",
|
|
@@ -28740,7 +29108,7 @@ async function isModelAvailable(config) {
|
|
|
28740
29108
|
}
|
|
28741
29109
|
function isFirstRun() {
|
|
28742
29110
|
try {
|
|
28743
|
-
return !
|
|
29111
|
+
return !existsSync29(join39(homedir10(), ".open-agents", "config.json"));
|
|
28744
29112
|
} catch {
|
|
28745
29113
|
return true;
|
|
28746
29114
|
}
|
|
@@ -28777,7 +29145,7 @@ function detectPkgManager() {
|
|
|
28777
29145
|
return null;
|
|
28778
29146
|
}
|
|
28779
29147
|
function getVenvDir() {
|
|
28780
|
-
return
|
|
29148
|
+
return join39(homedir10(), ".open-agents", "venv");
|
|
28781
29149
|
}
|
|
28782
29150
|
function hasVenvModule() {
|
|
28783
29151
|
try {
|
|
@@ -28789,8 +29157,8 @@ function hasVenvModule() {
|
|
|
28789
29157
|
}
|
|
28790
29158
|
function ensureVenv(log) {
|
|
28791
29159
|
const venvDir = getVenvDir();
|
|
28792
|
-
const venvPip =
|
|
28793
|
-
if (
|
|
29160
|
+
const venvPip = join39(venvDir, "bin", "pip");
|
|
29161
|
+
if (existsSync29(venvPip))
|
|
28794
29162
|
return venvDir;
|
|
28795
29163
|
log("Creating Python venv for vision deps...");
|
|
28796
29164
|
if (!hasCmd("python3")) {
|
|
@@ -28802,9 +29170,9 @@ function ensureVenv(log) {
|
|
|
28802
29170
|
return null;
|
|
28803
29171
|
}
|
|
28804
29172
|
try {
|
|
28805
|
-
|
|
29173
|
+
mkdirSync10(join39(homedir10(), ".open-agents"), { recursive: true });
|
|
28806
29174
|
execSync25(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
28807
|
-
execSync25(`"${
|
|
29175
|
+
execSync25(`"${join39(venvDir, "bin", "pip")}" install --upgrade pip`, {
|
|
28808
29176
|
stdio: "pipe",
|
|
28809
29177
|
timeout: 6e4
|
|
28810
29178
|
});
|
|
@@ -29013,15 +29381,15 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
29013
29381
|
}
|
|
29014
29382
|
}
|
|
29015
29383
|
const venvDir = getVenvDir();
|
|
29016
|
-
const venvBin =
|
|
29017
|
-
const venvMoondream =
|
|
29384
|
+
const venvBin = join39(venvDir, "bin");
|
|
29385
|
+
const venvMoondream = join39(venvBin, "moondream-station");
|
|
29018
29386
|
const venv = ensureVenv(log);
|
|
29019
|
-
if (venv && !hasCmd("moondream-station") && !
|
|
29020
|
-
const venvPip =
|
|
29387
|
+
if (venv && !hasCmd("moondream-station") && !existsSync29(venvMoondream)) {
|
|
29388
|
+
const venvPip = join39(venvBin, "pip");
|
|
29021
29389
|
log("Installing moondream-station in ~/.open-agents/venv...");
|
|
29022
29390
|
try {
|
|
29023
29391
|
execSync25(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
29024
|
-
if (
|
|
29392
|
+
if (existsSync29(venvMoondream)) {
|
|
29025
29393
|
log("moondream-station installed successfully.");
|
|
29026
29394
|
} else {
|
|
29027
29395
|
try {
|
|
@@ -29038,8 +29406,8 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
29038
29406
|
}
|
|
29039
29407
|
}
|
|
29040
29408
|
if (venv) {
|
|
29041
|
-
const venvPython =
|
|
29042
|
-
const venvPip2 =
|
|
29409
|
+
const venvPython = join39(venvBin, "python");
|
|
29410
|
+
const venvPip2 = join39(venvBin, "pip");
|
|
29043
29411
|
let ocrStackInstalled = false;
|
|
29044
29412
|
try {
|
|
29045
29413
|
execSync25(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
@@ -29152,10 +29520,10 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
|
|
|
29152
29520
|
`PARAMETER num_predict ${numPredict}`,
|
|
29153
29521
|
`PARAMETER stop "<|endoftext|>"`
|
|
29154
29522
|
].join("\n");
|
|
29155
|
-
const modelDir2 =
|
|
29156
|
-
|
|
29157
|
-
const modelfilePath =
|
|
29158
|
-
|
|
29523
|
+
const modelDir2 = join39(homedir10(), ".open-agents", "models");
|
|
29524
|
+
mkdirSync10(modelDir2, { recursive: true });
|
|
29525
|
+
const modelfilePath = join39(modelDir2, `Modelfile.${customName}`);
|
|
29526
|
+
writeFileSync10(modelfilePath, modelfileContent + "\n", "utf8");
|
|
29159
29527
|
execSync25(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
29160
29528
|
stdio: "pipe",
|
|
29161
29529
|
timeout: 12e4
|
|
@@ -29693,6 +30061,30 @@ async function handleSlashCommand(input, ctx) {
|
|
|
29693
30061
|
}
|
|
29694
30062
|
return "handled";
|
|
29695
30063
|
}
|
|
30064
|
+
case "commands":
|
|
30065
|
+
case "cmds": {
|
|
30066
|
+
if (!ctx.getCommandsMode || !ctx.setCommandsMode) {
|
|
30067
|
+
renderWarning("Commands mode not available in this context.");
|
|
30068
|
+
return "handled";
|
|
30069
|
+
}
|
|
30070
|
+
if (arg === "auto") {
|
|
30071
|
+
ctx.setCommandsMode("auto");
|
|
30072
|
+
const save = hasLocal ? ctx.saveLocalSettings.bind(ctx) : ctx.saveSettings.bind(ctx);
|
|
30073
|
+
save({ commandsMode: "auto" });
|
|
30074
|
+
renderInfo("Commands mode: auto \u2014 the agent can now invoke slash commands as tools.");
|
|
30075
|
+
} else if (arg === "manual") {
|
|
30076
|
+
ctx.setCommandsMode("manual");
|
|
30077
|
+
const save = hasLocal ? ctx.saveLocalSettings.bind(ctx) : ctx.saveSettings.bind(ctx);
|
|
30078
|
+
save({ commandsMode: "manual" });
|
|
30079
|
+
renderInfo("Commands mode: manual \u2014 slash commands are user-only.");
|
|
30080
|
+
} else {
|
|
30081
|
+
const current = ctx.getCommandsMode();
|
|
30082
|
+
renderInfo(`Commands mode: ${c2.bold(current)}`);
|
|
30083
|
+
renderInfo(" /commands auto \u2014 agent can invoke slash commands as tools");
|
|
30084
|
+
renderInfo(" /commands manual \u2014 slash commands are user-only (default)");
|
|
30085
|
+
}
|
|
30086
|
+
return "handled";
|
|
30087
|
+
}
|
|
29696
30088
|
case "dream": {
|
|
29697
30089
|
if (arg === "stop" || arg === "wake") {
|
|
29698
30090
|
if (ctx.isDreaming?.()) {
|
|
@@ -30459,17 +30851,17 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
30459
30851
|
try {
|
|
30460
30852
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
30461
30853
|
const { fileURLToPath: fileURLToPath14 } = await import("node:url");
|
|
30462
|
-
const { dirname:
|
|
30463
|
-
const { existsSync:
|
|
30854
|
+
const { dirname: dirname19, join: join54 } = await import("node:path");
|
|
30855
|
+
const { existsSync: existsSync40 } = await import("node:fs");
|
|
30464
30856
|
const req = createRequire4(import.meta.url);
|
|
30465
|
-
const thisDir =
|
|
30857
|
+
const thisDir = dirname19(fileURLToPath14(import.meta.url));
|
|
30466
30858
|
const candidates = [
|
|
30467
|
-
|
|
30468
|
-
|
|
30469
|
-
|
|
30859
|
+
join54(thisDir, "..", "package.json"),
|
|
30860
|
+
join54(thisDir, "..", "..", "package.json"),
|
|
30861
|
+
join54(thisDir, "..", "..", "..", "package.json")
|
|
30470
30862
|
];
|
|
30471
30863
|
for (const pkgPath of candidates) {
|
|
30472
|
-
if (
|
|
30864
|
+
if (existsSync40(pkgPath)) {
|
|
30473
30865
|
const pkg = req(pkgPath);
|
|
30474
30866
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
30475
30867
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -30744,8 +31136,8 @@ var init_commands = __esm({
|
|
|
30744
31136
|
});
|
|
30745
31137
|
|
|
30746
31138
|
// packages/cli/dist/tui/project-context.js
|
|
30747
|
-
import { existsSync as
|
|
30748
|
-
import { join as
|
|
31139
|
+
import { existsSync as existsSync30, readFileSync as readFileSync21, readdirSync as readdirSync8 } from "node:fs";
|
|
31140
|
+
import { join as join40, basename as basename10 } from "node:path";
|
|
30749
31141
|
import { execSync as execSync26 } from "node:child_process";
|
|
30750
31142
|
import { homedir as homedir11, platform as platform2, release } from "node:os";
|
|
30751
31143
|
function getModelTier(modelName) {
|
|
@@ -30780,10 +31172,10 @@ function loadProjectMap(repoRoot) {
|
|
|
30780
31172
|
if (!hasOaDirectory(repoRoot)) {
|
|
30781
31173
|
initOaDirectory(repoRoot);
|
|
30782
31174
|
}
|
|
30783
|
-
const mapPath =
|
|
30784
|
-
if (
|
|
31175
|
+
const mapPath = join40(repoRoot, OA_DIR, "context", "project-map.md");
|
|
31176
|
+
if (existsSync30(mapPath)) {
|
|
30785
31177
|
try {
|
|
30786
|
-
const content =
|
|
31178
|
+
const content = readFileSync21(mapPath, "utf-8");
|
|
30787
31179
|
return content;
|
|
30788
31180
|
} catch {
|
|
30789
31181
|
}
|
|
@@ -30824,31 +31216,31 @@ ${log}`);
|
|
|
30824
31216
|
}
|
|
30825
31217
|
function loadMemoryContext(repoRoot) {
|
|
30826
31218
|
const sections = [];
|
|
30827
|
-
const oaMemDir =
|
|
31219
|
+
const oaMemDir = join40(repoRoot, OA_DIR, "memory");
|
|
30828
31220
|
const oaEntries = loadMemoryDir(oaMemDir, "project");
|
|
30829
31221
|
if (oaEntries)
|
|
30830
31222
|
sections.push(oaEntries);
|
|
30831
|
-
const legacyMemDir =
|
|
30832
|
-
if (legacyMemDir !== oaMemDir &&
|
|
31223
|
+
const legacyMemDir = join40(repoRoot, ".open-agents", "memory");
|
|
31224
|
+
if (legacyMemDir !== oaMemDir && existsSync30(legacyMemDir)) {
|
|
30833
31225
|
const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
|
|
30834
31226
|
if (legacyEntries)
|
|
30835
31227
|
sections.push(legacyEntries);
|
|
30836
31228
|
}
|
|
30837
|
-
const globalMemDir =
|
|
31229
|
+
const globalMemDir = join40(homedir11(), ".open-agents", "memory");
|
|
30838
31230
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
30839
31231
|
if (globalEntries)
|
|
30840
31232
|
sections.push(globalEntries);
|
|
30841
31233
|
return sections.join("\n\n");
|
|
30842
31234
|
}
|
|
30843
31235
|
function loadMemoryDir(memDir, scope) {
|
|
30844
|
-
if (!
|
|
31236
|
+
if (!existsSync30(memDir))
|
|
30845
31237
|
return "";
|
|
30846
31238
|
const lines = [];
|
|
30847
31239
|
try {
|
|
30848
31240
|
const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
|
|
30849
31241
|
for (const file of files.slice(0, 10)) {
|
|
30850
31242
|
try {
|
|
30851
|
-
const raw =
|
|
31243
|
+
const raw = readFileSync21(join40(memDir, file), "utf-8");
|
|
30852
31244
|
const entries = JSON.parse(raw);
|
|
30853
31245
|
const topic = basename10(file, ".json");
|
|
30854
31246
|
const keys = Object.keys(entries);
|
|
@@ -31875,22 +32267,22 @@ var init_carousel = __esm({
|
|
|
31875
32267
|
});
|
|
31876
32268
|
|
|
31877
32269
|
// packages/cli/dist/tui/carousel-descriptors.js
|
|
31878
|
-
import { existsSync as
|
|
31879
|
-
import { join as
|
|
32270
|
+
import { existsSync as existsSync31, readFileSync as readFileSync22, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11, readdirSync as readdirSync9 } from "node:fs";
|
|
32271
|
+
import { join as join41, basename as basename11 } from "node:path";
|
|
31880
32272
|
function loadToolProfile(repoRoot) {
|
|
31881
|
-
const filePath =
|
|
32273
|
+
const filePath = join41(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
31882
32274
|
try {
|
|
31883
|
-
if (!
|
|
32275
|
+
if (!existsSync31(filePath))
|
|
31884
32276
|
return null;
|
|
31885
|
-
return JSON.parse(
|
|
32277
|
+
return JSON.parse(readFileSync22(filePath, "utf-8"));
|
|
31886
32278
|
} catch {
|
|
31887
32279
|
return null;
|
|
31888
32280
|
}
|
|
31889
32281
|
}
|
|
31890
32282
|
function saveToolProfile(repoRoot, profile) {
|
|
31891
|
-
const contextDir =
|
|
31892
|
-
|
|
31893
|
-
|
|
32283
|
+
const contextDir = join41(repoRoot, OA_DIR, "context");
|
|
32284
|
+
mkdirSync11(contextDir, { recursive: true });
|
|
32285
|
+
writeFileSync11(join41(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
|
|
31894
32286
|
}
|
|
31895
32287
|
function categorizeToolCall(toolName) {
|
|
31896
32288
|
for (const cat of TOOL_CATEGORIES) {
|
|
@@ -31948,25 +32340,25 @@ function weightedColor(profile) {
|
|
|
31948
32340
|
return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
|
|
31949
32341
|
}
|
|
31950
32342
|
function loadCachedDescriptors(repoRoot) {
|
|
31951
|
-
const filePath =
|
|
32343
|
+
const filePath = join41(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
|
|
31952
32344
|
try {
|
|
31953
|
-
if (!
|
|
32345
|
+
if (!existsSync31(filePath))
|
|
31954
32346
|
return null;
|
|
31955
|
-
const cached = JSON.parse(
|
|
32347
|
+
const cached = JSON.parse(readFileSync22(filePath, "utf-8"));
|
|
31956
32348
|
return cached.phrases.length > 0 ? cached.phrases : null;
|
|
31957
32349
|
} catch {
|
|
31958
32350
|
return null;
|
|
31959
32351
|
}
|
|
31960
32352
|
}
|
|
31961
32353
|
function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
|
|
31962
|
-
const contextDir =
|
|
31963
|
-
|
|
32354
|
+
const contextDir = join41(repoRoot, OA_DIR, "context");
|
|
32355
|
+
mkdirSync11(contextDir, { recursive: true });
|
|
31964
32356
|
const cached = {
|
|
31965
32357
|
phrases,
|
|
31966
32358
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31967
32359
|
sourceHash
|
|
31968
32360
|
};
|
|
31969
|
-
|
|
32361
|
+
writeFileSync11(join41(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
|
|
31970
32362
|
}
|
|
31971
32363
|
function generateDescriptors(repoRoot) {
|
|
31972
32364
|
const profile = loadToolProfile(repoRoot);
|
|
@@ -32014,11 +32406,11 @@ function generateDescriptors(repoRoot) {
|
|
|
32014
32406
|
return phrases;
|
|
32015
32407
|
}
|
|
32016
32408
|
function extractFromPackageJson(repoRoot, tags) {
|
|
32017
|
-
const pkgPath =
|
|
32409
|
+
const pkgPath = join41(repoRoot, "package.json");
|
|
32018
32410
|
try {
|
|
32019
|
-
if (!
|
|
32411
|
+
if (!existsSync31(pkgPath))
|
|
32020
32412
|
return;
|
|
32021
|
-
const pkg = JSON.parse(
|
|
32413
|
+
const pkg = JSON.parse(readFileSync22(pkgPath, "utf-8"));
|
|
32022
32414
|
if (pkg.name && typeof pkg.name === "string") {
|
|
32023
32415
|
const parts = pkg.name.replace(/^@/, "").split("/");
|
|
32024
32416
|
for (const p of parts)
|
|
@@ -32062,7 +32454,7 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
32062
32454
|
{ file: ".github/workflows", tag: "ci/cd" }
|
|
32063
32455
|
];
|
|
32064
32456
|
for (const check of manifestChecks) {
|
|
32065
|
-
if (
|
|
32457
|
+
if (existsSync31(join41(repoRoot, check.file))) {
|
|
32066
32458
|
tags.push(check.tag);
|
|
32067
32459
|
}
|
|
32068
32460
|
}
|
|
@@ -32084,16 +32476,16 @@ function extractFromSessions(repoRoot, tags) {
|
|
|
32084
32476
|
}
|
|
32085
32477
|
}
|
|
32086
32478
|
function extractFromMemory(repoRoot, tags) {
|
|
32087
|
-
const memoryDir =
|
|
32479
|
+
const memoryDir = join41(repoRoot, OA_DIR, "memory");
|
|
32088
32480
|
try {
|
|
32089
|
-
if (!
|
|
32481
|
+
if (!existsSync31(memoryDir))
|
|
32090
32482
|
return;
|
|
32091
32483
|
const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
|
|
32092
32484
|
for (const file of files) {
|
|
32093
32485
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
32094
32486
|
tags.push(topic);
|
|
32095
32487
|
try {
|
|
32096
|
-
const data = JSON.parse(
|
|
32488
|
+
const data = JSON.parse(readFileSync22(join41(memoryDir, file), "utf-8"));
|
|
32097
32489
|
if (data && typeof data === "object") {
|
|
32098
32490
|
const keys = Object.keys(data).slice(0, 3);
|
|
32099
32491
|
for (const key of keys) {
|
|
@@ -32228,25 +32620,25 @@ var init_carousel_descriptors = __esm({
|
|
|
32228
32620
|
});
|
|
32229
32621
|
|
|
32230
32622
|
// packages/cli/dist/tui/voice.js
|
|
32231
|
-
import { existsSync as
|
|
32232
|
-
import { join as
|
|
32623
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12, readFileSync as readFileSync23, unlinkSync as unlinkSync4 } from "node:fs";
|
|
32624
|
+
import { join as join42 } from "node:path";
|
|
32233
32625
|
import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
|
|
32234
32626
|
import { execSync as execSync27, spawn as nodeSpawn } from "node:child_process";
|
|
32235
32627
|
import { createRequire } from "node:module";
|
|
32236
32628
|
function voiceDir() {
|
|
32237
|
-
return
|
|
32629
|
+
return join42(homedir12(), ".open-agents", "voice");
|
|
32238
32630
|
}
|
|
32239
32631
|
function modelsDir() {
|
|
32240
|
-
return
|
|
32632
|
+
return join42(voiceDir(), "models");
|
|
32241
32633
|
}
|
|
32242
32634
|
function modelDir(id) {
|
|
32243
|
-
return
|
|
32635
|
+
return join42(modelsDir(), id);
|
|
32244
32636
|
}
|
|
32245
32637
|
function modelOnnxPath(id) {
|
|
32246
|
-
return
|
|
32638
|
+
return join42(modelDir(id), "model.onnx");
|
|
32247
32639
|
}
|
|
32248
32640
|
function modelConfigPath(id) {
|
|
32249
|
-
return
|
|
32641
|
+
return join42(modelDir(id), "config.json");
|
|
32250
32642
|
}
|
|
32251
32643
|
function emotionToPitchBias(emotion) {
|
|
32252
32644
|
const raw = emotion.valence * 0.6 + (emotion.arousal - 0.5) * 0.4;
|
|
@@ -33066,7 +33458,7 @@ var init_voice = __esm({
|
|
|
33066
33458
|
}
|
|
33067
33459
|
this.onPCMOutput(Buffer.from(int16.buffer), sampleRate);
|
|
33068
33460
|
}
|
|
33069
|
-
const wavPath =
|
|
33461
|
+
const wavPath = join42(tmpdir6(), `oa-voice-${Date.now()}.wav`);
|
|
33070
33462
|
this.writeWav(audioData, sampleRate, wavPath);
|
|
33071
33463
|
await this.playWav(wavPath);
|
|
33072
33464
|
try {
|
|
@@ -33198,7 +33590,7 @@ var init_voice = __esm({
|
|
|
33198
33590
|
return buffer;
|
|
33199
33591
|
}
|
|
33200
33592
|
writeWav(samples, sampleRate, path) {
|
|
33201
|
-
|
|
33593
|
+
writeFileSync12(path, this.buildWavBuffer(samples, sampleRate));
|
|
33202
33594
|
}
|
|
33203
33595
|
// -------------------------------------------------------------------------
|
|
33204
33596
|
// Audio playback (system default speakers)
|
|
@@ -33357,7 +33749,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
33357
33749
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
33358
33750
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
33359
33751
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
33360
|
-
const wavPath =
|
|
33752
|
+
const wavPath = join42(tmpdir6(), `oa-mlx-${Date.now()}.wav`);
|
|
33361
33753
|
const pyScript = [
|
|
33362
33754
|
"import sys, json",
|
|
33363
33755
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -33374,11 +33766,11 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
33374
33766
|
return;
|
|
33375
33767
|
}
|
|
33376
33768
|
}
|
|
33377
|
-
if (!
|
|
33769
|
+
if (!existsSync32(wavPath))
|
|
33378
33770
|
return;
|
|
33379
33771
|
if (volume !== 1) {
|
|
33380
33772
|
try {
|
|
33381
|
-
const wavData =
|
|
33773
|
+
const wavData = readFileSync23(wavPath);
|
|
33382
33774
|
if (wavData.length > 44) {
|
|
33383
33775
|
const header = wavData.subarray(0, 44);
|
|
33384
33776
|
const samples = new Int16Array(wavData.buffer, wavData.byteOffset + 44, (wavData.length - 44) / 2);
|
|
@@ -33386,14 +33778,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
33386
33778
|
samples[i] = Math.round(samples[i] * volume);
|
|
33387
33779
|
}
|
|
33388
33780
|
const scaled = Buffer.concat([header, Buffer.from(samples.buffer, samples.byteOffset, samples.byteLength)]);
|
|
33389
|
-
|
|
33781
|
+
writeFileSync12(wavPath, scaled);
|
|
33390
33782
|
}
|
|
33391
33783
|
} catch {
|
|
33392
33784
|
}
|
|
33393
33785
|
}
|
|
33394
33786
|
if (this.onPCMOutput) {
|
|
33395
33787
|
try {
|
|
33396
|
-
const wavData =
|
|
33788
|
+
const wavData = readFileSync23(wavPath);
|
|
33397
33789
|
if (wavData.length > 44) {
|
|
33398
33790
|
const pcm = Buffer.from(wavData.buffer, wavData.byteOffset + 44, wavData.length - 44);
|
|
33399
33791
|
const sampleRate = wavData.readUInt32LE(24);
|
|
@@ -33425,7 +33817,7 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
33425
33817
|
const mlxModelId = model.mlxModelId ?? "mlx-community/Kokoro-82M-bf16";
|
|
33426
33818
|
const mlxVoice = model.mlxVoice ?? "af_heart";
|
|
33427
33819
|
const mlxLangCode = model.mlxLangCode ?? "a";
|
|
33428
|
-
const wavPath =
|
|
33820
|
+
const wavPath = join42(tmpdir6(), `oa-mlx-buf-${Date.now()}.wav`);
|
|
33429
33821
|
const pyScript = [
|
|
33430
33822
|
"import sys, json",
|
|
33431
33823
|
"from mlx_audio.tts import generate as tts_gen",
|
|
@@ -33442,10 +33834,10 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
33442
33834
|
return null;
|
|
33443
33835
|
}
|
|
33444
33836
|
}
|
|
33445
|
-
if (!
|
|
33837
|
+
if (!existsSync32(wavPath))
|
|
33446
33838
|
return null;
|
|
33447
33839
|
try {
|
|
33448
|
-
const data =
|
|
33840
|
+
const data = readFileSync23(wavPath);
|
|
33449
33841
|
unlinkSync4(wavPath);
|
|
33450
33842
|
return data;
|
|
33451
33843
|
} catch {
|
|
@@ -33459,41 +33851,41 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
|
33459
33851
|
if (this.ort)
|
|
33460
33852
|
return;
|
|
33461
33853
|
const arch = process.arch;
|
|
33462
|
-
|
|
33463
|
-
const pkgPath =
|
|
33854
|
+
mkdirSync12(voiceDir(), { recursive: true });
|
|
33855
|
+
const pkgPath = join42(voiceDir(), "package.json");
|
|
33464
33856
|
const expectedDeps = {
|
|
33465
33857
|
"onnxruntime-node": "^1.21.0",
|
|
33466
33858
|
"phonemizer": "^1.2.1"
|
|
33467
33859
|
};
|
|
33468
|
-
if (
|
|
33860
|
+
if (existsSync32(pkgPath)) {
|
|
33469
33861
|
try {
|
|
33470
|
-
const existing = JSON.parse(
|
|
33862
|
+
const existing = JSON.parse(readFileSync23(pkgPath, "utf8"));
|
|
33471
33863
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
33472
33864
|
existing.dependencies = { ...existing.dependencies, ...expectedDeps };
|
|
33473
|
-
|
|
33865
|
+
writeFileSync12(pkgPath, JSON.stringify(existing, null, 2));
|
|
33474
33866
|
}
|
|
33475
33867
|
} catch {
|
|
33476
33868
|
}
|
|
33477
33869
|
}
|
|
33478
|
-
if (!
|
|
33479
|
-
|
|
33870
|
+
if (!existsSync32(pkgPath)) {
|
|
33871
|
+
writeFileSync12(pkgPath, JSON.stringify({
|
|
33480
33872
|
name: "open-agents-voice",
|
|
33481
33873
|
private: true,
|
|
33482
33874
|
dependencies: expectedDeps
|
|
33483
33875
|
}, null, 2));
|
|
33484
33876
|
}
|
|
33485
|
-
const voiceRequire = createRequire(
|
|
33877
|
+
const voiceRequire = createRequire(join42(voiceDir(), "index.js"));
|
|
33486
33878
|
const probeOnnx = () => {
|
|
33487
33879
|
try {
|
|
33488
|
-
const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH:
|
|
33880
|
+
const result = execSync27(`node -e "try { require('onnxruntime-node'); console.log('OK'); } catch(e) { console.log('FAIL:' + e.message); }"`, { cwd: voiceDir(), stdio: "pipe", timeout: 15e3, env: { ...process.env, NODE_PATH: join42(voiceDir(), "node_modules") } });
|
|
33489
33881
|
const output = result.toString().trim();
|
|
33490
33882
|
return output === "OK";
|
|
33491
33883
|
} catch {
|
|
33492
33884
|
return false;
|
|
33493
33885
|
}
|
|
33494
33886
|
};
|
|
33495
|
-
const onnxNodeModules =
|
|
33496
|
-
const onnxInstalled =
|
|
33887
|
+
const onnxNodeModules = join42(voiceDir(), "node_modules", "onnxruntime-node");
|
|
33888
|
+
const onnxInstalled = existsSync32(onnxNodeModules);
|
|
33497
33889
|
if (onnxInstalled && !probeOnnx()) {
|
|
33498
33890
|
throw new Error(`Voice synthesis unavailable: ONNX runtime crashes on this CPU (${process.platform}-${arch}). This is a known issue with some ARM SoCs where the CPU vendor is not recognized. Voice feedback will be disabled but all other features work normally.`);
|
|
33499
33891
|
}
|
|
@@ -33551,18 +33943,18 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
33551
33943
|
const dir = modelDir(id);
|
|
33552
33944
|
const onnxPath = modelOnnxPath(id);
|
|
33553
33945
|
const configPath = modelConfigPath(id);
|
|
33554
|
-
if (
|
|
33946
|
+
if (existsSync32(onnxPath) && existsSync32(configPath))
|
|
33555
33947
|
return;
|
|
33556
|
-
|
|
33557
|
-
if (!
|
|
33948
|
+
mkdirSync12(dir, { recursive: true });
|
|
33949
|
+
if (!existsSync32(configPath)) {
|
|
33558
33950
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
33559
33951
|
const configResp = await fetch(model.configUrl);
|
|
33560
33952
|
if (!configResp.ok)
|
|
33561
33953
|
throw new Error(`Failed to download config: HTTP ${configResp.status}`);
|
|
33562
33954
|
const configText = await configResp.text();
|
|
33563
|
-
|
|
33955
|
+
writeFileSync12(configPath, configText);
|
|
33564
33956
|
}
|
|
33565
|
-
if (!
|
|
33957
|
+
if (!existsSync32(onnxPath)) {
|
|
33566
33958
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
33567
33959
|
const onnxResp = await fetch(model.onnxUrl);
|
|
33568
33960
|
if (!onnxResp.ok)
|
|
@@ -33587,7 +33979,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
33587
33979
|
}
|
|
33588
33980
|
}
|
|
33589
33981
|
const fullBuffer = Buffer.concat(chunks);
|
|
33590
|
-
|
|
33982
|
+
writeFileSync12(onnxPath, fullBuffer);
|
|
33591
33983
|
renderInfo(`${model.label} model downloaded (${formatBytes2(fullBuffer.length)}).`);
|
|
33592
33984
|
}
|
|
33593
33985
|
}
|
|
@@ -33599,10 +33991,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
33599
33991
|
throw new Error("ONNX runtime not loaded");
|
|
33600
33992
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
33601
33993
|
const configPath = modelConfigPath(this.modelId);
|
|
33602
|
-
if (!
|
|
33994
|
+
if (!existsSync32(onnxPath) || !existsSync32(configPath)) {
|
|
33603
33995
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
33604
33996
|
}
|
|
33605
|
-
this.config = JSON.parse(
|
|
33997
|
+
this.config = JSON.parse(readFileSync23(configPath, "utf8"));
|
|
33606
33998
|
this.session = await this.ort.InferenceSession.create(onnxPath, {
|
|
33607
33999
|
executionProviders: ["cpu"],
|
|
33608
34000
|
graphOptimizationLevel: "all"
|
|
@@ -34463,13 +34855,13 @@ var init_stream_renderer = __esm({
|
|
|
34463
34855
|
});
|
|
34464
34856
|
|
|
34465
34857
|
// packages/cli/dist/tui/edit-history.js
|
|
34466
|
-
import { appendFileSync as appendFileSync2, mkdirSync as
|
|
34467
|
-
import { join as
|
|
34858
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync13 } from "node:fs";
|
|
34859
|
+
import { join as join43 } from "node:path";
|
|
34468
34860
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
34469
|
-
const historyDir =
|
|
34470
|
-
const logPath =
|
|
34861
|
+
const historyDir = join43(repoRoot, ".oa", "history");
|
|
34862
|
+
const logPath = join43(historyDir, "edits.jsonl");
|
|
34471
34863
|
try {
|
|
34472
|
-
|
|
34864
|
+
mkdirSync13(historyDir, { recursive: true });
|
|
34473
34865
|
} catch {
|
|
34474
34866
|
}
|
|
34475
34867
|
function logToolCall(toolName, toolArgs, success) {
|
|
@@ -34578,46 +34970,46 @@ var init_edit_history = __esm({
|
|
|
34578
34970
|
});
|
|
34579
34971
|
|
|
34580
34972
|
// packages/cli/dist/tui/promptLoader.js
|
|
34581
|
-
import { readFileSync as
|
|
34582
|
-
import { join as
|
|
34973
|
+
import { readFileSync as readFileSync24, existsSync as existsSync33 } from "node:fs";
|
|
34974
|
+
import { join as join44, dirname as dirname16 } from "node:path";
|
|
34583
34975
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
34584
34976
|
function loadPrompt3(promptPath, vars) {
|
|
34585
34977
|
let content = cache3.get(promptPath);
|
|
34586
34978
|
if (content === void 0) {
|
|
34587
|
-
const fullPath =
|
|
34588
|
-
if (!
|
|
34979
|
+
const fullPath = join44(PROMPTS_DIR3, promptPath);
|
|
34980
|
+
if (!existsSync33(fullPath)) {
|
|
34589
34981
|
throw new Error(`Prompt file not found: ${fullPath}`);
|
|
34590
34982
|
}
|
|
34591
|
-
content =
|
|
34983
|
+
content = readFileSync24(fullPath, "utf-8");
|
|
34592
34984
|
cache3.set(promptPath, content);
|
|
34593
34985
|
}
|
|
34594
34986
|
if (!vars)
|
|
34595
34987
|
return content;
|
|
34596
34988
|
return content.replace(/\{\{(\w+)\}\}/g, (_, key) => vars[key] ?? `{{${key}}}`);
|
|
34597
34989
|
}
|
|
34598
|
-
var __filename3,
|
|
34990
|
+
var __filename3, __dirname6, devPath2, publishedPath2, PROMPTS_DIR3, cache3;
|
|
34599
34991
|
var init_promptLoader3 = __esm({
|
|
34600
34992
|
"packages/cli/dist/tui/promptLoader.js"() {
|
|
34601
34993
|
"use strict";
|
|
34602
34994
|
__filename3 = fileURLToPath11(import.meta.url);
|
|
34603
|
-
|
|
34604
|
-
devPath2 =
|
|
34605
|
-
publishedPath2 =
|
|
34606
|
-
PROMPTS_DIR3 =
|
|
34995
|
+
__dirname6 = dirname16(__filename3);
|
|
34996
|
+
devPath2 = join44(__dirname6, "..", "..", "prompts");
|
|
34997
|
+
publishedPath2 = join44(__dirname6, "..", "prompts");
|
|
34998
|
+
PROMPTS_DIR3 = existsSync33(devPath2) ? devPath2 : publishedPath2;
|
|
34607
34999
|
cache3 = /* @__PURE__ */ new Map();
|
|
34608
35000
|
}
|
|
34609
35001
|
});
|
|
34610
35002
|
|
|
34611
35003
|
// packages/cli/dist/tui/dream-engine.js
|
|
34612
|
-
import { mkdirSync as
|
|
34613
|
-
import { join as
|
|
35004
|
+
import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync13, readFileSync as readFileSync25, existsSync as existsSync34, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
|
|
35005
|
+
import { join as join45, basename as basename12 } from "node:path";
|
|
34614
35006
|
import { execSync as execSync28 } from "node:child_process";
|
|
34615
35007
|
function loadAutoresearchMemory(repoRoot) {
|
|
34616
|
-
const memoryPath =
|
|
34617
|
-
if (!
|
|
35008
|
+
const memoryPath = join45(repoRoot, ".oa", "memory", "autoresearch.json");
|
|
35009
|
+
if (!existsSync34(memoryPath))
|
|
34618
35010
|
return "";
|
|
34619
35011
|
try {
|
|
34620
|
-
const raw =
|
|
35012
|
+
const raw = readFileSync25(memoryPath, "utf-8");
|
|
34621
35013
|
const data = JSON.parse(raw);
|
|
34622
35014
|
const sections = [];
|
|
34623
35015
|
for (const key of AUTORESEARCH_MEMORY_KEYS) {
|
|
@@ -34807,14 +35199,14 @@ var init_dream_engine = __esm({
|
|
|
34807
35199
|
const content = String(args["content"] ?? "");
|
|
34808
35200
|
if (!rawPath)
|
|
34809
35201
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
34810
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
35202
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join45(this.autoresearchDir, basename12(rawPath)) : join45(this.autoresearchDir, rawPath);
|
|
34811
35203
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
34812
35204
|
return { success: false, output: "", error: "Autoresearch mode: writes are confined to .oa/autoresearch/", durationMs: Date.now() - start };
|
|
34813
35205
|
}
|
|
34814
35206
|
try {
|
|
34815
|
-
const dir =
|
|
34816
|
-
|
|
34817
|
-
|
|
35207
|
+
const dir = join45(targetPath, "..");
|
|
35208
|
+
mkdirSync14(dir, { recursive: true });
|
|
35209
|
+
writeFileSync13(targetPath, content, "utf-8");
|
|
34818
35210
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
34819
35211
|
} catch (err) {
|
|
34820
35212
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -34842,20 +35234,20 @@ var init_dream_engine = __esm({
|
|
|
34842
35234
|
const rawPath = String(args["path"] ?? "");
|
|
34843
35235
|
const oldStr = String(args["old_string"] ?? "");
|
|
34844
35236
|
const newStr = String(args["new_string"] ?? "");
|
|
34845
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ?
|
|
35237
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/autoresearch") ? join45(this.autoresearchDir, basename12(rawPath)) : join45(this.autoresearchDir, rawPath);
|
|
34846
35238
|
if (!targetPath.startsWith(this.autoresearchDir)) {
|
|
34847
35239
|
return { success: false, output: "", error: "Autoresearch mode: edits are confined to .oa/autoresearch/", durationMs: Date.now() - start };
|
|
34848
35240
|
}
|
|
34849
35241
|
try {
|
|
34850
|
-
if (!
|
|
35242
|
+
if (!existsSync34(targetPath)) {
|
|
34851
35243
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
34852
35244
|
}
|
|
34853
|
-
let content =
|
|
35245
|
+
let content = readFileSync25(targetPath, "utf-8");
|
|
34854
35246
|
if (!content.includes(oldStr)) {
|
|
34855
35247
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
34856
35248
|
}
|
|
34857
35249
|
content = content.replace(oldStr, newStr);
|
|
34858
|
-
|
|
35250
|
+
writeFileSync13(targetPath, content, "utf-8");
|
|
34859
35251
|
return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
|
|
34860
35252
|
} catch (err) {
|
|
34861
35253
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -34896,14 +35288,14 @@ var init_dream_engine = __esm({
|
|
|
34896
35288
|
const content = String(args["content"] ?? "");
|
|
34897
35289
|
if (!rawPath)
|
|
34898
35290
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
34899
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
35291
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join45(this.dreamsDir, basename12(rawPath)) : join45(this.dreamsDir, rawPath);
|
|
34900
35292
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
34901
35293
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
34902
35294
|
}
|
|
34903
35295
|
try {
|
|
34904
|
-
const dir =
|
|
34905
|
-
|
|
34906
|
-
|
|
35296
|
+
const dir = join45(targetPath, "..");
|
|
35297
|
+
mkdirSync14(dir, { recursive: true });
|
|
35298
|
+
writeFileSync13(targetPath, content, "utf-8");
|
|
34907
35299
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
34908
35300
|
} catch (err) {
|
|
34909
35301
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -34931,20 +35323,20 @@ var init_dream_engine = __esm({
|
|
|
34931
35323
|
const rawPath = String(args["path"] ?? "");
|
|
34932
35324
|
const oldStr = String(args["old_string"] ?? "");
|
|
34933
35325
|
const newStr = String(args["new_string"] ?? "");
|
|
34934
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
35326
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join45(this.dreamsDir, basename12(rawPath)) : join45(this.dreamsDir, rawPath);
|
|
34935
35327
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
34936
35328
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
34937
35329
|
}
|
|
34938
35330
|
try {
|
|
34939
|
-
if (!
|
|
35331
|
+
if (!existsSync34(targetPath)) {
|
|
34940
35332
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
34941
35333
|
}
|
|
34942
|
-
let content =
|
|
35334
|
+
let content = readFileSync25(targetPath, "utf-8");
|
|
34943
35335
|
if (!content.includes(oldStr)) {
|
|
34944
35336
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
34945
35337
|
}
|
|
34946
35338
|
content = content.replace(oldStr, newStr);
|
|
34947
|
-
|
|
35339
|
+
writeFileSync13(targetPath, content, "utf-8");
|
|
34948
35340
|
return { success: true, output: `Edited ${rawPath}`, durationMs: Date.now() - start };
|
|
34949
35341
|
} catch (err) {
|
|
34950
35342
|
return { success: false, output: "", error: String(err), durationMs: Date.now() - start };
|
|
@@ -34998,7 +35390,7 @@ var init_dream_engine = __esm({
|
|
|
34998
35390
|
constructor(config, repoRoot) {
|
|
34999
35391
|
this.config = config;
|
|
35000
35392
|
this.repoRoot = repoRoot;
|
|
35001
|
-
this.dreamsDir =
|
|
35393
|
+
this.dreamsDir = join45(repoRoot, ".oa", "dreams");
|
|
35002
35394
|
this.state = {
|
|
35003
35395
|
mode: "default",
|
|
35004
35396
|
active: false,
|
|
@@ -35029,7 +35421,7 @@ var init_dream_engine = __esm({
|
|
|
35029
35421
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
35030
35422
|
results: []
|
|
35031
35423
|
};
|
|
35032
|
-
|
|
35424
|
+
mkdirSync14(this.dreamsDir, { recursive: true });
|
|
35033
35425
|
this.saveDreamState();
|
|
35034
35426
|
try {
|
|
35035
35427
|
for (let cycle = 1; cycle <= totalCycles; cycle++) {
|
|
@@ -35082,8 +35474,8 @@ ${result.summary}`;
|
|
|
35082
35474
|
if (mode !== "default" || cycle === totalCycles) {
|
|
35083
35475
|
renderDreamContraction(cycle);
|
|
35084
35476
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
35085
|
-
const summaryPath =
|
|
35086
|
-
|
|
35477
|
+
const summaryPath = join45(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
35478
|
+
writeFileSync13(summaryPath, cycleSummary, "utf-8");
|
|
35087
35479
|
}
|
|
35088
35480
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
35089
35481
|
this.saveVersionCheckpoint(cycle);
|
|
@@ -35295,7 +35687,7 @@ After synthesis, call task_complete with the final prioritized summary.`, toolMo
|
|
|
35295
35687
|
}
|
|
35296
35688
|
/** Build role-specific tool sets for swarm agents */
|
|
35297
35689
|
buildSwarmTools(role, _workspace) {
|
|
35298
|
-
const autoresearchDir =
|
|
35690
|
+
const autoresearchDir = join45(this.repoRoot, ".oa", "autoresearch");
|
|
35299
35691
|
const taskComplete = this.createSwarmTaskCompleteTool(role);
|
|
35300
35692
|
switch (role) {
|
|
35301
35693
|
case "researcher": {
|
|
@@ -35659,7 +36051,7 @@ INSTRUCTIONS:
|
|
|
35659
36051
|
2. Summarize the key learnings and next steps
|
|
35660
36052
|
|
|
35661
36053
|
Call task_complete with a human-readable summary of the autoresearch session.`, workspace, onEvent);
|
|
35662
|
-
const reportPath =
|
|
36054
|
+
const reportPath = join45(this.dreamsDir, `cycle-${cycleNum}-autoresearch-report.md`);
|
|
35663
36055
|
const report = `# Autoresearch Swarm Report \u2014 Cycle ${cycleNum}
|
|
35664
36056
|
|
|
35665
36057
|
**Date**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -35681,8 +36073,8 @@ ${summaryResult}
|
|
|
35681
36073
|
*Generated by open-agents autoresearch swarm*
|
|
35682
36074
|
`;
|
|
35683
36075
|
try {
|
|
35684
|
-
|
|
35685
|
-
|
|
36076
|
+
mkdirSync14(this.dreamsDir, { recursive: true });
|
|
36077
|
+
writeFileSync13(reportPath, report, "utf-8");
|
|
35686
36078
|
} catch {
|
|
35687
36079
|
}
|
|
35688
36080
|
renderSwarmComplete(workspace);
|
|
@@ -35748,9 +36140,9 @@ ${summaryResult}
|
|
|
35748
36140
|
}
|
|
35749
36141
|
/** Save workspace backup for lucid mode */
|
|
35750
36142
|
saveVersionCheckpoint(cycle) {
|
|
35751
|
-
const checkpointDir =
|
|
36143
|
+
const checkpointDir = join45(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
35752
36144
|
try {
|
|
35753
|
-
|
|
36145
|
+
mkdirSync14(checkpointDir, { recursive: true });
|
|
35754
36146
|
try {
|
|
35755
36147
|
const gitStatus = execSync28("git status --porcelain", {
|
|
35756
36148
|
cwd: this.repoRoot,
|
|
@@ -35767,10 +36159,10 @@ ${summaryResult}
|
|
|
35767
36159
|
encoding: "utf-8",
|
|
35768
36160
|
timeout: 5e3
|
|
35769
36161
|
}).trim();
|
|
35770
|
-
|
|
35771
|
-
|
|
35772
|
-
|
|
35773
|
-
|
|
36162
|
+
writeFileSync13(join45(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
|
|
36163
|
+
writeFileSync13(join45(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
|
|
36164
|
+
writeFileSync13(join45(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
|
|
36165
|
+
writeFileSync13(join45(checkpointDir, "checkpoint.json"), JSON.stringify({
|
|
35774
36166
|
cycle,
|
|
35775
36167
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
35776
36168
|
gitHash,
|
|
@@ -35778,7 +36170,7 @@ ${summaryResult}
|
|
|
35778
36170
|
}, null, 2), "utf-8");
|
|
35779
36171
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
35780
36172
|
} catch {
|
|
35781
|
-
|
|
36173
|
+
writeFileSync13(join45(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
|
|
35782
36174
|
renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
|
|
35783
36175
|
}
|
|
35784
36176
|
} catch (err) {
|
|
@@ -35836,14 +36228,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
|
|
|
35836
36228
|
---
|
|
35837
36229
|
*Auto-generated by open-agents dream engine*
|
|
35838
36230
|
`;
|
|
35839
|
-
|
|
36231
|
+
writeFileSync13(join45(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
35840
36232
|
} catch {
|
|
35841
36233
|
}
|
|
35842
36234
|
}
|
|
35843
36235
|
/** Save dream state for resume/inspection */
|
|
35844
36236
|
saveDreamState() {
|
|
35845
36237
|
try {
|
|
35846
|
-
|
|
36238
|
+
writeFileSync13(join45(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
35847
36239
|
} catch {
|
|
35848
36240
|
}
|
|
35849
36241
|
}
|
|
@@ -36217,8 +36609,8 @@ var init_bless_engine = __esm({
|
|
|
36217
36609
|
});
|
|
36218
36610
|
|
|
36219
36611
|
// packages/cli/dist/tui/dmn-engine.js
|
|
36220
|
-
import { existsSync as
|
|
36221
|
-
import { join as
|
|
36612
|
+
import { existsSync as existsSync35, readFileSync as readFileSync26, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15, readdirSync as readdirSync11, unlinkSync as unlinkSync5 } from "node:fs";
|
|
36613
|
+
import { join as join46, basename as basename13 } from "node:path";
|
|
36222
36614
|
function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer) {
|
|
36223
36615
|
const competenceReport = competence.length > 0 ? competence.map((c3) => {
|
|
36224
36616
|
const rate = c3.attempts > 0 ? Math.round(c3.successes / c3.attempts * 100) : 0;
|
|
@@ -36331,9 +36723,9 @@ var init_dmn_engine = __esm({
|
|
|
36331
36723
|
constructor(config, repoRoot) {
|
|
36332
36724
|
this.config = config;
|
|
36333
36725
|
this.repoRoot = repoRoot;
|
|
36334
|
-
this.stateDir =
|
|
36335
|
-
this.historyDir =
|
|
36336
|
-
|
|
36726
|
+
this.stateDir = join46(repoRoot, ".oa", "dmn");
|
|
36727
|
+
this.historyDir = join46(repoRoot, ".oa", "dmn", "cycles");
|
|
36728
|
+
mkdirSync15(this.historyDir, { recursive: true });
|
|
36337
36729
|
this.loadState();
|
|
36338
36730
|
}
|
|
36339
36731
|
get stats() {
|
|
@@ -36922,11 +37314,11 @@ OUTPUT: Call task_complete with JSON:
|
|
|
36922
37314
|
async gatherMemoryTopics() {
|
|
36923
37315
|
const topics = [];
|
|
36924
37316
|
const dirs = [
|
|
36925
|
-
|
|
36926
|
-
|
|
37317
|
+
join46(this.repoRoot, ".oa", "memory"),
|
|
37318
|
+
join46(this.repoRoot, ".open-agents", "memory")
|
|
36927
37319
|
];
|
|
36928
37320
|
for (const dir of dirs) {
|
|
36929
|
-
if (!
|
|
37321
|
+
if (!existsSync35(dir))
|
|
36930
37322
|
continue;
|
|
36931
37323
|
try {
|
|
36932
37324
|
const files = readdirSync11(dir).filter((f) => f.endsWith(".json"));
|
|
@@ -36942,29 +37334,29 @@ OUTPUT: Call task_complete with JSON:
|
|
|
36942
37334
|
}
|
|
36943
37335
|
// ── State persistence ─────────────────────────────────────────────────
|
|
36944
37336
|
loadState() {
|
|
36945
|
-
const path =
|
|
36946
|
-
if (
|
|
37337
|
+
const path = join46(this.stateDir, "state.json");
|
|
37338
|
+
if (existsSync35(path)) {
|
|
36947
37339
|
try {
|
|
36948
|
-
this.state = JSON.parse(
|
|
37340
|
+
this.state = JSON.parse(readFileSync26(path, "utf-8"));
|
|
36949
37341
|
} catch {
|
|
36950
37342
|
}
|
|
36951
37343
|
}
|
|
36952
37344
|
}
|
|
36953
37345
|
saveState() {
|
|
36954
37346
|
try {
|
|
36955
|
-
|
|
37347
|
+
writeFileSync14(join46(this.stateDir, "state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
36956
37348
|
} catch {
|
|
36957
37349
|
}
|
|
36958
37350
|
}
|
|
36959
37351
|
saveCycleResult(result) {
|
|
36960
37352
|
try {
|
|
36961
37353
|
const filename = `cycle-${result.cycleNumber}-${Date.now()}.json`;
|
|
36962
|
-
|
|
37354
|
+
writeFileSync14(join46(this.historyDir, filename), JSON.stringify(result, null, 2) + "\n", "utf-8");
|
|
36963
37355
|
const files = readdirSync11(this.historyDir).filter((f) => f.startsWith("cycle-") && f.endsWith(".json")).sort();
|
|
36964
37356
|
if (files.length > 50) {
|
|
36965
37357
|
for (const old of files.slice(0, files.length - 50)) {
|
|
36966
37358
|
try {
|
|
36967
|
-
unlinkSync5(
|
|
37359
|
+
unlinkSync5(join46(this.historyDir, old));
|
|
36968
37360
|
} catch {
|
|
36969
37361
|
}
|
|
36970
37362
|
}
|
|
@@ -36977,8 +37369,8 @@ OUTPUT: Call task_complete with JSON:
|
|
|
36977
37369
|
});
|
|
36978
37370
|
|
|
36979
37371
|
// packages/cli/dist/tui/snr-engine.js
|
|
36980
|
-
import { existsSync as
|
|
36981
|
-
import { join as
|
|
37372
|
+
import { existsSync as existsSync36, readdirSync as readdirSync12, readFileSync as readFileSync27 } from "node:fs";
|
|
37373
|
+
import { join as join47, basename as basename14 } from "node:path";
|
|
36982
37374
|
function computeDPrime(signalScores, noiseScores) {
|
|
36983
37375
|
if (signalScores.length === 0 || noiseScores.length === 0)
|
|
36984
37376
|
return 0;
|
|
@@ -37218,11 +37610,11 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
37218
37610
|
loadMemoryEntries(topics) {
|
|
37219
37611
|
const entries = [];
|
|
37220
37612
|
const dirs = [
|
|
37221
|
-
|
|
37222
|
-
|
|
37613
|
+
join47(this.repoRoot, ".oa", "memory"),
|
|
37614
|
+
join47(this.repoRoot, ".open-agents", "memory")
|
|
37223
37615
|
];
|
|
37224
37616
|
for (const dir of dirs) {
|
|
37225
|
-
if (!
|
|
37617
|
+
if (!existsSync36(dir))
|
|
37226
37618
|
continue;
|
|
37227
37619
|
try {
|
|
37228
37620
|
const files = readdirSync12(dir).filter((f) => f.endsWith(".json"));
|
|
@@ -37231,7 +37623,7 @@ Call task_complete with the JSON array when done.`, onEvent)
|
|
|
37231
37623
|
if (topics.length > 0 && !topics.includes(topic))
|
|
37232
37624
|
continue;
|
|
37233
37625
|
try {
|
|
37234
|
-
const data = JSON.parse(
|
|
37626
|
+
const data = JSON.parse(readFileSync27(join47(dir, f), "utf-8"));
|
|
37235
37627
|
for (const [key, val] of Object.entries(data)) {
|
|
37236
37628
|
const value = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
37237
37629
|
entries.push({ topic, key, value });
|
|
@@ -37782,8 +38174,8 @@ var init_tool_policy = __esm({
|
|
|
37782
38174
|
});
|
|
37783
38175
|
|
|
37784
38176
|
// packages/cli/dist/tui/telegram-bridge.js
|
|
37785
|
-
import { mkdirSync as
|
|
37786
|
-
import { join as
|
|
38177
|
+
import { mkdirSync as mkdirSync16, existsSync as existsSync37, unlinkSync as unlinkSync6, readdirSync as readdirSync13, statSync as statSync10 } from "node:fs";
|
|
38178
|
+
import { join as join48, resolve as resolve27 } from "node:path";
|
|
37787
38179
|
import { writeFile as writeFileAsync } from "node:fs/promises";
|
|
37788
38180
|
function convertMarkdownToTelegramHTML(md) {
|
|
37789
38181
|
let html = md;
|
|
@@ -38111,7 +38503,7 @@ with summary "no_reply" to silently skip without responding.
|
|
|
38111
38503
|
this.polling = true;
|
|
38112
38504
|
this.abortController = new AbortController();
|
|
38113
38505
|
try {
|
|
38114
|
-
|
|
38506
|
+
mkdirSync16(this.mediaCacheDir, { recursive: true });
|
|
38115
38507
|
} catch {
|
|
38116
38508
|
}
|
|
38117
38509
|
this.mediaCacheCleanupTimer = setInterval(() => this.cleanupMediaCache(), 5 * 60 * 1e3);
|
|
@@ -38548,7 +38940,7 @@ Telegram admin: @${msg.username}` : `Telegram ${isGroup ? "group" : "public"} ch
|
|
|
38548
38940
|
return null;
|
|
38549
38941
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
38550
38942
|
const fileName = `${Date.now()}-${fileId.slice(0, 8)}${extension}`;
|
|
38551
|
-
const localPath =
|
|
38943
|
+
const localPath = join48(this.mediaCacheDir, fileName);
|
|
38552
38944
|
await writeFileAsync(localPath, buffer);
|
|
38553
38945
|
return localPath;
|
|
38554
38946
|
} catch {
|
|
@@ -40285,11 +40677,11 @@ var init_status_bar = __esm({
|
|
|
40285
40677
|
import * as readline2 from "node:readline";
|
|
40286
40678
|
import { Writable } from "node:stream";
|
|
40287
40679
|
import { cwd } from "node:process";
|
|
40288
|
-
import { resolve as resolve28, join as
|
|
40680
|
+
import { resolve as resolve28, join as join49, dirname as dirname17, extname as extname9 } from "node:path";
|
|
40289
40681
|
import { createRequire as createRequire2 } from "node:module";
|
|
40290
40682
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
40291
|
-
import { readFileSync as
|
|
40292
|
-
import { existsSync as
|
|
40683
|
+
import { readFileSync as readFileSync28, writeFileSync as writeFileSync15, appendFileSync as appendFileSync3, rmSync as rmSync2, readdirSync as readdirSync14, mkdirSync as mkdirSync17 } from "node:fs";
|
|
40684
|
+
import { existsSync as existsSync38 } from "node:fs";
|
|
40293
40685
|
import { homedir as homedir13 } from "node:os";
|
|
40294
40686
|
function formatTimeAgo(date) {
|
|
40295
40687
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
@@ -40307,14 +40699,14 @@ function formatTimeAgo(date) {
|
|
|
40307
40699
|
function getVersion3() {
|
|
40308
40700
|
try {
|
|
40309
40701
|
const require2 = createRequire2(import.meta.url);
|
|
40310
|
-
const thisDir =
|
|
40702
|
+
const thisDir = dirname17(fileURLToPath12(import.meta.url));
|
|
40311
40703
|
const candidates = [
|
|
40312
|
-
|
|
40313
|
-
|
|
40314
|
-
|
|
40704
|
+
join49(thisDir, "..", "package.json"),
|
|
40705
|
+
join49(thisDir, "..", "..", "package.json"),
|
|
40706
|
+
join49(thisDir, "..", "..", "..", "package.json")
|
|
40315
40707
|
];
|
|
40316
40708
|
for (const pkgPath of candidates) {
|
|
40317
|
-
if (
|
|
40709
|
+
if (existsSync38(pkgPath)) {
|
|
40318
40710
|
const pkg = require2(pkgPath);
|
|
40319
40711
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
40320
40712
|
return pkg.version ?? "0.0.0";
|
|
@@ -40520,15 +40912,15 @@ Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
|
|
|
40520
40912
|
function gatherMemorySnippets(root) {
|
|
40521
40913
|
const snippets = [];
|
|
40522
40914
|
const dirs = [
|
|
40523
|
-
|
|
40524
|
-
|
|
40915
|
+
join49(root, ".oa", "memory"),
|
|
40916
|
+
join49(root, ".open-agents", "memory")
|
|
40525
40917
|
];
|
|
40526
40918
|
for (const dir of dirs) {
|
|
40527
|
-
if (!
|
|
40919
|
+
if (!existsSync38(dir))
|
|
40528
40920
|
continue;
|
|
40529
40921
|
try {
|
|
40530
40922
|
for (const f of readdirSync14(dir).filter((f2) => f2.endsWith(".json"))) {
|
|
40531
|
-
const data = JSON.parse(
|
|
40923
|
+
const data = JSON.parse(readFileSync28(join49(dir, f), "utf-8"));
|
|
40532
40924
|
for (const val of Object.values(data)) {
|
|
40533
40925
|
const v = typeof val === "object" && val !== null && "value" in val ? String(val.value) : String(val);
|
|
40534
40926
|
if (v.length > 10)
|
|
@@ -40597,7 +40989,7 @@ function formatDMNToolArgs(toolName, args) {
|
|
|
40597
40989
|
return "";
|
|
40598
40990
|
}
|
|
40599
40991
|
}
|
|
40600
|
-
function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps, personality, deepContext, onCompaction, emotionEngine, flowEnabled) {
|
|
40992
|
+
function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps, personality, deepContext, onCompaction, emotionEngine, flowEnabled, slashCommandHandler) {
|
|
40601
40993
|
const voiceStyleMap = {
|
|
40602
40994
|
concise: 1,
|
|
40603
40995
|
balanced: 3,
|
|
@@ -40703,6 +41095,89 @@ ${entry.fullContent}`
|
|
|
40703
41095
|
};
|
|
40704
41096
|
}
|
|
40705
41097
|
});
|
|
41098
|
+
{
|
|
41099
|
+
const llmCall = async (messages) => {
|
|
41100
|
+
const resp = await backend.chatCompletion({
|
|
41101
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
41102
|
+
tools: [],
|
|
41103
|
+
temperature: 0,
|
|
41104
|
+
maxTokens: 8192,
|
|
41105
|
+
timeoutMs: 12e4
|
|
41106
|
+
});
|
|
41107
|
+
return resp.choices[0]?.message?.content ?? "";
|
|
41108
|
+
};
|
|
41109
|
+
runner.registerTool(new SkillBuildTool(repoRoot, llmCall));
|
|
41110
|
+
}
|
|
41111
|
+
if (slashCommandHandler) {
|
|
41112
|
+
runner.registerTool({
|
|
41113
|
+
name: "slash_command",
|
|
41114
|
+
description: "Invoke a slash command programmatically. Available when /commands auto is set by the user. Safe commands: help, config, models, skills, tools, stats, cost, score, nexus, commands, verbose, stream, brute-force, deep-context, flow, style, emojis, colors, task-type, compact, context, evaluate. Skill commands: /<skill-name> <args>. BLOCKED commands (user-only): quit, exit, destroy, model, endpoint, update, telegram, call, listen, expose, p2p, secrets, dream, bless, clear. Use this to check configuration, run evaluations, discover skills, or adjust modes during a task.",
|
|
41115
|
+
parameters: {
|
|
41116
|
+
type: "object",
|
|
41117
|
+
properties: {
|
|
41118
|
+
command: {
|
|
41119
|
+
type: "string",
|
|
41120
|
+
description: "The slash command to run (without leading /), e.g. 'stats', 'skills security', 'verbose', 'config'"
|
|
41121
|
+
}
|
|
41122
|
+
},
|
|
41123
|
+
required: ["command"]
|
|
41124
|
+
},
|
|
41125
|
+
async execute(args) {
|
|
41126
|
+
const cmd = String(args.command ?? "").trim();
|
|
41127
|
+
if (!cmd) {
|
|
41128
|
+
return { success: false, output: "", error: "Command string is required (e.g. 'stats', 'config', 'skills')" };
|
|
41129
|
+
}
|
|
41130
|
+
const blocked = /* @__PURE__ */ new Set([
|
|
41131
|
+
"quit",
|
|
41132
|
+
"exit",
|
|
41133
|
+
"q",
|
|
41134
|
+
"destroy",
|
|
41135
|
+
"clear",
|
|
41136
|
+
"cls",
|
|
41137
|
+
"model",
|
|
41138
|
+
"endpoint",
|
|
41139
|
+
"ep",
|
|
41140
|
+
"update",
|
|
41141
|
+
"upgrade",
|
|
41142
|
+
"telegram",
|
|
41143
|
+
"tg",
|
|
41144
|
+
"call",
|
|
41145
|
+
"hangup",
|
|
41146
|
+
"listen",
|
|
41147
|
+
"mic",
|
|
41148
|
+
"expose",
|
|
41149
|
+
"p2p",
|
|
41150
|
+
"secrets",
|
|
41151
|
+
"secret",
|
|
41152
|
+
"vault",
|
|
41153
|
+
"dream",
|
|
41154
|
+
"bless",
|
|
41155
|
+
"full-send-bless",
|
|
41156
|
+
"pause",
|
|
41157
|
+
"stop",
|
|
41158
|
+
"resume"
|
|
41159
|
+
]);
|
|
41160
|
+
const cmdName = cmd.split(/\s+/)[0].toLowerCase();
|
|
41161
|
+
if (blocked.has(cmdName)) {
|
|
41162
|
+
return {
|
|
41163
|
+
success: false,
|
|
41164
|
+
output: "",
|
|
41165
|
+
error: `Command "/${cmdName}" is user-only and cannot be invoked by the agent. Ask the user to run /${cmdName} directly.`
|
|
41166
|
+
};
|
|
41167
|
+
}
|
|
41168
|
+
try {
|
|
41169
|
+
const result = await slashCommandHandler("/" + cmd);
|
|
41170
|
+
return { success: true, output: result || `Command /${cmdName} executed.` };
|
|
41171
|
+
} catch (err) {
|
|
41172
|
+
return {
|
|
41173
|
+
success: false,
|
|
41174
|
+
output: "",
|
|
41175
|
+
error: `Slash command error: ${err instanceof Error ? err.message : String(err)}`
|
|
41176
|
+
};
|
|
41177
|
+
}
|
|
41178
|
+
}
|
|
41179
|
+
});
|
|
41180
|
+
}
|
|
40706
41181
|
const filesTouched = /* @__PURE__ */ new Set();
|
|
40707
41182
|
const toolSequence = [];
|
|
40708
41183
|
const editSessionId = `task-${Date.now()}`;
|
|
@@ -41013,6 +41488,7 @@ async function startInteractive(config, repoPath) {
|
|
|
41013
41488
|
let currentStyle = PRESET_NAMES.includes(savedSettings.style) ? savedSettings.style : "balanced";
|
|
41014
41489
|
let deepContextEnabled = savedSettings.deepContext ?? false;
|
|
41015
41490
|
let flowEnabled = savedSettings.flow === true;
|
|
41491
|
+
let commandsMode = savedSettings.commandsMode ?? "manual";
|
|
41016
41492
|
if (savedSettings.emojis !== void 0)
|
|
41017
41493
|
setEmojisEnabled(savedSettings.emojis);
|
|
41018
41494
|
if (savedSettings.colors !== void 0)
|
|
@@ -41192,7 +41668,7 @@ async function startInteractive(config, repoPath) {
|
|
|
41192
41668
|
let exposeGateway = null;
|
|
41193
41669
|
let peerMesh = null;
|
|
41194
41670
|
let inferenceRouter = null;
|
|
41195
|
-
const secretVault = new SecretVault(
|
|
41671
|
+
const secretVault = new SecretVault(join49(repoRoot, ".oa", "vault.enc"));
|
|
41196
41672
|
let adminSessionKey = null;
|
|
41197
41673
|
const callSubAgents = /* @__PURE__ */ new Map();
|
|
41198
41674
|
const streamRenderer = new StreamRenderer();
|
|
@@ -41397,13 +41873,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
41397
41873
|
const hits = allCompletions.filter((c3) => c3.toLowerCase().startsWith(lower));
|
|
41398
41874
|
return [hits, line];
|
|
41399
41875
|
}
|
|
41400
|
-
const HISTORY_DIR =
|
|
41401
|
-
const HISTORY_FILE =
|
|
41876
|
+
const HISTORY_DIR = join49(homedir13(), ".open-agents");
|
|
41877
|
+
const HISTORY_FILE = join49(HISTORY_DIR, "repl-history");
|
|
41402
41878
|
const MAX_HISTORY_LINES = 500;
|
|
41403
41879
|
let savedHistory = [];
|
|
41404
41880
|
try {
|
|
41405
|
-
if (
|
|
41406
|
-
const raw =
|
|
41881
|
+
if (existsSync38(HISTORY_FILE)) {
|
|
41882
|
+
const raw = readFileSync28(HISTORY_FILE, "utf8").trim();
|
|
41407
41883
|
if (raw)
|
|
41408
41884
|
savedHistory = raw.split("\n").reverse();
|
|
41409
41885
|
}
|
|
@@ -41422,12 +41898,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
41422
41898
|
if (!line.trim())
|
|
41423
41899
|
return;
|
|
41424
41900
|
try {
|
|
41425
|
-
|
|
41901
|
+
mkdirSync17(HISTORY_DIR, { recursive: true });
|
|
41426
41902
|
appendFileSync3(HISTORY_FILE, line + "\n", "utf8");
|
|
41427
41903
|
if (Math.random() < 0.02) {
|
|
41428
|
-
const all =
|
|
41904
|
+
const all = readFileSync28(HISTORY_FILE, "utf8").trim().split("\n");
|
|
41429
41905
|
if (all.length > MAX_HISTORY_LINES) {
|
|
41430
|
-
|
|
41906
|
+
writeFileSync15(HISTORY_FILE, all.slice(-MAX_HISTORY_LINES).join("\n") + "\n", "utf8");
|
|
41431
41907
|
}
|
|
41432
41908
|
}
|
|
41433
41909
|
} catch {
|
|
@@ -41594,6 +42070,12 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
41594
42070
|
flowEnabled = !flowEnabled;
|
|
41595
42071
|
return flowEnabled;
|
|
41596
42072
|
},
|
|
42073
|
+
getCommandsMode() {
|
|
42074
|
+
return commandsMode;
|
|
42075
|
+
},
|
|
42076
|
+
setCommandsMode(mode) {
|
|
42077
|
+
commandsMode = mode;
|
|
42078
|
+
},
|
|
41597
42079
|
setStyle(preset) {
|
|
41598
42080
|
currentStyle = preset;
|
|
41599
42081
|
},
|
|
@@ -42281,8 +42763,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
42281
42763
|
return true;
|
|
42282
42764
|
},
|
|
42283
42765
|
destroyProject() {
|
|
42284
|
-
const oaPath =
|
|
42285
|
-
if (
|
|
42766
|
+
const oaPath = join49(repoRoot, OA_DIR);
|
|
42767
|
+
if (existsSync38(oaPath)) {
|
|
42286
42768
|
try {
|
|
42287
42769
|
rmSync2(oaPath, { recursive: true, force: true });
|
|
42288
42770
|
writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
|
|
@@ -42444,6 +42926,36 @@ ${sessionCtx}` : "",
|
|
|
42444
42926
|
process.stdout.write(`\r\x1B[K${label}`);
|
|
42445
42927
|
pasteIndicatorShown = true;
|
|
42446
42928
|
}
|
|
42929
|
+
const buildSlashCommandHandler = () => {
|
|
42930
|
+
if (commandsMode !== "auto")
|
|
42931
|
+
return void 0;
|
|
42932
|
+
return async (command) => {
|
|
42933
|
+
const captured = [];
|
|
42934
|
+
const origWrite = process.stdout.write;
|
|
42935
|
+
process.stdout.write = ((chunk) => {
|
|
42936
|
+
if (typeof chunk === "string") {
|
|
42937
|
+
captured.push(chunk.replace(/\x1B\[[0-9;]*m/g, ""));
|
|
42938
|
+
}
|
|
42939
|
+
return true;
|
|
42940
|
+
});
|
|
42941
|
+
try {
|
|
42942
|
+
const result = await handleSlashCommand(command, commandCtx);
|
|
42943
|
+
process.stdout.write = origWrite;
|
|
42944
|
+
if (result === "exit") {
|
|
42945
|
+
return "Cannot exit via slash_command tool. Ask the user to run /quit directly.";
|
|
42946
|
+
}
|
|
42947
|
+
if (typeof result === "object" && result.type === "skill") {
|
|
42948
|
+
return `Skill "${result.name}" loaded. Content:
|
|
42949
|
+
${result.content.slice(0, 2e3)}${result.content.length > 2e3 ? "\n[truncated]" : ""}`;
|
|
42950
|
+
}
|
|
42951
|
+
const output = captured.join("").trim();
|
|
42952
|
+
return output || `Command executed: ${command}`;
|
|
42953
|
+
} catch (err) {
|
|
42954
|
+
process.stdout.write = origWrite;
|
|
42955
|
+
throw err;
|
|
42956
|
+
}
|
|
42957
|
+
};
|
|
42958
|
+
};
|
|
42447
42959
|
rl.on("line", (line) => {
|
|
42448
42960
|
persistHistoryLine(line);
|
|
42449
42961
|
const input = line.trim();
|
|
@@ -42568,7 +43080,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
42568
43080
|
}, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary, meta) => {
|
|
42569
43081
|
lastCompletedSummary = summary;
|
|
42570
43082
|
lastTaskMeta = meta ?? null;
|
|
42571
|
-
}, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled);
|
|
43083
|
+
}, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler());
|
|
42572
43084
|
activeTask = task;
|
|
42573
43085
|
showPrompt();
|
|
42574
43086
|
await task.promise;
|
|
@@ -42583,13 +43095,13 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
42583
43095
|
}
|
|
42584
43096
|
}
|
|
42585
43097
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
42586
|
-
const isImage = isImagePath(cleanPath) &&
|
|
42587
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
43098
|
+
const isImage = isImagePath(cleanPath) && existsSync38(resolve28(repoRoot, cleanPath));
|
|
43099
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync38(resolve28(repoRoot, cleanPath));
|
|
42588
43100
|
if (activeTask) {
|
|
42589
43101
|
if (isImage) {
|
|
42590
43102
|
try {
|
|
42591
43103
|
const imgPath = resolve28(repoRoot, cleanPath);
|
|
42592
|
-
const imgBuffer =
|
|
43104
|
+
const imgBuffer = readFileSync28(imgPath);
|
|
42593
43105
|
const base64 = imgBuffer.toString("base64");
|
|
42594
43106
|
const ext = extname9(cleanPath).toLowerCase();
|
|
42595
43107
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -42785,7 +43297,7 @@ NEW TASK: ${fullInput}`;
|
|
|
42785
43297
|
}, bruteForceEnabled, statusBar, handleSudoRequest, costTracker, (summary, meta) => {
|
|
42786
43298
|
lastCompletedSummary = summary;
|
|
42787
43299
|
lastTaskMeta = meta ?? null;
|
|
42788
|
-
}, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled);
|
|
43300
|
+
}, currentTaskType, resolvedContextWindowSize, resolvedCaps, currentStyle, deepContextEnabled, compactionSNRCallback(), emotionEngine, flowEnabled, buildSlashCommandHandler());
|
|
42789
43301
|
activeTask = task;
|
|
42790
43302
|
showPrompt();
|
|
42791
43303
|
await task.promise;
|
|
@@ -43103,7 +43615,7 @@ import { glob } from "glob";
|
|
|
43103
43615
|
import ignore from "ignore";
|
|
43104
43616
|
import { readFile as readFile16, stat as stat4 } from "node:fs/promises";
|
|
43105
43617
|
import { createHash as createHash4 } from "node:crypto";
|
|
43106
|
-
import { join as
|
|
43618
|
+
import { join as join50, relative as relative3, extname as extname10, basename as basename15 } from "node:path";
|
|
43107
43619
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
43108
43620
|
var init_codebase_indexer = __esm({
|
|
43109
43621
|
"packages/indexer/dist/codebase-indexer.js"() {
|
|
@@ -43147,7 +43659,7 @@ var init_codebase_indexer = __esm({
|
|
|
43147
43659
|
const ig = ignore.default();
|
|
43148
43660
|
if (this.config.respectGitignore) {
|
|
43149
43661
|
try {
|
|
43150
|
-
const gitignoreContent = await readFile16(
|
|
43662
|
+
const gitignoreContent = await readFile16(join50(this.config.rootDir, ".gitignore"), "utf-8");
|
|
43151
43663
|
ig.add(gitignoreContent);
|
|
43152
43664
|
} catch {
|
|
43153
43665
|
}
|
|
@@ -43162,7 +43674,7 @@ var init_codebase_indexer = __esm({
|
|
|
43162
43674
|
for (const relativePath of files) {
|
|
43163
43675
|
if (ig.ignores(relativePath))
|
|
43164
43676
|
continue;
|
|
43165
|
-
const fullPath =
|
|
43677
|
+
const fullPath = join50(this.config.rootDir, relativePath);
|
|
43166
43678
|
try {
|
|
43167
43679
|
const fileStat = await stat4(fullPath);
|
|
43168
43680
|
if (fileStat.size > this.config.maxFileSize)
|
|
@@ -43208,7 +43720,7 @@ var init_codebase_indexer = __esm({
|
|
|
43208
43720
|
if (!child) {
|
|
43209
43721
|
child = {
|
|
43210
43722
|
name: part,
|
|
43211
|
-
path:
|
|
43723
|
+
path: join50(current.path, part),
|
|
43212
43724
|
type: "directory",
|
|
43213
43725
|
children: []
|
|
43214
43726
|
};
|
|
@@ -43291,13 +43803,13 @@ __export(index_repo_exports, {
|
|
|
43291
43803
|
indexRepoCommand: () => indexRepoCommand
|
|
43292
43804
|
});
|
|
43293
43805
|
import { resolve as resolve29 } from "node:path";
|
|
43294
|
-
import { existsSync as
|
|
43806
|
+
import { existsSync as existsSync39, statSync as statSync11 } from "node:fs";
|
|
43295
43807
|
import { cwd as cwd2 } from "node:process";
|
|
43296
43808
|
async function indexRepoCommand(opts, _config) {
|
|
43297
43809
|
const repoRoot = resolve29(opts.repoPath ?? cwd2());
|
|
43298
43810
|
printHeader("Index Repository");
|
|
43299
43811
|
printInfo(`Indexing: ${repoRoot}`);
|
|
43300
|
-
if (!
|
|
43812
|
+
if (!existsSync39(repoRoot)) {
|
|
43301
43813
|
printError(`Path does not exist: ${repoRoot}`);
|
|
43302
43814
|
process.exit(1);
|
|
43303
43815
|
}
|
|
@@ -43549,7 +44061,7 @@ var config_exports = {};
|
|
|
43549
44061
|
__export(config_exports, {
|
|
43550
44062
|
configCommand: () => configCommand
|
|
43551
44063
|
});
|
|
43552
|
-
import { join as
|
|
44064
|
+
import { join as join51, resolve as resolve30 } from "node:path";
|
|
43553
44065
|
import { homedir as homedir14 } from "node:os";
|
|
43554
44066
|
import { cwd as cwd3 } from "node:process";
|
|
43555
44067
|
function redactIfSensitive(key, value) {
|
|
@@ -43608,7 +44120,7 @@ function handleShow(opts, config) {
|
|
|
43608
44120
|
}
|
|
43609
44121
|
}
|
|
43610
44122
|
printSection("Config File");
|
|
43611
|
-
printInfo(`~/.open-agents/config.json (${
|
|
44123
|
+
printInfo(`~/.open-agents/config.json (${join51(homedir14(), ".open-agents", "config.json")})`);
|
|
43612
44124
|
printSection("Priority Chain");
|
|
43613
44125
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
43614
44126
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -43647,7 +44159,7 @@ function handleSet(opts, _config) {
|
|
|
43647
44159
|
const coerced = coerceForSettings(key, value);
|
|
43648
44160
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
43649
44161
|
printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
|
|
43650
|
-
printInfo(`Saved to ${
|
|
44162
|
+
printInfo(`Saved to ${join51(repoRoot, ".oa", "settings.json")}`);
|
|
43651
44163
|
printInfo("This override applies only when running in this workspace.");
|
|
43652
44164
|
} catch (err) {
|
|
43653
44165
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -43866,8 +44378,8 @@ __export(eval_exports, {
|
|
|
43866
44378
|
evalCommand: () => evalCommand
|
|
43867
44379
|
});
|
|
43868
44380
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
43869
|
-
import { mkdirSync as
|
|
43870
|
-
import { join as
|
|
44381
|
+
import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "node:fs";
|
|
44382
|
+
import { join as join52 } from "node:path";
|
|
43871
44383
|
async function evalCommand(opts, config) {
|
|
43872
44384
|
const suiteName = opts.suite ?? "basic";
|
|
43873
44385
|
const suite = SUITES[suiteName];
|
|
@@ -43992,9 +44504,9 @@ async function evalCommand(opts, config) {
|
|
|
43992
44504
|
process.exit(failed > 0 ? 1 : 0);
|
|
43993
44505
|
}
|
|
43994
44506
|
function createTempEvalRepo() {
|
|
43995
|
-
const dir =
|
|
43996
|
-
|
|
43997
|
-
|
|
44507
|
+
const dir = join52(tmpdir7(), `open-agents-eval-${Date.now()}`);
|
|
44508
|
+
mkdirSync18(dir, { recursive: true });
|
|
44509
|
+
writeFileSync16(join52(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
43998
44510
|
return dir;
|
|
43999
44511
|
}
|
|
44000
44512
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -44054,7 +44566,7 @@ init_updater();
|
|
|
44054
44566
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
44055
44567
|
import { createRequire as createRequire3 } from "node:module";
|
|
44056
44568
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
44057
|
-
import { dirname as
|
|
44569
|
+
import { dirname as dirname18, join as join53 } from "node:path";
|
|
44058
44570
|
|
|
44059
44571
|
// packages/cli/dist/cli.js
|
|
44060
44572
|
import { createInterface } from "node:readline";
|
|
@@ -44161,7 +44673,7 @@ init_output();
|
|
|
44161
44673
|
function getVersion4() {
|
|
44162
44674
|
try {
|
|
44163
44675
|
const require2 = createRequire3(import.meta.url);
|
|
44164
|
-
const pkgPath =
|
|
44676
|
+
const pkgPath = join53(dirname18(fileURLToPath13(import.meta.url)), "..", "package.json");
|
|
44165
44677
|
const pkg = require2(pkgPath);
|
|
44166
44678
|
return pkg.version;
|
|
44167
44679
|
} catch {
|