openAgent
gitlabThe open source UNIVERSAL agent.
clone
https://gitlab.com/bitzzdev/openAgent.gitAIagentautomationopen-sourceuniversal-agent
import type { CliRenderer } from "@opentui/core"import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"import { readFile, rm, writeFile } from "node:fs/promises"import os from "node:os"import path from "node:path"import { spawn } from "node:child_process"import type { Stream } from "node:stream"import { resolveZedDbPath, resolveZedSelection } from "./editor-zed"type EditorStdio = "inherit" | "pipe" | "ignore" | number | Streamexport function normalizePromptContent(content: string) {if (content.endsWith("\r\n")) {const body = content.slice(0, -2)return !body.includes("\n") && !body.includes("\r") ? body : content}if (content.endsWith("\n")) {const body = content.slice(0, -1)return !body.includes("\n") && !body.includes("\r") ? body : content}return content}export async function openEditor(input: { value: string; renderer: CliRenderer; cwd?: string; stdin?: EditorStdio }) {const editor = process.env.VISUAL || process.env.EDITORif (!editor) returnconst file = path.join(os.tmpdir(), `${Date.now()}.md`)await writeFile(file, input.value)input.renderer.suspend()input.renderer.currentRenderBuffer.clear()try {await new Promise<void>((resolve, reject) => {const parts = editor.split(" ")const child = spawn(parts[0]!, [...parts.slice(1), file], {cwd: input.cwd && existsSync(input.cwd) ? input.cwd : process.cwd(),stdio: [input.stdin ?? "inherit", "inherit", "inherit"],shell: process.platform === "win32",})child.on("error", reject)child.on("exit", (code, signal) => {if (code === 0) return resolve()reject(new Error(`Editor exited with ${signal ? `signal ${signal}` : `code ${code}`}`))})})return (await readFile(file, "utf8")) || undefined} finally {await rm(file, { force: true }).catch(() => {})input.renderer.currentRenderBuffer.clear()input.renderer.resume()input.renderer.requestRender()}}export function discoverEditorConnection(directory: string) {const root = path.join(os.homedir(), ".claude", "ide")const contains = (parent: string) => {const resolved = path.resolve(parent)const relative = path.relative(resolved, path.resolve(directory))return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative)) ? resolved.length : 0}try {return readdirSync(root).filter((entry) => entry.endsWith(".lock")).flatMap((entry) => {const file = path.join(root, entry)const port = Number.parseInt(path.basename(file, ".lock"), 10)if (!Number.isInteger(port) || port <= 0 || port > 65535) return []try {const value = JSON.parse(readFileSync(file, "utf8")) as Record<string, unknown>if (value.transport !== undefined && value.transport !== "ws") return []const folders = Array.isArray(value.workspaceFolders)? value.workspaceFolders.filter((item): item is string => typeof item === "string"): []const score = Math.max(0, ...folders.map(contains))if (!score) return []return [{url: `ws://127.0.0.1:${port}`,authToken: typeof value.authToken === "string" ? value.authToken : undefined,source: `lock:${port}`,score,mtime: statSync(file).mtimeMs,},]} catch {return []}}).sort((left, right) => right.score - left.score || right.mtime - left.mtime).map(({ url, authToken, source }) => ({ url, authToken, source }))[0]} catch {return undefined}}export const editorIntegration = {connection: discoverEditorConnection,selection: (directory: string) => resolveZedSelection(resolveZedDbPath() ?? "", directory),}