open-agents-ai 0.12.16 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +487 -144
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4489,6 +4489,286 @@ var init_tool_creator = __esm({
|
|
|
4489
4489
|
}
|
|
4490
4490
|
});
|
|
4491
4491
|
|
|
4492
|
+
// packages/execution/dist/tools/skill-tools.js
|
|
4493
|
+
import { existsSync as existsSync9, readdirSync as readdirSync5, readFileSync as readFileSync8 } from "node:fs";
|
|
4494
|
+
import { join as join12, basename as basename2 } from "node:path";
|
|
4495
|
+
import { homedir as homedir4 } from "node:os";
|
|
4496
|
+
function discoverSkills(repoRoot) {
|
|
4497
|
+
const skills = /* @__PURE__ */ new Map();
|
|
4498
|
+
if (existsSync9(AIWG_FRAMEWORKS_DIR)) {
|
|
4499
|
+
for (const framework of safeReaddir(AIWG_FRAMEWORKS_DIR)) {
|
|
4500
|
+
const skillsDir = join12(AIWG_FRAMEWORKS_DIR, framework, "skills");
|
|
4501
|
+
loadSkillsFromDir(skillsDir, `framework:${framework}`, skills);
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
if (existsSync9(AIWG_ADDONS_DIR)) {
|
|
4505
|
+
for (const addon of safeReaddir(AIWG_ADDONS_DIR)) {
|
|
4506
|
+
const skillsDir = join12(AIWG_ADDONS_DIR, addon, "skills");
|
|
4507
|
+
loadSkillsFromDir(skillsDir, `addon:${addon}`, skills);
|
|
4508
|
+
}
|
|
4509
|
+
}
|
|
4510
|
+
if (existsSync9(AIWG_PLUGINS_DIR)) {
|
|
4511
|
+
for (const plugin of safeReaddir(AIWG_PLUGINS_DIR)) {
|
|
4512
|
+
const skillsDir = join12(AIWG_PLUGINS_DIR, plugin, "skills");
|
|
4513
|
+
loadSkillsFromDir(skillsDir, `plugin:${plugin}`, skills);
|
|
4514
|
+
}
|
|
4515
|
+
}
|
|
4516
|
+
const projectAiwgSkills = join12(repoRoot, ".aiwg", "skills");
|
|
4517
|
+
loadSkillsFromDir(projectAiwgSkills, "project", skills);
|
|
4518
|
+
const projectOaSkills = join12(repoRoot, ".oa", "skills");
|
|
4519
|
+
loadSkillsFromDir(projectOaSkills, "local", skills);
|
|
4520
|
+
return Array.from(skills.values());
|
|
4521
|
+
}
|
|
4522
|
+
function loadSkillContent(skillPath) {
|
|
4523
|
+
try {
|
|
4524
|
+
return readFileSync8(skillPath, "utf-8");
|
|
4525
|
+
} catch {
|
|
4526
|
+
return null;
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
function buildSkillsSummary(skills) {
|
|
4530
|
+
if (skills.length === 0)
|
|
4531
|
+
return "";
|
|
4532
|
+
const lines = [
|
|
4533
|
+
"## Available Skills",
|
|
4534
|
+
"",
|
|
4535
|
+
"You have access to skills via the `skill_list` and `skill_execute` tools.",
|
|
4536
|
+
"Skills provide detailed behavioral guidance for specific tasks.",
|
|
4537
|
+
""
|
|
4538
|
+
];
|
|
4539
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
4540
|
+
for (const s of skills) {
|
|
4541
|
+
const group = bySource.get(s.source) ?? [];
|
|
4542
|
+
group.push(s);
|
|
4543
|
+
bySource.set(s.source, group);
|
|
4544
|
+
}
|
|
4545
|
+
for (const [source, group] of bySource) {
|
|
4546
|
+
lines.push(`### ${source} (${group.length} skills)`);
|
|
4547
|
+
for (const s of group) {
|
|
4548
|
+
const triggers = s.triggers.length > 0 ? ` \u2014 triggers: ${s.triggers.slice(0, 3).join(", ")}` : "";
|
|
4549
|
+
lines.push(`- **${s.name}**: ${s.description}${triggers}`);
|
|
4550
|
+
}
|
|
4551
|
+
lines.push("");
|
|
4552
|
+
}
|
|
4553
|
+
lines.push("Use `skill_execute` with a skill name to load its full instructions when a task matches a trigger pattern.");
|
|
4554
|
+
return lines.join("\n");
|
|
4555
|
+
}
|
|
4556
|
+
function safeReaddir(dir) {
|
|
4557
|
+
try {
|
|
4558
|
+
return readdirSync5(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
4559
|
+
} catch {
|
|
4560
|
+
return [];
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
function loadSkillsFromDir(dir, source, out) {
|
|
4564
|
+
if (!existsSync9(dir))
|
|
4565
|
+
return;
|
|
4566
|
+
const manifest = loadManifest(dir);
|
|
4567
|
+
const entries = safeReaddir(dir);
|
|
4568
|
+
for (const entry of entries) {
|
|
4569
|
+
const skillMd = join12(dir, entry, "SKILL.md");
|
|
4570
|
+
if (!existsSync9(skillMd))
|
|
4571
|
+
continue;
|
|
4572
|
+
const manifestEntry = manifest.get(entry);
|
|
4573
|
+
const info = {
|
|
4574
|
+
name: entry,
|
|
4575
|
+
description: manifestEntry?.description ?? parseDescription(skillMd),
|
|
4576
|
+
triggers: manifestEntry?.triggers ?? parseTriggers(skillMd),
|
|
4577
|
+
source,
|
|
4578
|
+
filePath: skillMd
|
|
4579
|
+
};
|
|
4580
|
+
out.set(entry, info);
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
function loadManifest(dir) {
|
|
4584
|
+
const result = /* @__PURE__ */ new Map();
|
|
4585
|
+
const manifestPath = join12(dir, "manifest.json");
|
|
4586
|
+
if (!existsSync9(manifestPath))
|
|
4587
|
+
return result;
|
|
4588
|
+
try {
|
|
4589
|
+
const content = readFileSync8(manifestPath, "utf-8");
|
|
4590
|
+
const data = JSON.parse(content);
|
|
4591
|
+
if (Array.isArray(data.skills)) {
|
|
4592
|
+
for (const s of data.skills) {
|
|
4593
|
+
if (s.name) {
|
|
4594
|
+
result.set(s.name, s);
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
4597
|
+
}
|
|
4598
|
+
} catch {
|
|
4599
|
+
}
|
|
4600
|
+
return result;
|
|
4601
|
+
}
|
|
4602
|
+
function parseDescription(filePath) {
|
|
4603
|
+
try {
|
|
4604
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
4605
|
+
const lines = content.split("\n");
|
|
4606
|
+
let pastHeading = false;
|
|
4607
|
+
for (const line of lines) {
|
|
4608
|
+
if (line.startsWith("# ")) {
|
|
4609
|
+
pastHeading = true;
|
|
4610
|
+
continue;
|
|
4611
|
+
}
|
|
4612
|
+
if (pastHeading && line.trim()) {
|
|
4613
|
+
return line.trim().slice(0, 200);
|
|
4614
|
+
}
|
|
4615
|
+
}
|
|
4616
|
+
} catch {
|
|
4617
|
+
}
|
|
4618
|
+
return "";
|
|
4619
|
+
}
|
|
4620
|
+
function parseTriggers(filePath) {
|
|
4621
|
+
const triggers = [];
|
|
4622
|
+
try {
|
|
4623
|
+
const content = readFileSync8(filePath, "utf-8");
|
|
4624
|
+
const lines = content.split("\n");
|
|
4625
|
+
let inTriggers = false;
|
|
4626
|
+
for (const line of lines) {
|
|
4627
|
+
if (/^##\s+Triggers/i.test(line)) {
|
|
4628
|
+
inTriggers = true;
|
|
4629
|
+
continue;
|
|
4630
|
+
}
|
|
4631
|
+
if (inTriggers && line.startsWith("## ")) {
|
|
4632
|
+
break;
|
|
4633
|
+
}
|
|
4634
|
+
if (inTriggers && line.startsWith("- ")) {
|
|
4635
|
+
const trigger = line.slice(2).replace(/^["']|["']$/g, "").trim();
|
|
4636
|
+
if (trigger)
|
|
4637
|
+
triggers.push(trigger);
|
|
4638
|
+
}
|
|
4639
|
+
}
|
|
4640
|
+
} catch {
|
|
4641
|
+
}
|
|
4642
|
+
return triggers;
|
|
4643
|
+
}
|
|
4644
|
+
var AIWG_DATA_DIR, AIWG_FRAMEWORKS_DIR, AIWG_ADDONS_DIR, AIWG_PLUGINS_DIR, SkillListTool, SkillExecuteTool;
|
|
4645
|
+
var init_skill_tools = __esm({
|
|
4646
|
+
"packages/execution/dist/tools/skill-tools.js"() {
|
|
4647
|
+
"use strict";
|
|
4648
|
+
AIWG_DATA_DIR = join12(homedir4(), ".local", "share", "ai-writing-guide");
|
|
4649
|
+
AIWG_FRAMEWORKS_DIR = join12(AIWG_DATA_DIR, "agentic", "code", "frameworks");
|
|
4650
|
+
AIWG_ADDONS_DIR = join12(AIWG_DATA_DIR, "addons");
|
|
4651
|
+
AIWG_PLUGINS_DIR = join12(AIWG_DATA_DIR, "plugins");
|
|
4652
|
+
SkillListTool = class {
|
|
4653
|
+
name = "skill_list";
|
|
4654
|
+
description = "List all available AIWG skills with their descriptions and trigger patterns. Use this to discover skills that can help with the current task.";
|
|
4655
|
+
parameters = {
|
|
4656
|
+
type: "object",
|
|
4657
|
+
properties: {
|
|
4658
|
+
filter: {
|
|
4659
|
+
type: "string",
|
|
4660
|
+
description: "Optional keyword to filter skills by name or description"
|
|
4661
|
+
},
|
|
4662
|
+
source: {
|
|
4663
|
+
type: "string",
|
|
4664
|
+
description: "Optional source filter (e.g. 'framework:sdlc-complete', 'addon:ralph', 'project', 'local')"
|
|
4665
|
+
}
|
|
4666
|
+
},
|
|
4667
|
+
required: []
|
|
4668
|
+
};
|
|
4669
|
+
repoRoot;
|
|
4670
|
+
constructor(repoRoot) {
|
|
4671
|
+
this.repoRoot = repoRoot;
|
|
4672
|
+
}
|
|
4673
|
+
async execute(args) {
|
|
4674
|
+
const start = performance.now();
|
|
4675
|
+
const filter = typeof args["filter"] === "string" ? args["filter"].toLowerCase() : "";
|
|
4676
|
+
const sourceFilter = typeof args["source"] === "string" ? args["source"] : "";
|
|
4677
|
+
let skills = discoverSkills(this.repoRoot);
|
|
4678
|
+
if (filter) {
|
|
4679
|
+
skills = skills.filter((s) => s.name.toLowerCase().includes(filter) || s.description.toLowerCase().includes(filter) || s.triggers.some((t) => t.toLowerCase().includes(filter)));
|
|
4680
|
+
}
|
|
4681
|
+
if (sourceFilter) {
|
|
4682
|
+
skills = skills.filter((s) => s.source.includes(sourceFilter));
|
|
4683
|
+
}
|
|
4684
|
+
if (skills.length === 0) {
|
|
4685
|
+
return {
|
|
4686
|
+
success: true,
|
|
4687
|
+
output: filter || sourceFilter ? `No skills found matching filter "${filter || sourceFilter}".` : "No skills found. Install AIWG (npm i -g aiwg && aiwg use sdlc) or add skills to .oa/skills/.",
|
|
4688
|
+
durationMs: performance.now() - start
|
|
4689
|
+
};
|
|
4690
|
+
}
|
|
4691
|
+
const lines = [`Found ${skills.length} skills:
|
|
4692
|
+
`];
|
|
4693
|
+
for (const s of skills) {
|
|
4694
|
+
lines.push(` ${s.name}`);
|
|
4695
|
+
lines.push(` ${s.description}`);
|
|
4696
|
+
if (s.triggers.length > 0) {
|
|
4697
|
+
lines.push(` Triggers: ${s.triggers.slice(0, 5).join(" | ")}`);
|
|
4698
|
+
}
|
|
4699
|
+
lines.push(` Source: ${s.source}`);
|
|
4700
|
+
lines.push("");
|
|
4701
|
+
}
|
|
4702
|
+
return {
|
|
4703
|
+
success: true,
|
|
4704
|
+
output: lines.join("\n"),
|
|
4705
|
+
durationMs: performance.now() - start
|
|
4706
|
+
};
|
|
4707
|
+
}
|
|
4708
|
+
};
|
|
4709
|
+
SkillExecuteTool = class {
|
|
4710
|
+
name = "skill_execute";
|
|
4711
|
+
description = "Load a skill's full instructions by name. Returns the SKILL.md content which provides detailed behavioral guidance, trigger patterns, CLI commands, and output formats. Use this when the current task matches a skill's trigger pattern.";
|
|
4712
|
+
parameters = {
|
|
4713
|
+
type: "object",
|
|
4714
|
+
properties: {
|
|
4715
|
+
name: {
|
|
4716
|
+
type: "string",
|
|
4717
|
+
description: "Skill name (e.g. 'artifact-lookup', 'test-coverage', 'security-assessment')"
|
|
4718
|
+
}
|
|
4719
|
+
},
|
|
4720
|
+
required: ["name"]
|
|
4721
|
+
};
|
|
4722
|
+
repoRoot;
|
|
4723
|
+
constructor(repoRoot) {
|
|
4724
|
+
this.repoRoot = repoRoot;
|
|
4725
|
+
}
|
|
4726
|
+
async execute(args) {
|
|
4727
|
+
const start = performance.now();
|
|
4728
|
+
const name = String(args["name"] ?? "").trim();
|
|
4729
|
+
if (!name) {
|
|
4730
|
+
return {
|
|
4731
|
+
success: false,
|
|
4732
|
+
output: "",
|
|
4733
|
+
error: "Skill name is required. Use skill_list to see available skills.",
|
|
4734
|
+
durationMs: performance.now() - start
|
|
4735
|
+
};
|
|
4736
|
+
}
|
|
4737
|
+
const skills = discoverSkills(this.repoRoot);
|
|
4738
|
+
const skill = skills.find((s) => s.name === name);
|
|
4739
|
+
if (!skill) {
|
|
4740
|
+
const fuzzy = skills.filter((s) => s.name.includes(name) || name.includes(s.name));
|
|
4741
|
+
const suggestion = fuzzy.length > 0 ? `
|
|
4742
|
+
Did you mean: ${fuzzy.map((s) => s.name).join(", ")}?` : "\nUse skill_list to see available skills.";
|
|
4743
|
+
return {
|
|
4744
|
+
success: false,
|
|
4745
|
+
output: "",
|
|
4746
|
+
error: `Skill "${name}" not found.${suggestion}`,
|
|
4747
|
+
durationMs: performance.now() - start
|
|
4748
|
+
};
|
|
4749
|
+
}
|
|
4750
|
+
const content = loadSkillContent(skill.filePath);
|
|
4751
|
+
if (!content) {
|
|
4752
|
+
return {
|
|
4753
|
+
success: false,
|
|
4754
|
+
output: "",
|
|
4755
|
+
error: `Could not read skill file: ${skill.filePath}`,
|
|
4756
|
+
durationMs: performance.now() - start
|
|
4757
|
+
};
|
|
4758
|
+
}
|
|
4759
|
+
return {
|
|
4760
|
+
success: true,
|
|
4761
|
+
output: `# Skill: ${skill.name}
|
|
4762
|
+
Source: ${skill.source}
|
|
4763
|
+
|
|
4764
|
+
${content}`,
|
|
4765
|
+
durationMs: performance.now() - start
|
|
4766
|
+
};
|
|
4767
|
+
}
|
|
4768
|
+
};
|
|
4769
|
+
}
|
|
4770
|
+
});
|
|
4771
|
+
|
|
4492
4772
|
// packages/execution/dist/shellRunner.js
|
|
4493
4773
|
var init_shellRunner = __esm({
|
|
4494
4774
|
"packages/execution/dist/shellRunner.js"() {
|
|
@@ -4591,6 +4871,7 @@ var init_dist2 = __esm({
|
|
|
4591
4871
|
init_image();
|
|
4592
4872
|
init_custom_tool();
|
|
4593
4873
|
init_tool_creator();
|
|
4874
|
+
init_skill_tools();
|
|
4594
4875
|
init_shellRunner();
|
|
4595
4876
|
init_gitWorktree();
|
|
4596
4877
|
init_patchApplier();
|
|
@@ -5722,7 +6003,7 @@ var init_code_retriever = __esm({
|
|
|
5722
6003
|
import { execFile as execFile4 } from "node:child_process";
|
|
5723
6004
|
import { promisify as promisify4 } from "node:util";
|
|
5724
6005
|
import { readFile as readFile7, readdir, stat } from "node:fs/promises";
|
|
5725
|
-
import { join as
|
|
6006
|
+
import { join as join13, extname as extname3 } from "node:path";
|
|
5726
6007
|
async function searchByPath(pathPattern, options) {
|
|
5727
6008
|
const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
|
|
5728
6009
|
const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
|
|
@@ -5864,7 +6145,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
|
|
|
5864
6145
|
continue;
|
|
5865
6146
|
if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
|
|
5866
6147
|
continue;
|
|
5867
|
-
const absPath =
|
|
6148
|
+
const absPath = join13(dir, entry.name);
|
|
5868
6149
|
if (entry.isDirectory()) {
|
|
5869
6150
|
await walkForFiles(rootDir, absPath, excludeGlobs, results);
|
|
5870
6151
|
} else if (entry.isFile()) {
|
|
@@ -6039,7 +6320,7 @@ var init_graphExpand = __esm({
|
|
|
6039
6320
|
|
|
6040
6321
|
// packages/retrieval/dist/snippetPacker.js
|
|
6041
6322
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
6042
|
-
import { join as
|
|
6323
|
+
import { join as join14 } from "node:path";
|
|
6043
6324
|
async function packSnippets(requests, opts = {}) {
|
|
6044
6325
|
const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
6045
6326
|
const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
|
|
@@ -6065,7 +6346,7 @@ async function packSnippets(requests, opts = {}) {
|
|
|
6065
6346
|
return { packed, dropped, totalTokens };
|
|
6066
6347
|
}
|
|
6067
6348
|
async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
|
|
6068
|
-
const absPath = req.filePath.startsWith("/") ? req.filePath :
|
|
6349
|
+
const absPath = req.filePath.startsWith("/") ? req.filePath : join14(repoRoot, req.filePath);
|
|
6069
6350
|
let content;
|
|
6070
6351
|
try {
|
|
6071
6352
|
content = await readFile8(absPath, "utf-8");
|
|
@@ -7247,6 +7528,13 @@ var init_agenticRunner = __esm({
|
|
|
7247
7528
|
- task_stop: Kill a running background task
|
|
7248
7529
|
- sub_agent: Delegate a sub-task to an independent agent with its own context
|
|
7249
7530
|
|
|
7531
|
+
## Skills (AIWG)
|
|
7532
|
+
|
|
7533
|
+
- skill_list: Discover available skills \u2014 shows descriptions and trigger patterns. Use filter param to search.
|
|
7534
|
+
- skill_execute: Load a skill's full instructions by name. Returns the SKILL.md content with detailed behavioral guidance.
|
|
7535
|
+
|
|
7536
|
+
When a user request matches a skill trigger pattern (listed in your context or discovered via skill_list), call skill_execute to load the skill instructions, then follow them.
|
|
7537
|
+
|
|
7250
7538
|
Use background_run for long-running commands (builds, test suites) so you can continue other work.
|
|
7251
7539
|
Use sub_agent to parallelize independent sub-tasks or explore different approaches simultaneously.
|
|
7252
7540
|
Check task_status periodically and read task_output when tasks complete.
|
|
@@ -8639,6 +8927,8 @@ function renderSlashHelp() {
|
|
|
8639
8927
|
["/dream stop", "Wake up \u2014 stop dreaming"],
|
|
8640
8928
|
["/bruteforce", "Toggle brute-force mode (auto re-engage on turn limit)"],
|
|
8641
8929
|
["/tools", "List agent-created custom tools"],
|
|
8930
|
+
["/skills", "List available AIWG skills"],
|
|
8931
|
+
["/skills <keyword>", "Filter skills by name or trigger"],
|
|
8642
8932
|
["/verbose", "Toggle verbose mode"],
|
|
8643
8933
|
["/clear", "Clear the screen"],
|
|
8644
8934
|
["/help", "Show this help"],
|
|
@@ -8933,52 +9223,52 @@ var init_render = __esm({
|
|
|
8933
9223
|
});
|
|
8934
9224
|
|
|
8935
9225
|
// packages/cli/dist/tui/oa-directory.js
|
|
8936
|
-
import { existsSync as
|
|
8937
|
-
import { join as
|
|
8938
|
-
import { homedir as
|
|
9226
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync9, writeFileSync as writeFileSync4, readdirSync as readdirSync6, statSync as statSync5, unlinkSync } from "node:fs";
|
|
9227
|
+
import { join as join15, relative as relative2, basename as basename3, extname as extname4 } from "node:path";
|
|
9228
|
+
import { homedir as homedir5 } from "node:os";
|
|
8939
9229
|
function initOaDirectory(repoRoot) {
|
|
8940
|
-
const oaPath =
|
|
9230
|
+
const oaPath = join15(repoRoot, OA_DIR);
|
|
8941
9231
|
for (const sub of SUBDIRS) {
|
|
8942
|
-
mkdirSync4(
|
|
9232
|
+
mkdirSync4(join15(oaPath, sub), { recursive: true });
|
|
8943
9233
|
}
|
|
8944
9234
|
return oaPath;
|
|
8945
9235
|
}
|
|
8946
9236
|
function hasOaDirectory(repoRoot) {
|
|
8947
|
-
return
|
|
9237
|
+
return existsSync10(join15(repoRoot, OA_DIR, "index"));
|
|
8948
9238
|
}
|
|
8949
9239
|
function loadProjectSettings(repoRoot) {
|
|
8950
|
-
const settingsPath =
|
|
9240
|
+
const settingsPath = join15(repoRoot, OA_DIR, "settings.json");
|
|
8951
9241
|
try {
|
|
8952
|
-
if (
|
|
8953
|
-
return JSON.parse(
|
|
9242
|
+
if (existsSync10(settingsPath)) {
|
|
9243
|
+
return JSON.parse(readFileSync9(settingsPath, "utf-8"));
|
|
8954
9244
|
}
|
|
8955
9245
|
} catch {
|
|
8956
9246
|
}
|
|
8957
9247
|
return {};
|
|
8958
9248
|
}
|
|
8959
9249
|
function saveProjectSettings(repoRoot, settings) {
|
|
8960
|
-
const oaPath =
|
|
9250
|
+
const oaPath = join15(repoRoot, OA_DIR);
|
|
8961
9251
|
mkdirSync4(oaPath, { recursive: true });
|
|
8962
9252
|
const existing = loadProjectSettings(repoRoot);
|
|
8963
9253
|
const merged = { ...existing, ...settings };
|
|
8964
|
-
writeFileSync4(
|
|
9254
|
+
writeFileSync4(join15(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
8965
9255
|
}
|
|
8966
9256
|
function loadGlobalSettings() {
|
|
8967
|
-
const settingsPath =
|
|
9257
|
+
const settingsPath = join15(homedir5(), ".open-agents", "settings.json");
|
|
8968
9258
|
try {
|
|
8969
|
-
if (
|
|
8970
|
-
return JSON.parse(
|
|
9259
|
+
if (existsSync10(settingsPath)) {
|
|
9260
|
+
return JSON.parse(readFileSync9(settingsPath, "utf-8"));
|
|
8971
9261
|
}
|
|
8972
9262
|
} catch {
|
|
8973
9263
|
}
|
|
8974
9264
|
return {};
|
|
8975
9265
|
}
|
|
8976
9266
|
function saveGlobalSettings(settings) {
|
|
8977
|
-
const dir =
|
|
9267
|
+
const dir = join15(homedir5(), ".open-agents");
|
|
8978
9268
|
mkdirSync4(dir, { recursive: true });
|
|
8979
9269
|
const existing = loadGlobalSettings();
|
|
8980
9270
|
const merged = { ...existing, ...settings };
|
|
8981
|
-
writeFileSync4(
|
|
9271
|
+
writeFileSync4(join15(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
8982
9272
|
}
|
|
8983
9273
|
function resolveSettings(repoRoot) {
|
|
8984
9274
|
const global = loadGlobalSettings();
|
|
@@ -8993,12 +9283,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
8993
9283
|
while (dir && !visited.has(dir)) {
|
|
8994
9284
|
visited.add(dir);
|
|
8995
9285
|
for (const name of CONTEXT_FILES) {
|
|
8996
|
-
const filePath =
|
|
9286
|
+
const filePath = join15(dir, name);
|
|
8997
9287
|
const normalizedName = name.toLowerCase();
|
|
8998
|
-
if (
|
|
9288
|
+
if (existsSync10(filePath) && !seen.has(filePath)) {
|
|
8999
9289
|
seen.add(filePath);
|
|
9000
9290
|
try {
|
|
9001
|
-
let content =
|
|
9291
|
+
let content = readFileSync9(filePath, "utf-8");
|
|
9002
9292
|
if (content.length > maxContentLen) {
|
|
9003
9293
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
9004
9294
|
}
|
|
@@ -9012,11 +9302,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
9012
9302
|
}
|
|
9013
9303
|
}
|
|
9014
9304
|
}
|
|
9015
|
-
const projectMap =
|
|
9016
|
-
if (
|
|
9305
|
+
const projectMap = join15(dir, OA_DIR, "context", "project-map.md");
|
|
9306
|
+
if (existsSync10(projectMap) && !seen.has(projectMap)) {
|
|
9017
9307
|
seen.add(projectMap);
|
|
9018
9308
|
try {
|
|
9019
|
-
let content =
|
|
9309
|
+
let content = readFileSync9(projectMap, "utf-8");
|
|
9020
9310
|
if (content.length > maxContentLen) {
|
|
9021
9311
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
9022
9312
|
}
|
|
@@ -9028,7 +9318,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
9028
9318
|
} catch {
|
|
9029
9319
|
}
|
|
9030
9320
|
}
|
|
9031
|
-
const parent =
|
|
9321
|
+
const parent = join15(dir, "..");
|
|
9032
9322
|
if (parent === dir)
|
|
9033
9323
|
break;
|
|
9034
9324
|
dir = parent;
|
|
@@ -9046,16 +9336,16 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
9046
9336
|
return found;
|
|
9047
9337
|
}
|
|
9048
9338
|
function readIndexMeta(repoRoot) {
|
|
9049
|
-
const metaPath =
|
|
9339
|
+
const metaPath = join15(repoRoot, OA_DIR, "index", "meta.json");
|
|
9050
9340
|
try {
|
|
9051
|
-
return JSON.parse(
|
|
9341
|
+
return JSON.parse(readFileSync9(metaPath, "utf-8"));
|
|
9052
9342
|
} catch {
|
|
9053
9343
|
return null;
|
|
9054
9344
|
}
|
|
9055
9345
|
}
|
|
9056
9346
|
function generateProjectMap(repoRoot) {
|
|
9057
9347
|
const sections = [];
|
|
9058
|
-
const repoName2 =
|
|
9348
|
+
const repoName2 = basename3(repoRoot);
|
|
9059
9349
|
sections.push(`# Project Map: ${repoName2}
|
|
9060
9350
|
`);
|
|
9061
9351
|
sections.push(`> Auto-generated by open-agents. Updated: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -9099,28 +9389,28 @@ ${tree}\`\`\`
|
|
|
9099
9389
|
sections.push("");
|
|
9100
9390
|
}
|
|
9101
9391
|
const content = sections.join("\n");
|
|
9102
|
-
const contextDir =
|
|
9392
|
+
const contextDir = join15(repoRoot, OA_DIR, "context");
|
|
9103
9393
|
mkdirSync4(contextDir, { recursive: true });
|
|
9104
|
-
writeFileSync4(
|
|
9394
|
+
writeFileSync4(join15(contextDir, "project-map.md"), content, "utf-8");
|
|
9105
9395
|
return content;
|
|
9106
9396
|
}
|
|
9107
9397
|
function saveSession(repoRoot, session) {
|
|
9108
|
-
const historyDir =
|
|
9398
|
+
const historyDir = join15(repoRoot, OA_DIR, "history");
|
|
9109
9399
|
mkdirSync4(historyDir, { recursive: true });
|
|
9110
|
-
writeFileSync4(
|
|
9400
|
+
writeFileSync4(join15(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
|
|
9111
9401
|
}
|
|
9112
9402
|
function loadRecentSessions(repoRoot, limit = 5) {
|
|
9113
|
-
const historyDir =
|
|
9114
|
-
if (!
|
|
9403
|
+
const historyDir = join15(repoRoot, OA_DIR, "history");
|
|
9404
|
+
if (!existsSync10(historyDir))
|
|
9115
9405
|
return [];
|
|
9116
9406
|
try {
|
|
9117
|
-
const files =
|
|
9118
|
-
const stat3 = statSync5(
|
|
9407
|
+
const files = readdirSync6(historyDir).filter((f) => f.endsWith(".json")).map((f) => {
|
|
9408
|
+
const stat3 = statSync5(join15(historyDir, f));
|
|
9119
9409
|
return { file: f, mtime: stat3.mtimeMs };
|
|
9120
9410
|
}).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
|
|
9121
9411
|
return files.map((f) => {
|
|
9122
9412
|
try {
|
|
9123
|
-
return JSON.parse(
|
|
9413
|
+
return JSON.parse(readFileSync9(join15(historyDir, f.file), "utf-8"));
|
|
9124
9414
|
} catch {
|
|
9125
9415
|
return null;
|
|
9126
9416
|
}
|
|
@@ -9130,16 +9420,16 @@ function loadRecentSessions(repoRoot, limit = 5) {
|
|
|
9130
9420
|
}
|
|
9131
9421
|
}
|
|
9132
9422
|
function savePendingTask(repoRoot, task) {
|
|
9133
|
-
const historyDir =
|
|
9423
|
+
const historyDir = join15(repoRoot, OA_DIR, "history");
|
|
9134
9424
|
mkdirSync4(historyDir, { recursive: true });
|
|
9135
|
-
writeFileSync4(
|
|
9425
|
+
writeFileSync4(join15(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
|
|
9136
9426
|
}
|
|
9137
9427
|
function loadPendingTask(repoRoot) {
|
|
9138
|
-
const filePath =
|
|
9428
|
+
const filePath = join15(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
|
|
9139
9429
|
try {
|
|
9140
|
-
if (!
|
|
9430
|
+
if (!existsSync10(filePath))
|
|
9141
9431
|
return null;
|
|
9142
|
-
const data = JSON.parse(
|
|
9432
|
+
const data = JSON.parse(readFileSync9(filePath, "utf-8"));
|
|
9143
9433
|
try {
|
|
9144
9434
|
unlinkSync(filePath);
|
|
9145
9435
|
} catch {
|
|
@@ -9167,12 +9457,12 @@ function detectManifests(repoRoot) {
|
|
|
9167
9457
|
{ file: "docker-compose.yaml", type: "Docker Compose" }
|
|
9168
9458
|
];
|
|
9169
9459
|
for (const check of checks) {
|
|
9170
|
-
const filePath =
|
|
9171
|
-
if (
|
|
9460
|
+
const filePath = join15(repoRoot, check.file);
|
|
9461
|
+
if (existsSync10(filePath)) {
|
|
9172
9462
|
let name;
|
|
9173
9463
|
if (check.nameField) {
|
|
9174
9464
|
try {
|
|
9175
|
-
const data = JSON.parse(
|
|
9465
|
+
const data = JSON.parse(readFileSync9(filePath, "utf-8"));
|
|
9176
9466
|
name = data[check.nameField];
|
|
9177
9467
|
} catch {
|
|
9178
9468
|
}
|
|
@@ -9201,7 +9491,7 @@ function findKeyFiles(repoRoot) {
|
|
|
9201
9491
|
{ pattern: "CLAUDE.md", description: "Claude Code context" }
|
|
9202
9492
|
];
|
|
9203
9493
|
for (const check of checks) {
|
|
9204
|
-
if (
|
|
9494
|
+
if (existsSync10(join15(repoRoot, check.pattern))) {
|
|
9205
9495
|
keyFiles.push({ path: check.pattern, description: check.description });
|
|
9206
9496
|
}
|
|
9207
9497
|
}
|
|
@@ -9212,7 +9502,7 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
9212
9502
|
return "";
|
|
9213
9503
|
let result = "";
|
|
9214
9504
|
try {
|
|
9215
|
-
const entries =
|
|
9505
|
+
const entries = readdirSync6(root, { withFileTypes: true }).filter((e) => !e.name.startsWith(".") || e.name === ".github").filter((e) => !SKIP_DIRS.has(e.name)).sort((a, b) => {
|
|
9216
9506
|
if (a.isDirectory() && !b.isDirectory())
|
|
9217
9507
|
return -1;
|
|
9218
9508
|
if (!a.isDirectory() && b.isDirectory())
|
|
@@ -9227,12 +9517,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
9227
9517
|
if (entry.isDirectory()) {
|
|
9228
9518
|
let fileCount = 0;
|
|
9229
9519
|
try {
|
|
9230
|
-
fileCount =
|
|
9520
|
+
fileCount = readdirSync6(join15(root, entry.name)).filter((f) => !f.startsWith(".")).length;
|
|
9231
9521
|
} catch {
|
|
9232
9522
|
}
|
|
9233
9523
|
result += `${prefix}${connector}${entry.name}/ (${fileCount})
|
|
9234
9524
|
`;
|
|
9235
|
-
result += buildDirTree(
|
|
9525
|
+
result += buildDirTree(join15(root, entry.name), maxDepth, childPrefix, depth + 1);
|
|
9236
9526
|
} else if (depth < maxDepth) {
|
|
9237
9527
|
result += `${prefix}${connector}${entry.name}
|
|
9238
9528
|
`;
|
|
@@ -9387,6 +9677,51 @@ async function handleSlashCommand(input, ctx) {
|
|
|
9387
9677
|
}
|
|
9388
9678
|
return "handled";
|
|
9389
9679
|
}
|
|
9680
|
+
case "skills":
|
|
9681
|
+
case "skill": {
|
|
9682
|
+
const skills = discoverSkills(ctx.repoRoot);
|
|
9683
|
+
if (skills.length === 0) {
|
|
9684
|
+
renderInfo("No skills found.");
|
|
9685
|
+
renderInfo("Install AIWG to get skills: npm i -g aiwg && aiwg use sdlc");
|
|
9686
|
+
renderInfo("Or add skills manually to .oa/skills/{name}/SKILL.md");
|
|
9687
|
+
} else {
|
|
9688
|
+
let filtered = skills;
|
|
9689
|
+
if (arg) {
|
|
9690
|
+
const q = arg.toLowerCase();
|
|
9691
|
+
filtered = skills.filter((s) => s.name.toLowerCase().includes(q) || s.description.toLowerCase().includes(q) || s.triggers.some((t) => t.toLowerCase().includes(q)));
|
|
9692
|
+
}
|
|
9693
|
+
if (filtered.length === 0) {
|
|
9694
|
+
renderWarning(`No skills matching "${arg}". Showing all ${skills.length} skills:`);
|
|
9695
|
+
filtered = skills;
|
|
9696
|
+
}
|
|
9697
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
9698
|
+
for (const s of filtered) {
|
|
9699
|
+
const group = bySource.get(s.source) ?? [];
|
|
9700
|
+
group.push(s);
|
|
9701
|
+
bySource.set(s.source, group);
|
|
9702
|
+
}
|
|
9703
|
+
process.stdout.write(`
|
|
9704
|
+
${c2.bold(`Available Skills (${filtered.length}):`)}
|
|
9705
|
+
`);
|
|
9706
|
+
for (const [source, group] of bySource) {
|
|
9707
|
+
process.stdout.write(`
|
|
9708
|
+
${c2.dim(`\u2500\u2500 ${source} (${group.length}) \u2500\u2500`)}
|
|
9709
|
+
`);
|
|
9710
|
+
for (const s of group) {
|
|
9711
|
+
process.stdout.write(` ${c2.cyan(s.name.padEnd(32))} ${s.description.slice(0, 60)}
|
|
9712
|
+
`);
|
|
9713
|
+
if (s.triggers.length > 0) {
|
|
9714
|
+
process.stdout.write(` ${"".padEnd(32)} ${c2.dim(`triggers: ${s.triggers.slice(0, 3).join(" | ")}`)}
|
|
9715
|
+
`);
|
|
9716
|
+
}
|
|
9717
|
+
}
|
|
9718
|
+
}
|
|
9719
|
+
process.stdout.write("\n");
|
|
9720
|
+
renderInfo("The agent can use these via the skill_execute tool.");
|
|
9721
|
+
renderInfo("Filter with: /skills <keyword>");
|
|
9722
|
+
}
|
|
9723
|
+
return "handled";
|
|
9724
|
+
}
|
|
9390
9725
|
case "dream": {
|
|
9391
9726
|
if (arg === "stop" || arg === "wake") {
|
|
9392
9727
|
if (ctx.isDreaming?.()) {
|
|
@@ -9545,17 +9880,17 @@ async function handleUpdate(subcommand, repoRoot, savePendingTaskState) {
|
|
|
9545
9880
|
try {
|
|
9546
9881
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
9547
9882
|
const { fileURLToPath: fileURLToPath3 } = await import("node:url");
|
|
9548
|
-
const { dirname: dirname4, join:
|
|
9549
|
-
const { existsSync:
|
|
9883
|
+
const { dirname: dirname4, join: join26 } = await import("node:path");
|
|
9884
|
+
const { existsSync: existsSync17 } = await import("node:fs");
|
|
9550
9885
|
const req = createRequire4(import.meta.url);
|
|
9551
9886
|
const thisDir = dirname4(fileURLToPath3(import.meta.url));
|
|
9552
9887
|
const candidates = [
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9888
|
+
join26(thisDir, "..", "package.json"),
|
|
9889
|
+
join26(thisDir, "..", "..", "package.json"),
|
|
9890
|
+
join26(thisDir, "..", "..", "..", "package.json")
|
|
9556
9891
|
];
|
|
9557
9892
|
for (const pkgPath of candidates) {
|
|
9558
|
-
if (
|
|
9893
|
+
if (existsSync17(pkgPath)) {
|
|
9559
9894
|
const pkg = req(pkgPath);
|
|
9560
9895
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
9561
9896
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -9640,9 +9975,9 @@ var init_commands = __esm({
|
|
|
9640
9975
|
// packages/cli/dist/tui/setup.js
|
|
9641
9976
|
import * as readline from "node:readline";
|
|
9642
9977
|
import { execSync as execSync8 } from "node:child_process";
|
|
9643
|
-
import { existsSync as
|
|
9644
|
-
import { join as
|
|
9645
|
-
import { homedir as
|
|
9978
|
+
import { existsSync as existsSync11, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "node:fs";
|
|
9979
|
+
import { join as join16 } from "node:path";
|
|
9980
|
+
import { homedir as homedir6 } from "node:os";
|
|
9646
9981
|
function detectSystemSpecs() {
|
|
9647
9982
|
let totalRamGB = 0;
|
|
9648
9983
|
let availableRamGB = 0;
|
|
@@ -9937,9 +10272,9 @@ async function doSetup(config, rl) {
|
|
|
9937
10272
|
`PARAMETER num_predict 16384`,
|
|
9938
10273
|
`PARAMETER stop "<|endoftext|>"`
|
|
9939
10274
|
].join("\n");
|
|
9940
|
-
const modelDir2 =
|
|
10275
|
+
const modelDir2 = join16(homedir6(), ".open-agents", "models");
|
|
9941
10276
|
mkdirSync5(modelDir2, { recursive: true });
|
|
9942
|
-
const modelfilePath =
|
|
10277
|
+
const modelfilePath = join16(modelDir2, `Modelfile.${customName}`);
|
|
9943
10278
|
writeFileSync5(modelfilePath, modelfileContent + "\n", "utf8");
|
|
9944
10279
|
process.stdout.write(` ${c2.dim("Creating model...")} `);
|
|
9945
10280
|
execSync8(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
@@ -9985,7 +10320,7 @@ async function isModelAvailable(config) {
|
|
|
9985
10320
|
}
|
|
9986
10321
|
function isFirstRun() {
|
|
9987
10322
|
try {
|
|
9988
|
-
return !
|
|
10323
|
+
return !existsSync11(join16(homedir6(), ".open-agents", "config.json"));
|
|
9989
10324
|
} catch {
|
|
9990
10325
|
return true;
|
|
9991
10326
|
}
|
|
@@ -10025,10 +10360,10 @@ var init_setup = __esm({
|
|
|
10025
10360
|
});
|
|
10026
10361
|
|
|
10027
10362
|
// packages/cli/dist/tui/project-context.js
|
|
10028
|
-
import { existsSync as
|
|
10029
|
-
import { join as
|
|
10363
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10, readdirSync as readdirSync7 } from "node:fs";
|
|
10364
|
+
import { join as join17, basename as basename4 } from "node:path";
|
|
10030
10365
|
import { execSync as execSync9 } from "node:child_process";
|
|
10031
|
-
import { homedir as
|
|
10366
|
+
import { homedir as homedir7, platform, release } from "node:os";
|
|
10032
10367
|
function loadProjectFiles(repoRoot) {
|
|
10033
10368
|
const discovered = discoverContextFiles(repoRoot);
|
|
10034
10369
|
if (discovered.length === 0)
|
|
@@ -10046,10 +10381,10 @@ function loadProjectMap(repoRoot) {
|
|
|
10046
10381
|
if (!hasOaDirectory(repoRoot)) {
|
|
10047
10382
|
initOaDirectory(repoRoot);
|
|
10048
10383
|
}
|
|
10049
|
-
const mapPath =
|
|
10050
|
-
if (
|
|
10384
|
+
const mapPath = join17(repoRoot, OA_DIR, "context", "project-map.md");
|
|
10385
|
+
if (existsSync12(mapPath)) {
|
|
10051
10386
|
try {
|
|
10052
|
-
const content =
|
|
10387
|
+
const content = readFileSync10(mapPath, "utf-8");
|
|
10053
10388
|
return content;
|
|
10054
10389
|
} catch {
|
|
10055
10390
|
}
|
|
@@ -10090,33 +10425,33 @@ ${log}`);
|
|
|
10090
10425
|
}
|
|
10091
10426
|
function loadMemoryContext(repoRoot) {
|
|
10092
10427
|
const sections = [];
|
|
10093
|
-
const oaMemDir =
|
|
10428
|
+
const oaMemDir = join17(repoRoot, OA_DIR, "memory");
|
|
10094
10429
|
const oaEntries = loadMemoryDir(oaMemDir, "project");
|
|
10095
10430
|
if (oaEntries)
|
|
10096
10431
|
sections.push(oaEntries);
|
|
10097
|
-
const legacyMemDir =
|
|
10098
|
-
if (legacyMemDir !== oaMemDir &&
|
|
10432
|
+
const legacyMemDir = join17(repoRoot, ".open-agents", "memory");
|
|
10433
|
+
if (legacyMemDir !== oaMemDir && existsSync12(legacyMemDir)) {
|
|
10099
10434
|
const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
|
|
10100
10435
|
if (legacyEntries)
|
|
10101
10436
|
sections.push(legacyEntries);
|
|
10102
10437
|
}
|
|
10103
|
-
const globalMemDir =
|
|
10438
|
+
const globalMemDir = join17(homedir7(), ".open-agents", "memory");
|
|
10104
10439
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
10105
10440
|
if (globalEntries)
|
|
10106
10441
|
sections.push(globalEntries);
|
|
10107
10442
|
return sections.join("\n\n");
|
|
10108
10443
|
}
|
|
10109
10444
|
function loadMemoryDir(memDir, scope) {
|
|
10110
|
-
if (!
|
|
10445
|
+
if (!existsSync12(memDir))
|
|
10111
10446
|
return "";
|
|
10112
10447
|
const lines = [];
|
|
10113
10448
|
try {
|
|
10114
|
-
const files =
|
|
10449
|
+
const files = readdirSync7(memDir).filter((f) => f.endsWith(".json"));
|
|
10115
10450
|
for (const file of files.slice(0, 10)) {
|
|
10116
10451
|
try {
|
|
10117
|
-
const raw =
|
|
10452
|
+
const raw = readFileSync10(join17(memDir, file), "utf-8");
|
|
10118
10453
|
const entries = JSON.parse(raw);
|
|
10119
|
-
const topic =
|
|
10454
|
+
const topic = basename4(file, ".json");
|
|
10120
10455
|
const keys = Object.keys(entries);
|
|
10121
10456
|
if (keys.length === 0)
|
|
10122
10457
|
continue;
|
|
@@ -10239,7 +10574,8 @@ function buildProjectContext(repoRoot, stores) {
|
|
|
10239
10574
|
environment: getEnvironment(repoRoot),
|
|
10240
10575
|
taskMemories: stores?.taskMemoryStore ? loadTaskMemories(repoRoot, stores.taskMemoryStore) : "",
|
|
10241
10576
|
failurePatterns: stores?.failureStore ? loadFailurePatterns(stores.failureStore) : "",
|
|
10242
|
-
patternSuggestions: stores?.toolPatternStore ? loadPatternSuggestions(repoRoot, stores.toolPatternStore) : ""
|
|
10577
|
+
patternSuggestions: stores?.toolPatternStore ? loadPatternSuggestions(repoRoot, stores.toolPatternStore) : "",
|
|
10578
|
+
skillsSummary: buildSkillsSummary(discoverSkills(repoRoot))
|
|
10243
10579
|
};
|
|
10244
10580
|
}
|
|
10245
10581
|
function formatContextForPrompt(ctx) {
|
|
@@ -10295,12 +10631,16 @@ ${ctx.patternSuggestions}
|
|
|
10295
10631
|
|
|
10296
10632
|
These patterns have been repeated 3+ times. Consider using create_tool to automate them.`);
|
|
10297
10633
|
}
|
|
10634
|
+
if (ctx.skillsSummary) {
|
|
10635
|
+
sections.push(ctx.skillsSummary);
|
|
10636
|
+
}
|
|
10298
10637
|
return sections.join("\n\n");
|
|
10299
10638
|
}
|
|
10300
10639
|
var init_project_context = __esm({
|
|
10301
10640
|
"packages/cli/dist/tui/project-context.js"() {
|
|
10302
10641
|
"use strict";
|
|
10303
10642
|
init_oa_directory();
|
|
10643
|
+
init_dist2();
|
|
10304
10644
|
}
|
|
10305
10645
|
});
|
|
10306
10646
|
|
|
@@ -11120,19 +11460,19 @@ var init_carousel = __esm({
|
|
|
11120
11460
|
});
|
|
11121
11461
|
|
|
11122
11462
|
// packages/cli/dist/tui/voice.js
|
|
11123
|
-
import { existsSync as
|
|
11124
|
-
import { join as
|
|
11125
|
-
import { homedir as
|
|
11463
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6, readFileSync as readFileSync11, unlinkSync as unlinkSync2 } from "node:fs";
|
|
11464
|
+
import { join as join18 } from "node:path";
|
|
11465
|
+
import { homedir as homedir8, tmpdir as tmpdir2, platform as platform2 } from "node:os";
|
|
11126
11466
|
import { execSync as execSync10, spawn as nodeSpawn } from "node:child_process";
|
|
11127
11467
|
import { createRequire } from "node:module";
|
|
11128
11468
|
function modelDir(id) {
|
|
11129
|
-
return
|
|
11469
|
+
return join18(MODELS_DIR, id);
|
|
11130
11470
|
}
|
|
11131
11471
|
function modelOnnxPath(id) {
|
|
11132
|
-
return
|
|
11472
|
+
return join18(modelDir(id), "model.onnx");
|
|
11133
11473
|
}
|
|
11134
11474
|
function modelConfigPath(id) {
|
|
11135
|
-
return
|
|
11475
|
+
return join18(modelDir(id), "config.json");
|
|
11136
11476
|
}
|
|
11137
11477
|
function describeToolCall(toolName, args) {
|
|
11138
11478
|
const path = args["path"];
|
|
@@ -11247,8 +11587,8 @@ var init_voice = __esm({
|
|
|
11247
11587
|
configUrl: "https://raw.githubusercontent.com/robit-man/combine_overwatch_onnx/main/overwatch.onnx.json"
|
|
11248
11588
|
}
|
|
11249
11589
|
};
|
|
11250
|
-
VOICE_DIR =
|
|
11251
|
-
MODELS_DIR =
|
|
11590
|
+
VOICE_DIR = join18(homedir8(), ".open-agents", "voice");
|
|
11591
|
+
MODELS_DIR = join18(VOICE_DIR, "models");
|
|
11252
11592
|
VoiceEngine = class {
|
|
11253
11593
|
enabled = false;
|
|
11254
11594
|
modelId = "glados";
|
|
@@ -11407,7 +11747,7 @@ var init_voice = __esm({
|
|
|
11407
11747
|
const audioData = result["output"].data;
|
|
11408
11748
|
if (audioData.length === 0)
|
|
11409
11749
|
return;
|
|
11410
|
-
const wavPath =
|
|
11750
|
+
const wavPath = join18(tmpdir2(), `oa-voice-${Date.now()}.wav`);
|
|
11411
11751
|
this.writeWav(audioData, this.config.audio.sample_rate, wavPath);
|
|
11412
11752
|
await this.playWav(wavPath);
|
|
11413
11753
|
try {
|
|
@@ -11560,14 +11900,14 @@ var init_voice = __esm({
|
|
|
11560
11900
|
if (this.ort)
|
|
11561
11901
|
return;
|
|
11562
11902
|
mkdirSync6(VOICE_DIR, { recursive: true });
|
|
11563
|
-
const pkgPath =
|
|
11903
|
+
const pkgPath = join18(VOICE_DIR, "package.json");
|
|
11564
11904
|
const expectedDeps = {
|
|
11565
11905
|
"onnxruntime-node": "^1.21.0",
|
|
11566
11906
|
"phonemizer": "^1.2.1"
|
|
11567
11907
|
};
|
|
11568
|
-
if (
|
|
11908
|
+
if (existsSync13(pkgPath)) {
|
|
11569
11909
|
try {
|
|
11570
|
-
const existing = JSON.parse(
|
|
11910
|
+
const existing = JSON.parse(readFileSync11(pkgPath, "utf8"));
|
|
11571
11911
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
11572
11912
|
existing.dependencies = { ...existing.dependencies, ...expectedDeps };
|
|
11573
11913
|
writeFileSync6(pkgPath, JSON.stringify(existing, null, 2));
|
|
@@ -11575,14 +11915,14 @@ var init_voice = __esm({
|
|
|
11575
11915
|
} catch {
|
|
11576
11916
|
}
|
|
11577
11917
|
}
|
|
11578
|
-
if (!
|
|
11918
|
+
if (!existsSync13(pkgPath)) {
|
|
11579
11919
|
writeFileSync6(pkgPath, JSON.stringify({
|
|
11580
11920
|
name: "open-agents-voice",
|
|
11581
11921
|
private: true,
|
|
11582
11922
|
dependencies: expectedDeps
|
|
11583
11923
|
}, null, 2));
|
|
11584
11924
|
}
|
|
11585
|
-
const voiceRequire = createRequire(
|
|
11925
|
+
const voiceRequire = createRequire(join18(VOICE_DIR, "index.js"));
|
|
11586
11926
|
try {
|
|
11587
11927
|
this.ort = voiceRequire("onnxruntime-node");
|
|
11588
11928
|
} catch {
|
|
@@ -11628,10 +11968,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
11628
11968
|
const dir = modelDir(id);
|
|
11629
11969
|
const onnxPath = modelOnnxPath(id);
|
|
11630
11970
|
const configPath = modelConfigPath(id);
|
|
11631
|
-
if (
|
|
11971
|
+
if (existsSync13(onnxPath) && existsSync13(configPath))
|
|
11632
11972
|
return;
|
|
11633
11973
|
mkdirSync6(dir, { recursive: true });
|
|
11634
|
-
if (!
|
|
11974
|
+
if (!existsSync13(configPath)) {
|
|
11635
11975
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
11636
11976
|
const configResp = await fetch(model.configUrl);
|
|
11637
11977
|
if (!configResp.ok)
|
|
@@ -11639,7 +11979,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
11639
11979
|
const configText = await configResp.text();
|
|
11640
11980
|
writeFileSync6(configPath, configText);
|
|
11641
11981
|
}
|
|
11642
|
-
if (!
|
|
11982
|
+
if (!existsSync13(onnxPath)) {
|
|
11643
11983
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
11644
11984
|
const onnxResp = await fetch(model.onnxUrl);
|
|
11645
11985
|
if (!onnxResp.ok)
|
|
@@ -11675,10 +12015,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
11675
12015
|
throw new Error("ONNX runtime not loaded");
|
|
11676
12016
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
11677
12017
|
const configPath = modelConfigPath(this.modelId);
|
|
11678
|
-
if (!
|
|
12018
|
+
if (!existsSync13(onnxPath) || !existsSync13(configPath)) {
|
|
11679
12019
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
11680
12020
|
}
|
|
11681
|
-
this.config = JSON.parse(
|
|
12021
|
+
this.config = JSON.parse(readFileSync11(configPath, "utf8"));
|
|
11682
12022
|
renderInfo("Loading voice model...");
|
|
11683
12023
|
this.session = await this.ort.InferenceSession.create(onnxPath, {
|
|
11684
12024
|
executionProviders: ["cpu"],
|
|
@@ -11952,10 +12292,10 @@ var init_stream_renderer = __esm({
|
|
|
11952
12292
|
|
|
11953
12293
|
// packages/cli/dist/tui/edit-history.js
|
|
11954
12294
|
import { appendFileSync, mkdirSync as mkdirSync7 } from "node:fs";
|
|
11955
|
-
import { join as
|
|
12295
|
+
import { join as join19 } from "node:path";
|
|
11956
12296
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
11957
|
-
const historyDir =
|
|
11958
|
-
const logPath =
|
|
12297
|
+
const historyDir = join19(repoRoot, ".oa", "history");
|
|
12298
|
+
const logPath = join19(historyDir, "edits.jsonl");
|
|
11959
12299
|
try {
|
|
11960
12300
|
mkdirSync7(historyDir, { recursive: true });
|
|
11961
12301
|
} catch {
|
|
@@ -12066,8 +12406,8 @@ var init_edit_history = __esm({
|
|
|
12066
12406
|
});
|
|
12067
12407
|
|
|
12068
12408
|
// packages/cli/dist/tui/dream-engine.js
|
|
12069
|
-
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync7, readFileSync as
|
|
12070
|
-
import { join as
|
|
12409
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync7, readFileSync as readFileSync12, existsSync as existsSync14, cpSync, rmSync, readdirSync as readdirSync8 } from "node:fs";
|
|
12410
|
+
import { join as join20, basename as basename5 } from "node:path";
|
|
12071
12411
|
import { execSync as execSync11 } from "node:child_process";
|
|
12072
12412
|
function adaptTool(tool) {
|
|
12073
12413
|
return {
|
|
@@ -12242,12 +12582,12 @@ var init_dream_engine = __esm({
|
|
|
12242
12582
|
const content = String(args["content"] ?? "");
|
|
12243
12583
|
if (!rawPath)
|
|
12244
12584
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
12245
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
12585
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join20(this.dreamsDir, basename5(rawPath)) : join20(this.dreamsDir, rawPath);
|
|
12246
12586
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
12247
12587
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
12248
12588
|
}
|
|
12249
12589
|
try {
|
|
12250
|
-
const dir =
|
|
12590
|
+
const dir = join20(targetPath, "..");
|
|
12251
12591
|
mkdirSync8(dir, { recursive: true });
|
|
12252
12592
|
writeFileSync7(targetPath, content, "utf-8");
|
|
12253
12593
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
@@ -12277,15 +12617,15 @@ var init_dream_engine = __esm({
|
|
|
12277
12617
|
const rawPath = String(args["path"] ?? "");
|
|
12278
12618
|
const oldStr = String(args["old_string"] ?? "");
|
|
12279
12619
|
const newStr = String(args["new_string"] ?? "");
|
|
12280
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
12620
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join20(this.dreamsDir, basename5(rawPath)) : join20(this.dreamsDir, rawPath);
|
|
12281
12621
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
12282
12622
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
12283
12623
|
}
|
|
12284
12624
|
try {
|
|
12285
|
-
if (!
|
|
12625
|
+
if (!existsSync14(targetPath)) {
|
|
12286
12626
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
12287
12627
|
}
|
|
12288
|
-
let content =
|
|
12628
|
+
let content = readFileSync12(targetPath, "utf-8");
|
|
12289
12629
|
if (!content.includes(oldStr)) {
|
|
12290
12630
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
12291
12631
|
}
|
|
@@ -12344,7 +12684,7 @@ var init_dream_engine = __esm({
|
|
|
12344
12684
|
constructor(config, repoRoot) {
|
|
12345
12685
|
this.config = config;
|
|
12346
12686
|
this.repoRoot = repoRoot;
|
|
12347
|
-
this.dreamsDir =
|
|
12687
|
+
this.dreamsDir = join20(repoRoot, ".oa", "dreams");
|
|
12348
12688
|
this.state = {
|
|
12349
12689
|
mode: "default",
|
|
12350
12690
|
active: false,
|
|
@@ -12416,7 +12756,7 @@ ${result.summary}`;
|
|
|
12416
12756
|
if (mode !== "default" || cycle === totalCycles) {
|
|
12417
12757
|
renderDreamContraction(cycle);
|
|
12418
12758
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
12419
|
-
const summaryPath =
|
|
12759
|
+
const summaryPath = join20(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
12420
12760
|
writeFileSync7(summaryPath, cycleSummary, "utf-8");
|
|
12421
12761
|
}
|
|
12422
12762
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
@@ -12537,7 +12877,7 @@ Dreams directory: ${this.dreamsDir}`);
|
|
|
12537
12877
|
}
|
|
12538
12878
|
/** Save workspace backup for lucid mode */
|
|
12539
12879
|
saveVersionCheckpoint(cycle) {
|
|
12540
|
-
const checkpointDir =
|
|
12880
|
+
const checkpointDir = join20(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
12541
12881
|
try {
|
|
12542
12882
|
mkdirSync8(checkpointDir, { recursive: true });
|
|
12543
12883
|
try {
|
|
@@ -12556,10 +12896,10 @@ Dreams directory: ${this.dreamsDir}`);
|
|
|
12556
12896
|
encoding: "utf-8",
|
|
12557
12897
|
timeout: 5e3
|
|
12558
12898
|
}).trim();
|
|
12559
|
-
writeFileSync7(
|
|
12560
|
-
writeFileSync7(
|
|
12561
|
-
writeFileSync7(
|
|
12562
|
-
writeFileSync7(
|
|
12899
|
+
writeFileSync7(join20(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
|
|
12900
|
+
writeFileSync7(join20(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
|
|
12901
|
+
writeFileSync7(join20(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
|
|
12902
|
+
writeFileSync7(join20(checkpointDir, "checkpoint.json"), JSON.stringify({
|
|
12563
12903
|
cycle,
|
|
12564
12904
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12565
12905
|
gitHash,
|
|
@@ -12567,7 +12907,7 @@ Dreams directory: ${this.dreamsDir}`);
|
|
|
12567
12907
|
}, null, 2), "utf-8");
|
|
12568
12908
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
12569
12909
|
} catch {
|
|
12570
|
-
writeFileSync7(
|
|
12910
|
+
writeFileSync7(join20(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
|
|
12571
12911
|
renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
|
|
12572
12912
|
}
|
|
12573
12913
|
} catch (err) {
|
|
@@ -12604,7 +12944,7 @@ Each proposal includes implementation entrypoints and estimated effort.
|
|
|
12604
12944
|
/** Update the master proposal index */
|
|
12605
12945
|
updateProposalIndex() {
|
|
12606
12946
|
try {
|
|
12607
|
-
const files =
|
|
12947
|
+
const files = readdirSync8(this.dreamsDir).filter((f) => f.endsWith(".md") && f !== "PROPOSAL-INDEX.md" && f !== "dream-state.json").sort();
|
|
12608
12948
|
const index = `# Dream Proposals Index
|
|
12609
12949
|
|
|
12610
12950
|
**Last updated**: ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}
|
|
@@ -12625,14 +12965,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
|
|
|
12625
12965
|
---
|
|
12626
12966
|
*Auto-generated by open-agents dream engine*
|
|
12627
12967
|
`;
|
|
12628
|
-
writeFileSync7(
|
|
12968
|
+
writeFileSync7(join20(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
12629
12969
|
} catch {
|
|
12630
12970
|
}
|
|
12631
12971
|
}
|
|
12632
12972
|
/** Save dream state for resume/inspection */
|
|
12633
12973
|
saveDreamState() {
|
|
12634
12974
|
try {
|
|
12635
|
-
writeFileSync7(
|
|
12975
|
+
writeFileSync7(join20(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
12636
12976
|
} catch {
|
|
12637
12977
|
}
|
|
12638
12978
|
}
|
|
@@ -12921,23 +13261,23 @@ var init_status_bar = __esm({
|
|
|
12921
13261
|
import * as readline2 from "node:readline";
|
|
12922
13262
|
import { Writable } from "node:stream";
|
|
12923
13263
|
import { cwd } from "node:process";
|
|
12924
|
-
import { resolve as resolve12, join as
|
|
13264
|
+
import { resolve as resolve12, join as join21, dirname as dirname2 } from "node:path";
|
|
12925
13265
|
import { createRequire as createRequire2 } from "node:module";
|
|
12926
13266
|
import { fileURLToPath } from "node:url";
|
|
12927
|
-
import { readFileSync as
|
|
12928
|
-
import { existsSync as
|
|
13267
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
13268
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
12929
13269
|
import { extname as extname5 } from "node:path";
|
|
12930
13270
|
function getVersion() {
|
|
12931
13271
|
try {
|
|
12932
13272
|
const require2 = createRequire2(import.meta.url);
|
|
12933
13273
|
const thisDir = dirname2(fileURLToPath(import.meta.url));
|
|
12934
13274
|
const candidates = [
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
13275
|
+
join21(thisDir, "..", "package.json"),
|
|
13276
|
+
join21(thisDir, "..", "..", "package.json"),
|
|
13277
|
+
join21(thisDir, "..", "..", "..", "package.json")
|
|
12938
13278
|
];
|
|
12939
13279
|
for (const pkgPath of candidates) {
|
|
12940
|
-
if (
|
|
13280
|
+
if (existsSync15(pkgPath)) {
|
|
12941
13281
|
const pkg = require2(pkgPath);
|
|
12942
13282
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
12943
13283
|
return pkg.version ?? "0.0.0";
|
|
@@ -13011,7 +13351,10 @@ function buildTools(repoRoot, config) {
|
|
|
13011
13351
|
new CreateToolTool(repoRoot),
|
|
13012
13352
|
new ManageToolsTool(repoRoot),
|
|
13013
13353
|
// Load agent-created custom tools from .oa/tools/ and ~/.open-agents/tools/
|
|
13014
|
-
...buildCustomTools(repoRoot)
|
|
13354
|
+
...buildCustomTools(repoRoot),
|
|
13355
|
+
// Skill system (AIWG skills — discovery and execution)
|
|
13356
|
+
new SkillListTool(repoRoot),
|
|
13357
|
+
new SkillExecuteTool(repoRoot)
|
|
13015
13358
|
];
|
|
13016
13359
|
return [
|
|
13017
13360
|
...executionTools.map(adaptTool2),
|
|
@@ -13582,12 +13925,12 @@ ${c2.dim("Goodbye!")}
|
|
|
13582
13925
|
}
|
|
13583
13926
|
}
|
|
13584
13927
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
13585
|
-
const isImage = isImagePath(cleanPath) &&
|
|
13928
|
+
const isImage = isImagePath(cleanPath) && existsSync15(resolve12(repoRoot, cleanPath));
|
|
13586
13929
|
if (activeTask) {
|
|
13587
13930
|
if (isImage) {
|
|
13588
13931
|
try {
|
|
13589
13932
|
const imgPath = resolve12(repoRoot, cleanPath);
|
|
13590
|
-
const imgBuffer =
|
|
13933
|
+
const imgBuffer = readFileSync13(imgPath);
|
|
13591
13934
|
const base64 = imgBuffer.toString("base64");
|
|
13592
13935
|
const ext = extname5(cleanPath).toLowerCase();
|
|
13593
13936
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -13807,7 +14150,7 @@ import { glob } from "glob";
|
|
|
13807
14150
|
import ignore from "ignore";
|
|
13808
14151
|
import { readFile as readFile9, stat as stat2 } from "node:fs/promises";
|
|
13809
14152
|
import { createHash } from "node:crypto";
|
|
13810
|
-
import { join as
|
|
14153
|
+
import { join as join22, relative as relative3, extname as extname6, basename as basename6 } from "node:path";
|
|
13811
14154
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
13812
14155
|
var init_codebase_indexer = __esm({
|
|
13813
14156
|
"packages/indexer/dist/codebase-indexer.js"() {
|
|
@@ -13851,7 +14194,7 @@ var init_codebase_indexer = __esm({
|
|
|
13851
14194
|
const ig = ignore.default();
|
|
13852
14195
|
if (this.config.respectGitignore) {
|
|
13853
14196
|
try {
|
|
13854
|
-
const gitignoreContent = await readFile9(
|
|
14197
|
+
const gitignoreContent = await readFile9(join22(this.config.rootDir, ".gitignore"), "utf-8");
|
|
13855
14198
|
ig.add(gitignoreContent);
|
|
13856
14199
|
} catch {
|
|
13857
14200
|
}
|
|
@@ -13866,7 +14209,7 @@ var init_codebase_indexer = __esm({
|
|
|
13866
14209
|
for (const relativePath of files) {
|
|
13867
14210
|
if (ig.ignores(relativePath))
|
|
13868
14211
|
continue;
|
|
13869
|
-
const fullPath =
|
|
14212
|
+
const fullPath = join22(this.config.rootDir, relativePath);
|
|
13870
14213
|
try {
|
|
13871
14214
|
const fileStat = await stat2(fullPath);
|
|
13872
14215
|
if (fileStat.size > this.config.maxFileSize)
|
|
@@ -13889,7 +14232,7 @@ var init_codebase_indexer = __esm({
|
|
|
13889
14232
|
}
|
|
13890
14233
|
buildTree(files) {
|
|
13891
14234
|
const root = {
|
|
13892
|
-
name:
|
|
14235
|
+
name: basename6(this.config.rootDir),
|
|
13893
14236
|
path: this.config.rootDir,
|
|
13894
14237
|
type: "directory",
|
|
13895
14238
|
children: []
|
|
@@ -13912,7 +14255,7 @@ var init_codebase_indexer = __esm({
|
|
|
13912
14255
|
if (!child) {
|
|
13913
14256
|
child = {
|
|
13914
14257
|
name: part,
|
|
13915
|
-
path:
|
|
14258
|
+
path: join22(current.path, part),
|
|
13916
14259
|
type: "directory",
|
|
13917
14260
|
children: []
|
|
13918
14261
|
};
|
|
@@ -13987,13 +14330,13 @@ __export(index_repo_exports, {
|
|
|
13987
14330
|
indexRepoCommand: () => indexRepoCommand
|
|
13988
14331
|
});
|
|
13989
14332
|
import { resolve as resolve13 } from "node:path";
|
|
13990
|
-
import { existsSync as
|
|
14333
|
+
import { existsSync as existsSync16, statSync as statSync6 } from "node:fs";
|
|
13991
14334
|
import { cwd as cwd2 } from "node:process";
|
|
13992
14335
|
async function indexRepoCommand(opts, _config) {
|
|
13993
14336
|
const repoRoot = resolve13(opts.repoPath ?? cwd2());
|
|
13994
14337
|
printHeader("Index Repository");
|
|
13995
14338
|
printInfo(`Indexing: ${repoRoot}`);
|
|
13996
|
-
if (!
|
|
14339
|
+
if (!existsSync16(repoRoot)) {
|
|
13997
14340
|
printError(`Path does not exist: ${repoRoot}`);
|
|
13998
14341
|
process.exit(1);
|
|
13999
14342
|
}
|
|
@@ -14239,8 +14582,8 @@ var config_exports = {};
|
|
|
14239
14582
|
__export(config_exports, {
|
|
14240
14583
|
configCommand: () => configCommand
|
|
14241
14584
|
});
|
|
14242
|
-
import { join as
|
|
14243
|
-
import { homedir as
|
|
14585
|
+
import { join as join23, resolve as resolve14 } from "node:path";
|
|
14586
|
+
import { homedir as homedir9 } from "node:os";
|
|
14244
14587
|
import { cwd as cwd3 } from "node:process";
|
|
14245
14588
|
function coerceForSettings(key, value) {
|
|
14246
14589
|
if (INT_KEYS.has(key))
|
|
@@ -14292,7 +14635,7 @@ function handleShow(opts, config) {
|
|
|
14292
14635
|
}
|
|
14293
14636
|
}
|
|
14294
14637
|
printSection("Config File");
|
|
14295
|
-
printInfo(`~/.open-agents/config.json (${
|
|
14638
|
+
printInfo(`~/.open-agents/config.json (${join23(homedir9(), ".open-agents", "config.json")})`);
|
|
14296
14639
|
printSection("Priority Chain");
|
|
14297
14640
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
14298
14641
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -14331,7 +14674,7 @@ function handleSet(opts, _config) {
|
|
|
14331
14674
|
const coerced = coerceForSettings(key, value);
|
|
14332
14675
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
14333
14676
|
printSuccess(`Project override set: ${key} = ${value}`);
|
|
14334
|
-
printInfo(`Saved to ${
|
|
14677
|
+
printInfo(`Saved to ${join23(repoRoot, ".oa", "settings.json")}`);
|
|
14335
14678
|
printInfo("This override applies only when running in this workspace.");
|
|
14336
14679
|
} catch (err) {
|
|
14337
14680
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -14550,7 +14893,7 @@ __export(eval_exports, {
|
|
|
14550
14893
|
});
|
|
14551
14894
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
14552
14895
|
import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync8 } from "node:fs";
|
|
14553
|
-
import { join as
|
|
14896
|
+
import { join as join24 } from "node:path";
|
|
14554
14897
|
async function evalCommand(opts, config) {
|
|
14555
14898
|
const suiteName = opts.suite ?? "basic";
|
|
14556
14899
|
const suite = SUITES[suiteName];
|
|
@@ -14671,9 +15014,9 @@ async function evalCommand(opts, config) {
|
|
|
14671
15014
|
process.exit(failed > 0 ? 1 : 0);
|
|
14672
15015
|
}
|
|
14673
15016
|
function createTempEvalRepo() {
|
|
14674
|
-
const dir =
|
|
15017
|
+
const dir = join24(tmpdir3(), `open-agents-eval-${Date.now()}`);
|
|
14675
15018
|
mkdirSync9(dir, { recursive: true });
|
|
14676
|
-
writeFileSync8(
|
|
15019
|
+
writeFileSync8(join24(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
14677
15020
|
return dir;
|
|
14678
15021
|
}
|
|
14679
15022
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -14733,7 +15076,7 @@ init_updater();
|
|
|
14733
15076
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
14734
15077
|
import { createRequire as createRequire3 } from "node:module";
|
|
14735
15078
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
14736
|
-
import { dirname as dirname3, join as
|
|
15079
|
+
import { dirname as dirname3, join as join25 } from "node:path";
|
|
14737
15080
|
|
|
14738
15081
|
// packages/cli/dist/cli.js
|
|
14739
15082
|
import { createInterface } from "node:readline";
|
|
@@ -14840,7 +15183,7 @@ init_output();
|
|
|
14840
15183
|
function getVersion2() {
|
|
14841
15184
|
try {
|
|
14842
15185
|
const require2 = createRequire3(import.meta.url);
|
|
14843
|
-
const pkgPath =
|
|
15186
|
+
const pkgPath = join25(dirname3(fileURLToPath2(import.meta.url)), "..", "package.json");
|
|
14844
15187
|
const pkg = require2(pkgPath);
|
|
14845
15188
|
return pkg.version;
|
|
14846
15189
|
} catch {
|
package/package.json
CHANGED