open-agents-ai 0.35.2 → 0.36.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 +32 -1
- package/dist/index.js +539 -274
- package/dist/scripts/web_scrape.py +1273 -0
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -2906,6 +2906,7 @@ var init_explore_tools = __esm({
|
|
|
2906
2906
|
code_sandbox: "Run code in an isolated sandbox",
|
|
2907
2907
|
structured_read: "Read structured data files (CSV, JSON)",
|
|
2908
2908
|
sub_agent: "Delegate a subtask to a new agent instance",
|
|
2909
|
+
browser_action: "Automate headless Chrome: navigate, click, type, screenshot, read DOM",
|
|
2909
2910
|
background_run: "Run a shell command in the background",
|
|
2910
2911
|
task_status: "Check status of background tasks",
|
|
2911
2912
|
task_output: "Read output from a background task",
|
|
@@ -8650,6 +8651,259 @@ Note: Advanced Python pipeline not available \u2014 install pytesseract, opencv-
|
|
|
8650
8651
|
}
|
|
8651
8652
|
});
|
|
8652
8653
|
|
|
8654
|
+
// packages/execution/dist/tools/browser-action.js
|
|
8655
|
+
import { execSync as execSync15, spawn as spawn7 } from "node:child_process";
|
|
8656
|
+
import { existsSync as existsSync18, readFileSync as readFileSync13 } from "node:fs";
|
|
8657
|
+
import { join as join21, dirname as dirname8 } from "node:path";
|
|
8658
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
8659
|
+
async function probeService() {
|
|
8660
|
+
try {
|
|
8661
|
+
const controller = new AbortController();
|
|
8662
|
+
const timeout = setTimeout(() => controller.abort(), 3e3);
|
|
8663
|
+
const res = await fetch(`${BASE_URL}/health`, { signal: controller.signal });
|
|
8664
|
+
clearTimeout(timeout);
|
|
8665
|
+
return res.ok;
|
|
8666
|
+
} catch {
|
|
8667
|
+
return false;
|
|
8668
|
+
}
|
|
8669
|
+
}
|
|
8670
|
+
function findPython2() {
|
|
8671
|
+
for (const cmd of ["python3", "python"]) {
|
|
8672
|
+
try {
|
|
8673
|
+
const ver = execSync15(`${cmd} --version 2>&1`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
|
|
8674
|
+
if (ver.includes("Python 3"))
|
|
8675
|
+
return cmd;
|
|
8676
|
+
} catch {
|
|
8677
|
+
}
|
|
8678
|
+
}
|
|
8679
|
+
return null;
|
|
8680
|
+
}
|
|
8681
|
+
async function launchService() {
|
|
8682
|
+
if (await probeService())
|
|
8683
|
+
return null;
|
|
8684
|
+
const python = findPython2();
|
|
8685
|
+
if (!python)
|
|
8686
|
+
return "Python 3 not found. Install Python 3.9+ to use browser automation.";
|
|
8687
|
+
if (!existsSync18(SCRAPE_SCRIPT)) {
|
|
8688
|
+
return `Scrape service script not found at ${SCRAPE_SCRIPT}`;
|
|
8689
|
+
}
|
|
8690
|
+
serviceProcess = spawn7(python, [SCRAPE_SCRIPT], {
|
|
8691
|
+
stdio: "ignore",
|
|
8692
|
+
detached: true,
|
|
8693
|
+
env: {
|
|
8694
|
+
...process.env,
|
|
8695
|
+
SCRAPE_PORT: String(DEFAULT_PORT),
|
|
8696
|
+
SCRAPE_HEADLESS_DEFAULT: "1",
|
|
8697
|
+
SCRAPE_REQUIRE_AUTH: "0"
|
|
8698
|
+
}
|
|
8699
|
+
});
|
|
8700
|
+
serviceProcess.unref();
|
|
8701
|
+
for (let i = 0; i < 120; i++) {
|
|
8702
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
8703
|
+
if (await probeService())
|
|
8704
|
+
return null;
|
|
8705
|
+
}
|
|
8706
|
+
return "Scrape service failed to start within 60s. Check Chrome/Chromium installation.";
|
|
8707
|
+
}
|
|
8708
|
+
async function ensureSession() {
|
|
8709
|
+
if (activeSessionId) {
|
|
8710
|
+
try {
|
|
8711
|
+
const res2 = await fetch(`${BASE_URL}/health`);
|
|
8712
|
+
if (res2.ok)
|
|
8713
|
+
return { sessionId: activeSessionId };
|
|
8714
|
+
} catch {
|
|
8715
|
+
}
|
|
8716
|
+
activeSessionId = null;
|
|
8717
|
+
}
|
|
8718
|
+
const res = await fetch(`${BASE_URL}/session/start`, {
|
|
8719
|
+
method: "POST",
|
|
8720
|
+
headers: { "Content-Type": "application/json" },
|
|
8721
|
+
body: JSON.stringify({ headless: true })
|
|
8722
|
+
});
|
|
8723
|
+
const data = await res.json();
|
|
8724
|
+
if (!data.ok)
|
|
8725
|
+
return { error: String(data.message ?? "Failed to start browser session"), sessionId: "" };
|
|
8726
|
+
activeSessionId = data.session_id;
|
|
8727
|
+
return { sessionId: activeSessionId };
|
|
8728
|
+
}
|
|
8729
|
+
async function apiCall(endpoint, method = "POST", body) {
|
|
8730
|
+
const options = {
|
|
8731
|
+
method,
|
|
8732
|
+
headers: { "Content-Type": "application/json" }
|
|
8733
|
+
};
|
|
8734
|
+
if (body && method === "POST") {
|
|
8735
|
+
options.body = JSON.stringify({ sid: activeSessionId, ...body });
|
|
8736
|
+
}
|
|
8737
|
+
let url = `${BASE_URL}${endpoint}`;
|
|
8738
|
+
if (method === "GET" && activeSessionId) {
|
|
8739
|
+
url += `?sid=${encodeURIComponent(activeSessionId)}`;
|
|
8740
|
+
}
|
|
8741
|
+
const res = await fetch(url, options);
|
|
8742
|
+
return await res.json();
|
|
8743
|
+
}
|
|
8744
|
+
var __dirname2, SCRAPE_SCRIPT, DEFAULT_PORT, BASE_URL, serviceProcess, activeSessionId, BrowserActionTool;
|
|
8745
|
+
var init_browser_action = __esm({
|
|
8746
|
+
"packages/execution/dist/tools/browser-action.js"() {
|
|
8747
|
+
"use strict";
|
|
8748
|
+
__dirname2 = dirname8(fileURLToPath5(import.meta.url));
|
|
8749
|
+
SCRAPE_SCRIPT = join21(__dirname2, "..", "..", "scripts", "web_scrape.py");
|
|
8750
|
+
DEFAULT_PORT = 8130;
|
|
8751
|
+
BASE_URL = `http://localhost:${DEFAULT_PORT}`;
|
|
8752
|
+
serviceProcess = null;
|
|
8753
|
+
activeSessionId = null;
|
|
8754
|
+
BrowserActionTool = class {
|
|
8755
|
+
name = "browser_action";
|
|
8756
|
+
description = "Automate a headless Chrome browser: navigate to URLs, click elements, type text, take screenshots, read DOM content, scroll, and navigate history. Uses a local Selenium-based service that auto-starts on first use. Better than xdotool for web automation \u2014 works headlessly without a display server. Actions: navigate, click, click_xy, type, screenshot, dom, scroll, back, forward, close.";
|
|
8757
|
+
parameters = {
|
|
8758
|
+
type: "object",
|
|
8759
|
+
properties: {
|
|
8760
|
+
action: {
|
|
8761
|
+
type: "string",
|
|
8762
|
+
enum: ["navigate", "click", "click_xy", "type", "screenshot", "dom", "scroll", "scroll_up", "scroll_down", "back", "forward", "close"],
|
|
8763
|
+
description: "Browser action to perform"
|
|
8764
|
+
},
|
|
8765
|
+
url: {
|
|
8766
|
+
type: "string",
|
|
8767
|
+
description: "URL to navigate to (for 'navigate' action)"
|
|
8768
|
+
},
|
|
8769
|
+
selector: {
|
|
8770
|
+
type: "string",
|
|
8771
|
+
description: "CSS selector of element to interact with (for 'click' and 'type' actions)"
|
|
8772
|
+
},
|
|
8773
|
+
text: {
|
|
8774
|
+
type: "string",
|
|
8775
|
+
description: "Text to type into the selected element (for 'type' action)"
|
|
8776
|
+
},
|
|
8777
|
+
x: {
|
|
8778
|
+
type: "number",
|
|
8779
|
+
description: "X coordinate for click_xy action (viewport pixels)"
|
|
8780
|
+
},
|
|
8781
|
+
y: {
|
|
8782
|
+
type: "number",
|
|
8783
|
+
description: "Y coordinate for click_xy action (viewport pixels)"
|
|
8784
|
+
},
|
|
8785
|
+
amount: {
|
|
8786
|
+
type: "number",
|
|
8787
|
+
description: "Scroll amount in pixels (for 'scroll' action, default 600)"
|
|
8788
|
+
}
|
|
8789
|
+
},
|
|
8790
|
+
required: ["action"]
|
|
8791
|
+
};
|
|
8792
|
+
async execute(args) {
|
|
8793
|
+
const start = Date.now();
|
|
8794
|
+
const action = args.action;
|
|
8795
|
+
const launchErr = await launchService();
|
|
8796
|
+
if (launchErr) {
|
|
8797
|
+
return { success: false, output: "", error: launchErr, durationMs: Date.now() - start };
|
|
8798
|
+
}
|
|
8799
|
+
if (action === "close") {
|
|
8800
|
+
if (activeSessionId) {
|
|
8801
|
+
try {
|
|
8802
|
+
await apiCall("/session/close");
|
|
8803
|
+
} catch {
|
|
8804
|
+
}
|
|
8805
|
+
activeSessionId = null;
|
|
8806
|
+
}
|
|
8807
|
+
return { success: true, output: "Browser session closed.", durationMs: Date.now() - start };
|
|
8808
|
+
}
|
|
8809
|
+
const session = await ensureSession();
|
|
8810
|
+
if (session.error) {
|
|
8811
|
+
return { success: false, output: "", error: session.error, durationMs: Date.now() - start };
|
|
8812
|
+
}
|
|
8813
|
+
try {
|
|
8814
|
+
let result;
|
|
8815
|
+
switch (action) {
|
|
8816
|
+
case "navigate":
|
|
8817
|
+
if (!args.url)
|
|
8818
|
+
return { success: false, output: "", error: "url is required for navigate action", durationMs: Date.now() - start };
|
|
8819
|
+
result = await apiCall("/navigate", "POST", { url: args.url });
|
|
8820
|
+
return {
|
|
8821
|
+
success: !!result.ok,
|
|
8822
|
+
output: result.ok ? `Navigated to ${args.url}` : String(result.message ?? "Navigation failed"),
|
|
8823
|
+
durationMs: Date.now() - start
|
|
8824
|
+
};
|
|
8825
|
+
case "click":
|
|
8826
|
+
if (!args.selector)
|
|
8827
|
+
return { success: false, output: "", error: "selector is required for click action", durationMs: Date.now() - start };
|
|
8828
|
+
result = await apiCall("/click", "POST", { selector: args.selector });
|
|
8829
|
+
return {
|
|
8830
|
+
success: !!result.ok,
|
|
8831
|
+
output: result.ok ? `Clicked element: ${args.selector}` : String(result.message ?? "Click failed"),
|
|
8832
|
+
durationMs: Date.now() - start
|
|
8833
|
+
};
|
|
8834
|
+
case "click_xy":
|
|
8835
|
+
if (args.x == null || args.y == null)
|
|
8836
|
+
return { success: false, output: "", error: "x and y are required for click_xy action", durationMs: Date.now() - start };
|
|
8837
|
+
result = await apiCall("/click_xy", "POST", { x: args.x, y: args.y });
|
|
8838
|
+
return {
|
|
8839
|
+
success: !!result.ok,
|
|
8840
|
+
output: result.ok ? `Clicked at (${args.x}, ${args.y})` : String(result.message ?? "Click failed"),
|
|
8841
|
+
durationMs: Date.now() - start
|
|
8842
|
+
};
|
|
8843
|
+
case "type":
|
|
8844
|
+
if (!args.selector || !args.text)
|
|
8845
|
+
return { success: false, output: "", error: "selector and text are required for type action", durationMs: Date.now() - start };
|
|
8846
|
+
result = await apiCall("/type", "POST", { selector: args.selector, text: args.text });
|
|
8847
|
+
return {
|
|
8848
|
+
success: !!result.ok,
|
|
8849
|
+
output: result.ok ? `Typed "${args.text.slice(0, 50)}" into ${args.selector}` : String(result.message ?? "Type failed"),
|
|
8850
|
+
durationMs: Date.now() - start
|
|
8851
|
+
};
|
|
8852
|
+
case "screenshot": {
|
|
8853
|
+
result = await apiCall("/screenshot", "GET");
|
|
8854
|
+
const b64 = result.b64;
|
|
8855
|
+
const width = result.width;
|
|
8856
|
+
const height = result.height;
|
|
8857
|
+
if (b64) {
|
|
8858
|
+
return {
|
|
8859
|
+
success: true,
|
|
8860
|
+
output: `Screenshot captured (${width}x${height}). Base64 length: ${b64.length} chars.
|
|
8861
|
+
[IMAGE_BASE64:image/png:${b64.slice(0, 200)}...]`,
|
|
8862
|
+
durationMs: Date.now() - start
|
|
8863
|
+
};
|
|
8864
|
+
}
|
|
8865
|
+
return { success: false, output: "", error: "Screenshot failed", durationMs: Date.now() - start };
|
|
8866
|
+
}
|
|
8867
|
+
case "dom": {
|
|
8868
|
+
result = await apiCall("/dom", "GET");
|
|
8869
|
+
const dom = result.dom;
|
|
8870
|
+
if (dom) {
|
|
8871
|
+
const truncated = dom.length > 5e4 ? dom.slice(0, 5e4) + "\n... (truncated)" : dom;
|
|
8872
|
+
return { success: true, output: truncated, durationMs: Date.now() - start };
|
|
8873
|
+
}
|
|
8874
|
+
return { success: false, output: "", error: "DOM capture failed", durationMs: Date.now() - start };
|
|
8875
|
+
}
|
|
8876
|
+
case "scroll":
|
|
8877
|
+
result = await apiCall("/scroll", "POST", { amount: args.amount ?? 600 });
|
|
8878
|
+
return { success: !!result.ok, output: `Scrolled ${args.amount ?? 600}px`, durationMs: Date.now() - start };
|
|
8879
|
+
case "scroll_up":
|
|
8880
|
+
result = await apiCall("/scroll/up", "POST");
|
|
8881
|
+
return { success: !!result.ok, output: "Scrolled up", durationMs: Date.now() - start };
|
|
8882
|
+
case "scroll_down":
|
|
8883
|
+
result = await apiCall("/scroll/down", "POST");
|
|
8884
|
+
return { success: !!result.ok, output: "Scrolled down", durationMs: Date.now() - start };
|
|
8885
|
+
case "back":
|
|
8886
|
+
result = await apiCall("/history/back", "POST");
|
|
8887
|
+
return { success: !!result.ok, output: "Navigated back", durationMs: Date.now() - start };
|
|
8888
|
+
case "forward":
|
|
8889
|
+
result = await apiCall("/history/forward", "POST");
|
|
8890
|
+
return { success: !!result.ok, output: "Navigated forward", durationMs: Date.now() - start };
|
|
8891
|
+
default:
|
|
8892
|
+
return { success: false, output: "", error: `Unknown action: ${action}. Available: navigate, click, click_xy, type, screenshot, dom, scroll, scroll_up, scroll_down, back, forward, close`, durationMs: Date.now() - start };
|
|
8893
|
+
}
|
|
8894
|
+
} catch (err) {
|
|
8895
|
+
return {
|
|
8896
|
+
success: false,
|
|
8897
|
+
output: "",
|
|
8898
|
+
error: `Browser action failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
8899
|
+
durationMs: Date.now() - start
|
|
8900
|
+
};
|
|
8901
|
+
}
|
|
8902
|
+
}
|
|
8903
|
+
};
|
|
8904
|
+
}
|
|
8905
|
+
});
|
|
8906
|
+
|
|
8653
8907
|
// packages/execution/dist/shellRunner.js
|
|
8654
8908
|
var init_shellRunner = __esm({
|
|
8655
8909
|
"packages/execution/dist/shellRunner.js"() {
|
|
@@ -8765,6 +9019,7 @@ var init_dist2 = __esm({
|
|
|
8765
9019
|
init_ocr_pdf();
|
|
8766
9020
|
init_pdf_to_text();
|
|
8767
9021
|
init_ocr_image_advanced();
|
|
9022
|
+
init_browser_action();
|
|
8768
9023
|
init_system_deps();
|
|
8769
9024
|
init_shellRunner();
|
|
8770
9025
|
init_gitWorktree();
|
|
@@ -9897,7 +10152,7 @@ var init_code_retriever = __esm({
|
|
|
9897
10152
|
import { execFile as execFile5 } from "node:child_process";
|
|
9898
10153
|
import { promisify as promisify4 } from "node:util";
|
|
9899
10154
|
import { readFile as readFile9, readdir as readdir3, stat as stat3 } from "node:fs/promises";
|
|
9900
|
-
import { join as
|
|
10155
|
+
import { join as join22, extname as extname7 } from "node:path";
|
|
9901
10156
|
async function searchByPath(pathPattern, options) {
|
|
9902
10157
|
const allFiles = await collectFiles(options.rootDir, options.includeGlobs ?? DEFAULT_INCLUDE_GLOBS, options.excludeGlobs ?? DEFAULT_EXCLUDE_GLOBS);
|
|
9903
10158
|
const pattern = options.caseInsensitive ? pathPattern.toLowerCase() : pathPattern;
|
|
@@ -10039,7 +10294,7 @@ async function walkForFiles(rootDir, dir, excludeGlobs, results) {
|
|
|
10039
10294
|
continue;
|
|
10040
10295
|
if (excludeGlobs.some((g) => entry.name === g || matchesGlob(entry.name, g)))
|
|
10041
10296
|
continue;
|
|
10042
|
-
const absPath =
|
|
10297
|
+
const absPath = join22(dir, entry.name);
|
|
10043
10298
|
if (entry.isDirectory()) {
|
|
10044
10299
|
await walkForFiles(rootDir, absPath, excludeGlobs, results);
|
|
10045
10300
|
} else if (entry.isFile()) {
|
|
@@ -10346,7 +10601,7 @@ var init_graphExpand = __esm({
|
|
|
10346
10601
|
|
|
10347
10602
|
// packages/retrieval/dist/snippetPacker.js
|
|
10348
10603
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
10349
|
-
import { join as
|
|
10604
|
+
import { join as join23 } from "node:path";
|
|
10350
10605
|
async function packSnippets(requests, opts = {}) {
|
|
10351
10606
|
const maxTokens = opts.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
10352
10607
|
const contextLines = opts.contextLines ?? DEFAULT_CONTEXT_LINES;
|
|
@@ -10372,7 +10627,7 @@ async function packSnippets(requests, opts = {}) {
|
|
|
10372
10627
|
return { packed, dropped, totalTokens };
|
|
10373
10628
|
}
|
|
10374
10629
|
async function extractSnippet(req, repoRoot, contextLines = DEFAULT_CONTEXT_LINES) {
|
|
10375
|
-
const absPath = req.filePath.startsWith("/") ? req.filePath :
|
|
10630
|
+
const absPath = req.filePath.startsWith("/") ? req.filePath : join23(repoRoot, req.filePath);
|
|
10376
10631
|
let content;
|
|
10377
10632
|
try {
|
|
10378
10633
|
content = await readFile10(absPath, "utf-8");
|
|
@@ -12298,7 +12553,8 @@ Integrate this guidance into your current approach. Continue working on the task
|
|
|
12298
12553
|
"task_output",
|
|
12299
12554
|
"image_read",
|
|
12300
12555
|
"screenshot",
|
|
12301
|
-
"ocr"
|
|
12556
|
+
"ocr",
|
|
12557
|
+
"browser_action"
|
|
12302
12558
|
]);
|
|
12303
12559
|
const executeSingle = async (tc) => {
|
|
12304
12560
|
if (this.aborted)
|
|
@@ -12789,8 +13045,8 @@ ${marker}` : marker);
|
|
|
12789
13045
|
return;
|
|
12790
13046
|
try {
|
|
12791
13047
|
const { mkdirSync: mkdirSync13, writeFileSync: writeFileSync12 } = __require("node:fs");
|
|
12792
|
-
const { join:
|
|
12793
|
-
const sessionDir =
|
|
13048
|
+
const { join: join38 } = __require("node:path");
|
|
13049
|
+
const sessionDir = join38(this._workingDirectory, ".oa", "session", this._sessionId);
|
|
12794
13050
|
mkdirSync13(sessionDir, { recursive: true });
|
|
12795
13051
|
const checkpoint = {
|
|
12796
13052
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -12803,7 +13059,7 @@ ${marker}` : marker);
|
|
|
12803
13059
|
memexEntryCount: this._memexArchive.size,
|
|
12804
13060
|
fileRegistrySize: this._fileRegistry.size
|
|
12805
13061
|
};
|
|
12806
|
-
writeFileSync12(
|
|
13062
|
+
writeFileSync12(join38(sessionDir, "checkpoint.json"), JSON.stringify(checkpoint, null, 2));
|
|
12807
13063
|
} catch {
|
|
12808
13064
|
}
|
|
12809
13065
|
}
|
|
@@ -13759,6 +14015,7 @@ ${transcript}`
|
|
|
13759
14015
|
temperature: request.temperature,
|
|
13760
14016
|
max_tokens: request.maxTokens,
|
|
13761
14017
|
stream: true,
|
|
14018
|
+
stream_options: { include_usage: true },
|
|
13762
14019
|
think: true
|
|
13763
14020
|
};
|
|
13764
14021
|
const resp = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
@@ -14340,11 +14597,11 @@ var init_dist5 = __esm({
|
|
|
14340
14597
|
});
|
|
14341
14598
|
|
|
14342
14599
|
// packages/cli/dist/tui/listen.js
|
|
14343
|
-
import { spawn as
|
|
14344
|
-
import { existsSync as
|
|
14345
|
-
import { join as
|
|
14600
|
+
import { spawn as spawn8, execSync as execSync16 } from "node:child_process";
|
|
14601
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readdirSync as readdirSync6 } from "node:fs";
|
|
14602
|
+
import { join as join24, dirname as dirname9 } from "node:path";
|
|
14346
14603
|
import { homedir as homedir8 } from "node:os";
|
|
14347
|
-
import { fileURLToPath as
|
|
14604
|
+
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
14348
14605
|
import { EventEmitter } from "node:events";
|
|
14349
14606
|
import { createInterface as createInterface2 } from "node:readline";
|
|
14350
14607
|
function isAudioPath(path) {
|
|
@@ -14362,7 +14619,7 @@ function findMicCaptureCommand() {
|
|
|
14362
14619
|
const platform4 = process.platform;
|
|
14363
14620
|
if (platform4 === "linux") {
|
|
14364
14621
|
try {
|
|
14365
|
-
|
|
14622
|
+
execSync16("which arecord", { stdio: "pipe" });
|
|
14366
14623
|
return {
|
|
14367
14624
|
cmd: "arecord",
|
|
14368
14625
|
args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
|
|
@@ -14372,7 +14629,7 @@ function findMicCaptureCommand() {
|
|
|
14372
14629
|
}
|
|
14373
14630
|
if (platform4 === "darwin") {
|
|
14374
14631
|
try {
|
|
14375
|
-
|
|
14632
|
+
execSync16("which sox", { stdio: "pipe" });
|
|
14376
14633
|
return {
|
|
14377
14634
|
cmd: "sox",
|
|
14378
14635
|
args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
|
|
@@ -14381,7 +14638,7 @@ function findMicCaptureCommand() {
|
|
|
14381
14638
|
}
|
|
14382
14639
|
}
|
|
14383
14640
|
try {
|
|
14384
|
-
|
|
14641
|
+
execSync16("which ffmpeg", { stdio: "pipe" });
|
|
14385
14642
|
if (platform4 === "linux") {
|
|
14386
14643
|
return {
|
|
14387
14644
|
cmd: "ffmpeg",
|
|
@@ -14426,41 +14683,41 @@ function findMicCaptureCommand() {
|
|
|
14426
14683
|
return null;
|
|
14427
14684
|
}
|
|
14428
14685
|
function findLiveWhisperScript() {
|
|
14429
|
-
const thisDir =
|
|
14686
|
+
const thisDir = dirname9(fileURLToPath6(import.meta.url));
|
|
14430
14687
|
const candidates = [
|
|
14431
|
-
|
|
14432
|
-
|
|
14433
|
-
|
|
14688
|
+
join24(thisDir, "../../../../packages/execution/scripts/live-whisper.py"),
|
|
14689
|
+
join24(thisDir, "../../../packages/execution/scripts/live-whisper.py"),
|
|
14690
|
+
join24(thisDir, "../../execution/scripts/live-whisper.py"),
|
|
14434
14691
|
// npm install layout — scripts bundled alongside dist
|
|
14435
|
-
|
|
14436
|
-
|
|
14692
|
+
join24(thisDir, "../scripts/live-whisper.py"),
|
|
14693
|
+
join24(thisDir, "../../scripts/live-whisper.py")
|
|
14437
14694
|
];
|
|
14438
14695
|
for (const p of candidates) {
|
|
14439
|
-
if (
|
|
14696
|
+
if (existsSync19(p))
|
|
14440
14697
|
return p;
|
|
14441
14698
|
}
|
|
14442
14699
|
try {
|
|
14443
|
-
const globalRoot =
|
|
14700
|
+
const globalRoot = execSync16("npm root -g", {
|
|
14444
14701
|
encoding: "utf-8",
|
|
14445
14702
|
timeout: 5e3,
|
|
14446
14703
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14447
14704
|
}).trim();
|
|
14448
14705
|
const candidates2 = [
|
|
14449
|
-
|
|
14450
|
-
|
|
14706
|
+
join24(globalRoot, "open-agents-ai", "dist", "scripts", "live-whisper.py"),
|
|
14707
|
+
join24(globalRoot, "open-agents-ai", "scripts", "live-whisper.py")
|
|
14451
14708
|
];
|
|
14452
14709
|
for (const p of candidates2) {
|
|
14453
|
-
if (
|
|
14710
|
+
if (existsSync19(p))
|
|
14454
14711
|
return p;
|
|
14455
14712
|
}
|
|
14456
14713
|
} catch {
|
|
14457
14714
|
}
|
|
14458
|
-
const nvmBase =
|
|
14459
|
-
if (
|
|
14715
|
+
const nvmBase = join24(homedir8(), ".nvm", "versions", "node");
|
|
14716
|
+
if (existsSync19(nvmBase)) {
|
|
14460
14717
|
try {
|
|
14461
14718
|
for (const ver of readdirSync6(nvmBase)) {
|
|
14462
|
-
const p =
|
|
14463
|
-
if (
|
|
14719
|
+
const p = join24(nvmBase, ver, "lib", "node_modules", "open-agents-ai", "dist", "scripts", "live-whisper.py");
|
|
14720
|
+
if (existsSync19(p))
|
|
14464
14721
|
return p;
|
|
14465
14722
|
}
|
|
14466
14723
|
} catch {
|
|
@@ -14473,12 +14730,12 @@ function ensureTranscribeCliBackground() {
|
|
|
14473
14730
|
return;
|
|
14474
14731
|
_bgInstallPromise = (async () => {
|
|
14475
14732
|
try {
|
|
14476
|
-
const globalRoot =
|
|
14733
|
+
const globalRoot = execSync16("npm root -g", {
|
|
14477
14734
|
encoding: "utf-8",
|
|
14478
14735
|
timeout: 5e3,
|
|
14479
14736
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14480
14737
|
}).trim();
|
|
14481
|
-
if (
|
|
14738
|
+
if (existsSync19(join24(globalRoot, "transcribe-cli", "dist", "index.js"))) {
|
|
14482
14739
|
return true;
|
|
14483
14740
|
}
|
|
14484
14741
|
} catch {
|
|
@@ -14544,7 +14801,7 @@ var init_listen = __esm({
|
|
|
14544
14801
|
const timeout = setTimeout(() => {
|
|
14545
14802
|
reject(new Error("Whisper fallback: model load timeout (5 min). First run downloads the model."));
|
|
14546
14803
|
}, 3e5);
|
|
14547
|
-
this.process =
|
|
14804
|
+
this.process = spawn8("python3", [
|
|
14548
14805
|
this.scriptPath,
|
|
14549
14806
|
"--model",
|
|
14550
14807
|
this.model,
|
|
@@ -14673,7 +14930,7 @@ var init_listen = __esm({
|
|
|
14673
14930
|
}
|
|
14674
14931
|
if (!this.transcribeCliAvailable) {
|
|
14675
14932
|
try {
|
|
14676
|
-
|
|
14933
|
+
execSync16("which transcribe-cli", { stdio: "pipe" });
|
|
14677
14934
|
this.transcribeCliAvailable = true;
|
|
14678
14935
|
} catch {
|
|
14679
14936
|
this.transcribeCliAvailable = false;
|
|
@@ -14690,29 +14947,29 @@ var init_listen = __esm({
|
|
|
14690
14947
|
} catch {
|
|
14691
14948
|
}
|
|
14692
14949
|
try {
|
|
14693
|
-
const globalRoot =
|
|
14950
|
+
const globalRoot = execSync16("npm root -g", {
|
|
14694
14951
|
encoding: "utf-8",
|
|
14695
14952
|
timeout: 5e3,
|
|
14696
14953
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14697
14954
|
}).trim();
|
|
14698
|
-
const tcPath =
|
|
14699
|
-
if (
|
|
14955
|
+
const tcPath = join24(globalRoot, "transcribe-cli");
|
|
14956
|
+
if (existsSync19(join24(tcPath, "dist", "index.js"))) {
|
|
14700
14957
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
14701
14958
|
const req = createRequire4(import.meta.url);
|
|
14702
|
-
return req(
|
|
14959
|
+
return req(join24(tcPath, "dist", "index.js"));
|
|
14703
14960
|
}
|
|
14704
14961
|
} catch {
|
|
14705
14962
|
}
|
|
14706
|
-
const nvmBase =
|
|
14707
|
-
if (
|
|
14963
|
+
const nvmBase = join24(homedir8(), ".nvm", "versions", "node");
|
|
14964
|
+
if (existsSync19(nvmBase)) {
|
|
14708
14965
|
try {
|
|
14709
14966
|
const { readdirSync: readdirSync11 } = await import("node:fs");
|
|
14710
14967
|
for (const ver of readdirSync11(nvmBase)) {
|
|
14711
|
-
const tcPath =
|
|
14712
|
-
if (
|
|
14968
|
+
const tcPath = join24(nvmBase, ver, "lib", "node_modules", "transcribe-cli");
|
|
14969
|
+
if (existsSync19(join24(tcPath, "dist", "index.js"))) {
|
|
14713
14970
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
14714
14971
|
const req = createRequire4(import.meta.url);
|
|
14715
|
-
return req(
|
|
14972
|
+
return req(join24(tcPath, "dist", "index.js"));
|
|
14716
14973
|
}
|
|
14717
14974
|
}
|
|
14718
14975
|
} catch {
|
|
@@ -14740,7 +14997,7 @@ var init_listen = __esm({
|
|
|
14740
14997
|
}
|
|
14741
14998
|
if (!tc) {
|
|
14742
14999
|
try {
|
|
14743
|
-
|
|
15000
|
+
execSync16("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
|
|
14744
15001
|
this.transcribeCliAvailable = null;
|
|
14745
15002
|
tc = await this.loadTranscribeCli();
|
|
14746
15003
|
} catch {
|
|
@@ -14826,7 +15083,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
14826
15083
|
return `Failed to start live transcription: ${msg}${tcHint}`;
|
|
14827
15084
|
}
|
|
14828
15085
|
}
|
|
14829
|
-
this.micProcess =
|
|
15086
|
+
this.micProcess = spawn8(micCmd.cmd, micCmd.args, {
|
|
14830
15087
|
stdio: ["pipe", "pipe", "pipe"],
|
|
14831
15088
|
env: { ...process.env }
|
|
14832
15089
|
});
|
|
@@ -14921,7 +15178,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
14921
15178
|
}
|
|
14922
15179
|
if (!tc) {
|
|
14923
15180
|
try {
|
|
14924
|
-
|
|
15181
|
+
execSync16("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
|
|
14925
15182
|
this.transcribeCliAvailable = null;
|
|
14926
15183
|
tc = await this.loadTranscribeCli();
|
|
14927
15184
|
} catch {
|
|
@@ -14938,9 +15195,9 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
14938
15195
|
});
|
|
14939
15196
|
if (outputDir) {
|
|
14940
15197
|
const { basename: basename14 } = await import("node:path");
|
|
14941
|
-
const transcriptDir =
|
|
15198
|
+
const transcriptDir = join24(outputDir, ".oa", "transcripts");
|
|
14942
15199
|
mkdirSync5(transcriptDir, { recursive: true });
|
|
14943
|
-
const outFile =
|
|
15200
|
+
const outFile = join24(transcriptDir, `${basename14(filePath)}.txt`);
|
|
14944
15201
|
writeFileSync5(outFile, result.text, "utf-8");
|
|
14945
15202
|
}
|
|
14946
15203
|
return {
|
|
@@ -16220,8 +16477,8 @@ Approach this task thoughtfully:
|
|
|
16220
16477
|
});
|
|
16221
16478
|
|
|
16222
16479
|
// packages/prompts/dist/index.js
|
|
16223
|
-
import { join as
|
|
16224
|
-
import { fileURLToPath as
|
|
16480
|
+
import { join as join25, dirname as dirname10 } from "node:path";
|
|
16481
|
+
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
16225
16482
|
var _dir, _packageRoot;
|
|
16226
16483
|
var init_dist6 = __esm({
|
|
16227
16484
|
"packages/prompts/dist/index.js"() {
|
|
@@ -16230,25 +16487,25 @@ var init_dist6 = __esm({
|
|
|
16230
16487
|
init_render2();
|
|
16231
16488
|
init_task_templates();
|
|
16232
16489
|
init_render2();
|
|
16233
|
-
_dir =
|
|
16234
|
-
_packageRoot =
|
|
16490
|
+
_dir = dirname10(fileURLToPath7(import.meta.url));
|
|
16491
|
+
_packageRoot = join25(_dir, "..");
|
|
16235
16492
|
}
|
|
16236
16493
|
});
|
|
16237
16494
|
|
|
16238
16495
|
// packages/cli/dist/tui/oa-directory.js
|
|
16239
|
-
import { existsSync as
|
|
16240
|
-
import { join as
|
|
16496
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync6, readFileSync as readFileSync14, writeFileSync as writeFileSync6, readdirSync as readdirSync7, statSync as statSync9, unlinkSync as unlinkSync3 } from "node:fs";
|
|
16497
|
+
import { join as join26, relative as relative2, basename as basename9, extname as extname8 } from "node:path";
|
|
16241
16498
|
import { homedir as homedir9 } from "node:os";
|
|
16242
16499
|
function initOaDirectory(repoRoot) {
|
|
16243
|
-
const oaPath =
|
|
16500
|
+
const oaPath = join26(repoRoot, OA_DIR);
|
|
16244
16501
|
for (const sub of SUBDIRS) {
|
|
16245
|
-
mkdirSync6(
|
|
16502
|
+
mkdirSync6(join26(oaPath, sub), { recursive: true });
|
|
16246
16503
|
}
|
|
16247
16504
|
try {
|
|
16248
|
-
const gitignorePath =
|
|
16505
|
+
const gitignorePath = join26(repoRoot, ".gitignore");
|
|
16249
16506
|
const settingsPattern = ".oa/settings.json";
|
|
16250
|
-
if (
|
|
16251
|
-
const content =
|
|
16507
|
+
if (existsSync20(gitignorePath)) {
|
|
16508
|
+
const content = readFileSync14(gitignorePath, "utf-8");
|
|
16252
16509
|
if (!content.includes(settingsPattern)) {
|
|
16253
16510
|
writeFileSync6(gitignorePath, content.trimEnd() + "\n" + settingsPattern + "\n", "utf-8");
|
|
16254
16511
|
}
|
|
@@ -16258,41 +16515,41 @@ function initOaDirectory(repoRoot) {
|
|
|
16258
16515
|
return oaPath;
|
|
16259
16516
|
}
|
|
16260
16517
|
function hasOaDirectory(repoRoot) {
|
|
16261
|
-
return
|
|
16518
|
+
return existsSync20(join26(repoRoot, OA_DIR, "index"));
|
|
16262
16519
|
}
|
|
16263
16520
|
function loadProjectSettings(repoRoot) {
|
|
16264
|
-
const settingsPath =
|
|
16521
|
+
const settingsPath = join26(repoRoot, OA_DIR, "settings.json");
|
|
16265
16522
|
try {
|
|
16266
|
-
if (
|
|
16267
|
-
return JSON.parse(
|
|
16523
|
+
if (existsSync20(settingsPath)) {
|
|
16524
|
+
return JSON.parse(readFileSync14(settingsPath, "utf-8"));
|
|
16268
16525
|
}
|
|
16269
16526
|
} catch {
|
|
16270
16527
|
}
|
|
16271
16528
|
return {};
|
|
16272
16529
|
}
|
|
16273
16530
|
function saveProjectSettings(repoRoot, settings) {
|
|
16274
|
-
const oaPath =
|
|
16531
|
+
const oaPath = join26(repoRoot, OA_DIR);
|
|
16275
16532
|
mkdirSync6(oaPath, { recursive: true });
|
|
16276
16533
|
const existing = loadProjectSettings(repoRoot);
|
|
16277
16534
|
const merged = { ...existing, ...settings };
|
|
16278
|
-
writeFileSync6(
|
|
16535
|
+
writeFileSync6(join26(oaPath, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
16279
16536
|
}
|
|
16280
16537
|
function loadGlobalSettings() {
|
|
16281
|
-
const settingsPath =
|
|
16538
|
+
const settingsPath = join26(homedir9(), ".open-agents", "settings.json");
|
|
16282
16539
|
try {
|
|
16283
|
-
if (
|
|
16284
|
-
return JSON.parse(
|
|
16540
|
+
if (existsSync20(settingsPath)) {
|
|
16541
|
+
return JSON.parse(readFileSync14(settingsPath, "utf-8"));
|
|
16285
16542
|
}
|
|
16286
16543
|
} catch {
|
|
16287
16544
|
}
|
|
16288
16545
|
return {};
|
|
16289
16546
|
}
|
|
16290
16547
|
function saveGlobalSettings(settings) {
|
|
16291
|
-
const dir =
|
|
16548
|
+
const dir = join26(homedir9(), ".open-agents");
|
|
16292
16549
|
mkdirSync6(dir, { recursive: true });
|
|
16293
16550
|
const existing = loadGlobalSettings();
|
|
16294
16551
|
const merged = { ...existing, ...settings };
|
|
16295
|
-
writeFileSync6(
|
|
16552
|
+
writeFileSync6(join26(dir, "settings.json"), JSON.stringify(merged, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
16296
16553
|
}
|
|
16297
16554
|
function resolveSettings(repoRoot) {
|
|
16298
16555
|
const global = loadGlobalSettings();
|
|
@@ -16307,12 +16564,12 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
16307
16564
|
while (dir && !visited.has(dir)) {
|
|
16308
16565
|
visited.add(dir);
|
|
16309
16566
|
for (const name of CONTEXT_FILES) {
|
|
16310
|
-
const filePath =
|
|
16567
|
+
const filePath = join26(dir, name);
|
|
16311
16568
|
const normalizedName = name.toLowerCase();
|
|
16312
|
-
if (
|
|
16569
|
+
if (existsSync20(filePath) && !seen.has(filePath)) {
|
|
16313
16570
|
seen.add(filePath);
|
|
16314
16571
|
try {
|
|
16315
|
-
let content =
|
|
16572
|
+
let content = readFileSync14(filePath, "utf-8");
|
|
16316
16573
|
if (content.length > maxContentLen) {
|
|
16317
16574
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
16318
16575
|
}
|
|
@@ -16326,11 +16583,11 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
16326
16583
|
}
|
|
16327
16584
|
}
|
|
16328
16585
|
}
|
|
16329
|
-
const projectMap =
|
|
16330
|
-
if (
|
|
16586
|
+
const projectMap = join26(dir, OA_DIR, "context", "project-map.md");
|
|
16587
|
+
if (existsSync20(projectMap) && !seen.has(projectMap)) {
|
|
16331
16588
|
seen.add(projectMap);
|
|
16332
16589
|
try {
|
|
16333
|
-
let content =
|
|
16590
|
+
let content = readFileSync14(projectMap, "utf-8");
|
|
16334
16591
|
if (content.length > maxContentLen) {
|
|
16335
16592
|
content = content.slice(0, maxContentLen) + "\n\n...(truncated)";
|
|
16336
16593
|
}
|
|
@@ -16342,7 +16599,7 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
16342
16599
|
} catch {
|
|
16343
16600
|
}
|
|
16344
16601
|
}
|
|
16345
|
-
const parent =
|
|
16602
|
+
const parent = join26(dir, "..");
|
|
16346
16603
|
if (parent === dir)
|
|
16347
16604
|
break;
|
|
16348
16605
|
dir = parent;
|
|
@@ -16360,9 +16617,9 @@ function discoverContextFiles(repoRoot, maxContentLen = 8e3) {
|
|
|
16360
16617
|
return found;
|
|
16361
16618
|
}
|
|
16362
16619
|
function readIndexMeta(repoRoot) {
|
|
16363
|
-
const metaPath =
|
|
16620
|
+
const metaPath = join26(repoRoot, OA_DIR, "index", "meta.json");
|
|
16364
16621
|
try {
|
|
16365
|
-
return JSON.parse(
|
|
16622
|
+
return JSON.parse(readFileSync14(metaPath, "utf-8"));
|
|
16366
16623
|
} catch {
|
|
16367
16624
|
return null;
|
|
16368
16625
|
}
|
|
@@ -16413,28 +16670,28 @@ ${tree}\`\`\`
|
|
|
16413
16670
|
sections.push("");
|
|
16414
16671
|
}
|
|
16415
16672
|
const content = sections.join("\n");
|
|
16416
|
-
const contextDir =
|
|
16673
|
+
const contextDir = join26(repoRoot, OA_DIR, "context");
|
|
16417
16674
|
mkdirSync6(contextDir, { recursive: true });
|
|
16418
|
-
writeFileSync6(
|
|
16675
|
+
writeFileSync6(join26(contextDir, "project-map.md"), content, "utf-8");
|
|
16419
16676
|
return content;
|
|
16420
16677
|
}
|
|
16421
16678
|
function saveSession(repoRoot, session) {
|
|
16422
|
-
const historyDir =
|
|
16679
|
+
const historyDir = join26(repoRoot, OA_DIR, "history");
|
|
16423
16680
|
mkdirSync6(historyDir, { recursive: true });
|
|
16424
|
-
writeFileSync6(
|
|
16681
|
+
writeFileSync6(join26(historyDir, `${session.id}.json`), JSON.stringify(session, null, 2), "utf-8");
|
|
16425
16682
|
}
|
|
16426
16683
|
function loadRecentSessions(repoRoot, limit = 5) {
|
|
16427
|
-
const historyDir =
|
|
16428
|
-
if (!
|
|
16684
|
+
const historyDir = join26(repoRoot, OA_DIR, "history");
|
|
16685
|
+
if (!existsSync20(historyDir))
|
|
16429
16686
|
return [];
|
|
16430
16687
|
try {
|
|
16431
16688
|
const files = readdirSync7(historyDir).filter((f) => f.endsWith(".json") && f !== "pending-task.json").map((f) => {
|
|
16432
|
-
const stat5 = statSync9(
|
|
16689
|
+
const stat5 = statSync9(join26(historyDir, f));
|
|
16433
16690
|
return { file: f, mtime: stat5.mtimeMs };
|
|
16434
16691
|
}).sort((a, b) => b.mtime - a.mtime).slice(0, limit);
|
|
16435
16692
|
return files.map((f) => {
|
|
16436
16693
|
try {
|
|
16437
|
-
return JSON.parse(
|
|
16694
|
+
return JSON.parse(readFileSync14(join26(historyDir, f.file), "utf-8"));
|
|
16438
16695
|
} catch {
|
|
16439
16696
|
return null;
|
|
16440
16697
|
}
|
|
@@ -16444,16 +16701,16 @@ function loadRecentSessions(repoRoot, limit = 5) {
|
|
|
16444
16701
|
}
|
|
16445
16702
|
}
|
|
16446
16703
|
function savePendingTask(repoRoot, task) {
|
|
16447
|
-
const historyDir =
|
|
16704
|
+
const historyDir = join26(repoRoot, OA_DIR, "history");
|
|
16448
16705
|
mkdirSync6(historyDir, { recursive: true });
|
|
16449
|
-
writeFileSync6(
|
|
16706
|
+
writeFileSync6(join26(historyDir, PENDING_TASK_FILE), JSON.stringify(task, null, 2) + "\n", "utf-8");
|
|
16450
16707
|
}
|
|
16451
16708
|
function loadPendingTask(repoRoot) {
|
|
16452
|
-
const filePath =
|
|
16709
|
+
const filePath = join26(repoRoot, OA_DIR, "history", PENDING_TASK_FILE);
|
|
16453
16710
|
try {
|
|
16454
|
-
if (!
|
|
16711
|
+
if (!existsSync20(filePath))
|
|
16455
16712
|
return null;
|
|
16456
|
-
const data = JSON.parse(
|
|
16713
|
+
const data = JSON.parse(readFileSync14(filePath, "utf-8"));
|
|
16457
16714
|
try {
|
|
16458
16715
|
unlinkSync3(filePath);
|
|
16459
16716
|
} catch {
|
|
@@ -16464,13 +16721,13 @@ function loadPendingTask(repoRoot) {
|
|
|
16464
16721
|
}
|
|
16465
16722
|
}
|
|
16466
16723
|
function saveSessionContext(repoRoot, entry) {
|
|
16467
|
-
const contextDir =
|
|
16724
|
+
const contextDir = join26(repoRoot, OA_DIR, "context");
|
|
16468
16725
|
mkdirSync6(contextDir, { recursive: true });
|
|
16469
|
-
const filePath =
|
|
16726
|
+
const filePath = join26(contextDir, CONTEXT_SAVE_FILE);
|
|
16470
16727
|
let ctx;
|
|
16471
16728
|
try {
|
|
16472
|
-
if (
|
|
16473
|
-
ctx = JSON.parse(
|
|
16729
|
+
if (existsSync20(filePath)) {
|
|
16730
|
+
ctx = JSON.parse(readFileSync14(filePath, "utf-8"));
|
|
16474
16731
|
} else {
|
|
16475
16732
|
ctx = { entries: [], maxEntries: MAX_CONTEXT_ENTRIES, updatedAt: "" };
|
|
16476
16733
|
}
|
|
@@ -16485,11 +16742,11 @@ function saveSessionContext(repoRoot, entry) {
|
|
|
16485
16742
|
writeFileSync6(filePath, JSON.stringify(ctx, null, 2) + "\n", "utf-8");
|
|
16486
16743
|
}
|
|
16487
16744
|
function loadSessionContext(repoRoot) {
|
|
16488
|
-
const filePath =
|
|
16745
|
+
const filePath = join26(repoRoot, OA_DIR, "context", CONTEXT_SAVE_FILE);
|
|
16489
16746
|
try {
|
|
16490
|
-
if (!
|
|
16747
|
+
if (!existsSync20(filePath))
|
|
16491
16748
|
return null;
|
|
16492
|
-
return JSON.parse(
|
|
16749
|
+
return JSON.parse(readFileSync14(filePath, "utf-8"));
|
|
16493
16750
|
} catch {
|
|
16494
16751
|
return null;
|
|
16495
16752
|
}
|
|
@@ -16536,12 +16793,12 @@ function detectManifests(repoRoot) {
|
|
|
16536
16793
|
{ file: "docker-compose.yaml", type: "Docker Compose" }
|
|
16537
16794
|
];
|
|
16538
16795
|
for (const check of checks) {
|
|
16539
|
-
const filePath =
|
|
16540
|
-
if (
|
|
16796
|
+
const filePath = join26(repoRoot, check.file);
|
|
16797
|
+
if (existsSync20(filePath)) {
|
|
16541
16798
|
let name;
|
|
16542
16799
|
if (check.nameField) {
|
|
16543
16800
|
try {
|
|
16544
|
-
const data = JSON.parse(
|
|
16801
|
+
const data = JSON.parse(readFileSync14(filePath, "utf-8"));
|
|
16545
16802
|
name = data[check.nameField];
|
|
16546
16803
|
} catch {
|
|
16547
16804
|
}
|
|
@@ -16570,7 +16827,7 @@ function findKeyFiles(repoRoot) {
|
|
|
16570
16827
|
{ pattern: "CLAUDE.md", description: "Claude Code context" }
|
|
16571
16828
|
];
|
|
16572
16829
|
for (const check of checks) {
|
|
16573
|
-
if (
|
|
16830
|
+
if (existsSync20(join26(repoRoot, check.pattern))) {
|
|
16574
16831
|
keyFiles.push({ path: check.pattern, description: check.description });
|
|
16575
16832
|
}
|
|
16576
16833
|
}
|
|
@@ -16596,12 +16853,12 @@ function buildDirTree(root, maxDepth, prefix = "", depth = 0) {
|
|
|
16596
16853
|
if (entry.isDirectory()) {
|
|
16597
16854
|
let fileCount = 0;
|
|
16598
16855
|
try {
|
|
16599
|
-
fileCount = readdirSync7(
|
|
16856
|
+
fileCount = readdirSync7(join26(root, entry.name)).filter((f) => !f.startsWith(".")).length;
|
|
16600
16857
|
} catch {
|
|
16601
16858
|
}
|
|
16602
16859
|
result += `${prefix}${connector}${entry.name}/ (${fileCount})
|
|
16603
16860
|
`;
|
|
16604
|
-
result += buildDirTree(
|
|
16861
|
+
result += buildDirTree(join26(root, entry.name), maxDepth, childPrefix, depth + 1);
|
|
16605
16862
|
} else if (depth < maxDepth) {
|
|
16606
16863
|
result += `${prefix}${connector}${entry.name}
|
|
16607
16864
|
`;
|
|
@@ -16654,9 +16911,9 @@ var init_oa_directory = __esm({
|
|
|
16654
16911
|
|
|
16655
16912
|
// packages/cli/dist/tui/setup.js
|
|
16656
16913
|
import * as readline from "node:readline";
|
|
16657
|
-
import { execSync as
|
|
16658
|
-
import { existsSync as
|
|
16659
|
-
import { join as
|
|
16914
|
+
import { execSync as execSync17, spawn as spawn9 } from "node:child_process";
|
|
16915
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
|
|
16916
|
+
import { join as join27 } from "node:path";
|
|
16660
16917
|
import { homedir as homedir10, platform } from "node:os";
|
|
16661
16918
|
function detectSystemSpecs() {
|
|
16662
16919
|
let totalRamGB = 0;
|
|
@@ -16664,7 +16921,7 @@ function detectSystemSpecs() {
|
|
|
16664
16921
|
let gpuVramGB = 0;
|
|
16665
16922
|
let gpuName = "";
|
|
16666
16923
|
try {
|
|
16667
|
-
const memInfo =
|
|
16924
|
+
const memInfo = execSync17("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
|
|
16668
16925
|
encoding: "utf8",
|
|
16669
16926
|
timeout: 5e3
|
|
16670
16927
|
});
|
|
@@ -16684,7 +16941,7 @@ function detectSystemSpecs() {
|
|
|
16684
16941
|
} catch {
|
|
16685
16942
|
}
|
|
16686
16943
|
try {
|
|
16687
|
-
const nvidiaSmi =
|
|
16944
|
+
const nvidiaSmi = execSync17("nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
|
|
16688
16945
|
const lines = nvidiaSmi.trim().split("\n");
|
|
16689
16946
|
if (lines.length > 0) {
|
|
16690
16947
|
for (const line of lines) {
|
|
@@ -16809,7 +17066,7 @@ function installOllamaLinux() {
|
|
|
16809
17066
|
|
|
16810
17067
|
`);
|
|
16811
17068
|
try {
|
|
16812
|
-
|
|
17069
|
+
execSync17("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
16813
17070
|
stdio: "inherit",
|
|
16814
17071
|
timeout: 3e5
|
|
16815
17072
|
});
|
|
@@ -16848,10 +17105,10 @@ async function installOllamaMac(rl) {
|
|
|
16848
17105
|
|
|
16849
17106
|
`);
|
|
16850
17107
|
try {
|
|
16851
|
-
|
|
17108
|
+
execSync17('/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"', { stdio: "inherit", timeout: 6e5 });
|
|
16852
17109
|
if (!hasCmd("brew")) {
|
|
16853
17110
|
try {
|
|
16854
|
-
const brewPrefix =
|
|
17111
|
+
const brewPrefix = existsSync21("/opt/homebrew/bin/brew") ? "/opt/homebrew" : "/usr/local";
|
|
16855
17112
|
process.env["PATH"] = `${brewPrefix}/bin:${process.env["PATH"]}`;
|
|
16856
17113
|
} catch {
|
|
16857
17114
|
}
|
|
@@ -16881,7 +17138,7 @@ async function installOllamaMac(rl) {
|
|
|
16881
17138
|
|
|
16882
17139
|
`);
|
|
16883
17140
|
try {
|
|
16884
|
-
|
|
17141
|
+
execSync17("brew install ollama", {
|
|
16885
17142
|
stdio: "inherit",
|
|
16886
17143
|
timeout: 3e5
|
|
16887
17144
|
});
|
|
@@ -16908,7 +17165,7 @@ function installOllamaWindows() {
|
|
|
16908
17165
|
|
|
16909
17166
|
`);
|
|
16910
17167
|
try {
|
|
16911
|
-
|
|
17168
|
+
execSync17('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
|
|
16912
17169
|
stdio: "inherit",
|
|
16913
17170
|
timeout: 3e5
|
|
16914
17171
|
});
|
|
@@ -16931,7 +17188,7 @@ function installOllamaWindows() {
|
|
|
16931
17188
|
}
|
|
16932
17189
|
function pullModelWithAutoUpdate(tag) {
|
|
16933
17190
|
try {
|
|
16934
|
-
|
|
17191
|
+
execSync17(`ollama pull ${tag}`, {
|
|
16935
17192
|
stdio: "inherit",
|
|
16936
17193
|
timeout: 36e5
|
|
16937
17194
|
// 1 hour max
|
|
@@ -16948,7 +17205,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
16948
17205
|
|
|
16949
17206
|
`);
|
|
16950
17207
|
try {
|
|
16951
|
-
|
|
17208
|
+
execSync17("curl -fsSL https://ollama.com/install.sh | sh", {
|
|
16952
17209
|
stdio: "inherit",
|
|
16953
17210
|
timeout: 3e5
|
|
16954
17211
|
// 5 min max for install
|
|
@@ -16959,7 +17216,7 @@ function pullModelWithAutoUpdate(tag) {
|
|
|
16959
17216
|
process.stdout.write(` ${c2.cyan("\u25CF")} Retrying pull of ${c2.bold(tag)}...
|
|
16960
17217
|
|
|
16961
17218
|
`);
|
|
16962
|
-
|
|
17219
|
+
execSync17(`ollama pull ${tag}`, {
|
|
16963
17220
|
stdio: "inherit",
|
|
16964
17221
|
timeout: 36e5
|
|
16965
17222
|
});
|
|
@@ -17140,7 +17397,7 @@ async function doSetup(config, rl) {
|
|
|
17140
17397
|
${c2.cyan("\u25CF")} Starting ollama serve in background...
|
|
17141
17398
|
`);
|
|
17142
17399
|
try {
|
|
17143
|
-
const child =
|
|
17400
|
+
const child = spawn9("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
17144
17401
|
child.unref();
|
|
17145
17402
|
await new Promise((resolve23) => setTimeout(resolve23, 3e3));
|
|
17146
17403
|
try {
|
|
@@ -17168,7 +17425,7 @@ async function doSetup(config, rl) {
|
|
|
17168
17425
|
${c2.cyan("\u25CF")} Starting ollama serve...
|
|
17169
17426
|
`);
|
|
17170
17427
|
try {
|
|
17171
|
-
const child =
|
|
17428
|
+
const child = spawn9("ollama", ["serve"], { stdio: "ignore", detached: true });
|
|
17172
17429
|
child.unref();
|
|
17173
17430
|
await new Promise((resolve23) => setTimeout(resolve23, 3e3));
|
|
17174
17431
|
try {
|
|
@@ -17325,12 +17582,12 @@ async function doSetup(config, rl) {
|
|
|
17325
17582
|
`PARAMETER num_predict ${numPredict}`,
|
|
17326
17583
|
`PARAMETER stop "<|endoftext|>"`
|
|
17327
17584
|
].join("\n");
|
|
17328
|
-
const modelDir2 =
|
|
17585
|
+
const modelDir2 = join27(homedir10(), ".open-agents", "models");
|
|
17329
17586
|
mkdirSync7(modelDir2, { recursive: true });
|
|
17330
|
-
const modelfilePath =
|
|
17587
|
+
const modelfilePath = join27(modelDir2, `Modelfile.${customName}`);
|
|
17331
17588
|
writeFileSync7(modelfilePath, modelfileContent + "\n", "utf8");
|
|
17332
17589
|
process.stdout.write(` ${c2.dim("Creating model...")} `);
|
|
17333
|
-
|
|
17590
|
+
execSync17(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
17334
17591
|
stdio: "pipe",
|
|
17335
17592
|
timeout: 12e4
|
|
17336
17593
|
});
|
|
@@ -17373,7 +17630,7 @@ async function isModelAvailable(config) {
|
|
|
17373
17630
|
}
|
|
17374
17631
|
function isFirstRun() {
|
|
17375
17632
|
try {
|
|
17376
|
-
return !
|
|
17633
|
+
return !existsSync21(join27(homedir10(), ".open-agents", "config.json"));
|
|
17377
17634
|
} catch {
|
|
17378
17635
|
return true;
|
|
17379
17636
|
}
|
|
@@ -17381,7 +17638,7 @@ function isFirstRun() {
|
|
|
17381
17638
|
function hasCmd(cmd) {
|
|
17382
17639
|
try {
|
|
17383
17640
|
const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
17384
|
-
|
|
17641
|
+
execSync17(whichCmd, { stdio: "pipe", timeout: 3e3 });
|
|
17385
17642
|
return true;
|
|
17386
17643
|
} catch {
|
|
17387
17644
|
return false;
|
|
@@ -17410,11 +17667,11 @@ function detectPkgManager() {
|
|
|
17410
17667
|
return null;
|
|
17411
17668
|
}
|
|
17412
17669
|
function getVenvDir() {
|
|
17413
|
-
return
|
|
17670
|
+
return join27(homedir10(), ".open-agents", "venv");
|
|
17414
17671
|
}
|
|
17415
17672
|
function hasVenvModule() {
|
|
17416
17673
|
try {
|
|
17417
|
-
|
|
17674
|
+
execSync17("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
|
|
17418
17675
|
return true;
|
|
17419
17676
|
} catch {
|
|
17420
17677
|
return false;
|
|
@@ -17422,8 +17679,8 @@ function hasVenvModule() {
|
|
|
17422
17679
|
}
|
|
17423
17680
|
function ensureVenv(log) {
|
|
17424
17681
|
const venvDir = getVenvDir();
|
|
17425
|
-
const venvPip =
|
|
17426
|
-
if (
|
|
17682
|
+
const venvPip = join27(venvDir, "bin", "pip");
|
|
17683
|
+
if (existsSync21(venvPip))
|
|
17427
17684
|
return venvDir;
|
|
17428
17685
|
log("Creating Python venv for vision deps...");
|
|
17429
17686
|
if (!hasCmd("python3")) {
|
|
@@ -17435,9 +17692,9 @@ function ensureVenv(log) {
|
|
|
17435
17692
|
return null;
|
|
17436
17693
|
}
|
|
17437
17694
|
try {
|
|
17438
|
-
mkdirSync7(
|
|
17439
|
-
|
|
17440
|
-
|
|
17695
|
+
mkdirSync7(join27(homedir10(), ".open-agents"), { recursive: true });
|
|
17696
|
+
execSync17(`python3 -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
|
|
17697
|
+
execSync17(`"${join27(venvDir, "bin", "pip")}" install --upgrade pip`, {
|
|
17441
17698
|
stdio: "pipe",
|
|
17442
17699
|
timeout: 6e4
|
|
17443
17700
|
});
|
|
@@ -17450,7 +17707,7 @@ function ensureVenv(log) {
|
|
|
17450
17707
|
}
|
|
17451
17708
|
function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
17452
17709
|
try {
|
|
17453
|
-
|
|
17710
|
+
execSync17(`sudo -n ${cmd}`, {
|
|
17454
17711
|
stdio: "pipe",
|
|
17455
17712
|
timeout: timeoutMs,
|
|
17456
17713
|
env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
|
|
@@ -17462,7 +17719,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
|
|
|
17462
17719
|
}
|
|
17463
17720
|
function runWithSudo(cmd, password, timeoutMs = 12e4) {
|
|
17464
17721
|
try {
|
|
17465
|
-
|
|
17722
|
+
execSync17(`sudo -S ${cmd}`, {
|
|
17466
17723
|
input: password + "\n",
|
|
17467
17724
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17468
17725
|
timeout: timeoutMs,
|
|
@@ -17522,7 +17779,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
17522
17779
|
} else {
|
|
17523
17780
|
log("Installing tesseract-ocr...");
|
|
17524
17781
|
try {
|
|
17525
|
-
|
|
17782
|
+
execSync17(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
|
|
17526
17783
|
if (hasCmd("tesseract")) {
|
|
17527
17784
|
log("tesseract-ocr installed successfully.");
|
|
17528
17785
|
} else {
|
|
@@ -17594,7 +17851,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
17594
17851
|
} else {
|
|
17595
17852
|
log(`Installing ${dep.label}...`);
|
|
17596
17853
|
try {
|
|
17597
|
-
|
|
17854
|
+
execSync17(pkg.cmd, { stdio: "pipe", timeout: 12e4 });
|
|
17598
17855
|
if (hasCmd(dep.binary)) {
|
|
17599
17856
|
log(`${dep.label} installed successfully.`);
|
|
17600
17857
|
} else {
|
|
@@ -17625,7 +17882,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
17625
17882
|
const venvCmds = {
|
|
17626
17883
|
apt: () => {
|
|
17627
17884
|
try {
|
|
17628
|
-
const pyVer =
|
|
17885
|
+
const pyVer = execSync17(`python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).trim();
|
|
17629
17886
|
return `apt-get install -y python3-venv python${pyVer}-venv`;
|
|
17630
17887
|
} catch {
|
|
17631
17888
|
return "apt-get install -y python3-venv";
|
|
@@ -17646,19 +17903,19 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
17646
17903
|
}
|
|
17647
17904
|
}
|
|
17648
17905
|
const venvDir = getVenvDir();
|
|
17649
|
-
const venvBin =
|
|
17650
|
-
const venvMoondream =
|
|
17906
|
+
const venvBin = join27(venvDir, "bin");
|
|
17907
|
+
const venvMoondream = join27(venvBin, "moondream-station");
|
|
17651
17908
|
const venv = ensureVenv(log);
|
|
17652
|
-
if (venv && !hasCmd("moondream-station") && !
|
|
17653
|
-
const venvPip =
|
|
17909
|
+
if (venv && !hasCmd("moondream-station") && !existsSync21(venvMoondream)) {
|
|
17910
|
+
const venvPip = join27(venvBin, "pip");
|
|
17654
17911
|
log("Installing moondream-station in ~/.open-agents/venv...");
|
|
17655
17912
|
try {
|
|
17656
|
-
|
|
17657
|
-
if (
|
|
17913
|
+
execSync17(`"${venvPip}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
|
|
17914
|
+
if (existsSync21(venvMoondream)) {
|
|
17658
17915
|
log("moondream-station installed successfully.");
|
|
17659
17916
|
} else {
|
|
17660
17917
|
try {
|
|
17661
|
-
const check =
|
|
17918
|
+
const check = execSync17(`"${venvPip}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
|
|
17662
17919
|
if (check.includes("moondream")) {
|
|
17663
17920
|
log("moondream-station package installed.");
|
|
17664
17921
|
}
|
|
@@ -17671,11 +17928,11 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
17671
17928
|
}
|
|
17672
17929
|
}
|
|
17673
17930
|
if (venv) {
|
|
17674
|
-
const venvPython =
|
|
17675
|
-
const venvPip2 =
|
|
17931
|
+
const venvPython = join27(venvBin, "python");
|
|
17932
|
+
const venvPip2 = join27(venvBin, "pip");
|
|
17676
17933
|
let ocrStackInstalled = false;
|
|
17677
17934
|
try {
|
|
17678
|
-
|
|
17935
|
+
execSync17(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
17679
17936
|
ocrStackInstalled = true;
|
|
17680
17937
|
} catch {
|
|
17681
17938
|
}
|
|
@@ -17683,9 +17940,9 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
|
|
|
17683
17940
|
const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
|
|
17684
17941
|
log("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
|
|
17685
17942
|
try {
|
|
17686
|
-
|
|
17943
|
+
execSync17(`"${venvPip2}" install ${ocrPackages}`, { stdio: "pipe", timeout: 3e5 });
|
|
17687
17944
|
try {
|
|
17688
|
-
|
|
17945
|
+
execSync17(`"${venvPython}" -c "import cv2, pytesseract, numpy, PIL"`, { stdio: "pipe", timeout: 1e4 });
|
|
17689
17946
|
log("OCR Python stack installed successfully.");
|
|
17690
17947
|
} catch {
|
|
17691
17948
|
log("OCR Python stack install completed but import verification failed.");
|
|
@@ -17732,11 +17989,11 @@ function createExpandedVariant(baseModel, specs, sizeGB) {
|
|
|
17732
17989
|
`PARAMETER num_predict ${numPredict}`,
|
|
17733
17990
|
`PARAMETER stop "<|endoftext|>"`
|
|
17734
17991
|
].join("\n");
|
|
17735
|
-
const modelDir2 =
|
|
17992
|
+
const modelDir2 = join27(homedir10(), ".open-agents", "models");
|
|
17736
17993
|
mkdirSync7(modelDir2, { recursive: true });
|
|
17737
|
-
const modelfilePath =
|
|
17994
|
+
const modelfilePath = join27(modelDir2, `Modelfile.${customName}`);
|
|
17738
17995
|
writeFileSync7(modelfilePath, modelfileContent + "\n", "utf8");
|
|
17739
|
-
|
|
17996
|
+
execSync17(`ollama create ${customName} -f ${modelfilePath}`, {
|
|
17740
17997
|
stdio: "pipe",
|
|
17741
17998
|
timeout: 12e4
|
|
17742
17999
|
});
|
|
@@ -18522,18 +18779,18 @@ async function handleUpdate(subcommand, ctx) {
|
|
|
18522
18779
|
let currentVersion = "0.0.0";
|
|
18523
18780
|
try {
|
|
18524
18781
|
const { createRequire: createRequire4 } = await import("node:module");
|
|
18525
|
-
const { fileURLToPath:
|
|
18526
|
-
const { dirname:
|
|
18527
|
-
const { existsSync:
|
|
18782
|
+
const { fileURLToPath: fileURLToPath10 } = await import("node:url");
|
|
18783
|
+
const { dirname: dirname13, join: join38 } = await import("node:path");
|
|
18784
|
+
const { existsSync: existsSync28 } = await import("node:fs");
|
|
18528
18785
|
const req = createRequire4(import.meta.url);
|
|
18529
|
-
const thisDir =
|
|
18786
|
+
const thisDir = dirname13(fileURLToPath10(import.meta.url));
|
|
18530
18787
|
const candidates = [
|
|
18531
|
-
|
|
18532
|
-
|
|
18533
|
-
|
|
18788
|
+
join38(thisDir, "..", "package.json"),
|
|
18789
|
+
join38(thisDir, "..", "..", "package.json"),
|
|
18790
|
+
join38(thisDir, "..", "..", "..", "package.json")
|
|
18534
18791
|
];
|
|
18535
18792
|
for (const pkgPath of candidates) {
|
|
18536
|
-
if (
|
|
18793
|
+
if (existsSync28(pkgPath)) {
|
|
18537
18794
|
const pkg = req(pkgPath);
|
|
18538
18795
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
18539
18796
|
currentVersion = pkg.version ?? "0.0.0";
|
|
@@ -18665,9 +18922,9 @@ var init_commands = __esm({
|
|
|
18665
18922
|
});
|
|
18666
18923
|
|
|
18667
18924
|
// packages/cli/dist/tui/project-context.js
|
|
18668
|
-
import { existsSync as
|
|
18669
|
-
import { join as
|
|
18670
|
-
import { execSync as
|
|
18925
|
+
import { existsSync as existsSync22, readFileSync as readFileSync15, readdirSync as readdirSync8 } from "node:fs";
|
|
18926
|
+
import { join as join28, basename as basename10 } from "node:path";
|
|
18927
|
+
import { execSync as execSync18 } from "node:child_process";
|
|
18671
18928
|
import { homedir as homedir11, platform as platform2, release } from "node:os";
|
|
18672
18929
|
function getModelTier(modelName) {
|
|
18673
18930
|
const m = modelName.toLowerCase();
|
|
@@ -18701,10 +18958,10 @@ function loadProjectMap(repoRoot) {
|
|
|
18701
18958
|
if (!hasOaDirectory(repoRoot)) {
|
|
18702
18959
|
initOaDirectory(repoRoot);
|
|
18703
18960
|
}
|
|
18704
|
-
const mapPath =
|
|
18705
|
-
if (
|
|
18961
|
+
const mapPath = join28(repoRoot, OA_DIR, "context", "project-map.md");
|
|
18962
|
+
if (existsSync22(mapPath)) {
|
|
18706
18963
|
try {
|
|
18707
|
-
const content =
|
|
18964
|
+
const content = readFileSync15(mapPath, "utf-8");
|
|
18708
18965
|
return content;
|
|
18709
18966
|
} catch {
|
|
18710
18967
|
}
|
|
@@ -18713,19 +18970,19 @@ function loadProjectMap(repoRoot) {
|
|
|
18713
18970
|
}
|
|
18714
18971
|
function getGitInfo(repoRoot) {
|
|
18715
18972
|
try {
|
|
18716
|
-
|
|
18973
|
+
execSync18("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
|
|
18717
18974
|
} catch {
|
|
18718
18975
|
return "";
|
|
18719
18976
|
}
|
|
18720
18977
|
const lines = [];
|
|
18721
18978
|
try {
|
|
18722
|
-
const branch =
|
|
18979
|
+
const branch = execSync18("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
18723
18980
|
if (branch)
|
|
18724
18981
|
lines.push(`Branch: ${branch}`);
|
|
18725
18982
|
} catch {
|
|
18726
18983
|
}
|
|
18727
18984
|
try {
|
|
18728
|
-
const status =
|
|
18985
|
+
const status = execSync18("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
18729
18986
|
if (status) {
|
|
18730
18987
|
const changed = status.split("\n").length;
|
|
18731
18988
|
lines.push(`Working tree: ${changed} changed file(s)`);
|
|
@@ -18735,7 +18992,7 @@ function getGitInfo(repoRoot) {
|
|
|
18735
18992
|
} catch {
|
|
18736
18993
|
}
|
|
18737
18994
|
try {
|
|
18738
|
-
const log =
|
|
18995
|
+
const log = execSync18("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
|
|
18739
18996
|
if (log)
|
|
18740
18997
|
lines.push(`Recent commits:
|
|
18741
18998
|
${log}`);
|
|
@@ -18745,31 +19002,31 @@ ${log}`);
|
|
|
18745
19002
|
}
|
|
18746
19003
|
function loadMemoryContext(repoRoot) {
|
|
18747
19004
|
const sections = [];
|
|
18748
|
-
const oaMemDir =
|
|
19005
|
+
const oaMemDir = join28(repoRoot, OA_DIR, "memory");
|
|
18749
19006
|
const oaEntries = loadMemoryDir(oaMemDir, "project");
|
|
18750
19007
|
if (oaEntries)
|
|
18751
19008
|
sections.push(oaEntries);
|
|
18752
|
-
const legacyMemDir =
|
|
18753
|
-
if (legacyMemDir !== oaMemDir &&
|
|
19009
|
+
const legacyMemDir = join28(repoRoot, ".open-agents", "memory");
|
|
19010
|
+
if (legacyMemDir !== oaMemDir && existsSync22(legacyMemDir)) {
|
|
18754
19011
|
const legacyEntries = loadMemoryDir(legacyMemDir, "project/legacy");
|
|
18755
19012
|
if (legacyEntries)
|
|
18756
19013
|
sections.push(legacyEntries);
|
|
18757
19014
|
}
|
|
18758
|
-
const globalMemDir =
|
|
19015
|
+
const globalMemDir = join28(homedir11(), ".open-agents", "memory");
|
|
18759
19016
|
const globalEntries = loadMemoryDir(globalMemDir, "global");
|
|
18760
19017
|
if (globalEntries)
|
|
18761
19018
|
sections.push(globalEntries);
|
|
18762
19019
|
return sections.join("\n\n");
|
|
18763
19020
|
}
|
|
18764
19021
|
function loadMemoryDir(memDir, scope) {
|
|
18765
|
-
if (!
|
|
19022
|
+
if (!existsSync22(memDir))
|
|
18766
19023
|
return "";
|
|
18767
19024
|
const lines = [];
|
|
18768
19025
|
try {
|
|
18769
19026
|
const files = readdirSync8(memDir).filter((f) => f.endsWith(".json"));
|
|
18770
19027
|
for (const file of files.slice(0, 10)) {
|
|
18771
19028
|
try {
|
|
18772
|
-
const raw =
|
|
19029
|
+
const raw = readFileSync15(join28(memDir, file), "utf-8");
|
|
18773
19030
|
const entries = JSON.parse(raw);
|
|
18774
19031
|
const topic = basename10(file, ".json");
|
|
18775
19032
|
const keys = Object.keys(entries);
|
|
@@ -19796,22 +20053,22 @@ var init_carousel = __esm({
|
|
|
19796
20053
|
});
|
|
19797
20054
|
|
|
19798
20055
|
// packages/cli/dist/tui/carousel-descriptors.js
|
|
19799
|
-
import { existsSync as
|
|
19800
|
-
import { join as
|
|
20056
|
+
import { existsSync as existsSync23, readFileSync as readFileSync16, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, readdirSync as readdirSync9 } from "node:fs";
|
|
20057
|
+
import { join as join29, basename as basename11 } from "node:path";
|
|
19801
20058
|
function loadToolProfile(repoRoot) {
|
|
19802
|
-
const filePath =
|
|
20059
|
+
const filePath = join29(repoRoot, OA_DIR, "context", TOOL_PROFILE_FILE);
|
|
19803
20060
|
try {
|
|
19804
|
-
if (!
|
|
20061
|
+
if (!existsSync23(filePath))
|
|
19805
20062
|
return null;
|
|
19806
|
-
return JSON.parse(
|
|
20063
|
+
return JSON.parse(readFileSync16(filePath, "utf-8"));
|
|
19807
20064
|
} catch {
|
|
19808
20065
|
return null;
|
|
19809
20066
|
}
|
|
19810
20067
|
}
|
|
19811
20068
|
function saveToolProfile(repoRoot, profile) {
|
|
19812
|
-
const contextDir =
|
|
20069
|
+
const contextDir = join29(repoRoot, OA_DIR, "context");
|
|
19813
20070
|
mkdirSync8(contextDir, { recursive: true });
|
|
19814
|
-
writeFileSync8(
|
|
20071
|
+
writeFileSync8(join29(contextDir, TOOL_PROFILE_FILE), JSON.stringify(profile, null, 2), "utf-8");
|
|
19815
20072
|
}
|
|
19816
20073
|
function categorizeToolCall(toolName) {
|
|
19817
20074
|
for (const cat of TOOL_CATEGORIES) {
|
|
@@ -19869,25 +20126,25 @@ function weightedColor(profile) {
|
|
|
19869
20126
|
return selectedCat.colors[Math.floor(Math.random() * selectedCat.colors.length)];
|
|
19870
20127
|
}
|
|
19871
20128
|
function loadCachedDescriptors(repoRoot) {
|
|
19872
|
-
const filePath =
|
|
20129
|
+
const filePath = join29(repoRoot, OA_DIR, "context", DESCRIPTOR_FILE);
|
|
19873
20130
|
try {
|
|
19874
|
-
if (!
|
|
20131
|
+
if (!existsSync23(filePath))
|
|
19875
20132
|
return null;
|
|
19876
|
-
const cached = JSON.parse(
|
|
20133
|
+
const cached = JSON.parse(readFileSync16(filePath, "utf-8"));
|
|
19877
20134
|
return cached.phrases.length > 0 ? cached.phrases : null;
|
|
19878
20135
|
} catch {
|
|
19879
20136
|
return null;
|
|
19880
20137
|
}
|
|
19881
20138
|
}
|
|
19882
20139
|
function saveCachedDescriptors(repoRoot, phrases, sourceHash) {
|
|
19883
|
-
const contextDir =
|
|
20140
|
+
const contextDir = join29(repoRoot, OA_DIR, "context");
|
|
19884
20141
|
mkdirSync8(contextDir, { recursive: true });
|
|
19885
20142
|
const cached = {
|
|
19886
20143
|
phrases,
|
|
19887
20144
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19888
20145
|
sourceHash
|
|
19889
20146
|
};
|
|
19890
|
-
writeFileSync8(
|
|
20147
|
+
writeFileSync8(join29(contextDir, DESCRIPTOR_FILE), JSON.stringify(cached, null, 2), "utf-8");
|
|
19891
20148
|
}
|
|
19892
20149
|
function generateDescriptors(repoRoot) {
|
|
19893
20150
|
const profile = loadToolProfile(repoRoot);
|
|
@@ -19935,11 +20192,11 @@ function generateDescriptors(repoRoot) {
|
|
|
19935
20192
|
return phrases;
|
|
19936
20193
|
}
|
|
19937
20194
|
function extractFromPackageJson(repoRoot, tags) {
|
|
19938
|
-
const pkgPath =
|
|
20195
|
+
const pkgPath = join29(repoRoot, "package.json");
|
|
19939
20196
|
try {
|
|
19940
|
-
if (!
|
|
20197
|
+
if (!existsSync23(pkgPath))
|
|
19941
20198
|
return;
|
|
19942
|
-
const pkg = JSON.parse(
|
|
20199
|
+
const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
|
|
19943
20200
|
if (pkg.name && typeof pkg.name === "string") {
|
|
19944
20201
|
const parts = pkg.name.replace(/^@/, "").split("/");
|
|
19945
20202
|
for (const p of parts)
|
|
@@ -19983,7 +20240,7 @@ function extractFromManifests(repoRoot, tags) {
|
|
|
19983
20240
|
{ file: ".github/workflows", tag: "ci/cd" }
|
|
19984
20241
|
];
|
|
19985
20242
|
for (const check of manifestChecks) {
|
|
19986
|
-
if (
|
|
20243
|
+
if (existsSync23(join29(repoRoot, check.file))) {
|
|
19987
20244
|
tags.push(check.tag);
|
|
19988
20245
|
}
|
|
19989
20246
|
}
|
|
@@ -20005,16 +20262,16 @@ function extractFromSessions(repoRoot, tags) {
|
|
|
20005
20262
|
}
|
|
20006
20263
|
}
|
|
20007
20264
|
function extractFromMemory(repoRoot, tags) {
|
|
20008
|
-
const memoryDir =
|
|
20265
|
+
const memoryDir = join29(repoRoot, OA_DIR, "memory");
|
|
20009
20266
|
try {
|
|
20010
|
-
if (!
|
|
20267
|
+
if (!existsSync23(memoryDir))
|
|
20011
20268
|
return;
|
|
20012
20269
|
const files = readdirSync9(memoryDir).filter((f) => f.endsWith(".json"));
|
|
20013
20270
|
for (const file of files) {
|
|
20014
20271
|
const topic = file.replace(/\.json$/, "").replace(/[-_]/g, " ");
|
|
20015
20272
|
tags.push(topic);
|
|
20016
20273
|
try {
|
|
20017
|
-
const data = JSON.parse(
|
|
20274
|
+
const data = JSON.parse(readFileSync16(join29(memoryDir, file), "utf-8"));
|
|
20018
20275
|
if (data && typeof data === "object") {
|
|
20019
20276
|
const keys = Object.keys(data).slice(0, 3);
|
|
20020
20277
|
for (const key of keys) {
|
|
@@ -20149,25 +20406,25 @@ var init_carousel_descriptors = __esm({
|
|
|
20149
20406
|
});
|
|
20150
20407
|
|
|
20151
20408
|
// packages/cli/dist/tui/voice.js
|
|
20152
|
-
import { existsSync as
|
|
20153
|
-
import { join as
|
|
20409
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync17, unlinkSync as unlinkSync4 } from "node:fs";
|
|
20410
|
+
import { join as join30 } from "node:path";
|
|
20154
20411
|
import { homedir as homedir12, tmpdir as tmpdir6, platform as platform3 } from "node:os";
|
|
20155
|
-
import { execSync as
|
|
20412
|
+
import { execSync as execSync19, spawn as nodeSpawn } from "node:child_process";
|
|
20156
20413
|
import { createRequire } from "node:module";
|
|
20157
20414
|
function voiceDir() {
|
|
20158
|
-
return
|
|
20415
|
+
return join30(homedir12(), ".open-agents", "voice");
|
|
20159
20416
|
}
|
|
20160
20417
|
function modelsDir() {
|
|
20161
|
-
return
|
|
20418
|
+
return join30(voiceDir(), "models");
|
|
20162
20419
|
}
|
|
20163
20420
|
function modelDir(id) {
|
|
20164
|
-
return
|
|
20421
|
+
return join30(modelsDir(), id);
|
|
20165
20422
|
}
|
|
20166
20423
|
function modelOnnxPath(id) {
|
|
20167
|
-
return
|
|
20424
|
+
return join30(modelDir(id), "model.onnx");
|
|
20168
20425
|
}
|
|
20169
20426
|
function modelConfigPath(id) {
|
|
20170
|
-
return
|
|
20427
|
+
return join30(modelDir(id), "config.json");
|
|
20171
20428
|
}
|
|
20172
20429
|
function describeToolCall(toolName, args, personality = 2) {
|
|
20173
20430
|
const path = args["path"];
|
|
@@ -20242,6 +20499,8 @@ function describeToolCallTerse(toolName, args, file) {
|
|
|
20242
20499
|
return `Creating custom tool`;
|
|
20243
20500
|
case "manage_tools":
|
|
20244
20501
|
return `Managing custom tools`;
|
|
20502
|
+
case "browser_action":
|
|
20503
|
+
return `Browser ${args["action"] ?? "action"}`;
|
|
20245
20504
|
default:
|
|
20246
20505
|
return `Using ${toolName}`;
|
|
20247
20506
|
}
|
|
@@ -20288,6 +20547,8 @@ function describeToolCallConversational(toolName, args, file) {
|
|
|
20288
20547
|
return `Taking a look at that image`;
|
|
20289
20548
|
case "screenshot":
|
|
20290
20549
|
return `Grabbing a screenshot`;
|
|
20550
|
+
case "browser_action":
|
|
20551
|
+
return `Let me ${args["action"] === "navigate" ? "open that page" : args["action"] === "screenshot" ? "grab a screenshot of the browser" : `do a browser ${args["action"] ?? "action"}`}`;
|
|
20291
20552
|
default:
|
|
20292
20553
|
return `Working with ${toolName}`;
|
|
20293
20554
|
}
|
|
@@ -20334,6 +20595,8 @@ function describeToolCallChatty(toolName, args, file) {
|
|
|
20334
20595
|
return `Let me get a good look at that image`;
|
|
20335
20596
|
case "screenshot":
|
|
20336
20597
|
return `Snapping a screenshot to see what's happening`;
|
|
20598
|
+
case "browser_action":
|
|
20599
|
+
return `Firing up the browser, let's ${args["action"] === "navigate" ? "see what's on that page" : args["action"] === "screenshot" ? "get a visual" : `${args["action"] ?? "do this"}`}`;
|
|
20337
20600
|
default:
|
|
20338
20601
|
return `Pulling in ${toolName}, hang tight`;
|
|
20339
20602
|
}
|
|
@@ -20589,7 +20852,7 @@ var init_voice = __esm({
|
|
|
20589
20852
|
const audioData = result["output"].data;
|
|
20590
20853
|
if (audioData.length === 0)
|
|
20591
20854
|
return;
|
|
20592
|
-
const wavPath =
|
|
20855
|
+
const wavPath = join30(tmpdir6(), `oa-voice-${Date.now()}.wav`);
|
|
20593
20856
|
this.writeWav(audioData, this.config.audio.sample_rate, wavPath);
|
|
20594
20857
|
await this.playWav(wavPath);
|
|
20595
20858
|
try {
|
|
@@ -20719,7 +20982,7 @@ var init_voice = __esm({
|
|
|
20719
20982
|
}
|
|
20720
20983
|
for (const player of ["paplay", "pw-play", "aplay"]) {
|
|
20721
20984
|
try {
|
|
20722
|
-
|
|
20985
|
+
execSync19(`which ${player}`, { stdio: "pipe" });
|
|
20723
20986
|
return [player, path];
|
|
20724
20987
|
} catch {
|
|
20725
20988
|
}
|
|
@@ -20744,14 +21007,14 @@ var init_voice = __esm({
|
|
|
20744
21007
|
const arch = process.arch;
|
|
20745
21008
|
const isArmLinux = (arch === "arm64" || arch === "arm") && process.platform === "linux";
|
|
20746
21009
|
mkdirSync9(voiceDir(), { recursive: true });
|
|
20747
|
-
const pkgPath =
|
|
21010
|
+
const pkgPath = join30(voiceDir(), "package.json");
|
|
20748
21011
|
const expectedDeps = {
|
|
20749
21012
|
"onnxruntime-node": "^1.21.0",
|
|
20750
21013
|
"phonemizer": "^1.2.1"
|
|
20751
21014
|
};
|
|
20752
|
-
if (
|
|
21015
|
+
if (existsSync24(pkgPath)) {
|
|
20753
21016
|
try {
|
|
20754
|
-
const existing = JSON.parse(
|
|
21017
|
+
const existing = JSON.parse(readFileSync17(pkgPath, "utf8"));
|
|
20755
21018
|
if (!existing.dependencies?.["phonemizer"]) {
|
|
20756
21019
|
existing.dependencies = { ...existing.dependencies, ...expectedDeps };
|
|
20757
21020
|
writeFileSync9(pkgPath, JSON.stringify(existing, null, 2));
|
|
@@ -20759,14 +21022,14 @@ var init_voice = __esm({
|
|
|
20759
21022
|
} catch {
|
|
20760
21023
|
}
|
|
20761
21024
|
}
|
|
20762
|
-
if (!
|
|
21025
|
+
if (!existsSync24(pkgPath)) {
|
|
20763
21026
|
writeFileSync9(pkgPath, JSON.stringify({
|
|
20764
21027
|
name: "open-agents-voice",
|
|
20765
21028
|
private: true,
|
|
20766
21029
|
dependencies: expectedDeps
|
|
20767
21030
|
}, null, 2));
|
|
20768
21031
|
}
|
|
20769
|
-
const voiceRequire = createRequire(
|
|
21032
|
+
const voiceRequire = createRequire(join30(voiceDir(), "index.js"));
|
|
20770
21033
|
try {
|
|
20771
21034
|
this.ort = voiceRequire("onnxruntime-node");
|
|
20772
21035
|
} catch {
|
|
@@ -20775,7 +21038,7 @@ var init_voice = __esm({
|
|
|
20775
21038
|
}
|
|
20776
21039
|
renderInfo("Installing ONNX runtime for voice synthesis...");
|
|
20777
21040
|
try {
|
|
20778
|
-
|
|
21041
|
+
execSync19("npm install --no-audit --no-fund", {
|
|
20779
21042
|
cwd: voiceDir(),
|
|
20780
21043
|
stdio: "pipe",
|
|
20781
21044
|
timeout: 12e4
|
|
@@ -20796,7 +21059,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
20796
21059
|
}
|
|
20797
21060
|
renderInfo("Installing phonemizer for voice synthesis...");
|
|
20798
21061
|
try {
|
|
20799
|
-
|
|
21062
|
+
execSync19("npm install --no-audit --no-fund", {
|
|
20800
21063
|
cwd: voiceDir(),
|
|
20801
21064
|
stdio: "pipe",
|
|
20802
21065
|
timeout: 12e4
|
|
@@ -20820,10 +21083,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
20820
21083
|
const dir = modelDir(id);
|
|
20821
21084
|
const onnxPath = modelOnnxPath(id);
|
|
20822
21085
|
const configPath = modelConfigPath(id);
|
|
20823
|
-
if (
|
|
21086
|
+
if (existsSync24(onnxPath) && existsSync24(configPath))
|
|
20824
21087
|
return;
|
|
20825
21088
|
mkdirSync9(dir, { recursive: true });
|
|
20826
|
-
if (!
|
|
21089
|
+
if (!existsSync24(configPath)) {
|
|
20827
21090
|
renderInfo(`Downloading ${model.label} voice config...`);
|
|
20828
21091
|
const configResp = await fetch(model.configUrl);
|
|
20829
21092
|
if (!configResp.ok)
|
|
@@ -20831,7 +21094,7 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
20831
21094
|
const configText = await configResp.text();
|
|
20832
21095
|
writeFileSync9(configPath, configText);
|
|
20833
21096
|
}
|
|
20834
|
-
if (!
|
|
21097
|
+
if (!existsSync24(onnxPath)) {
|
|
20835
21098
|
renderInfo(`Downloading ${model.label} voice model (this may take a minute)...`);
|
|
20836
21099
|
const onnxResp = await fetch(model.onnxUrl);
|
|
20837
21100
|
if (!onnxResp.ok)
|
|
@@ -20867,10 +21130,10 @@ Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
|
20867
21130
|
throw new Error("ONNX runtime not loaded");
|
|
20868
21131
|
const onnxPath = modelOnnxPath(this.modelId);
|
|
20869
21132
|
const configPath = modelConfigPath(this.modelId);
|
|
20870
|
-
if (!
|
|
21133
|
+
if (!existsSync24(onnxPath) || !existsSync24(configPath)) {
|
|
20871
21134
|
throw new Error(`Model files not found for ${this.modelId}`);
|
|
20872
21135
|
}
|
|
20873
|
-
this.config = JSON.parse(
|
|
21136
|
+
this.config = JSON.parse(readFileSync17(configPath, "utf8"));
|
|
20874
21137
|
renderInfo("Loading voice model...");
|
|
20875
21138
|
this.session = await this.ort.InferenceSession.create(onnxPath, {
|
|
20876
21139
|
executionProviders: ["cpu"],
|
|
@@ -21371,10 +21634,10 @@ var init_stream_renderer = __esm({
|
|
|
21371
21634
|
|
|
21372
21635
|
// packages/cli/dist/tui/edit-history.js
|
|
21373
21636
|
import { appendFileSync, mkdirSync as mkdirSync10 } from "node:fs";
|
|
21374
|
-
import { join as
|
|
21637
|
+
import { join as join31 } from "node:path";
|
|
21375
21638
|
function createEditHistoryLogger(repoRoot, sessionId) {
|
|
21376
|
-
const historyDir =
|
|
21377
|
-
const logPath =
|
|
21639
|
+
const historyDir = join31(repoRoot, ".oa", "history");
|
|
21640
|
+
const logPath = join31(historyDir, "edits.jsonl");
|
|
21378
21641
|
try {
|
|
21379
21642
|
mkdirSync10(historyDir, { recursive: true });
|
|
21380
21643
|
} catch {
|
|
@@ -21485,9 +21748,9 @@ var init_edit_history = __esm({
|
|
|
21485
21748
|
});
|
|
21486
21749
|
|
|
21487
21750
|
// packages/cli/dist/tui/dream-engine.js
|
|
21488
|
-
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, readFileSync as
|
|
21489
|
-
import { join as
|
|
21490
|
-
import { execSync as
|
|
21751
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync10, readFileSync as readFileSync18, existsSync as existsSync25, cpSync, rmSync, readdirSync as readdirSync10 } from "node:fs";
|
|
21752
|
+
import { join as join32, basename as basename12 } from "node:path";
|
|
21753
|
+
import { execSync as execSync20 } from "node:child_process";
|
|
21491
21754
|
function adaptTool(tool) {
|
|
21492
21755
|
return {
|
|
21493
21756
|
name: tool.name,
|
|
@@ -21661,12 +21924,12 @@ var init_dream_engine = __esm({
|
|
|
21661
21924
|
const content = String(args["content"] ?? "");
|
|
21662
21925
|
if (!rawPath)
|
|
21663
21926
|
return { success: false, output: "", error: "path is required", durationMs: Date.now() - start };
|
|
21664
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
21927
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join32(this.dreamsDir, basename12(rawPath)) : join32(this.dreamsDir, rawPath);
|
|
21665
21928
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
21666
21929
|
return { success: false, output: "", error: "Dream mode: writes are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
21667
21930
|
}
|
|
21668
21931
|
try {
|
|
21669
|
-
const dir =
|
|
21932
|
+
const dir = join32(targetPath, "..");
|
|
21670
21933
|
mkdirSync11(dir, { recursive: true });
|
|
21671
21934
|
writeFileSync10(targetPath, content, "utf-8");
|
|
21672
21935
|
return { success: true, output: `Wrote ${content.length} bytes to ${rawPath}`, durationMs: Date.now() - start };
|
|
@@ -21696,15 +21959,15 @@ var init_dream_engine = __esm({
|
|
|
21696
21959
|
const rawPath = String(args["path"] ?? "");
|
|
21697
21960
|
const oldStr = String(args["old_string"] ?? "");
|
|
21698
21961
|
const newStr = String(args["new_string"] ?? "");
|
|
21699
|
-
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ?
|
|
21962
|
+
const targetPath = rawPath.startsWith("/") || rawPath.startsWith(".oa/dreams") ? join32(this.dreamsDir, basename12(rawPath)) : join32(this.dreamsDir, rawPath);
|
|
21700
21963
|
if (!targetPath.startsWith(this.dreamsDir)) {
|
|
21701
21964
|
return { success: false, output: "", error: "Dream mode: edits are confined to .oa/dreams/", durationMs: Date.now() - start };
|
|
21702
21965
|
}
|
|
21703
21966
|
try {
|
|
21704
|
-
if (!
|
|
21967
|
+
if (!existsSync25(targetPath)) {
|
|
21705
21968
|
return { success: false, output: "", error: `File not found: ${rawPath}`, durationMs: Date.now() - start };
|
|
21706
21969
|
}
|
|
21707
|
-
let content =
|
|
21970
|
+
let content = readFileSync18(targetPath, "utf-8");
|
|
21708
21971
|
if (!content.includes(oldStr)) {
|
|
21709
21972
|
return { success: false, output: "", error: "old_string not found in file", durationMs: Date.now() - start };
|
|
21710
21973
|
}
|
|
@@ -21740,7 +22003,7 @@ var init_dream_engine = __esm({
|
|
|
21740
22003
|
}
|
|
21741
22004
|
}
|
|
21742
22005
|
try {
|
|
21743
|
-
const output =
|
|
22006
|
+
const output = execSync20(cmd, {
|
|
21744
22007
|
cwd: this.repoRoot,
|
|
21745
22008
|
timeout: 3e4,
|
|
21746
22009
|
encoding: "utf-8",
|
|
@@ -21763,7 +22026,7 @@ var init_dream_engine = __esm({
|
|
|
21763
22026
|
constructor(config, repoRoot) {
|
|
21764
22027
|
this.config = config;
|
|
21765
22028
|
this.repoRoot = repoRoot;
|
|
21766
|
-
this.dreamsDir =
|
|
22029
|
+
this.dreamsDir = join32(repoRoot, ".oa", "dreams");
|
|
21767
22030
|
this.state = {
|
|
21768
22031
|
mode: "default",
|
|
21769
22032
|
active: false,
|
|
@@ -21835,7 +22098,7 @@ ${result.summary}`;
|
|
|
21835
22098
|
if (mode !== "default" || cycle === totalCycles) {
|
|
21836
22099
|
renderDreamContraction(cycle);
|
|
21837
22100
|
const cycleSummary = this.buildCycleSummary(cycle, previousFindings);
|
|
21838
|
-
const summaryPath =
|
|
22101
|
+
const summaryPath = join32(this.dreamsDir, `cycle-${cycle}-summary.md`);
|
|
21839
22102
|
writeFileSync10(summaryPath, cycleSummary, "utf-8");
|
|
21840
22103
|
}
|
|
21841
22104
|
if (mode === "lucid" && !this.abortController.signal.aborted) {
|
|
@@ -21958,29 +22221,29 @@ Dreams directory: ${this.dreamsDir}`);
|
|
|
21958
22221
|
}
|
|
21959
22222
|
/** Save workspace backup for lucid mode */
|
|
21960
22223
|
saveVersionCheckpoint(cycle) {
|
|
21961
|
-
const checkpointDir =
|
|
22224
|
+
const checkpointDir = join32(this.dreamsDir, "checkpoints", `cycle-${cycle}`);
|
|
21962
22225
|
try {
|
|
21963
22226
|
mkdirSync11(checkpointDir, { recursive: true });
|
|
21964
22227
|
try {
|
|
21965
|
-
const gitStatus =
|
|
22228
|
+
const gitStatus = execSync20("git status --porcelain", {
|
|
21966
22229
|
cwd: this.repoRoot,
|
|
21967
22230
|
encoding: "utf-8",
|
|
21968
22231
|
timeout: 1e4
|
|
21969
22232
|
});
|
|
21970
|
-
const gitDiff =
|
|
22233
|
+
const gitDiff = execSync20("git diff", {
|
|
21971
22234
|
cwd: this.repoRoot,
|
|
21972
22235
|
encoding: "utf-8",
|
|
21973
22236
|
timeout: 1e4
|
|
21974
22237
|
});
|
|
21975
|
-
const gitHash =
|
|
22238
|
+
const gitHash = execSync20("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
|
|
21976
22239
|
cwd: this.repoRoot,
|
|
21977
22240
|
encoding: "utf-8",
|
|
21978
22241
|
timeout: 5e3
|
|
21979
22242
|
}).trim();
|
|
21980
|
-
writeFileSync10(
|
|
21981
|
-
writeFileSync10(
|
|
21982
|
-
writeFileSync10(
|
|
21983
|
-
writeFileSync10(
|
|
22243
|
+
writeFileSync10(join32(checkpointDir, "git-status.txt"), gitStatus, "utf-8");
|
|
22244
|
+
writeFileSync10(join32(checkpointDir, "git-diff.patch"), gitDiff, "utf-8");
|
|
22245
|
+
writeFileSync10(join32(checkpointDir, "git-hash.txt"), gitHash, "utf-8");
|
|
22246
|
+
writeFileSync10(join32(checkpointDir, "checkpoint.json"), JSON.stringify({
|
|
21984
22247
|
cycle,
|
|
21985
22248
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21986
22249
|
gitHash,
|
|
@@ -21988,7 +22251,7 @@ Dreams directory: ${this.dreamsDir}`);
|
|
|
21988
22251
|
}, null, 2), "utf-8");
|
|
21989
22252
|
renderInfo(`Checkpoint saved: cycle ${cycle} (${gitHash.slice(0, 8)})`);
|
|
21990
22253
|
} catch {
|
|
21991
|
-
writeFileSync10(
|
|
22254
|
+
writeFileSync10(join32(checkpointDir, "checkpoint.json"), JSON.stringify({ cycle, timestamp: (/* @__PURE__ */ new Date()).toISOString(), mode: this.state.mode }, null, 2), "utf-8");
|
|
21992
22255
|
renderInfo(`Checkpoint saved: cycle ${cycle} (no git)`);
|
|
21993
22256
|
}
|
|
21994
22257
|
} catch (err) {
|
|
@@ -22046,14 +22309,14 @@ ${files.map((f) => `- [\`${f}\`](./${f})`).join("\n")}
|
|
|
22046
22309
|
---
|
|
22047
22310
|
*Auto-generated by open-agents dream engine*
|
|
22048
22311
|
`;
|
|
22049
|
-
writeFileSync10(
|
|
22312
|
+
writeFileSync10(join32(this.dreamsDir, "PROPOSAL-INDEX.md"), index, "utf-8");
|
|
22050
22313
|
} catch {
|
|
22051
22314
|
}
|
|
22052
22315
|
}
|
|
22053
22316
|
/** Save dream state for resume/inspection */
|
|
22054
22317
|
saveDreamState() {
|
|
22055
22318
|
try {
|
|
22056
|
-
writeFileSync10(
|
|
22319
|
+
writeFileSync10(join32(this.dreamsDir, "dream-state.json"), JSON.stringify(this.state, null, 2) + "\n", "utf-8");
|
|
22057
22320
|
} catch {
|
|
22058
22321
|
}
|
|
22059
22322
|
}
|
|
@@ -23109,11 +23372,11 @@ var init_status_bar = __esm({
|
|
|
23109
23372
|
import * as readline2 from "node:readline";
|
|
23110
23373
|
import { Writable } from "node:stream";
|
|
23111
23374
|
import { cwd } from "node:process";
|
|
23112
|
-
import { resolve as resolve20, join as
|
|
23375
|
+
import { resolve as resolve20, join as join33, dirname as dirname11, extname as extname9 } from "node:path";
|
|
23113
23376
|
import { createRequire as createRequire2 } from "node:module";
|
|
23114
|
-
import { fileURLToPath as
|
|
23115
|
-
import { readFileSync as
|
|
23116
|
-
import { existsSync as
|
|
23377
|
+
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
23378
|
+
import { readFileSync as readFileSync19, rmSync as rmSync2 } from "node:fs";
|
|
23379
|
+
import { existsSync as existsSync26 } from "node:fs";
|
|
23117
23380
|
function formatTimeAgo(date) {
|
|
23118
23381
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
|
|
23119
23382
|
if (seconds < 60)
|
|
@@ -23130,14 +23393,14 @@ function formatTimeAgo(date) {
|
|
|
23130
23393
|
function getVersion() {
|
|
23131
23394
|
try {
|
|
23132
23395
|
const require2 = createRequire2(import.meta.url);
|
|
23133
|
-
const thisDir =
|
|
23396
|
+
const thisDir = dirname11(fileURLToPath8(import.meta.url));
|
|
23134
23397
|
const candidates = [
|
|
23135
|
-
|
|
23136
|
-
|
|
23137
|
-
|
|
23398
|
+
join33(thisDir, "..", "package.json"),
|
|
23399
|
+
join33(thisDir, "..", "..", "package.json"),
|
|
23400
|
+
join33(thisDir, "..", "..", "..", "package.json")
|
|
23138
23401
|
];
|
|
23139
23402
|
for (const pkgPath of candidates) {
|
|
23140
|
-
if (
|
|
23403
|
+
if (existsSync26(pkgPath)) {
|
|
23141
23404
|
const pkg = require2(pkgPath);
|
|
23142
23405
|
if (pkg.name === "open-agents-ai" || pkg.name === "@open-agents/cli") {
|
|
23143
23406
|
return pkg.version ?? "0.0.0";
|
|
@@ -23235,7 +23498,9 @@ function buildTools(repoRoot, config, contextWindowSize) {
|
|
|
23235
23498
|
new OcrPdfTool(repoRoot),
|
|
23236
23499
|
new PdfToTextTool(repoRoot),
|
|
23237
23500
|
// Advanced image OCR (multi-variant preprocessing pipeline)
|
|
23238
|
-
new OcrImageAdvancedTool(repoRoot)
|
|
23501
|
+
new OcrImageAdvancedTool(repoRoot),
|
|
23502
|
+
// Browser automation (headless Chrome via Hydra scrape service)
|
|
23503
|
+
new BrowserActionTool()
|
|
23239
23504
|
];
|
|
23240
23505
|
return [
|
|
23241
23506
|
...executionTools.map(adaptTool2),
|
|
@@ -24230,8 +24495,8 @@ async function startInteractive(config, repoPath) {
|
|
|
24230
24495
|
return true;
|
|
24231
24496
|
},
|
|
24232
24497
|
destroyProject() {
|
|
24233
|
-
const oaPath =
|
|
24234
|
-
if (
|
|
24498
|
+
const oaPath = join33(repoRoot, OA_DIR);
|
|
24499
|
+
if (existsSync26(oaPath)) {
|
|
24235
24500
|
try {
|
|
24236
24501
|
rmSync2(oaPath, { recursive: true, force: true });
|
|
24237
24502
|
writeContent(() => renderInfo(`Removed ${OA_DIR}/ directory.`));
|
|
@@ -24463,13 +24728,13 @@ Execute this skill now. Follow the behavioral guidance above.`;
|
|
|
24463
24728
|
}
|
|
24464
24729
|
}
|
|
24465
24730
|
const cleanPath = input.replace(/^['"]|['"]$/g, "").trim();
|
|
24466
|
-
const isImage = isImagePath(cleanPath) &&
|
|
24467
|
-
const isMedia = !isImage && isTranscribablePath(cleanPath) &&
|
|
24731
|
+
const isImage = isImagePath(cleanPath) && existsSync26(resolve20(repoRoot, cleanPath));
|
|
24732
|
+
const isMedia = !isImage && isTranscribablePath(cleanPath) && existsSync26(resolve20(repoRoot, cleanPath));
|
|
24468
24733
|
if (activeTask) {
|
|
24469
24734
|
if (isImage) {
|
|
24470
24735
|
try {
|
|
24471
24736
|
const imgPath = resolve20(repoRoot, cleanPath);
|
|
24472
|
-
const imgBuffer =
|
|
24737
|
+
const imgBuffer = readFileSync19(imgPath);
|
|
24473
24738
|
const base64 = imgBuffer.toString("base64");
|
|
24474
24739
|
const ext = extname9(cleanPath).toLowerCase();
|
|
24475
24740
|
const mime = ext === ".png" ? "image/png" : ext === ".gif" ? "image/gif" : ext === ".webp" ? "image/webp" : "image/jpeg";
|
|
@@ -24752,7 +25017,7 @@ import { glob } from "glob";
|
|
|
24752
25017
|
import ignore from "ignore";
|
|
24753
25018
|
import { readFile as readFile11, stat as stat4 } from "node:fs/promises";
|
|
24754
25019
|
import { createHash } from "node:crypto";
|
|
24755
|
-
import { join as
|
|
25020
|
+
import { join as join34, relative as relative3, extname as extname10, basename as basename13 } from "node:path";
|
|
24756
25021
|
var DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
24757
25022
|
var init_codebase_indexer = __esm({
|
|
24758
25023
|
"packages/indexer/dist/codebase-indexer.js"() {
|
|
@@ -24796,7 +25061,7 @@ var init_codebase_indexer = __esm({
|
|
|
24796
25061
|
const ig = ignore.default();
|
|
24797
25062
|
if (this.config.respectGitignore) {
|
|
24798
25063
|
try {
|
|
24799
|
-
const gitignoreContent = await readFile11(
|
|
25064
|
+
const gitignoreContent = await readFile11(join34(this.config.rootDir, ".gitignore"), "utf-8");
|
|
24800
25065
|
ig.add(gitignoreContent);
|
|
24801
25066
|
} catch {
|
|
24802
25067
|
}
|
|
@@ -24811,7 +25076,7 @@ var init_codebase_indexer = __esm({
|
|
|
24811
25076
|
for (const relativePath of files) {
|
|
24812
25077
|
if (ig.ignores(relativePath))
|
|
24813
25078
|
continue;
|
|
24814
|
-
const fullPath =
|
|
25079
|
+
const fullPath = join34(this.config.rootDir, relativePath);
|
|
24815
25080
|
try {
|
|
24816
25081
|
const fileStat = await stat4(fullPath);
|
|
24817
25082
|
if (fileStat.size > this.config.maxFileSize)
|
|
@@ -24857,7 +25122,7 @@ var init_codebase_indexer = __esm({
|
|
|
24857
25122
|
if (!child) {
|
|
24858
25123
|
child = {
|
|
24859
25124
|
name: part,
|
|
24860
|
-
path:
|
|
25125
|
+
path: join34(current.path, part),
|
|
24861
25126
|
type: "directory",
|
|
24862
25127
|
children: []
|
|
24863
25128
|
};
|
|
@@ -24940,13 +25205,13 @@ __export(index_repo_exports, {
|
|
|
24940
25205
|
indexRepoCommand: () => indexRepoCommand
|
|
24941
25206
|
});
|
|
24942
25207
|
import { resolve as resolve21 } from "node:path";
|
|
24943
|
-
import { existsSync as
|
|
25208
|
+
import { existsSync as existsSync27, statSync as statSync10 } from "node:fs";
|
|
24944
25209
|
import { cwd as cwd2 } from "node:process";
|
|
24945
25210
|
async function indexRepoCommand(opts, _config) {
|
|
24946
25211
|
const repoRoot = resolve21(opts.repoPath ?? cwd2());
|
|
24947
25212
|
printHeader("Index Repository");
|
|
24948
25213
|
printInfo(`Indexing: ${repoRoot}`);
|
|
24949
|
-
if (!
|
|
25214
|
+
if (!existsSync27(repoRoot)) {
|
|
24950
25215
|
printError(`Path does not exist: ${repoRoot}`);
|
|
24951
25216
|
process.exit(1);
|
|
24952
25217
|
}
|
|
@@ -25198,7 +25463,7 @@ var config_exports = {};
|
|
|
25198
25463
|
__export(config_exports, {
|
|
25199
25464
|
configCommand: () => configCommand
|
|
25200
25465
|
});
|
|
25201
|
-
import { join as
|
|
25466
|
+
import { join as join35, resolve as resolve22 } from "node:path";
|
|
25202
25467
|
import { homedir as homedir13 } from "node:os";
|
|
25203
25468
|
import { cwd as cwd3 } from "node:process";
|
|
25204
25469
|
function redactIfSensitive(key, value) {
|
|
@@ -25257,7 +25522,7 @@ function handleShow(opts, config) {
|
|
|
25257
25522
|
}
|
|
25258
25523
|
}
|
|
25259
25524
|
printSection("Config File");
|
|
25260
|
-
printInfo(`~/.open-agents/config.json (${
|
|
25525
|
+
printInfo(`~/.open-agents/config.json (${join35(homedir13(), ".open-agents", "config.json")})`);
|
|
25261
25526
|
printSection("Priority Chain");
|
|
25262
25527
|
printInfo(" 1. CLI flags (--model, --backend-url, etc.)");
|
|
25263
25528
|
printInfo(" 2. Project .oa/settings.json (--local)");
|
|
@@ -25296,7 +25561,7 @@ function handleSet(opts, _config) {
|
|
|
25296
25561
|
const coerced = coerceForSettings(key, value);
|
|
25297
25562
|
saveProjectSettings(repoRoot, { [key]: coerced });
|
|
25298
25563
|
printSuccess(`Project override set: ${key} = ${redactIfSensitive(key, value)}`);
|
|
25299
|
-
printInfo(`Saved to ${
|
|
25564
|
+
printInfo(`Saved to ${join35(repoRoot, ".oa", "settings.json")}`);
|
|
25300
25565
|
printInfo("This override applies only when running in this workspace.");
|
|
25301
25566
|
} catch (err) {
|
|
25302
25567
|
printError(`Failed to save: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -25357,7 +25622,7 @@ var serve_exports = {};
|
|
|
25357
25622
|
__export(serve_exports, {
|
|
25358
25623
|
serveCommand: () => serveCommand
|
|
25359
25624
|
});
|
|
25360
|
-
import { spawn as
|
|
25625
|
+
import { spawn as spawn10 } from "node:child_process";
|
|
25361
25626
|
async function serveCommand(opts, config) {
|
|
25362
25627
|
const backendType = config.backendType;
|
|
25363
25628
|
if (backendType === "ollama") {
|
|
@@ -25450,7 +25715,7 @@ async function serveVllm(opts, config) {
|
|
|
25450
25715
|
}
|
|
25451
25716
|
async function runVllmServer(args, verbose) {
|
|
25452
25717
|
return new Promise((resolve23, reject) => {
|
|
25453
|
-
const child =
|
|
25718
|
+
const child = spawn10("python", args, {
|
|
25454
25719
|
stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"],
|
|
25455
25720
|
env: { ...process.env }
|
|
25456
25721
|
});
|
|
@@ -25516,7 +25781,7 @@ __export(eval_exports, {
|
|
|
25516
25781
|
});
|
|
25517
25782
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
25518
25783
|
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync11 } from "node:fs";
|
|
25519
|
-
import { join as
|
|
25784
|
+
import { join as join36 } from "node:path";
|
|
25520
25785
|
async function evalCommand(opts, config) {
|
|
25521
25786
|
const suiteName = opts.suite ?? "basic";
|
|
25522
25787
|
const suite = SUITES[suiteName];
|
|
@@ -25637,9 +25902,9 @@ async function evalCommand(opts, config) {
|
|
|
25637
25902
|
process.exit(failed > 0 ? 1 : 0);
|
|
25638
25903
|
}
|
|
25639
25904
|
function createTempEvalRepo() {
|
|
25640
|
-
const dir =
|
|
25905
|
+
const dir = join36(tmpdir7(), `open-agents-eval-${Date.now()}`);
|
|
25641
25906
|
mkdirSync12(dir, { recursive: true });
|
|
25642
|
-
writeFileSync11(
|
|
25907
|
+
writeFileSync11(join36(dir, "package.json"), JSON.stringify({ name: "eval-repo", version: "0.0.0" }, null, 2) + "\n", "utf8");
|
|
25643
25908
|
return dir;
|
|
25644
25909
|
}
|
|
25645
25910
|
var BASIC_SUITE, FULL_SUITE, SUITES;
|
|
@@ -25698,8 +25963,8 @@ init_output();
|
|
|
25698
25963
|
init_updater();
|
|
25699
25964
|
import { parseArgs as nodeParseArgs2 } from "node:util";
|
|
25700
25965
|
import { createRequire as createRequire3 } from "node:module";
|
|
25701
|
-
import { fileURLToPath as
|
|
25702
|
-
import { dirname as
|
|
25966
|
+
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
25967
|
+
import { dirname as dirname12, join as join37 } from "node:path";
|
|
25703
25968
|
|
|
25704
25969
|
// packages/cli/dist/cli.js
|
|
25705
25970
|
import { createInterface } from "node:readline";
|
|
@@ -25806,7 +26071,7 @@ init_output();
|
|
|
25806
26071
|
function getVersion2() {
|
|
25807
26072
|
try {
|
|
25808
26073
|
const require2 = createRequire3(import.meta.url);
|
|
25809
|
-
const pkgPath =
|
|
26074
|
+
const pkgPath = join37(dirname12(fileURLToPath9(import.meta.url)), "..", "package.json");
|
|
25810
26075
|
const pkg = require2(pkgPath);
|
|
25811
26076
|
return pkg.version;
|
|
25812
26077
|
} catch {
|