From 60178ceafa2da561a66e631b3a373e99ee7543f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 17 Apr 2026 02:20:46 -0400 Subject: [PATCH] chore(adapter): delete adapter packages and drop build wiring Removes the four workspace adapter packages (claude-local, codex-local, gemini-local, adapter-utils) now that all runtime provider dispatch lives in @mariozechner/pi-ai + pi-agent-core + pi-coding-agent. Refreshes the lockfile, drops bundledMainDependencies from the Vite config, and adds pi-coding-agent as a direct dependency for the worker's coding tools. --- electron.vite.config.ts | 9 +- package.json | 7 +- packages/adapter-claude-local/package.json | 51 - .../src/cli/format-event.ts | 83 - .../adapter-claude-local/src/cli/index.ts | 1 - packages/adapter-claude-local/src/index.ts | 37 - .../src/server/execute-helpers.ts | 134 - .../src/server/execute.ts | 336 --- .../adapter-claude-local/src/server/index.ts | 12 - .../adapter-claude-local/src/server/parse.ts | 179 -- .../adapter-claude-local/src/server/skills.ts | 131 - .../adapter-claude-local/src/server/test.ts | 124 - .../src/ui/build-config.ts | 39 - packages/adapter-claude-local/src/ui/index.ts | 2 - .../src/ui/parse-stdout.ts | 115 - packages/adapter-claude-local/tsconfig.json | 8 - packages/adapter-codex-local/package.json | 51 - .../src/cli/format-event.ts | 202 -- packages/adapter-codex-local/src/cli/index.ts | 1 - packages/adapter-codex-local/src/index.ts | 46 - .../src/server/execute-helpers.ts | 96 - .../adapter-codex-local/src/server/execute.ts | 258 -- .../adapter-codex-local/src/server/index.ts | 7 - .../adapter-codex-local/src/server/parse.ts | 79 - .../adapter-codex-local/src/server/skills.ts | 99 - .../adapter-codex-local/src/server/test.ts | 122 - .../src/ui/build-config.ts | 45 - packages/adapter-codex-local/src/ui/index.ts | 2 - .../src/ui/parse-stdout.ts | 234 -- packages/adapter-codex-local/tsconfig.json | 8 - packages/adapter-gemini-local/package.json | 51 - .../src/cli/format-event.ts | 171 -- .../adapter-gemini-local/src/cli/index.ts | 1 - packages/adapter-gemini-local/src/index.ts | 47 - .../src/server/execute-helpers.ts | 127 - .../src/server/execute.ts | 294 --- .../adapter-gemini-local/src/server/index.ts | 13 - .../adapter-gemini-local/src/server/parse.ts | 263 -- .../adapter-gemini-local/src/server/skills.ts | 113 - .../adapter-gemini-local/src/server/test.ts | 152 -- .../src/ui/build-config.ts | 26 - packages/adapter-gemini-local/src/ui/index.ts | 2 - .../src/ui/parse-stdout.ts | 245 -- packages/adapter-gemini-local/tsconfig.json | 8 - packages/adapter-utils/package.json | 36 - packages/adapter-utils/src/config-utils.ts | 61 - packages/adapter-utils/src/execute-helpers.ts | 232 -- packages/adapter-utils/src/index.ts | 50 - packages/adapter-utils/src/log-redaction.ts | 49 - packages/adapter-utils/src/parse-utils.ts | 47 - .../adapter-utils/src/server-utils-parsers.ts | 138 -- .../adapter-utils/src/server-utils-process.ts | 394 --- .../src/server-utils-skills-sync.ts | 305 --- .../adapter-utils/src/server-utils-skills.ts | 176 -- packages/adapter-utils/src/server-utils.ts | 4 - packages/adapter-utils/src/session-codec.ts | 61 - packages/adapter-utils/src/test-utils.ts | 37 - packages/adapter-utils/src/types.ts | 291 --- packages/adapter-utils/tsconfig.json | 8 - pnpm-lock.yaml | 2161 ++++++++++++++++- 60 files changed, 2067 insertions(+), 6014 deletions(-) delete mode 100644 packages/adapter-claude-local/package.json delete mode 100644 packages/adapter-claude-local/src/cli/format-event.ts delete mode 100644 packages/adapter-claude-local/src/cli/index.ts delete mode 100644 packages/adapter-claude-local/src/index.ts delete mode 100644 packages/adapter-claude-local/src/server/execute-helpers.ts delete mode 100644 packages/adapter-claude-local/src/server/execute.ts delete mode 100644 packages/adapter-claude-local/src/server/index.ts delete mode 100644 packages/adapter-claude-local/src/server/parse.ts delete mode 100644 packages/adapter-claude-local/src/server/skills.ts delete mode 100644 packages/adapter-claude-local/src/server/test.ts delete mode 100644 packages/adapter-claude-local/src/ui/build-config.ts delete mode 100644 packages/adapter-claude-local/src/ui/index.ts delete mode 100644 packages/adapter-claude-local/src/ui/parse-stdout.ts delete mode 100644 packages/adapter-claude-local/tsconfig.json delete mode 100644 packages/adapter-codex-local/package.json delete mode 100644 packages/adapter-codex-local/src/cli/format-event.ts delete mode 100644 packages/adapter-codex-local/src/cli/index.ts delete mode 100644 packages/adapter-codex-local/src/index.ts delete mode 100644 packages/adapter-codex-local/src/server/execute-helpers.ts delete mode 100644 packages/adapter-codex-local/src/server/execute.ts delete mode 100644 packages/adapter-codex-local/src/server/index.ts delete mode 100644 packages/adapter-codex-local/src/server/parse.ts delete mode 100644 packages/adapter-codex-local/src/server/skills.ts delete mode 100644 packages/adapter-codex-local/src/server/test.ts delete mode 100644 packages/adapter-codex-local/src/ui/build-config.ts delete mode 100644 packages/adapter-codex-local/src/ui/index.ts delete mode 100644 packages/adapter-codex-local/src/ui/parse-stdout.ts delete mode 100644 packages/adapter-codex-local/tsconfig.json delete mode 100644 packages/adapter-gemini-local/package.json delete mode 100644 packages/adapter-gemini-local/src/cli/format-event.ts delete mode 100644 packages/adapter-gemini-local/src/cli/index.ts delete mode 100644 packages/adapter-gemini-local/src/index.ts delete mode 100644 packages/adapter-gemini-local/src/server/execute-helpers.ts delete mode 100644 packages/adapter-gemini-local/src/server/execute.ts delete mode 100644 packages/adapter-gemini-local/src/server/index.ts delete mode 100644 packages/adapter-gemini-local/src/server/parse.ts delete mode 100644 packages/adapter-gemini-local/src/server/skills.ts delete mode 100644 packages/adapter-gemini-local/src/server/test.ts delete mode 100644 packages/adapter-gemini-local/src/ui/build-config.ts delete mode 100644 packages/adapter-gemini-local/src/ui/index.ts delete mode 100644 packages/adapter-gemini-local/src/ui/parse-stdout.ts delete mode 100644 packages/adapter-gemini-local/tsconfig.json delete mode 100644 packages/adapter-utils/package.json delete mode 100644 packages/adapter-utils/src/config-utils.ts delete mode 100644 packages/adapter-utils/src/execute-helpers.ts delete mode 100644 packages/adapter-utils/src/index.ts delete mode 100644 packages/adapter-utils/src/log-redaction.ts delete mode 100644 packages/adapter-utils/src/parse-utils.ts delete mode 100644 packages/adapter-utils/src/server-utils-parsers.ts delete mode 100644 packages/adapter-utils/src/server-utils-process.ts delete mode 100644 packages/adapter-utils/src/server-utils-skills-sync.ts delete mode 100644 packages/adapter-utils/src/server-utils-skills.ts delete mode 100644 packages/adapter-utils/src/server-utils.ts delete mode 100644 packages/adapter-utils/src/session-codec.ts delete mode 100644 packages/adapter-utils/src/test-utils.ts delete mode 100644 packages/adapter-utils/src/types.ts delete mode 100644 packages/adapter-utils/tsconfig.json diff --git a/electron.vite.config.ts b/electron.vite.config.ts index 62cd48a9..87aab7b8 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -3,16 +3,9 @@ import react from "@vitejs/plugin-react"; import tailwindcss from "@tailwindcss/vite"; import { defineConfig, externalizeDepsPlugin } from "electron-vite"; -const bundledMainDependencies = [ - "@agentcompany/adapter-claude-local", - "@agentcompany/adapter-codex-local", - "@agentcompany/adapter-gemini-local", - "@agentcompany/adapter-utils", -]; - export default defineConfig({ main: { - plugins: [externalizeDepsPlugin({ exclude: bundledMainDependencies })], + plugins: [externalizeDepsPlugin()], resolve: { alias: { "@shared": resolve("src/shared"), diff --git a/package.json b/package.json index 0483515a..fb408f1d 100644 --- a/package.json +++ b/package.json @@ -34,10 +34,9 @@ "postinstall": "node scripts/postinstall.mjs" }, "dependencies": { - "@agentcompany/adapter-claude-local": "workspace:*", - "@agentcompany/adapter-codex-local": "workspace:*", - "@agentcompany/adapter-gemini-local": "workspace:*", - "@agentcompany/adapter-utils": "workspace:*", + "@mariozechner/pi-agent-core": "^0.67.6", + "@mariozechner/pi-ai": "^0.67.6", + "@mariozechner/pi-coding-agent": "^0.67.6", "@phosphor-icons/react": "2.1.10", "@tanstack/react-virtual": "^3.13.23", "electron-log": "5.4.3", diff --git a/packages/adapter-claude-local/package.json b/packages/adapter-claude-local/package.json deleted file mode 100644 index 4123e33e..00000000 --- a/packages/adapter-claude-local/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@agentcompany/adapter-claude-local", - "version": "0.3.0", - "type": "module", - "exports": { - ".": "./src/index.ts", - "./server": "./src/server/index.ts", - "./ui": "./src/ui/index.ts", - "./cli": "./src/cli/index.ts" - }, - "publishConfig": { - "access": "public", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - }, - "./server": { - "types": "./dist/server/index.d.ts", - "import": "./dist/server/index.js" - }, - "./ui": { - "types": "./dist/ui/index.d.ts", - "import": "./dist/ui/index.js" - }, - "./cli": { - "types": "./dist/cli/index.d.ts", - "import": "./dist/cli/index.js" - } - }, - "main": "./dist/index.js", - "types": "./dist/index.d.ts" - }, - "files": [ - "dist", - "skills" - ], - "scripts": { - "build": "tsc", - "clean": "rm -rf dist", - "typecheck": "tsc --noEmit" - }, - "dependencies": { - "@agentcompany/adapter-utils": "workspace:*", - "picocolors": "^1.1.1" - }, - "devDependencies": { - "@types/node": "^24.6.0", - "typescript": "^5.7.3" - } -} diff --git a/packages/adapter-claude-local/src/cli/format-event.ts b/packages/adapter-claude-local/src/cli/format-event.ts deleted file mode 100644 index 30fe9d13..00000000 --- a/packages/adapter-claude-local/src/cli/format-event.ts +++ /dev/null @@ -1,83 +0,0 @@ -import pc from "picocolors"; -import { errorText as asErrorText } from "@agentcompany/adapter-utils/parse-utils"; - -export function printClaudeStreamEvent(raw: string, debug: boolean): void { - const line = raw.trim(); - if (!line) return; - - let parsed: Record | null = null; - try { - parsed = JSON.parse(line) as Record; - } catch { - console.log(line); - return; - } - - const type = typeof parsed.type === "string" ? parsed.type : ""; - - if (type === "system" && parsed.subtype === "init") { - const model = typeof parsed.model === "string" ? parsed.model : "unknown"; - const sessionId = typeof parsed.session_id === "string" ? parsed.session_id : ""; - console.log(pc.blue(`Claude initialized (model: ${model}${sessionId ? `, session: ${sessionId}` : ""})`)); - return; - } - - if (type === "assistant") { - const message = - typeof parsed.message === "object" && parsed.message !== null && !Array.isArray(parsed.message) - ? (parsed.message as Record) - : {}; - const content = Array.isArray(message.content) ? message.content : []; - for (const blockRaw of content) { - if (typeof blockRaw !== "object" || blockRaw === null || Array.isArray(blockRaw)) continue; - const block = blockRaw as Record; - const blockType = typeof block.type === "string" ? block.type : ""; - if (blockType === "text") { - const text = typeof block.text === "string" ? block.text : ""; - if (text) console.log(pc.green(`assistant: ${text}`)); - } else if (blockType === "tool_use") { - const name = typeof block.name === "string" ? block.name : "unknown"; - console.log(pc.yellow(`tool_call: ${name}`)); - if (block.input !== undefined) { - console.log(pc.gray(JSON.stringify(block.input, null, 2))); - } - } - } - return; - } - - if (type === "result") { - const usage = - typeof parsed.usage === "object" && parsed.usage !== null && !Array.isArray(parsed.usage) - ? (parsed.usage as Record) - : {}; - const input = Number(usage.input_tokens ?? 0); - const output = Number(usage.output_tokens ?? 0); - const cached = Number(usage.cache_read_input_tokens ?? 0); - const cost = Number(parsed.total_cost_usd ?? 0); - const subtype = typeof parsed.subtype === "string" ? parsed.subtype : ""; - const isError = parsed.is_error === true; - const resultText = typeof parsed.result === "string" ? parsed.result : ""; - if (resultText) { - console.log(pc.green("result:")); - console.log(resultText); - } - const errors = Array.isArray(parsed.errors) ? parsed.errors.map(asErrorText).filter(Boolean) : []; - if (subtype.startsWith("error") || isError || errors.length > 0) { - console.log(pc.red(`claude_result: subtype=${subtype || "unknown"} is_error=${isError ? "true" : "false"}`)); - if (errors.length > 0) { - console.log(pc.red(`claude_errors: ${errors.join(" | ")}`)); - } - } - console.log( - pc.blue( - `tokens: in=${Number.isFinite(input) ? input : 0} out=${Number.isFinite(output) ? output : 0} cached=${Number.isFinite(cached) ? cached : 0} cost=$${Number.isFinite(cost) ? cost.toFixed(6) : "0.000000"}`, - ), - ); - return; - } - - if (debug) { - console.log(pc.gray(line)); - } -} diff --git a/packages/adapter-claude-local/src/cli/index.ts b/packages/adapter-claude-local/src/cli/index.ts deleted file mode 100644 index 7c81ab6f..00000000 --- a/packages/adapter-claude-local/src/cli/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { printClaudeStreamEvent } from "./format-event.js"; diff --git a/packages/adapter-claude-local/src/index.ts b/packages/adapter-claude-local/src/index.ts deleted file mode 100644 index a273e009..00000000 --- a/packages/adapter-claude-local/src/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -export const type = "claude_local"; -export const label = "Claude Code (local)"; - -export const models = [ - { id: "claude-opus-4-6", label: "Claude Opus 4.6" }, - { id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6" }, - { id: "claude-haiku-4-6", label: "Claude Haiku 4.6" }, - { id: "claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5" }, - { id: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5" }, -]; - -export const agentConfigurationDoc = `# claude_local agent configuration - -Adapter: claude_local - -Core fields: -- cwd (string, optional): default absolute working directory fallback for the agent process (created if missing when possible) -- instructionsFilePath (string, optional): absolute path to a markdown instructions file injected at runtime -- model (string, optional): Claude model id -- effort (string, optional): reasoning effort passed via --effort (low|medium|high) -- chrome (boolean, optional): pass --chrome when running Claude -- promptTemplate (string, optional): run prompt template -- maxTurnsPerRun (number, optional): max turns for one run -- dangerouslySkipPermissions (boolean, optional): pass --dangerously-skip-permissions to claude -- command (string, optional): defaults to "claude" -- extraArgs (string[], optional): additional CLI args -- env (object, optional): KEY=VALUE environment variables -- workspaceStrategy (object, optional): execution workspace strategy; currently supports { type: "git_worktree", baseRef?, branchTemplate?, worktreeParentDir? } -- workspaceRuntime (object, optional): workspace runtime service intents; local host-managed services are realized before Claude starts and exposed back via context/env - -Operational fields: -- timeoutSec (number, optional): run timeout in seconds -- graceSec (number, optional): SIGTERM grace period in seconds - -Notes: -- When AgentCompany realizes a workspace/runtime for a run, it injects AGENT_COMPANY_WORKSPACE_* and AGENT_COMPANY_RUNTIME_* env vars for agent-side tooling. -`; diff --git a/packages/adapter-claude-local/src/server/execute-helpers.ts b/packages/adapter-claude-local/src/server/execute-helpers.ts deleted file mode 100644 index d3a15ec5..00000000 --- a/packages/adapter-claude-local/src/server/execute-helpers.ts +++ /dev/null @@ -1,134 +0,0 @@ -import fs from "node:fs/promises"; -import os from "node:os"; -import path from "node:path"; -import type { AdapterExecutionContext, ManagedSkillRef } from "@agentcompany/adapter-utils"; -import type { RunProcessResult } from "@agentcompany/adapter-utils/server-utils"; -import { - asString, - asNumber, - ensureAbsoluteDirectory, - ensureCommandResolvable, - ensurePathInEnv, - createManagedSkillSymlinks, -} from "@agentcompany/adapter-utils/server-utils"; -import { - hasNonEmptyEnvValue, - buildSkillsCandidates, - resolveSkillsDir, - parseManagedSkills, - parseExtraArgs, - buildCommonAgentCompanyEnv, - resolveSessionResumeState, -} from "@agentcompany/adapter-utils"; - -export { - hasNonEmptyEnvValue, - buildSkillsCandidates, - resolveSkillsDir as resolveAgentCompanySkillsDir, - parseManagedSkills, - parseExtraArgs, - buildCommonAgentCompanyEnv, - resolveSessionResumeState, -}; - -export const SKILLS_CANDIDATES = buildSkillsCandidates(import.meta.url); - -/** - * Create a tmpdir with `.claude/skills/` containing symlinks to skills from - * managed skill entries (preferred) or the repo's static `skills/` directory - * (backward compatibility fallback), so `--add-dir` makes Claude Code discover - * them as proper registered skills. - */ -export async function buildSkillsDir( - managedSkills: ManagedSkillRef[], - onLog: (stream: "stdout" | "stderr", chunk: string) => Promise, -): Promise { - const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "agent-company-skills-")); - const target = path.join(tmp, ".claude", "skills"); - await fs.mkdir(target, { recursive: true }); - - if (managedSkills.length > 0) { - await createManagedSkillSymlinks(managedSkills, target, onLog); - return tmp; - } - - const skillsDir = await resolveSkillsDir(SKILLS_CANDIDATES); - if (!skillsDir) return tmp; - const entries = await fs.readdir(skillsDir, { withFileTypes: true }); - for (const entry of entries) { - if (entry.isDirectory()) { - await fs.symlink( - path.join(skillsDir, entry.name), - path.join(target, entry.name), - ); - } - } - return tmp; -} - -export interface ClaudeExecutionInput { - runId: string; - agent: AdapterExecutionContext["agent"]; - config: Record; - context: Record; - authToken?: string; -} - -export interface ClaudeRuntimeConfig { - command: string; - cwd: string; - workspaceId: string | null; - workspaceRepoUrl: string | null; - workspaceRepoRef: string | null; - env: Record; - timeoutSec: number; - graceSec: number; - extraArgs: string[]; -} - -export function buildLoginResult(input: { - proc: RunProcessResult; - loginUrl: string | null; -}) { - return { - exitCode: input.proc.exitCode, - signal: input.proc.signal, - timedOut: input.proc.timedOut, - stdout: input.proc.stdout, - stderr: input.proc.stderr, - loginUrl: input.loginUrl, - }; -} - -export function resolveClaudeBillingType(env: Record): "api" | "subscription" { - return hasNonEmptyEnvValue(env, "ANTHROPIC_API_KEY") ? "api" : "subscription"; -} - -export async function buildClaudeRuntimeConfig(input: ClaudeExecutionInput): Promise { - const { runId, agent, config, context, authToken } = input; - - const command = asString(config.command, "claude"); - const { env, cwd, workspaceId, workspaceRepoUrl, workspaceRepoRef } = await buildCommonAgentCompanyEnv( - { runId, agent, config, context, authToken }, - { ensureAbsoluteDirectory }, - ); - - const runtimeEnv = ensurePathInEnv(env); - await ensureCommandResolvable(command, cwd, runtimeEnv); - - const timeoutSec = asNumber(config.timeoutSec, 0); - const graceSec = asNumber(config.graceSec, 20); - const extraArgs = parseExtraArgs(config); - - return { - command, - cwd, - workspaceId, - workspaceRepoUrl, - workspaceRepoRef, - env, - timeoutSec, - graceSec, - extraArgs, - }; -} diff --git a/packages/adapter-claude-local/src/server/execute.ts b/packages/adapter-claude-local/src/server/execute.ts deleted file mode 100644 index e62ad6a5..00000000 --- a/packages/adapter-claude-local/src/server/execute.ts +++ /dev/null @@ -1,336 +0,0 @@ -import fs from "node:fs/promises"; -import path from "node:path"; -import type { AdapterExecutionContext, AdapterExecutionResult } from "@agentcompany/adapter-utils"; -import type { RunProcessResult } from "@agentcompany/adapter-utils/server-utils"; -import { - asString, - asNumber, - asBoolean, - parseObject, - parseJson, - redactEnvForLogs, - filterConflictingArgs, - renderTemplate, - runChildProcess, -} from "@agentcompany/adapter-utils/server-utils"; -import { - parseClaudeStreamJson, - describeClaudeFailure, - detectClaudeLoginRequired, - isClaudeMaxTurnsResult, - isClaudeUnknownSessionError, -} from "./parse.js"; -import { - buildSkillsDir, - buildLoginResult, - resolveClaudeBillingType, - buildClaudeRuntimeConfig, - parseManagedSkills, - resolveSessionResumeState, -} from "./execute-helpers.js"; - -export async function runClaudeLogin(input: { - runId: string; - agent: AdapterExecutionContext["agent"]; - config: Record; - context?: Record; - authToken?: string; - onLog?: (stream: "stdout" | "stderr", chunk: string) => Promise; -}) { - const onLog = input.onLog ?? (async () => {}); - const runtime = await buildClaudeRuntimeConfig({ - runId: input.runId, - agent: input.agent, - config: input.config, - context: input.context ?? {}, - authToken: input.authToken, - }); - - const proc = await runChildProcess(input.runId, runtime.command, ["login"], { - cwd: runtime.cwd, - env: runtime.env, - timeoutSec: runtime.timeoutSec, - graceSec: runtime.graceSec, - onLog, - }); - - const loginMeta = detectClaudeLoginRequired({ - parsed: null, - stdout: proc.stdout, - stderr: proc.stderr, - }); - - return buildLoginResult({ - proc, - loginUrl: loginMeta.loginUrl, - }); -} - -export async function execute(ctx: AdapterExecutionContext): Promise { - const { runId, agent, runtime, config, context, onLog, onMeta, authToken } = ctx; - - const promptTemplate = asString( - config.promptTemplate, - "{{context.taskTitle}}\n\n{{context.taskDescription}}", - ); - const model = asString(config.model, ""); - const effort = asString(config.effort, ""); - const chrome = asBoolean(config.chrome, false); - const maxTurns = asNumber(config.maxTurnsPerRun, 0); - const dangerouslySkipPermissions = asBoolean(config.dangerouslySkipPermissions, false); - const instructionsFilePath = asString(config.instructionsFilePath, "").trim(); - const instructionsFileDir = instructionsFilePath ? `${path.dirname(instructionsFilePath)}/` : ""; - const commandNotes = instructionsFilePath - ? [ - `Injected agent instructions via --append-system-prompt-file ${instructionsFilePath} (with path directive appended)`, - ] - : []; - - const runtimeConfig = await buildClaudeRuntimeConfig({ - runId, - agent, - config, - context, - authToken, - }); - const { - command, - cwd, - workspaceId, - workspaceRepoUrl, - workspaceRepoRef, - env, - timeoutSec, - graceSec, - extraArgs, - } = runtimeConfig; - const billingType = resolveClaudeBillingType(env); - const managedSkills = parseManagedSkills(config); - const skillsDir = await buildSkillsDir(managedSkills, onLog); - - // When instructionsFilePath is configured, create a combined temp file that - // includes both the file content and the path directive, so we only need - // --append-system-prompt-file (Claude CLI forbids using both flags together). - let effectiveInstructionsFilePath = instructionsFilePath; - if (instructionsFilePath) { - const instructionsContent = await fs.readFile(instructionsFilePath, "utf-8"); - const pathDirective = `\nThe above agent instructions were loaded from ${instructionsFilePath}. Resolve any relative file references from ${instructionsFileDir}.`; - const combinedPath = path.join(skillsDir, "agent-instructions.md"); - await fs.writeFile(combinedPath, instructionsContent + pathDirective, "utf-8"); - effectiveInstructionsFilePath = combinedPath; - } - - const sessionResume = resolveSessionResumeState(runtime, cwd); - const { sessionId, runtimeSessionId, runtimeSessionCwd, canResumeSession } = sessionResume; - if (runtimeSessionId && !canResumeSession) { - await onLog( - "stderr", - `[agent-company] Claude session "${runtimeSessionId}" was saved for cwd "${runtimeSessionCwd}" and will not be resumed in "${cwd}".\n`, - ); - } - const prompt = renderTemplate(promptTemplate, { - agentId: agent.id, - companyId: agent.companyId, - runId, - company: { id: agent.companyId }, - agent, - run: { id: runId, source: "on_demand" }, - context, - }); - - const buildClaudeArgs = (resumeSessionId: string | null) => { - const args = ["--print", "-", "--output-format", "stream-json", "--verbose"]; - if (resumeSessionId) args.push("--resume", resumeSessionId); - if (dangerouslySkipPermissions) args.push("--dangerously-skip-permissions"); - if (chrome) args.push("--chrome"); - if (model) args.push("--model", model); - if (effort) args.push("--effort", effort); - if (maxTurns > 0) args.push("--max-turns", String(maxTurns)); - if (effectiveInstructionsFilePath) { - args.push("--append-system-prompt-file", effectiveInstructionsFilePath); - } - args.push("--add-dir", skillsDir); - if (extraArgs.length > 0) { - // Filter out flags the adapter already manages to prevent duplicates - // (e.g. user shell aliases that inject --dangerously-skip-permissions) - const managedFlags = [ - "--dangerously-skip-permissions", - "--output-format", - "--model", - "--effort", - "--max-turns", - "--add-dir", - "--append-system-prompt-file", - "--teammate-mode", - ]; - const cleaned = filterConflictingArgs(extraArgs, managedFlags); - if (cleaned.length > 0) args.push(...cleaned); - } - return args; - }; - - const parseFallbackErrorMessage = (proc: RunProcessResult) => { - const stderrLine = - proc.stderr - .split(/\r?\n/) - .map((line) => line.trim()) - .find(Boolean) ?? ""; - - if ((proc.exitCode ?? 0) === 0) { - return "Failed to parse claude JSON output"; - } - - return stderrLine - ? `Claude exited with code ${proc.exitCode ?? -1}: ${stderrLine}` - : `Claude exited with code ${proc.exitCode ?? -1}`; - }; - - const runAttempt = async (resumeSessionId: string | null) => { - const args = buildClaudeArgs(resumeSessionId); - if (onMeta) { - await onMeta({ - adapterType: "claude_local", - command, - cwd, - commandArgs: args, - commandNotes, - env: redactEnvForLogs(env), - prompt, - context, - }); - } - - const proc = await runChildProcess(runId, command, args, { - cwd, - env, - stdin: prompt, - timeoutSec, - graceSec, - onLog, - }); - - const parsedStream = parseClaudeStreamJson(proc.stdout); - const parsed = parsedStream.resultJson ?? parseJson(proc.stdout); - return { proc, parsedStream, parsed }; - }; - - const toAdapterResult = ( - attempt: { - proc: RunProcessResult; - parsedStream: ReturnType; - parsed: Record | null; - }, - opts: { fallbackSessionId: string | null; clearSessionOnMissingSession?: boolean }, - ): AdapterExecutionResult => { - const { proc, parsedStream, parsed } = attempt; - const loginMeta = detectClaudeLoginRequired({ - parsed, - stdout: proc.stdout, - stderr: proc.stderr, - }); - const errorMeta = - loginMeta.loginUrl != null - ? { - loginUrl: loginMeta.loginUrl, - } - : undefined; - - if (proc.timedOut) { - return { - exitCode: proc.exitCode, - signal: proc.signal, - timedOut: true, - errorMessage: `Timed out after ${timeoutSec}s`, - errorCode: "timeout", - errorMeta, - clearSession: Boolean(opts.clearSessionOnMissingSession), - }; - } - - if (!parsed) { - return { - exitCode: proc.exitCode, - signal: proc.signal, - timedOut: false, - errorMessage: parseFallbackErrorMessage(proc), - errorCode: loginMeta.requiresLogin ? "claude_auth_required" : null, - errorMeta, - resultJson: { - stdout: proc.stdout, - stderr: proc.stderr, - }, - clearSession: Boolean(opts.clearSessionOnMissingSession), - }; - } - - const usage = - parsedStream.usage ?? - (() => { - const usageObj = parseObject(parsed.usage); - return { - inputTokens: asNumber(usageObj.input_tokens, 0), - cachedInputTokens: asNumber(usageObj.cache_read_input_tokens, 0), - outputTokens: asNumber(usageObj.output_tokens, 0), - }; - })(); - - const resolvedSessionId = - parsedStream.sessionId ?? - (asString(parsed.session_id, opts.fallbackSessionId ?? "") || opts.fallbackSessionId); - const resolvedSessionParams = resolvedSessionId - ? ({ - sessionId: resolvedSessionId, - cwd, - ...(workspaceId ? { workspaceId } : {}), - ...(workspaceRepoUrl ? { repoUrl: workspaceRepoUrl } : {}), - ...(workspaceRepoRef ? { repoRef: workspaceRepoRef } : {}), - } as Record) - : null; - const clearSessionForMaxTurns = isClaudeMaxTurnsResult(parsed); - - return { - exitCode: proc.exitCode, - signal: proc.signal, - timedOut: false, - errorMessage: - (proc.exitCode ?? 0) === 0 - ? null - : describeClaudeFailure(parsed) ?? `Claude exited with code ${proc.exitCode ?? -1}`, - errorCode: loginMeta.requiresLogin ? "claude_auth_required" : null, - errorMeta, - usage, - sessionId: resolvedSessionId, - sessionParams: resolvedSessionParams, - sessionDisplayId: resolvedSessionId, - provider: "anthropic", - model: parsedStream.model || asString(parsed.model, model), - billingType, - costUsd: parsedStream.costUsd ?? asNumber(parsed.total_cost_usd, 0), - resultJson: parsed, - summary: parsedStream.summary || asString(parsed.result, ""), - clearSession: clearSessionForMaxTurns || Boolean(opts.clearSessionOnMissingSession && !resolvedSessionId), - }; - }; - - try { - const initial = await runAttempt(sessionId ?? null); - if ( - sessionId && - !initial.proc.timedOut && - (initial.proc.exitCode ?? 0) !== 0 && - initial.parsed && - isClaudeUnknownSessionError(initial.parsed) - ) { - await onLog( - "stderr", - `[agent-company] Claude resume session "${sessionId}" is unavailable; retrying with a fresh session.\n`, - ); - const retry = await runAttempt(null); - return toAdapterResult(retry, { fallbackSessionId: null, clearSessionOnMissingSession: true }); - } - - return toAdapterResult(initial, { fallbackSessionId: runtimeSessionId || runtime.sessionId }); - } finally { - fs.rm(skillsDir, { recursive: true, force: true }).catch(() => {}); - } -} diff --git a/packages/adapter-claude-local/src/server/index.ts b/packages/adapter-claude-local/src/server/index.ts deleted file mode 100644 index 702c28cd..00000000 --- a/packages/adapter-claude-local/src/server/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export { execute, runClaudeLogin } from "./execute.js"; -export { testEnvironment } from "./test.js"; -export { - parseClaudeStreamJson, - describeClaudeFailure, - isClaudeMaxTurnsResult, - isClaudeUnknownSessionError, -} from "./parse.js"; -export { listClaudeSkills, syncClaudeSkills } from "./skills.js"; -import { createStandardSessionCodec } from "@agentcompany/adapter-utils/session-codec"; - -export const sessionCodec = createStandardSessionCodec(); diff --git a/packages/adapter-claude-local/src/server/parse.ts b/packages/adapter-claude-local/src/server/parse.ts deleted file mode 100644 index fca598fc..00000000 --- a/packages/adapter-claude-local/src/server/parse.ts +++ /dev/null @@ -1,179 +0,0 @@ -import type { UsageSummary } from "@agentcompany/adapter-utils"; -import { asString, asNumber, parseObject, parseJson } from "@agentcompany/adapter-utils/server-utils"; - -const CLAUDE_AUTH_REQUIRED_RE = /(?:not\s+logged\s+in|please\s+log\s+in|please\s+run\s+`?claude\s+login`?|login\s+required|requires\s+login|unauthorized|authentication\s+required)/i; -const URL_RE = /(https?:\/\/[^\s'"`<>()[\]{};,!?]+[^\s'"`<>()[\]{};,!.?:]+)/gi; - -export function parseClaudeStreamJson(stdout: string) { - let sessionId: string | null = null; - let model = ""; - let finalResult: Record | null = null; - const assistantTexts: string[] = []; - - for (const rawLine of stdout.split(/\r?\n/)) { - const line = rawLine.trim(); - if (!line) continue; - const event = parseJson(line); - if (!event) continue; - - const type = asString(event.type, ""); - if (type === "system" && asString(event.subtype, "") === "init") { - sessionId = asString(event.session_id, sessionId ?? "") || sessionId; - model = asString(event.model, model); - continue; - } - - if (type === "assistant") { - sessionId = asString(event.session_id, sessionId ?? "") || sessionId; - const message = parseObject(event.message); - const content = Array.isArray(message.content) ? message.content : []; - for (const entry of content) { - if (typeof entry !== "object" || entry === null || Array.isArray(entry)) continue; - const block = entry as Record; - if (asString(block.type, "") === "text") { - const text = asString(block.text, ""); - if (text) assistantTexts.push(text); - } - } - continue; - } - - if (type === "result") { - finalResult = event; - sessionId = asString(event.session_id, sessionId ?? "") || sessionId; - } - } - - if (!finalResult) { - return { - sessionId, - model, - costUsd: null as number | null, - usage: null as UsageSummary | null, - summary: assistantTexts.join("\n\n").trim(), - resultJson: null as Record | null, - }; - } - - const usageObj = parseObject(finalResult.usage); - const usage: UsageSummary = { - inputTokens: asNumber(usageObj.input_tokens, 0), - cachedInputTokens: asNumber(usageObj.cache_read_input_tokens, 0), - outputTokens: asNumber(usageObj.output_tokens, 0), - }; - const costRaw = finalResult.total_cost_usd; - const costUsd = typeof costRaw === "number" && Number.isFinite(costRaw) ? costRaw : null; - const summary = asString(finalResult.result, assistantTexts.join("\n\n")).trim(); - - return { - sessionId, - model, - costUsd, - usage, - summary, - resultJson: finalResult, - }; -} - -function extractClaudeErrorMessages(parsed: Record): string[] { - const raw = Array.isArray(parsed.errors) ? parsed.errors : []; - const messages: string[] = []; - - for (const entry of raw) { - if (typeof entry === "string") { - const msg = entry.trim(); - if (msg) messages.push(msg); - continue; - } - - if (typeof entry !== "object" || entry === null || Array.isArray(entry)) { - continue; - } - - const obj = entry as Record; - const msg = asString(obj.message, "") || asString(obj.error, "") || asString(obj.code, ""); - if (msg) { - messages.push(msg); - continue; - } - - try { - messages.push(JSON.stringify(obj)); - } catch { - // skip non-serializable entry - } - } - - return messages; -} - -export function extractClaudeLoginUrl(text: string): string | null { - const match = text.match(URL_RE); - if (!match || match.length === 0) return null; - for (const rawUrl of match) { - const cleaned = rawUrl.replace(/[\])}.!,?;:'"]+$/g, ""); - if (cleaned.includes("claude") || cleaned.includes("anthropic") || cleaned.includes("auth")) { - return cleaned; - } - } - return match[0]?.replace(/[\])}.!,?;:'"]+$/g, "") ?? null; -} - -export function detectClaudeLoginRequired(input: { - parsed: Record | null; - stdout: string; - stderr: string; -}): { requiresLogin: boolean; loginUrl: string | null } { - const resultText = asString(input.parsed?.result, "").trim(); - const messages = [resultText, ...extractClaudeErrorMessages(input.parsed ?? {}), input.stdout, input.stderr] - .join("\n") - .split(/\r?\n/) - .map((line) => line.trim()) - .filter(Boolean); - - const requiresLogin = messages.some((line) => CLAUDE_AUTH_REQUIRED_RE.test(line)); - return { - requiresLogin, - loginUrl: extractClaudeLoginUrl([input.stdout, input.stderr].join("\n")), - }; -} - -export function describeClaudeFailure(parsed: Record): string | null { - const subtype = asString(parsed.subtype, ""); - const resultText = asString(parsed.result, "").trim(); - const errors = extractClaudeErrorMessages(parsed); - - let detail = resultText; - if (!detail && errors.length > 0) { - detail = errors[0] ?? ""; - } - - const parts = ["Claude run failed"]; - if (subtype) parts.push(`subtype=${subtype}`); - if (detail) parts.push(detail); - return parts.length > 1 ? parts.join(": ") : null; -} - -export function isClaudeMaxTurnsResult(parsed: Record | null | undefined): boolean { - if (!parsed) return false; - - const subtype = asString(parsed.subtype, "").trim().toLowerCase(); - if (subtype === "error_max_turns") return true; - - const stopReason = asString(parsed.stop_reason, "").trim().toLowerCase(); - if (stopReason === "max_turns") return true; - - const resultText = asString(parsed.result, "").trim(); - return /max(?:imum)?\s+turns?/i.test(resultText); -} - -export function isClaudeUnknownSessionError(parsed: Record): boolean { - const resultText = asString(parsed.result, "").trim(); - const allMessages = [resultText, ...extractClaudeErrorMessages(parsed)] - .map((msg) => msg.trim()) - .filter(Boolean); - - return allMessages.some((msg) => - /no conversation found with session id|unknown session|session .* not found/i.test(msg), - ); -} diff --git a/packages/adapter-claude-local/src/server/skills.ts b/packages/adapter-claude-local/src/server/skills.ts deleted file mode 100644 index a86a5e94..00000000 --- a/packages/adapter-claude-local/src/server/skills.ts +++ /dev/null @@ -1,131 +0,0 @@ -// --------------------------------------------------------------------------- -// Claude adapter skill listing / sync -- ephemeral mode -// Skills are mounted into a temp dir via --add-dir at run time, not persisted. -// --------------------------------------------------------------------------- - -import path from "node:path"; -import type { - AdapterSkillContext, - AdapterSkillEntry, - AdapterSkillSnapshot, -} from "@agentcompany/adapter-utils"; -import { - parseObject, - asString, - readAgentCompanyRuntimeSkillEntries, - readInstalledSkillTargets, - resolveAgentCompanyDesiredSkillNames, -} from "@agentcompany/adapter-utils/server-utils"; - -function resolveClaudeSkillsHome(config: Record): string { - const env = parseObject(config.env); - const home = asString(env.HOME, asString(env.USERPROFILE, "")); - const base = home || (process.env.HOME ?? process.env.USERPROFILE ?? ""); - return path.join(base, ".claude", "skills"); -} - -async function buildClaudeSkillSnapshot( - config: Record, -): Promise { - const moduleDir = path.resolve(import.meta.dirname ?? __dirname); - const availableEntries = await readAgentCompanyRuntimeSkillEntries(config, moduleDir); - const desiredSkills = resolveAgentCompanyDesiredSkillNames(config, availableEntries); - const desiredSet = new Set(desiredSkills); - const entries: AdapterSkillEntry[] = []; - const warnings: string[] = []; - - for (const available of availableEntries) { - const desired = desiredSet.has(available.key); - entries.push({ - key: available.key, - runtimeName: available.runtimeName, - desired, - managed: true, - state: desired ? "configured" : "available", - sourcePath: available.source, - targetPath: null, - detail: desired - ? "Will be mounted into the ephemeral Claude skill directory on the next run." - : null, - required: Boolean(available.required), - requiredReason: available.requiredReason ?? null, - origin: available.required ? "paperclip_required" : "company_managed", - originLabel: available.required ? "Required by AgentCompany" : "Managed by AgentCompany", - readOnly: false, - }); - } - - // Scan installed Claude skills for external entries - const skillsHome = resolveClaudeSkillsHome(config); - const installed = await readInstalledSkillTargets(skillsHome); - for (const [name, installedEntry] of installed.entries()) { - if (availableEntries.some((entry) => entry.runtimeName === name)) continue; - entries.push({ - key: name, - runtimeName: name, - desired: false, - managed: false, - state: "external", - origin: "user_installed", - originLabel: "User-installed", - locationLabel: "~/.claude/skills", - readOnly: true, - sourcePath: null, - targetPath: installedEntry.targetPath ?? path.join(skillsHome, name), - detail: "Installed outside AgentCompany management.", - }); - } - - // Check for desired skills not in available - for (const desiredSkill of desiredSkills) { - if (availableEntries.some((entry) => entry.key === desiredSkill)) continue; - if (entries.some((entry) => entry.key === desiredSkill)) continue; - warnings.push(`Desired skill "${desiredSkill}" is not available from the AgentCompany skills directory.`); - entries.push({ - key: desiredSkill, - runtimeName: null, - desired: true, - managed: true, - state: "missing", - sourcePath: null, - targetPath: null, - detail: "AgentCompany cannot find this skill in the local runtime skills directory.", - origin: "external_unknown", - originLabel: "External or unavailable", - readOnly: false, - }); - } - - entries.sort((left, right) => left.key.localeCompare(right.key)); - - return { - adapterType: "claude_local", - supported: true, - mode: "ephemeral", - desiredSkills, - entries, - warnings, - }; -} - -/** - * List the current skill state for the Claude adapter. - * Ephemeral mode: skills are injected at run time via --add-dir, not persisted. - */ -export async function listClaudeSkills( - ctx: AdapterSkillContext, -): Promise { - return buildClaudeSkillSnapshot(ctx.config); -} - -/** - * Sync skills for the Claude adapter. - * Ephemeral mode: no on-disk sync needed; skills are injected at run time. - * Returns the current snapshot for informational purposes. - */ -export async function syncClaudeSkills( - ctx: AdapterSkillContext, - _desiredSkills: string[], -): Promise { - return buildClaudeSkillSnapshot(ctx.config); -} diff --git a/packages/adapter-claude-local/src/server/test.ts b/packages/adapter-claude-local/src/server/test.ts deleted file mode 100644 index a636f911..00000000 --- a/packages/adapter-claude-local/src/server/test.ts +++ /dev/null @@ -1,124 +0,0 @@ -import type { - AdapterEnvironmentCheck, - AdapterEnvironmentTestContext, - AdapterEnvironmentTestResult, -} from "@agentcompany/adapter-utils"; -import { - asString, - asBoolean, - asNumber, - asStringArray, - parseObject, - ensureAbsoluteDirectory, - ensureCommandResolvable, - ensurePathInEnv, - runChildProcess, -} from "@agentcompany/adapter-utils/server-utils"; -import { summarizeStatus, isNonEmpty, commandLooksLike, summarizeProbeDetail } from "@agentcompany/adapter-utils/test-utils"; -import { detectClaudeLoginRequired, parseClaudeStreamJson } from "./parse.js"; - -export async function testEnvironment( - ctx: AdapterEnvironmentTestContext, -): Promise { - const checks: AdapterEnvironmentCheck[] = []; - const config = parseObject(ctx.config); - const command = asString(config.command, "claude"); - const cwd = asString(config.cwd, process.cwd()); - - try { - await ensureAbsoluteDirectory(cwd, { createIfMissing: true }); - checks.push({ code: "claude_cwd_valid", level: "info", message: `Working directory is valid: ${cwd}` }); - } catch (err) { - checks.push({ code: "claude_cwd_invalid", level: "error", message: err instanceof Error ? err.message : "Invalid working directory", detail: cwd }); - } - - const envConfig = parseObject(config.env); - const env: Record = {}; - for (const [key, value] of Object.entries(envConfig)) { - if (typeof value === "string") env[key] = value; - } - const runtimeEnv = ensurePathInEnv(env); - try { - await ensureCommandResolvable(command, cwd, runtimeEnv); - checks.push({ code: "claude_command_resolvable", level: "info", message: `Command is executable: ${command}` }); - } catch (err) { - checks.push({ code: "claude_command_unresolvable", level: "error", message: err instanceof Error ? err.message : "Command is not executable", detail: command }); - } - - const configApiKey = env.ANTHROPIC_API_KEY; - if (isNonEmpty(configApiKey)) { - checks.push({ code: "claude_anthropic_api_key_overrides_subscription", level: "info", message: "ANTHROPIC_API_KEY is set. Claude will use API-key auth." }); - } else { - checks.push({ code: "claude_subscription_mode_possible", level: "info", message: "ANTHROPIC_API_KEY is not set; subscription-based auth can be used if Claude is logged in." }); - } - - // Hello probe: wrapped in try-catch so probe failures never crash the test. - // If the command is resolvable, that is sufficient for "pass" status. - const canRunProbe = checks.every((c) => c.code !== "claude_cwd_invalid" && c.code !== "claude_command_unresolvable"); - if (canRunProbe && commandLooksLike(command, "claude")) { - try { - const model = asString(config.model, "").trim(); - const effort = asString(config.effort, "").trim(); - const chrome = asBoolean(config.chrome, false); - const maxTurns = asNumber(config.maxTurnsPerRun, 0); - const dangerouslySkipPermissions = asBoolean(config.dangerouslySkipPermissions, false); - const extraArgs = (() => { - const fromExtraArgs = asStringArray(config.extraArgs); - if (fromExtraArgs.length > 0) return fromExtraArgs; - return asStringArray(config.args); - })(); - - const args = ["--print", "-", "--output-format", "stream-json", "--verbose"]; - if (dangerouslySkipPermissions) args.push("--dangerously-skip-permissions"); - if (chrome) args.push("--chrome"); - if (model) args.push("--model", model); - if (effort) args.push("--effort", effort); - if (maxTurns > 0) args.push("--max-turns", String(maxTurns)); - if (extraArgs.length > 0) args.push(...extraArgs); - - const probe = await runChildProcess( - `claude-envtest-${Date.now()}-${Math.random().toString(16).slice(2)}`, - command, - args, - { cwd, env, timeoutSec: 45, graceSec: 5, stdin: "Respond with hello.", onLog: async () => {} }, - ); - - const parsedStream = parseClaudeStreamJson(probe.stdout); - const parsed = parsedStream.resultJson; - const loginMeta = detectClaudeLoginRequired({ parsed, stdout: probe.stdout, stderr: probe.stderr }); - const detail = summarizeProbeDetail(probe.stdout, probe.stderr); - - if (probe.timedOut) { - checks.push({ code: "claude_hello_probe_timed_out", level: "info", message: "Claude hello probe timed out." }); - } else if (loginMeta.requiresLogin) { - checks.push({ - code: "claude_hello_probe_auth_required", level: "warn", - message: "Claude CLI is installed, but login is required.", - ...(detail ? { detail } : {}), - hint: loginMeta.loginUrl ? `Run \`claude login\` at ${loginMeta.loginUrl}` : "Run `claude login` first.", - }); - } else if ((probe.exitCode ?? 1) === 0) { - const summary = parsedStream.summary.trim(); - const hasHello = /\bhello\b/i.test(summary); - checks.push({ - code: hasHello ? "claude_hello_probe_passed" : "claude_hello_probe_unexpected_output", - level: "info", - message: hasHello ? "Claude hello probe succeeded." : "Claude probe completed.", - ...(summary ? { detail: summary.replace(/\s+/g, " ").trim().slice(0, 240) } : {}), - }); - } else { - checks.push({ code: "claude_hello_probe_failed", level: "info", message: "Claude hello probe exited with non-zero code.", ...(detail ? { detail } : {}) }); - } - } catch { - // Probe failed to run — command is still resolvable so this is non-fatal. - checks.push({ code: "claude_hello_probe_error", level: "info", message: "Claude hello probe could not run." }); - } - } - - return { - adapterType: ctx.adapterType, - status: summarizeStatus(checks), - checks, - testedAt: new Date().toISOString(), - }; -} diff --git a/packages/adapter-claude-local/src/ui/build-config.ts b/packages/adapter-claude-local/src/ui/build-config.ts deleted file mode 100644 index 595b528b..00000000 --- a/packages/adapter-claude-local/src/ui/build-config.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { CreateConfigValues } from "@agentcompany/adapter-utils"; -import { parseCommaArgs, parseEnvVars, parseEnvBindings, parseJsonObject } from "@agentcompany/adapter-utils/config-utils"; - -export function buildClaudeLocalConfig(v: CreateConfigValues): Record { - const ac: Record = {}; - if (v.cwd) ac.cwd = v.cwd; - if (v.instructionsFilePath) ac.instructionsFilePath = v.instructionsFilePath; - if (v.promptTemplate) ac.promptTemplate = v.promptTemplate; - if (v.model) ac.model = v.model; - if (v.thinkingEffort) ac.effort = v.thinkingEffort; - if (v.chrome) ac.chrome = true; - ac.timeoutSec = 0; - ac.graceSec = 15; - const env = parseEnvBindings(v.envBindings); - const legacy = parseEnvVars(v.envVars); - for (const [key, value] of Object.entries(legacy)) { - if (!Object.prototype.hasOwnProperty.call(env, key)) { - env[key] = { type: "plain", value }; - } - } - if (Object.keys(env).length > 0) ac.env = env; - ac.maxTurnsPerRun = v.maxTurnsPerRun; - ac.dangerouslySkipPermissions = v.dangerouslySkipPermissions; - if (v.workspaceStrategyType === "git_worktree") { - ac.workspaceStrategy = { - type: "git_worktree", - ...(v.workspaceBaseRef ? { baseRef: v.workspaceBaseRef } : {}), - ...(v.workspaceBranchTemplate ? { branchTemplate: v.workspaceBranchTemplate } : {}), - ...(v.worktreeParentDir ? { worktreeParentDir: v.worktreeParentDir } : {}), - }; - } - const runtimeServices = parseJsonObject(v.runtimeServicesJson ?? ""); - if (runtimeServices && Array.isArray(runtimeServices.services)) { - ac.workspaceRuntime = runtimeServices; - } - if (v.command) ac.command = v.command; - if (v.extraArgs) ac.extraArgs = parseCommaArgs(v.extraArgs); - return ac; -} diff --git a/packages/adapter-claude-local/src/ui/index.ts b/packages/adapter-claude-local/src/ui/index.ts deleted file mode 100644 index a7939af3..00000000 --- a/packages/adapter-claude-local/src/ui/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { parseClaudeStdoutLine } from "./parse-stdout.js"; -export { buildClaudeLocalConfig } from "./build-config.js"; diff --git a/packages/adapter-claude-local/src/ui/parse-stdout.ts b/packages/adapter-claude-local/src/ui/parse-stdout.ts deleted file mode 100644 index fda73ee2..00000000 --- a/packages/adapter-claude-local/src/ui/parse-stdout.ts +++ /dev/null @@ -1,115 +0,0 @@ -import type { TranscriptEntry } from "@agentcompany/adapter-utils"; -import { asRecord, safeJsonParse, errorText } from "@agentcompany/adapter-utils/parse-utils"; - -function asNumber(value: unknown): number { - return typeof value === "number" && Number.isFinite(value) ? value : 0; -} - -export function parseClaudeStdoutLine(line: string, ts: string): TranscriptEntry[] { - const parsed = asRecord(safeJsonParse(line)); - if (!parsed) { - return [{ kind: "stdout", ts, text: line }]; - } - - const type = typeof parsed.type === "string" ? parsed.type : ""; - if (type === "system" && parsed.subtype === "init") { - return [ - { - kind: "init", - ts, - model: typeof parsed.model === "string" ? parsed.model : "unknown", - sessionId: typeof parsed.session_id === "string" ? parsed.session_id : "", - }, - ]; - } - - if (type === "assistant") { - const message = asRecord(parsed.message) ?? {}; - const content = Array.isArray(message.content) ? message.content : []; - const entries: TranscriptEntry[] = []; - for (const blockRaw of content) { - const block = asRecord(blockRaw); - if (!block) continue; - const blockType = typeof block.type === "string" ? block.type : ""; - if (blockType === "text") { - const text = typeof block.text === "string" ? block.text : ""; - if (text) entries.push({ kind: "assistant", ts, text }); - } else if (blockType === "thinking") { - const text = typeof block.thinking === "string" ? block.thinking : ""; - if (text) entries.push({ kind: "thinking", ts, text }); - } else if (blockType === "tool_use") { - entries.push({ - kind: "tool_call", - ts, - name: typeof block.name === "string" ? block.name : "unknown", - toolUseId: - typeof block.id === "string" - ? block.id - : typeof block.tool_use_id === "string" - ? block.tool_use_id - : undefined, - input: block.input ?? {}, - }); - } - } - return entries.length > 0 ? entries : [{ kind: "stdout", ts, text: line }]; - } - - if (type === "user") { - const message = asRecord(parsed.message) ?? {}; - const content = Array.isArray(message.content) ? message.content : []; - const entries: TranscriptEntry[] = []; - for (const blockRaw of content) { - const block = asRecord(blockRaw); - if (!block) continue; - const blockType = typeof block.type === "string" ? block.type : ""; - if (blockType === "text") { - const text = typeof block.text === "string" ? block.text : ""; - if (text) entries.push({ kind: "user", ts, text }); - } else if (blockType === "tool_result") { - const toolUseId = typeof block.tool_use_id === "string" ? block.tool_use_id : ""; - const isError = block.is_error === true; - let text = ""; - if (typeof block.content === "string") { - text = block.content; - } else if (Array.isArray(block.content)) { - const parts: string[] = []; - for (const part of block.content) { - const p = asRecord(part); - if (p && typeof p.text === "string") parts.push(p.text); - } - text = parts.join("\n"); - } - entries.push({ kind: "tool_result", ts, toolUseId, content: text, isError }); - } - } - if (entries.length > 0) return entries; - // fall through to stdout for user messages without recognized blocks - } - - if (type === "result") { - const usage = asRecord(parsed.usage) ?? {}; - const inputTokens = asNumber(usage.input_tokens); - const outputTokens = asNumber(usage.output_tokens); - const cachedTokens = asNumber(usage.cache_read_input_tokens); - const costUsd = asNumber(parsed.total_cost_usd); - const subtype = typeof parsed.subtype === "string" ? parsed.subtype : ""; - const isError = parsed.is_error === true; - const errors = Array.isArray(parsed.errors) ? parsed.errors.map(errorText).filter(Boolean) : []; - const text = typeof parsed.result === "string" ? parsed.result : ""; - return [{ - kind: "result", - ts, - text, - inputTokens, - outputTokens, - cachedTokens, - costUsd, - subtype, - isError, - errors, - }]; - } - - return [{ kind: "stdout", ts, text: line }]; -} diff --git a/packages/adapter-claude-local/tsconfig.json b/packages/adapter-claude-local/tsconfig.json deleted file mode 100644 index 5a24989c..00000000 --- a/packages/adapter-claude-local/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "dist", - "rootDir": "src" - }, - "include": ["src"] -} diff --git a/packages/adapter-codex-local/package.json b/packages/adapter-codex-local/package.json deleted file mode 100644 index 38a3e231..00000000 --- a/packages/adapter-codex-local/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@agentcompany/adapter-codex-local", - "version": "0.3.0", - "type": "module", - "exports": { - ".": "./src/index.ts", - "./server": "./src/server/index.ts", - "./ui": "./src/ui/index.ts", - "./cli": "./src/cli/index.ts" - }, - "publishConfig": { - "access": "public", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - }, - "./server": { - "types": "./dist/server/index.d.ts", - "import": "./dist/server/index.js" - }, - "./ui": { - "types": "./dist/ui/index.d.ts", - "import": "./dist/ui/index.js" - }, - "./cli": { - "types": "./dist/cli/index.d.ts", - "import": "./dist/cli/index.js" - } - }, - "main": "./dist/index.js", - "types": "./dist/index.d.ts" - }, - "files": [ - "dist", - "skills" - ], - "scripts": { - "build": "tsc", - "clean": "rm -rf dist", - "typecheck": "tsc --noEmit" - }, - "dependencies": { - "@agentcompany/adapter-utils": "workspace:*", - "picocolors": "^1.1.1" - }, - "devDependencies": { - "@types/node": "^24.6.0", - "typescript": "^5.7.3" - } -} diff --git a/packages/adapter-codex-local/src/cli/format-event.ts b/packages/adapter-codex-local/src/cli/format-event.ts deleted file mode 100644 index c6294097..00000000 --- a/packages/adapter-codex-local/src/cli/format-event.ts +++ /dev/null @@ -1,202 +0,0 @@ -import pc from "picocolors"; -import { asRecord, errorText, asString, asNumber } from "@agentcompany/adapter-utils/parse-utils"; - -function printItemStarted(item: Record): boolean { - const itemType = asString(item.type); - if (itemType === "command_execution") { - const command = asString(item.command); - console.log(pc.yellow("tool_call: command_execution")); - if (command) console.log(pc.gray(command)); - return true; - } - - if (itemType === "tool_use") { - const name = asString(item.name, "unknown"); - console.log(pc.yellow(`tool_call: ${name}`)); - if (item.input !== undefined) { - try { - console.log(pc.gray(JSON.stringify(item.input, null, 2))); - } catch { - console.log(pc.gray(String(item.input))); - } - } - return true; - } - - return false; -} - -function printItemCompleted(item: Record): boolean { - const itemType = asString(item.type); - - if (itemType === "agent_message") { - const text = asString(item.text); - if (text) console.log(pc.green(`assistant: ${text}`)); - return true; - } - - if (itemType === "reasoning") { - const text = asString(item.text); - if (text) console.log(pc.gray(`thinking: ${text}`)); - return true; - } - - if (itemType === "tool_use") { - const name = asString(item.name, "unknown"); - console.log(pc.yellow(`tool_call: ${name}`)); - if (item.input !== undefined) { - try { - console.log(pc.gray(JSON.stringify(item.input, null, 2))); - } catch { - console.log(pc.gray(String(item.input))); - } - } - return true; - } - - if (itemType === "command_execution") { - const command = asString(item.command); - const status = asString(item.status); - const exitCode = typeof item.exit_code === "number" && Number.isFinite(item.exit_code) ? item.exit_code : null; - const output = asString(item.aggregated_output).replace(/\s+$/, ""); - const isError = - (exitCode !== null && exitCode !== 0) || - status === "failed" || - status === "errored" || - status === "error" || - status === "cancelled"; - - const summaryParts = [ - "tool_result: command_execution", - command ? `command="${command}"` : "", - status ? `status=${status}` : "", - exitCode !== null ? `exit_code=${exitCode}` : "", - ].filter(Boolean); - console.log((isError ? pc.red : pc.cyan)(summaryParts.join(" "))); - if (output) console.log((isError ? pc.red : pc.gray)(output)); - return true; - } - - if (itemType === "file_change") { - const changes = Array.isArray(item.changes) ? item.changes : []; - const entries = changes - .map((changeRaw) => asRecord(changeRaw)) - .filter((change): change is Record => Boolean(change)) - .map((change) => { - const kind = asString(change.kind, "update"); - const path = asString(change.path, "unknown"); - return `${kind} ${path}`; - }); - const preview = entries.length > 0 ? entries.slice(0, 6).join(", ") : "none"; - const more = entries.length > 6 ? ` (+${entries.length - 6} more)` : ""; - console.log(pc.cyan(`file_change: ${preview}${more}`)); - return true; - } - - if (itemType === "error") { - const message = errorText(item.message ?? item.error ?? item); - if (message) console.log(pc.red(`error: ${message}`)); - return true; - } - - if (itemType === "tool_result") { - const isError = item.is_error === true || asString(item.status) === "error"; - const text = asString(item.content) || asString(item.result) || asString(item.output); - console.log((isError ? pc.red : pc.cyan)(`tool_result${isError ? " (error)" : ""}`)); - if (text) console.log((isError ? pc.red : pc.gray)(text)); - return true; - } - - return false; -} - -export function printCodexStreamEvent(raw: string, debug: boolean): void { - const line = raw.trim(); - if (!line) return; - - let parsed: Record | null = null; - try { - parsed = JSON.parse(line) as Record; - } catch { - console.log(line); - return; - } - - const type = asString(parsed.type); - - if (type === "thread.started") { - const threadId = asString(parsed.thread_id); - const model = asString(parsed.model); - const details = [threadId ? `session: ${threadId}` : "", model ? `model: ${model}` : ""].filter(Boolean).join(", "); - console.log(pc.blue(`Codex thread started${details ? ` (${details})` : ""}`)); - return; - } - - if (type === "turn.started") { - console.log(pc.blue("turn started")); - return; - } - - if (type === "item.started" || type === "item.completed") { - const item = asRecord(parsed.item); - if (item) { - const handled = - type === "item.started" - ? printItemStarted(item) - : printItemCompleted(item); - if (!handled) { - const itemType = asString(item.type, "unknown"); - const id = asString(item.id); - const status = asString(item.status); - const meta = [id ? `id=${id}` : "", status ? `status=${status}` : ""].filter(Boolean).join(" "); - console.log(pc.gray(`${type}: ${itemType}${meta ? ` (${meta})` : ""}`)); - } - } else { - console.log(pc.gray(type)); - } - return; - } - - if (type === "turn.completed") { - const usage = asRecord(parsed.usage); - const input = asNumber(usage?.input_tokens); - const output = asNumber(usage?.output_tokens); - const cached = asNumber(usage?.cached_input_tokens, asNumber(usage?.cache_read_input_tokens)); - const cost = asNumber(parsed.total_cost_usd); - const isError = parsed.is_error === true; - const subtype = asString(parsed.subtype); - const errors = Array.isArray(parsed.errors) ? parsed.errors.map(errorText).filter(Boolean) : []; - - console.log( - pc.blue(`tokens: in=${input} out=${output} cached=${cached} cost=$${cost.toFixed(6)}`), - ); - if (subtype || isError || errors.length > 0) { - console.log( - pc.red(`result: subtype=${subtype || "unknown"} is_error=${isError ? "true" : "false"}`), - ); - if (errors.length > 0) console.log(pc.red(`errors: ${errors.join(" | ")}`)); - } - return; - } - - if (type === "turn.failed") { - const usage = asRecord(parsed.usage); - const input = asNumber(usage?.input_tokens); - const output = asNumber(usage?.output_tokens); - const cached = asNumber(usage?.cached_input_tokens, asNumber(usage?.cache_read_input_tokens)); - const message = errorText(parsed.error ?? parsed.message); - console.log(pc.red(`turn failed${message ? `: ${message}` : ""}`)); - console.log(pc.blue(`tokens: in=${input} out=${output} cached=${cached}`)); - return; - } - - if (type === "error") { - const message = errorText(parsed.message ?? parsed.error ?? parsed); - if (message) console.log(pc.red(`error: ${message}`)); - return; - } - - if (debug) { - console.log(pc.gray(line)); - } -} diff --git a/packages/adapter-codex-local/src/cli/index.ts b/packages/adapter-codex-local/src/cli/index.ts deleted file mode 100644 index 22fec464..00000000 --- a/packages/adapter-codex-local/src/cli/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { printCodexStreamEvent } from "./format-event.js"; diff --git a/packages/adapter-codex-local/src/index.ts b/packages/adapter-codex-local/src/index.ts deleted file mode 100644 index a1eb329a..00000000 --- a/packages/adapter-codex-local/src/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -export const type = "codex_local"; -export const label = "Codex (local)"; -export const DEFAULT_CODEX_LOCAL_MODEL = "gpt-5.3-codex"; -export const DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX = true; - -export const models = [ - { id: "gpt-5.4", label: "gpt-5.4" }, - { id: DEFAULT_CODEX_LOCAL_MODEL, label: DEFAULT_CODEX_LOCAL_MODEL }, - { id: "gpt-5.3-codex-spark", label: "gpt-5.3-codex-spark" }, - { id: "gpt-5", label: "gpt-5" }, - { id: "o3", label: "o3" }, - { id: "o4-mini", label: "o4-mini" }, - { id: "gpt-5-mini", label: "gpt-5-mini" }, - { id: "gpt-5-nano", label: "gpt-5-nano" }, - { id: "o3-mini", label: "o3-mini" }, - { id: "codex-mini-latest", label: "Codex Mini" }, -]; - -export const agentConfigurationDoc = `# codex_local agent configuration - -Adapter: codex_local - -Core fields: -- cwd (string, optional): default absolute working directory fallback for the agent process (created if missing when possible) -- instructionsFilePath (string, optional): absolute path to a markdown instructions file prepended to stdin prompt at runtime -- model (string, optional): Codex model id -- modelReasoningEffort (string, optional): reasoning effort override (minimal|low|medium|high) passed via -c model_reasoning_effort=... -- promptTemplate (string, optional): run prompt template -- search (boolean, optional): run codex with --search -- dangerouslyBypassApprovalsAndSandbox (boolean, optional): run with bypass flag -- command (string, optional): defaults to "codex" -- extraArgs (string[], optional): additional CLI args -- env (object, optional): KEY=VALUE environment variables -- workspaceStrategy (object, optional): execution workspace strategy; currently supports { type: "git_worktree", baseRef?, branchTemplate?, worktreeParentDir? } -- workspaceRuntime (object, optional): workspace runtime service intents; local host-managed services are realized before Codex starts and exposed back via context/env - -Operational fields: -- timeoutSec (number, optional): run timeout in seconds -- graceSec (number, optional): SIGTERM grace period in seconds - -Notes: -- Prompts are piped via stdin (Codex receives "-" prompt argument). -- AgentCompany auto-injects local skills into Codex personal skills dir ("$CODEX_HOME/skills" or "~/.codex/skills") when missing, so Codex can discover "$agentcompany" and related skills. -- Some model/tool combinations reject certain effort levels (for example minimal with web search enabled). -- When AgentCompany realizes a workspace/runtime for a run, it injects AGENT_COMPANY_WORKSPACE_* and AGENT_COMPANY_RUNTIME_* env vars for agent-side tooling. -`; diff --git a/packages/adapter-codex-local/src/server/execute-helpers.ts b/packages/adapter-codex-local/src/server/execute-helpers.ts deleted file mode 100644 index baac1d8a..00000000 --- a/packages/adapter-codex-local/src/server/execute-helpers.ts +++ /dev/null @@ -1,96 +0,0 @@ -import os from "node:os"; -import path from "node:path"; -import type { AdapterExecutionContext, ManagedSkillRef } from "@agentcompany/adapter-utils"; -import { - hasNonEmptyEnvValue, - buildSkillsCandidates, - resolveSkillsDir, - parseManagedSkills, - parseExtraArgs, - buildCommonAgentCompanyEnv, - resolveSessionResumeState, -} from "@agentcompany/adapter-utils"; -import { - createManagedSkillSymlinks, -} from "@agentcompany/adapter-utils/server-utils"; -import fs from "node:fs/promises"; - -export { - hasNonEmptyEnvValue, - parseManagedSkills, - parseExtraArgs, - buildCommonAgentCompanyEnv, - resolveSessionResumeState, -}; - -export const SKILLS_CANDIDATES = buildSkillsCandidates(import.meta.url); - -export const CODEX_ROLLOUT_NOISE_RE = - /^\d{4}-\d{2}-\d{2}T[^\s]+\s+ERROR\s+codex_core::rollout::list:\s+state db missing rollout path for thread\s+[a-z0-9-]+$/i; - -export function stripCodexRolloutNoise(text: string): string { - const parts = text.split(/\r?\n/); - const kept: string[] = []; - for (const part of parts) { - const trimmed = part.trim(); - if (!trimmed) { - kept.push(part); - continue; - } - if (CODEX_ROLLOUT_NOISE_RE.test(trimmed)) continue; - kept.push(part); - } - return kept.join("\n"); -} - -export function resolveCodexBillingType(env: Record): "api" | "subscription" { - return hasNonEmptyEnvValue(env, "OPENAI_API_KEY") ? "api" : "subscription"; -} - -export function codexHomeDir(): string { - const fromEnv = process.env.CODEX_HOME; - if (typeof fromEnv === "string" && fromEnv.trim().length > 0) return fromEnv.trim(); - return path.join(os.homedir(), ".codex"); -} - -export async function resolveAgentCompanySkillsDir(): Promise { - return resolveSkillsDir(SKILLS_CANDIDATES); -} - -export async function ensureCodexSkillsInjected( - managedSkills: ManagedSkillRef[], - onLog: AdapterExecutionContext["onLog"], -) { - const skillsHome = path.join(codexHomeDir(), "skills"); - - if (managedSkills.length > 0) { - await createManagedSkillSymlinks(managedSkills, skillsHome, onLog); - return; - } - - const skillsDir = await resolveSkillsDir(SKILLS_CANDIDATES); - if (!skillsDir) return; - - await fs.mkdir(skillsHome, { recursive: true }); - const entries = await fs.readdir(skillsDir, { withFileTypes: true }); - for (const entry of entries) { - if (!entry.isDirectory()) continue; - const source = path.join(skillsDir, entry.name); - const target = path.join(skillsHome, entry.name); - const existing = await fs.lstat(target).catch(() => null); - if (existing) continue; - - try { - await fs.symlink(source, target); - await onLog( - "stderr", - `[agent-company] Injected Codex skill "${entry.name}" into ${skillsHome}\n`, - ); - } catch (err) { - await onLog( - "stderr", - `[agent-company] Failed to inject Codex skill "${entry.name}" into ${skillsHome}: ${err instanceof Error ? err.message : String(err)}\n`, - ); - } - } -} diff --git a/packages/adapter-codex-local/src/server/execute.ts b/packages/adapter-codex-local/src/server/execute.ts deleted file mode 100644 index 6fa5b632..00000000 --- a/packages/adapter-codex-local/src/server/execute.ts +++ /dev/null @@ -1,258 +0,0 @@ -import path from "node:path"; -import fs from "node:fs/promises"; -import type { AdapterExecutionContext, AdapterExecutionResult } from "@agentcompany/adapter-utils"; -import { - asString, - asNumber, - asBoolean, - redactEnvForLogs, - ensureAbsoluteDirectory, - ensureCommandResolvable, - ensurePathInEnv, - filterConflictingArgs, - renderTemplate, - runChildProcess, -} from "@agentcompany/adapter-utils/server-utils"; -import { firstNonEmptyLine } from "@agentcompany/adapter-utils/test-utils"; -import { parseCodexJsonl, isCodexUnknownSessionError } from "./parse.js"; -import { - stripCodexRolloutNoise, - resolveCodexBillingType, - ensureCodexSkillsInjected, - parseManagedSkills, - parseExtraArgs, - buildCommonAgentCompanyEnv, - resolveSessionResumeState, -} from "./execute-helpers.js"; - -export async function execute(ctx: AdapterExecutionContext): Promise { - const { runId, agent, runtime, config, context, onLog, onMeta, authToken } = ctx; - - const promptTemplate = asString( - config.promptTemplate, - "{{context.taskTitle}}\n\n{{context.taskDescription}}", - ); - const command = asString(config.command, "codex"); - const model = asString(config.model, ""); - const modelReasoningEffort = asString( - config.modelReasoningEffort, - asString(config.reasoningEffort, ""), - ); - const search = asBoolean(config.search, false); - const bypass = asBoolean( - config.dangerouslyBypassApprovalsAndSandbox, - asBoolean(config.dangerouslyBypassSandbox, false), - ); - - const { env, cwd, workspaceId, workspaceRepoUrl, workspaceRepoRef } = - await buildCommonAgentCompanyEnv( - { runId, agent, config, context, authToken }, - { ensureAbsoluteDirectory }, - ); - - const managedSkills = parseManagedSkills(config); - await ensureCodexSkillsInjected(managedSkills, onLog); - - const billingType = resolveCodexBillingType(env); - const runtimeEnv = ensurePathInEnv(env); - await ensureCommandResolvable(command, cwd, runtimeEnv); - - const timeoutSec = asNumber(config.timeoutSec, 0); - const graceSec = asNumber(config.graceSec, 20); - const extraArgs = parseExtraArgs(config); - - const { sessionId, runtimeSessionId, runtimeSessionCwd, canResumeSession } = - resolveSessionResumeState(runtime, cwd); - if (runtimeSessionId && !canResumeSession) { - await onLog( - "stderr", - `[agent-company] Codex session "${runtimeSessionId}" was saved for cwd "${runtimeSessionCwd}" and will not be resumed in "${cwd}".\n`, - ); - } - - const instructionsFilePath = asString(config.instructionsFilePath, "").trim(); - const instructionsDir = instructionsFilePath ? `${path.dirname(instructionsFilePath)}/` : ""; - let instructionsPrefix = ""; - if (instructionsFilePath) { - try { - const instructionsContents = await fs.readFile(instructionsFilePath, "utf8"); - instructionsPrefix = - `${instructionsContents}\n\n` + - `The above agent instructions were loaded from ${instructionsFilePath}. ` + - `Resolve any relative file references from ${instructionsDir}.\n\n`; - await onLog( - "stderr", - `[agent-company] Loaded agent instructions file: ${instructionsFilePath}\n`, - ); - } catch (err) { - const reason = err instanceof Error ? err.message : String(err); - await onLog( - "stderr", - `[agent-company] Warning: could not read agent instructions file "${instructionsFilePath}": ${reason}\n`, - ); - } - } - const commandNotes = (() => { - if (!instructionsFilePath) return [] as string[]; - if (instructionsPrefix.length > 0) { - return [ - `Loaded agent instructions from ${instructionsFilePath}`, - `Prepended instructions + path directive to stdin prompt (relative references from ${instructionsDir}).`, - ]; - } - return [ - `Configured instructionsFilePath ${instructionsFilePath}, but file could not be read; continuing without injected instructions.`, - ]; - })(); - const renderedPrompt = renderTemplate(promptTemplate, { - agentId: agent.id, - companyId: agent.companyId, - runId, - company: { id: agent.companyId }, - agent, - run: { id: runId, source: "on_demand" }, - context, - }); - const prompt = `${instructionsPrefix}${renderedPrompt}`; - - const buildArgs = (resumeSessionId: string | null) => { - const args = ["exec", "--json"]; - if (search) args.unshift("--search"); - if (bypass) args.push("--dangerously-bypass-approvals-and-sandbox"); - if (model) args.push("--model", model); - if (modelReasoningEffort) args.push("-c", `model_reasoning_effort=${JSON.stringify(modelReasoningEffort)}`); - if (extraArgs.length > 0) { - const managedFlags = [ - "--dangerously-bypass-approvals-and-sandbox", - "--json", - "--model", - "--sandbox", - "--skip-git-repo-check", - "--ask-for-approval", - ]; - const cleaned = filterConflictingArgs(extraArgs, managedFlags); - if (cleaned.length > 0) args.push(...cleaned); - } - if (resumeSessionId) args.push("resume", resumeSessionId, "-"); - else args.push("-"); - return args; - }; - - const runAttempt = async (resumeSessionId: string | null) => { - const args = buildArgs(resumeSessionId); - if (onMeta) { - await onMeta({ - adapterType: "codex_local", - command, - cwd, - commandNotes, - commandArgs: args.map((value, idx) => { - if (idx === args.length - 1 && value !== "-") return ``; - return value; - }), - env: redactEnvForLogs(env), - prompt, - context, - }); - } - - const proc = await runChildProcess(runId, command, args, { - cwd, - env, - stdin: prompt, - timeoutSec, - graceSec, - onLog: async (stream, chunk) => { - if (stream !== "stderr") { - await onLog(stream, chunk); - return; - } - const cleaned = stripCodexRolloutNoise(chunk); - if (!cleaned.trim()) return; - await onLog(stream, cleaned); - }, - }); - const cleanedStderr = stripCodexRolloutNoise(proc.stderr); - return { - proc: { - ...proc, - stderr: cleanedStderr, - }, - rawStderr: proc.stderr, - parsed: parseCodexJsonl(proc.stdout), - }; - }; - - const toResult = ( - attempt: { proc: { exitCode: number | null; signal: string | null; timedOut: boolean; stdout: string; stderr: string }; rawStderr: string; parsed: ReturnType }, - clearSessionOnMissingSession = false, - ): AdapterExecutionResult => { - if (attempt.proc.timedOut) { - return { - exitCode: attempt.proc.exitCode, - signal: attempt.proc.signal, - timedOut: true, - errorMessage: `Timed out after ${timeoutSec}s`, - clearSession: clearSessionOnMissingSession, - }; - } - - const resolvedSessionId = attempt.parsed.sessionId ?? runtimeSessionId ?? runtime.sessionId ?? null; - const resolvedSessionParams = resolvedSessionId - ? ({ - sessionId: resolvedSessionId, - cwd, - ...(workspaceId ? { workspaceId } : {}), - ...(workspaceRepoUrl ? { repoUrl: workspaceRepoUrl } : {}), - ...(workspaceRepoRef ? { repoRef: workspaceRepoRef } : {}), - } as Record) - : null; - const parsedError = typeof attempt.parsed.errorMessage === "string" ? attempt.parsed.errorMessage.trim() : ""; - const stderrLine = firstNonEmptyLine(attempt.proc.stderr); - const fallbackErrorMessage = - parsedError || - stderrLine || - `Codex exited with code ${attempt.proc.exitCode ?? -1}`; - - return { - exitCode: attempt.proc.exitCode, - signal: attempt.proc.signal, - timedOut: false, - errorMessage: - (attempt.proc.exitCode ?? 0) === 0 - ? null - : fallbackErrorMessage, - usage: attempt.parsed.usage, - sessionId: resolvedSessionId, - sessionParams: resolvedSessionParams, - sessionDisplayId: resolvedSessionId, - provider: "openai", - model, - billingType, - costUsd: attempt.parsed.costUsd, - resultJson: { - stdout: attempt.proc.stdout, - stderr: attempt.proc.stderr, - }, - summary: attempt.parsed.summary, - clearSession: Boolean(clearSessionOnMissingSession && !resolvedSessionId), - }; - }; - - const initial = await runAttempt(sessionId); - if ( - sessionId && - !initial.proc.timedOut && - (initial.proc.exitCode ?? 0) !== 0 && - isCodexUnknownSessionError(initial.proc.stdout, initial.rawStderr) - ) { - await onLog( - "stderr", - `[agent-company] Codex resume session "${sessionId}" is unavailable; retrying with a fresh session.\n`, - ); - const retry = await runAttempt(null); - return toResult(retry, true); - } - - return toResult(initial); -} diff --git a/packages/adapter-codex-local/src/server/index.ts b/packages/adapter-codex-local/src/server/index.ts deleted file mode 100644 index 869b35fb..00000000 --- a/packages/adapter-codex-local/src/server/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { execute } from "./execute.js"; -export { testEnvironment } from "./test.js"; -export { parseCodexJsonl, isCodexUnknownSessionError } from "./parse.js"; -export { listCodexSkills, syncCodexSkills } from "./skills.js"; -import { createStandardSessionCodec } from "@agentcompany/adapter-utils/session-codec"; - -export const sessionCodec = createStandardSessionCodec(); diff --git a/packages/adapter-codex-local/src/server/parse.ts b/packages/adapter-codex-local/src/server/parse.ts deleted file mode 100644 index 4453bd45..00000000 --- a/packages/adapter-codex-local/src/server/parse.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { asString, asNumber, parseObject, parseJson } from "@agentcompany/adapter-utils/server-utils"; - -export function parseCodexJsonl(stdout: string) { - let sessionId: string | null = null; - const messages: string[] = []; - let errorMessage: string | null = null; - let costUsd: number | null = null; - const usage = { - inputTokens: 0, - cachedInputTokens: 0, - outputTokens: 0, - }; - - for (const rawLine of stdout.split(/\r?\n/)) { - const line = rawLine.trim(); - if (!line) continue; - - const event = parseJson(line); - if (!event) continue; - - const type = asString(event.type, ""); - if (type === "thread.started") { - sessionId = asString(event.thread_id, sessionId ?? "") || sessionId; - continue; - } - - if (type === "error") { - const msg = asString(event.message, "").trim(); - if (msg) errorMessage = msg; - continue; - } - - if (type === "item.completed") { - const item = parseObject(event.item); - if (asString(item.type, "") === "agent_message") { - const text = asString(item.text, ""); - if (text) messages.push(text); - } - continue; - } - - if (type === "turn.completed") { - const usageObj = parseObject(event.usage); - usage.inputTokens = asNumber(usageObj.input_tokens, usage.inputTokens); - usage.cachedInputTokens = asNumber(usageObj.cached_input_tokens, usage.cachedInputTokens); - usage.outputTokens = asNumber(usageObj.output_tokens, usage.outputTokens); - const rawCost = event.total_cost_usd; - if (typeof rawCost === "number" && Number.isFinite(rawCost)) costUsd = rawCost; - continue; - } - - if (type === "turn.failed") { - const err = parseObject(event.error); - const msg = asString(err.message, "").trim(); - if (msg) errorMessage = msg; - const rawCost = event.total_cost_usd; - if (typeof rawCost === "number" && Number.isFinite(rawCost)) costUsd = rawCost; - } - } - - return { - sessionId, - summary: messages.join("\n\n").trim(), - usage, - costUsd, - errorMessage, - }; -} - -export function isCodexUnknownSessionError(stdout: string, stderr: string): boolean { - const haystack = `${stdout}\n${stderr}` - .split(/\r?\n/) - .map((line) => line.trim()) - .filter(Boolean) - .join("\n"); - return /unknown (session|thread)|session .* not found|thread .* not found|conversation .* not found|missing rollout path for thread|state db missing rollout path/i.test( - haystack, - ); -} diff --git a/packages/adapter-codex-local/src/server/skills.ts b/packages/adapter-codex-local/src/server/skills.ts deleted file mode 100644 index 43d4dd19..00000000 --- a/packages/adapter-codex-local/src/server/skills.ts +++ /dev/null @@ -1,99 +0,0 @@ -// --------------------------------------------------------------------------- -// Codex adapter skill listing / sync -- ephemeral mode -// Skills are linked into the workspace .agents/skills directory at run time. -// --------------------------------------------------------------------------- - -import path from "node:path"; -import type { - AdapterSkillContext, - AdapterSkillEntry, - AdapterSkillSnapshot, -} from "@agentcompany/adapter-utils"; -import { - readAgentCompanyRuntimeSkillEntries, - resolveAgentCompanyDesiredSkillNames, -} from "@agentcompany/adapter-utils/server-utils"; - -async function buildCodexSkillSnapshot( - config: Record, -): Promise { - const moduleDir = path.resolve(import.meta.dirname ?? __dirname); - const availableEntries = await readAgentCompanyRuntimeSkillEntries(config, moduleDir); - const desiredSkills = resolveAgentCompanyDesiredSkillNames(config, availableEntries); - const desiredSet = new Set(desiredSkills); - const entries: AdapterSkillEntry[] = []; - const warnings: string[] = []; - - for (const available of availableEntries) { - const desired = desiredSet.has(available.key); - entries.push({ - key: available.key, - runtimeName: available.runtimeName, - desired, - managed: true, - state: desired ? "configured" : "available", - sourcePath: available.source, - targetPath: null, - detail: desired - ? "Will be linked into the workspace .agents/skills directory on the next run." - : null, - required: Boolean(available.required), - requiredReason: available.requiredReason ?? null, - origin: available.required ? "paperclip_required" : "company_managed", - originLabel: available.required ? "Required by AgentCompany" : "Managed by AgentCompany", - readOnly: false, - }); - } - - // Check for desired skills not in available - for (const desiredSkill of desiredSkills) { - if (availableEntries.some((entry) => entry.key === desiredSkill)) continue; - warnings.push(`Desired skill "${desiredSkill}" is not available from the AgentCompany skills directory.`); - entries.push({ - key: desiredSkill, - runtimeName: null, - desired: true, - managed: true, - state: "missing", - sourcePath: null, - targetPath: null, - detail: "AgentCompany cannot find this skill in the local runtime skills directory.", - origin: "external_unknown", - originLabel: "External or unavailable", - readOnly: false, - }); - } - - entries.sort((left, right) => left.key.localeCompare(right.key)); - - return { - adapterType: "codex_local", - supported: true, - mode: "ephemeral", - desiredSkills, - entries, - warnings, - }; -} - -/** - * List the current skill state for the Codex adapter. - * Ephemeral mode: skills are linked into workspace at run time. - */ -export async function listCodexSkills( - ctx: AdapterSkillContext, -): Promise { - return buildCodexSkillSnapshot(ctx.config); -} - -/** - * Sync skills for the Codex adapter. - * Ephemeral mode: no on-disk sync needed; skills are linked at run time. - * Returns the current snapshot for informational purposes. - */ -export async function syncCodexSkills( - ctx: AdapterSkillContext, - _desiredSkills: string[], -): Promise { - return buildCodexSkillSnapshot(ctx.config); -} diff --git a/packages/adapter-codex-local/src/server/test.ts b/packages/adapter-codex-local/src/server/test.ts deleted file mode 100644 index 3284f211..00000000 --- a/packages/adapter-codex-local/src/server/test.ts +++ /dev/null @@ -1,122 +0,0 @@ -import type { - AdapterEnvironmentCheck, - AdapterEnvironmentTestContext, - AdapterEnvironmentTestResult, -} from "@agentcompany/adapter-utils"; -import { - asString, - asBoolean, - asStringArray, - parseObject, - ensureAbsoluteDirectory, - ensureCommandResolvable, - ensurePathInEnv, - runChildProcess, -} from "@agentcompany/adapter-utils/server-utils"; -import { summarizeStatus, isNonEmpty, commandLooksLike, summarizeProbeDetail } from "@agentcompany/adapter-utils/test-utils"; -import { parseCodexJsonl } from "./parse.js"; - -const CODEX_AUTH_REQUIRED_RE = - /(?:not\s+logged\s+in|login\s+required|authentication\s+required|unauthorized|invalid(?:\s+or\s+missing)?\s+api(?:[_\s-]?key)?|openai[_\s-]?api[_\s-]?key|api[_\s-]?key.*required|please\s+run\s+`?codex\s+login`?)/i; - -export async function testEnvironment( - ctx: AdapterEnvironmentTestContext, -): Promise { - const checks: AdapterEnvironmentCheck[] = []; - const config = parseObject(ctx.config); - const command = asString(config.command, "codex"); - const cwd = asString(config.cwd, process.cwd()); - - try { - await ensureAbsoluteDirectory(cwd, { createIfMissing: true }); - checks.push({ code: "codex_cwd_valid", level: "info", message: `Working directory is valid: ${cwd}` }); - } catch (err) { - checks.push({ code: "codex_cwd_invalid", level: "error", message: err instanceof Error ? err.message : "Invalid working directory", detail: cwd }); - } - - const envConfig = parseObject(config.env); - const env: Record = {}; - for (const [key, value] of Object.entries(envConfig)) { - if (typeof value === "string") env[key] = value; - } - const runtimeEnv = ensurePathInEnv(env); - try { - await ensureCommandResolvable(command, cwd, runtimeEnv); - checks.push({ code: "codex_command_resolvable", level: "info", message: `Command is executable: ${command}` }); - } catch (err) { - checks.push({ code: "codex_command_unresolvable", level: "error", message: err instanceof Error ? err.message : "Command is not executable", detail: command }); - } - - const configOpenAiKey = env.OPENAI_API_KEY; - if (isNonEmpty(configOpenAiKey)) { - checks.push({ code: "codex_openai_api_key_present", level: "info", message: "OPENAI_API_KEY is set for Codex authentication." }); - } else { - checks.push({ code: "codex_openai_api_key_missing", level: "info", message: "OPENAI_API_KEY is not set. Codex may use its own auth configuration." }); - } - - // Hello probe: wrapped in try-catch so probe failures never crash the test. - const canRunProbe = checks.every((c) => c.code !== "codex_cwd_invalid" && c.code !== "codex_command_unresolvable"); - if (canRunProbe && commandLooksLike(command, "codex")) { - try { - const model = asString(config.model, "").trim(); - const modelReasoningEffort = asString(config.modelReasoningEffort, asString(config.reasoningEffort, "")).trim(); - const search = asBoolean(config.search, false); - const bypass = asBoolean(config.dangerouslyBypassApprovalsAndSandbox, asBoolean(config.dangerouslyBypassSandbox, false)); - const extraArgs = (() => { - const fromExtraArgs = asStringArray(config.extraArgs); - if (fromExtraArgs.length > 0) return fromExtraArgs; - return asStringArray(config.args); - })(); - - const args = ["exec", "--json"]; - args.push("--skip-git-repo-check"); - if (search) args.unshift("--search"); - if (bypass) args.push("--dangerously-bypass-approvals-and-sandbox"); - if (model) args.push("--model", model); - if (modelReasoningEffort) args.push("-c", `model_reasoning_effort=${JSON.stringify(modelReasoningEffort)}`); - if (extraArgs.length > 0) args.push(...extraArgs); - args.push("-"); - - const probe = await runChildProcess( - `codex-envtest-${Date.now()}-${Math.random().toString(16).slice(2)}`, - command, - args, - { cwd, env, timeoutSec: 45, graceSec: 5, stdin: "Respond with hello.", onLog: async () => {} }, - ); - const parsed = parseCodexJsonl(probe.stdout); - const detail = summarizeProbeDetail(probe.stdout, probe.stderr, parsed.errorMessage); - const authEvidence = `${parsed.errorMessage ?? ""}\n${probe.stdout}\n${probe.stderr}`.trim(); - - if (probe.timedOut) { - checks.push({ code: "codex_hello_probe_timed_out", level: "info", message: "Codex hello probe timed out." }); - } else if ((probe.exitCode ?? 1) === 0) { - const summary = parsed.summary.trim(); - const hasHello = /\bhello\b/i.test(summary); - checks.push({ - code: hasHello ? "codex_hello_probe_passed" : "codex_hello_probe_unexpected_output", - level: "info", - message: hasHello ? "Codex hello probe succeeded." : "Codex probe completed.", - ...(summary ? { detail: summary.replace(/\s+/g, " ").trim().slice(0, 240) } : {}), - }); - } else if (CODEX_AUTH_REQUIRED_RE.test(authEvidence)) { - checks.push({ - code: "codex_hello_probe_auth_required", level: "warn", - message: "Codex CLI is installed, but authentication is not ready.", - ...(detail ? { detail } : {}), - hint: "Configure OPENAI_API_KEY or run `codex login`.", - }); - } else { - checks.push({ code: "codex_hello_probe_failed", level: "info", message: "Codex hello probe exited with non-zero code.", ...(detail ? { detail } : {}) }); - } - } catch { - checks.push({ code: "codex_hello_probe_error", level: "info", message: "Codex hello probe could not run." }); - } - } - - return { - adapterType: ctx.adapterType, - status: summarizeStatus(checks), - checks, - testedAt: new Date().toISOString(), - }; -} diff --git a/packages/adapter-codex-local/src/ui/build-config.ts b/packages/adapter-codex-local/src/ui/build-config.ts deleted file mode 100644 index b72af635..00000000 --- a/packages/adapter-codex-local/src/ui/build-config.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { CreateConfigValues } from "@agentcompany/adapter-utils"; -import { parseCommaArgs, parseEnvVars, parseEnvBindings, parseJsonObject } from "@agentcompany/adapter-utils/config-utils"; -import { - DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX, - DEFAULT_CODEX_LOCAL_MODEL, -} from "../index.js"; - -export function buildCodexLocalConfig(v: CreateConfigValues): Record { - const ac: Record = {}; - if (v.cwd) ac.cwd = v.cwd; - if (v.instructionsFilePath) ac.instructionsFilePath = v.instructionsFilePath; - if (v.promptTemplate) ac.promptTemplate = v.promptTemplate; - ac.model = v.model || DEFAULT_CODEX_LOCAL_MODEL; - if (v.thinkingEffort) ac.modelReasoningEffort = v.thinkingEffort; - ac.timeoutSec = 0; - ac.graceSec = 15; - const env = parseEnvBindings(v.envBindings); - const legacy = parseEnvVars(v.envVars); - for (const [key, value] of Object.entries(legacy)) { - if (!Object.prototype.hasOwnProperty.call(env, key)) { - env[key] = { type: "plain", value }; - } - } - if (Object.keys(env).length > 0) ac.env = env; - ac.search = v.search; - ac.dangerouslyBypassApprovalsAndSandbox = - typeof v.dangerouslyBypassSandbox === "boolean" - ? v.dangerouslyBypassSandbox - : DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX; - if (v.workspaceStrategyType === "git_worktree") { - ac.workspaceStrategy = { - type: "git_worktree", - ...(v.workspaceBaseRef ? { baseRef: v.workspaceBaseRef } : {}), - ...(v.workspaceBranchTemplate ? { branchTemplate: v.workspaceBranchTemplate } : {}), - ...(v.worktreeParentDir ? { worktreeParentDir: v.worktreeParentDir } : {}), - }; - } - const runtimeServices = parseJsonObject(v.runtimeServicesJson ?? ""); - if (runtimeServices && Array.isArray(runtimeServices.services)) { - ac.workspaceRuntime = runtimeServices; - } - if (v.command) ac.command = v.command; - if (v.extraArgs) ac.extraArgs = parseCommaArgs(v.extraArgs); - return ac; -} diff --git a/packages/adapter-codex-local/src/ui/index.ts b/packages/adapter-codex-local/src/ui/index.ts deleted file mode 100644 index ba222502..00000000 --- a/packages/adapter-codex-local/src/ui/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { parseCodexStdoutLine } from "./parse-stdout.js"; -export { buildCodexLocalConfig } from "./build-config.js"; diff --git a/packages/adapter-codex-local/src/ui/parse-stdout.ts b/packages/adapter-codex-local/src/ui/parse-stdout.ts deleted file mode 100644 index 68360397..00000000 --- a/packages/adapter-codex-local/src/ui/parse-stdout.ts +++ /dev/null @@ -1,234 +0,0 @@ -import { - redactHomePathUserSegments, - redactHomePathUserSegmentsInValue, - type TranscriptEntry, -} from "@agentcompany/adapter-utils"; -import { asRecord, safeJsonParse, errorText } from "@agentcompany/adapter-utils/parse-utils"; - -function asString(value: unknown, fallback = ""): string { - return typeof value === "string" ? value : fallback; -} - -function asNumber(value: unknown, fallback = 0): number { - return typeof value === "number" && Number.isFinite(value) ? value : fallback; -} - -function stringifyUnknown(value: unknown): string { - if (typeof value === "string") return redactHomePathUserSegments(value); - if (value === null || value === undefined) return ""; - try { - return JSON.stringify(redactHomePathUserSegmentsInValue(value), null, 2); - } catch { - return redactHomePathUserSegments(String(value)); - } -} - -function parseCommandExecutionItem( - item: Record, - ts: string, - phase: "started" | "completed", -): TranscriptEntry[] { - const id = asString(item.id); - const command = asString(item.command); - const status = asString(item.status); - const exitCode = typeof item.exit_code === "number" && Number.isFinite(item.exit_code) ? item.exit_code : null; - const safeCommand = redactHomePathUserSegments(command); - const output = redactHomePathUserSegments(asString(item.aggregated_output)).replace(/\s+$/, ""); - - if (phase === "started") { - return [{ - kind: "tool_call", - ts, - name: "command_execution", - toolUseId: id || command || "command_execution", - input: { - id, - command: safeCommand, - }, - }]; - } - - const lines: string[] = []; - if (safeCommand) lines.push(`command: ${safeCommand}`); - if (status) lines.push(`status: ${status}`); - if (exitCode !== null) lines.push(`exit_code: ${exitCode}`); - if (output) { - if (lines.length > 0) lines.push(""); - lines.push(output); - } - - const isError = - (exitCode !== null && exitCode !== 0) || - status === "failed" || - status === "errored" || - status === "error" || - status === "cancelled"; - - return [{ - kind: "tool_result", - ts, - toolUseId: id || command || "command_execution", - content: lines.join("\n").trim() || "command completed", - isError, - }]; -} - -function parseFileChangeItem(item: Record, ts: string): TranscriptEntry[] { - const changes = Array.isArray(item.changes) ? item.changes : []; - const entries = changes - .map((changeRaw) => asRecord(changeRaw)) - .filter((change): change is Record => Boolean(change)) - .map((change) => { - const kind = asString(change.kind, "update"); - const path = redactHomePathUserSegments(asString(change.path, "unknown")); - return `${kind} ${path}`; - }); - - if (entries.length === 0) { - return [{ kind: "system", ts, text: "file changes applied" }]; - } - - const preview = entries.slice(0, 6).join(", "); - const more = entries.length > 6 ? ` (+${entries.length - 6} more)` : ""; - return [{ kind: "system", ts, text: `file changes: ${preview}${more}` }]; -} - -function parseCodexItem( - item: Record, - ts: string, - phase: "started" | "completed", -): TranscriptEntry[] { - const itemType = asString(item.type); - - if (itemType === "agent_message") { - const text = asString(item.text); - if (text) return [{ kind: "assistant", ts, text: redactHomePathUserSegments(text) }]; - return []; - } - - if (itemType === "reasoning") { - const text = asString(item.text); - if (text) return [{ kind: "thinking", ts, text: redactHomePathUserSegments(text) }]; - return [{ kind: "system", ts, text: phase === "started" ? "reasoning started" : "reasoning completed" }]; - } - - if (itemType === "command_execution") { - return parseCommandExecutionItem(item, ts, phase); - } - - if (itemType === "file_change" && phase === "completed") { - return parseFileChangeItem(item, ts); - } - - if (itemType === "tool_use") { - return [{ - kind: "tool_call", - ts, - name: redactHomePathUserSegments(asString(item.name, "unknown")), - toolUseId: asString(item.id), - input: redactHomePathUserSegmentsInValue(item.input ?? {}), - }]; - } - - if (itemType === "tool_result" && phase === "completed") { - const toolUseId = asString(item.tool_use_id, asString(item.id)); - const content = - asString(item.content) || - asString(item.output) || - asString(item.result) || - stringifyUnknown(item.content ?? item.output ?? item.result); - const isError = item.is_error === true || asString(item.status) === "error"; - return [{ kind: "tool_result", ts, toolUseId, content: redactHomePathUserSegments(content), isError }]; - } - - if (itemType === "error" && phase === "completed") { - const text = errorText(item.message ?? item.error ?? item); - return [{ kind: "stderr", ts, text: redactHomePathUserSegments(text || "error") }]; - } - - const id = asString(item.id); - const status = asString(item.status); - const meta = [id ? `id=${id}` : "", status ? `status=${status}` : ""].filter(Boolean).join(" "); - return [{ - kind: "system", - ts, - text: redactHomePathUserSegments(`item ${phase}: ${itemType || "unknown"}${meta ? ` (${meta})` : ""}`), - }]; -} - -export function parseCodexStdoutLine(line: string, ts: string): TranscriptEntry[] { - const parsed = asRecord(safeJsonParse(line)); - if (!parsed) { - return [{ kind: "stdout", ts, text: redactHomePathUserSegments(line) }]; - } - - const type = asString(parsed.type); - - if (type === "thread.started") { - const threadId = asString(parsed.thread_id); - return [{ - kind: "init", - ts, - model: redactHomePathUserSegments(asString(parsed.model, "codex")), - sessionId: redactHomePathUserSegments(threadId), - }]; - } - - if (type === "turn.started") { - return [{ kind: "system", ts, text: "turn started" }]; - } - - if (type === "item.started" || type === "item.completed") { - const item = asRecord(parsed.item); - if (!item) return [{ kind: "system", ts, text: type.replace(".", " ") }]; - return parseCodexItem(item, ts, type === "item.started" ? "started" : "completed"); - } - - if (type === "turn.completed") { - const usage = asRecord(parsed.usage); - const inputTokens = asNumber(usage?.input_tokens); - const outputTokens = asNumber(usage?.output_tokens); - const cachedTokens = asNumber(usage?.cached_input_tokens, asNumber(usage?.cache_read_input_tokens)); - return [{ - kind: "result", - ts, - text: redactHomePathUserSegments(asString(parsed.result)), - inputTokens, - outputTokens, - cachedTokens, - costUsd: asNumber(parsed.total_cost_usd), - subtype: redactHomePathUserSegments(asString(parsed.subtype)), - isError: parsed.is_error === true, - errors: Array.isArray(parsed.errors) - ? parsed.errors.map(errorText).map(redactHomePathUserSegments).filter(Boolean) - : [], - }]; - } - - if (type === "turn.failed") { - const usage = asRecord(parsed.usage); - const inputTokens = asNumber(usage?.input_tokens); - const outputTokens = asNumber(usage?.output_tokens); - const cachedTokens = asNumber(usage?.cached_input_tokens, asNumber(usage?.cache_read_input_tokens)); - const message = errorText(parsed.error ?? parsed.message); - return [{ - kind: "result", - ts, - text: redactHomePathUserSegments(asString(parsed.result)), - inputTokens, - outputTokens, - cachedTokens, - costUsd: asNumber(parsed.total_cost_usd), - subtype: redactHomePathUserSegments(asString(parsed.subtype, "turn.failed")), - isError: true, - errors: message ? [redactHomePathUserSegments(message)] : [], - }]; - } - - if (type === "error") { - const message = errorText(parsed.message ?? parsed.error ?? parsed); - return [{ kind: "stderr", ts, text: redactHomePathUserSegments(message || line) }]; - } - - return [{ kind: "stdout", ts, text: redactHomePathUserSegments(line) }]; -} diff --git a/packages/adapter-codex-local/tsconfig.json b/packages/adapter-codex-local/tsconfig.json deleted file mode 100644 index 5a24989c..00000000 --- a/packages/adapter-codex-local/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "dist", - "rootDir": "src" - }, - "include": ["src"] -} diff --git a/packages/adapter-gemini-local/package.json b/packages/adapter-gemini-local/package.json deleted file mode 100644 index 627f09be..00000000 --- a/packages/adapter-gemini-local/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "@agentcompany/adapter-gemini-local", - "version": "0.3.0", - "type": "module", - "exports": { - ".": "./src/index.ts", - "./server": "./src/server/index.ts", - "./ui": "./src/ui/index.ts", - "./cli": "./src/cli/index.ts" - }, - "publishConfig": { - "access": "public", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - }, - "./server": { - "types": "./dist/server/index.d.ts", - "import": "./dist/server/index.js" - }, - "./ui": { - "types": "./dist/ui/index.d.ts", - "import": "./dist/ui/index.js" - }, - "./cli": { - "types": "./dist/cli/index.d.ts", - "import": "./dist/cli/index.js" - } - }, - "main": "./dist/index.js", - "types": "./dist/index.d.ts" - }, - "files": [ - "dist", - "skills" - ], - "scripts": { - "build": "tsc", - "clean": "rm -rf dist", - "typecheck": "tsc --noEmit" - }, - "dependencies": { - "@agentcompany/adapter-utils": "workspace:*", - "picocolors": "^1.1.1" - }, - "devDependencies": { - "@types/node": "^24.6.0", - "typescript": "^5.7.3" - } -} diff --git a/packages/adapter-gemini-local/src/cli/format-event.ts b/packages/adapter-gemini-local/src/cli/format-event.ts deleted file mode 100644 index f1623bd5..00000000 --- a/packages/adapter-gemini-local/src/cli/format-event.ts +++ /dev/null @@ -1,171 +0,0 @@ -import pc from "picocolors"; -import { asRecord, errorText, asString, asNumber, stringifyUnknown } from "@agentcompany/adapter-utils/parse-utils"; - -function printTextMessage(prefix: string, colorize: (text: string) => string, messageRaw: unknown): void { - if (typeof messageRaw === "string") { - const text = messageRaw.trim(); - if (text) console.log(colorize(`${prefix}: ${text}`)); - return; - } - - const message = asRecord(messageRaw); - if (!message) return; - - const directText = asString(message.text).trim(); - if (directText) console.log(colorize(`${prefix}: ${directText}`)); - - const content = Array.isArray(message.content) ? message.content : []; - for (const partRaw of content) { - const part = asRecord(partRaw); - if (!part) continue; - const type = asString(part.type).trim(); - - if (type === "output_text" || type === "text" || type === "content") { - const text = asString(part.text).trim() || asString(part.content).trim(); - if (text) console.log(colorize(`${prefix}: ${text}`)); - continue; - } - - if (type === "thinking") { - const text = asString(part.text).trim(); - if (text) console.log(pc.gray(`thinking: ${text}`)); - continue; - } - - if (type === "tool_call") { - const name = asString(part.name, asString(part.tool, "tool")); - console.log(pc.yellow(`tool_call: ${name}`)); - const input = part.input ?? part.arguments ?? part.args; - if (input !== undefined) console.log(pc.gray(stringifyUnknown(input))); - continue; - } - - if (type === "tool_result" || type === "tool_response") { - const isError = part.is_error === true || asString(part.status).toLowerCase() === "error"; - const contentText = - asString(part.output) || - asString(part.text) || - asString(part.result) || - stringifyUnknown(part.output ?? part.result ?? part.text ?? part.response); - console.log((isError ? pc.red : pc.cyan)(`tool_result${isError ? " (error)" : ""}`)); - if (contentText) console.log((isError ? pc.red : pc.gray)(contentText)); - } - } -} - -function printUsage(parsed: Record) { - const usage = asRecord(parsed.usage) ?? asRecord(parsed.usageMetadata); - const usageMetadata = asRecord(usage?.usageMetadata); - const source = usageMetadata ?? usage ?? {}; - const input = asNumber(source.input_tokens, asNumber(source.inputTokens, asNumber(source.promptTokenCount))); - const output = asNumber(source.output_tokens, asNumber(source.outputTokens, asNumber(source.candidatesTokenCount))); - const cached = asNumber( - source.cached_input_tokens, - asNumber(source.cachedInputTokens, asNumber(source.cachedContentTokenCount)), - ); - const cost = asNumber(parsed.total_cost_usd, asNumber(parsed.cost_usd, asNumber(parsed.cost))); - console.log(pc.blue(`tokens: in=${input} out=${output} cached=${cached} cost=$${cost.toFixed(6)}`)); -} - -export function printGeminiStreamEvent(raw: string, debug: boolean): void { - const line = raw.trim(); - if (!line) return; - - let parsed: Record | null = null; - try { - parsed = JSON.parse(line) as Record; - } catch { - console.log(line); - return; - } - - const type = asString(parsed.type); - - if (type === "system") { - const subtype = asString(parsed.subtype); - if (subtype === "init") { - const sessionId = - asString(parsed.session_id) || - asString(parsed.sessionId) || - asString(parsed.sessionID) || - asString(parsed.checkpoint_id); - const model = asString(parsed.model); - const details = [sessionId ? `session: ${sessionId}` : "", model ? `model: ${model}` : ""] - .filter(Boolean) - .join(", "); - console.log(pc.blue(`Gemini init${details ? ` (${details})` : ""}`)); - return; - } - if (subtype === "error") { - const text = errorText(parsed.error ?? parsed.message ?? parsed.detail); - if (text) console.log(pc.red(`error: ${text}`)); - return; - } - console.log(pc.blue(`system: ${subtype || "event"}`)); - return; - } - - if (type === "assistant") { - printTextMessage("assistant", pc.green, parsed.message); - return; - } - - if (type === "user") { - printTextMessage("user", pc.gray, parsed.message); - return; - } - - if (type === "thinking") { - const text = asString(parsed.text).trim() || asString(asRecord(parsed.delta)?.text).trim(); - if (text) console.log(pc.gray(`thinking: ${text}`)); - return; - } - - if (type === "tool_call") { - const subtype = asString(parsed.subtype).trim().toLowerCase(); - const toolCall = asRecord(parsed.tool_call ?? parsed.toolCall); - const [toolName] = toolCall ? Object.keys(toolCall) : []; - if (!toolCall || !toolName) { - console.log(pc.yellow(`tool_call${subtype ? `: ${subtype}` : ""}`)); - return; - } - const payload = asRecord(toolCall[toolName]) ?? {}; - if (subtype === "started" || subtype === "start") { - console.log(pc.yellow(`tool_call: ${toolName}`)); - console.log(pc.gray(stringifyUnknown(payload.args ?? payload.input ?? payload.arguments ?? payload))); - return; - } - if (subtype === "completed" || subtype === "complete" || subtype === "finished") { - const isError = - parsed.is_error === true || - payload.is_error === true || - payload.error !== undefined || - asString(payload.status).toLowerCase() === "error"; - console.log((isError ? pc.red : pc.cyan)(`tool_result${isError ? " (error)" : ""}`)); - console.log((isError ? pc.red : pc.gray)(stringifyUnknown(payload.result ?? payload.output ?? payload.error))); - return; - } - console.log(pc.yellow(`tool_call: ${toolName}${subtype ? ` (${subtype})` : ""}`)); - return; - } - - if (type === "result") { - printUsage(parsed); - const subtype = asString(parsed.subtype, "result"); - const isError = parsed.is_error === true; - if (subtype || isError) { - console.log((isError ? pc.red : pc.blue)(`result: subtype=${subtype} is_error=${isError ? "true" : "false"}`)); - } - return; - } - - if (type === "error") { - const text = errorText(parsed.error ?? parsed.message ?? parsed.detail); - if (text) console.log(pc.red(`error: ${text}`)); - return; - } - - if (debug) { - console.log(pc.gray(line)); - } -} diff --git a/packages/adapter-gemini-local/src/cli/index.ts b/packages/adapter-gemini-local/src/cli/index.ts deleted file mode 100644 index 49ec4426..00000000 --- a/packages/adapter-gemini-local/src/cli/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { printGeminiStreamEvent } from "./format-event.js"; diff --git a/packages/adapter-gemini-local/src/index.ts b/packages/adapter-gemini-local/src/index.ts deleted file mode 100644 index ec05f725..00000000 --- a/packages/adapter-gemini-local/src/index.ts +++ /dev/null @@ -1,47 +0,0 @@ -export const type = "gemini_local"; -export const label = "Gemini CLI (local)"; -export const DEFAULT_GEMINI_LOCAL_MODEL = "auto"; - -export const models = [ - { id: DEFAULT_GEMINI_LOCAL_MODEL, label: "Auto" }, - { id: "gemini-2.5-pro", label: "Gemini 2.5 Pro" }, - { id: "gemini-2.5-flash", label: "Gemini 2.5 Flash" }, - { id: "gemini-2.5-flash-lite", label: "Gemini 2.5 Flash Lite" }, - { id: "gemini-2.0-flash", label: "Gemini 2.0 Flash" }, - { id: "gemini-2.0-flash-lite", label: "Gemini 2.0 Flash Lite" }, -]; - -export const agentConfigurationDoc = `# gemini_local agent configuration - -Adapter: gemini_local - -Use when: -- You want AgentCompany to run the Gemini CLI locally on the host machine -- You want Gemini chat sessions resumed across heartbeats with --resume -- You want AgentCompany skills injected locally without polluting the global environment - -Don't use when: -- You need webhook-style external invocation (use http or openclaw_gateway) -- You only need a one-shot script without an AI coding agent loop (use process) -- Gemini CLI is not installed on the machine that runs AgentCompany - -Core fields: -- cwd (string, optional): default absolute working directory fallback for the agent process (created if missing when possible) -- instructionsFilePath (string, optional): absolute path to a markdown instructions file prepended to the run prompt -- promptTemplate (string, optional): run prompt template -- model (string, optional): Gemini model id. Defaults to auto. -- sandbox (boolean, optional): run in sandbox mode (default: false, passes --sandbox=none) -- command (string, optional): defaults to "gemini" -- extraArgs (string[], optional): additional CLI args -- env (object, optional): KEY=VALUE environment variables - -Operational fields: -- timeoutSec (number, optional): run timeout in seconds -- graceSec (number, optional): SIGTERM grace period in seconds - -Notes: -- Runs use positional prompt arguments, not stdin. -- Sessions resume with --resume when stored session cwd matches the current cwd. -- AgentCompany auto-injects local skills into \`~/.gemini/skills/\` via symlinks, so the CLI can discover both credentials and skills in their natural location. -- Authentication can use GEMINI_API_KEY / GOOGLE_API_KEY or local Gemini CLI login. -`; diff --git a/packages/adapter-gemini-local/src/server/execute-helpers.ts b/packages/adapter-gemini-local/src/server/execute-helpers.ts deleted file mode 100644 index 02400587..00000000 --- a/packages/adapter-gemini-local/src/server/execute-helpers.ts +++ /dev/null @@ -1,127 +0,0 @@ -import fs from "node:fs/promises"; -import type { Dirent } from "node:fs"; -import os from "node:os"; -import path from "node:path"; -import type { AdapterExecutionContext, ManagedSkillRef } from "@agentcompany/adapter-utils"; -import { - hasNonEmptyEnvValue, - buildSkillsCandidates, - resolveSkillsDir, - parseManagedSkills, - parseExtraArgs, - buildCommonAgentCompanyEnv, - resolveSessionResumeState, -} from "@agentcompany/adapter-utils"; -import { - createManagedSkillSymlinks, -} from "@agentcompany/adapter-utils/server-utils"; - -export { - hasNonEmptyEnvValue, - parseManagedSkills, - parseExtraArgs, - buildCommonAgentCompanyEnv, - resolveSessionResumeState, -}; - -export const SKILLS_CANDIDATES = buildSkillsCandidates(import.meta.url); - -export function resolveGeminiBillingType(env: Record): "api" | "subscription" { - return hasNonEmptyEnvValue(env, "GEMINI_API_KEY") || hasNonEmptyEnvValue(env, "GOOGLE_API_KEY") - ? "api" - : "subscription"; -} - -export function renderEnvNote(env: Record): string { - const agentCompanyKeys = Object.keys(env) - .filter((key) => key.startsWith("AGENT_COMPANY_")) - .sort(); - if (agentCompanyKeys.length === 0) return ""; - return [ - "Runtime note:", - `The following AGENT_COMPANY_* environment variables are available in this run: ${agentCompanyKeys.join(", ")}`, - "Do not assume these variables are missing without checking your shell environment.", - "", - "", - ].join("\n"); -} - -export function renderApiAccessNote(env: Record): string { - if (!hasNonEmptyEnvValue(env, "AGENT_COMPANY_API_URL") || !hasNonEmptyEnvValue(env, "AGENT_COMPANY_API_KEY")) return ""; - return [ - "API access note:", - "Use run_shell_command with curl to make API requests.", - "GET example:", - ` run_shell_command({ command: "curl -s -H \\"Authorization: Bearer $AGENT_COMPANY_API_KEY\\" \\"$AGENT_COMPANY_API_URL/api/agents/me\\"" })`, - "POST/PATCH example:", - ` run_shell_command({ command: "curl -s -X POST -H \\"Authorization: Bearer $AGENT_COMPANY_API_KEY\\" -H 'Content-Type: application/json' -H \\"X-Agent-Company-Run-Id: $AGENT_COMPANY_RUN_ID\\" -d '{...}' \\"$AGENT_COMPANY_API_URL/api/issues/{id}/checkout\\"" })`, - "", - "", - ].join("\n"); -} - -export async function resolveAgentCompanySkillsDir(): Promise { - return resolveSkillsDir(SKILLS_CANDIDATES); -} - -export function geminiSkillsHome(): string { - return path.join(os.homedir(), ".gemini", "skills"); -} - -/** - * Inject AgentCompany skills directly into `~/.gemini/skills/` via symlinks. - * Uses managed skills when available; falls back to static repo scan. - */ -export async function ensureGeminiSkillsInjected( - managedSkills: ManagedSkillRef[], - onLog: AdapterExecutionContext["onLog"], -): Promise { - const skillsHome = geminiSkillsHome(); - - if (managedSkills.length > 0) { - await createManagedSkillSymlinks(managedSkills, skillsHome, onLog); - return; - } - - const skillsDir = await resolveSkillsDir(SKILLS_CANDIDATES); - if (!skillsDir) return; - - try { - await fs.mkdir(skillsHome, { recursive: true }); - } catch (err) { - await onLog( - "stderr", - `[agent-company] Failed to prepare Gemini skills directory ${skillsHome}: ${err instanceof Error ? err.message : String(err)}\n`, - ); - return; - } - - let entries: Dirent[]; - try { - entries = await fs.readdir(skillsDir, { withFileTypes: true }); - } catch (err) { - await onLog( - "stderr", - `[agent-company] Failed to read AgentCompany skills from ${skillsDir}: ${err instanceof Error ? err.message : String(err)}\n`, - ); - return; - } - - for (const entry of entries) { - if (!entry.isDirectory()) continue; - const source = path.join(skillsDir, entry.name); - const target = path.join(skillsHome, entry.name); - const existing = await fs.lstat(target).catch(() => null); - if (existing) continue; - - try { - await fs.symlink(source, target); - await onLog("stderr", `[agent-company] Linked Gemini skill: ${entry.name}\n`); - } catch (err) { - await onLog( - "stderr", - `[agent-company] Failed to link Gemini skill "${entry.name}": ${err instanceof Error ? err.message : String(err)}\n`, - ); - } - } -} diff --git a/packages/adapter-gemini-local/src/server/execute.ts b/packages/adapter-gemini-local/src/server/execute.ts deleted file mode 100644 index 1cb18eeb..00000000 --- a/packages/adapter-gemini-local/src/server/execute.ts +++ /dev/null @@ -1,294 +0,0 @@ -import fs from "node:fs/promises"; -import os from "node:os"; -import path from "node:path"; -import type { AdapterExecutionContext, AdapterExecutionResult } from "@agentcompany/adapter-utils"; -import { - asBoolean, - asNumber, - asString, - ensureAbsoluteDirectory, - ensureCommandResolvable, - ensurePathInEnv, - filterConflictingArgs, - redactEnvForLogs, - renderTemplate, - runChildProcess, -} from "@agentcompany/adapter-utils/server-utils"; -import { DEFAULT_GEMINI_LOCAL_MODEL } from "../index.js"; -import { - describeGeminiFailure, - detectGeminiAuthRequired, - isGeminiTurnLimitResult, - isGeminiUnknownSessionError, - parseGeminiJsonl, -} from "./parse.js"; -import { firstNonEmptyLine } from "@agentcompany/adapter-utils/test-utils"; -import { - resolveGeminiBillingType, - renderEnvNote, - renderApiAccessNote, - ensureGeminiSkillsInjected, - parseManagedSkills, - parseExtraArgs, - buildCommonAgentCompanyEnv, - resolveSessionResumeState, -} from "./execute-helpers.js"; - -export async function execute(ctx: AdapterExecutionContext): Promise { - const { runId, agent, runtime, config, context, onLog, onMeta, authToken } = ctx; - - const promptTemplate = asString( - config.promptTemplate, - "{{context.taskTitle}}\n\n{{context.taskDescription}}", - ); - const command = asString(config.command, "gemini"); - const model = asString(config.model, DEFAULT_GEMINI_LOCAL_MODEL).trim(); - const sandbox = asBoolean(config.sandbox, false); - - const { env, cwd, workspaceId, workspaceRepoUrl, workspaceRepoRef } = - await buildCommonAgentCompanyEnv( - { runId, agent, config, context, authToken }, - { ensureAbsoluteDirectory }, - ); - - const managedSkills = parseManagedSkills(config); - await ensureGeminiSkillsInjected(managedSkills, onLog); - - const billingType = resolveGeminiBillingType(env); - const runtimeEnv = ensurePathInEnv(env); - await ensureCommandResolvable(command, cwd, runtimeEnv); - - const timeoutSec = asNumber(config.timeoutSec, 0); - const graceSec = asNumber(config.graceSec, 20); - const extraArgs = parseExtraArgs(config); - - const { sessionId, runtimeSessionId, runtimeSessionCwd, canResumeSession } = - resolveSessionResumeState(runtime, cwd); - if (runtimeSessionId && !canResumeSession) { - await onLog( - "stderr", - `[agent-company] Gemini session "${runtimeSessionId}" was saved for cwd "${runtimeSessionCwd}" and will not be resumed in "${cwd}".\n`, - ); - } - - const instructionsFilePath = asString(config.instructionsFilePath, "").trim(); - const instructionsDir = instructionsFilePath ? `${path.dirname(instructionsFilePath)}/` : ""; - let instructionsPrefix = ""; - if (instructionsFilePath) { - try { - const instructionsContents = await fs.readFile(instructionsFilePath, "utf8"); - instructionsPrefix = - `${instructionsContents}\n\n` + - `The above agent instructions were loaded from ${instructionsFilePath}. ` + - `Resolve any relative file references from ${instructionsDir}.\n\n`; - await onLog( - "stderr", - `[agent-company] Loaded agent instructions file: ${instructionsFilePath}\n`, - ); - } catch (err) { - const reason = err instanceof Error ? err.message : String(err); - await onLog( - "stderr", - `[agent-company] Warning: could not read agent instructions file "${instructionsFilePath}": ${reason}\n`, - ); - } - } - const renderedPrompt = renderTemplate(promptTemplate, { - agentId: agent.id, - companyId: agent.companyId, - runId, - company: { id: agent.companyId }, - agent, - run: { id: runId, source: "on_demand" }, - context, - }); - const envNote = renderEnvNote(env); - const apiAccessNote = renderApiAccessNote(env); - const prompt = `${instructionsPrefix}${envNote}${apiAccessNote}${renderedPrompt}`; - - const SAFE_ARG_LIMIT = 30_000; - const useStdin = prompt.length > SAFE_ARG_LIMIT; - const commandNotes = (() => { - const notes: string[] = [useStdin - ? "Prompt passed via stdin (exceeds command-line length limit)." - : "Prompt is passed to Gemini as the final positional argument."]; - notes.push("Added --approval-mode yolo for unattended execution."); - if (!instructionsFilePath) return notes; - if (instructionsPrefix.length > 0) { - notes.push( - `Loaded agent instructions from ${instructionsFilePath}`, - `Prepended instructions + path directive to prompt (relative references from ${instructionsDir}).`, - ); - return notes; - } - notes.push( - `Configured instructionsFilePath ${instructionsFilePath}, but file could not be read; continuing without injected instructions.`, - ); - return notes; - })(); - let promptFilePath: string | null = null; - if (useStdin) { - promptFilePath = path.join(os.tmpdir(), `agentcompany-gemini-prompt-${runId}.txt`); - await fs.writeFile(promptFilePath, prompt, "utf8"); - } - - const buildArgs = (resumeSessionId: string | null) => { - const args = ["--output-format", "stream-json"]; - if (resumeSessionId) args.push("--resume", resumeSessionId); - if (model && model !== DEFAULT_GEMINI_LOCAL_MODEL) args.push("--model", model); - args.push("--approval-mode", "yolo"); - if (sandbox) { - args.push("--sandbox"); - } else { - args.push("--sandbox=none"); - } - if (extraArgs.length > 0) { - const managedFlags = [ - "--approval-mode", - "--output-format", - "--model", - "--sandbox", - ]; - const cleaned = filterConflictingArgs(extraArgs, managedFlags); - if (cleaned.length > 0) args.push(...cleaned); - } - if (!useStdin) { - args.push(prompt); - } - return args; - }; - - const runAttempt = async (resumeSessionId: string | null) => { - const args = buildArgs(resumeSessionId); - if (onMeta) { - await onMeta({ - adapterType: "gemini_local", - command, - cwd, - commandNotes, - commandArgs: args.map((value, index) => ( - index === args.length - 1 ? `` : value - )), - env: redactEnvForLogs(env), - prompt, - context, - }); - } - - const proc = await runChildProcess(runId, command, args, { - cwd, - env, - timeoutSec, - graceSec, - onLog, - ...(useStdin ? { stdin: prompt } : {}), - }); - return { - proc, - parsed: parseGeminiJsonl(proc.stdout), - }; - }; - - const toResult = ( - attempt: { - proc: { - exitCode: number | null; - signal: string | null; - timedOut: boolean; - stdout: string; - stderr: string; - }; - parsed: ReturnType; - }, - clearSessionOnMissingSession = false, - isRetry = false, - ): AdapterExecutionResult => { - const authMeta = detectGeminiAuthRequired({ - parsed: attempt.parsed.resultEvent, - stdout: attempt.proc.stdout, - stderr: attempt.proc.stderr, - }); - - if (attempt.proc.timedOut) { - return { - exitCode: attempt.proc.exitCode, - signal: attempt.proc.signal, - timedOut: true, - errorMessage: `Timed out after ${timeoutSec}s`, - errorCode: authMeta.requiresAuth ? "gemini_auth_required" : null, - clearSession: clearSessionOnMissingSession, - }; - } - - const clearSessionForTurnLimit = isGeminiTurnLimitResult(attempt.parsed.resultEvent, attempt.proc.exitCode); - - const canFallbackToRuntimeSession = !isRetry; - const resolvedSessionId = attempt.parsed.sessionId - ?? (canFallbackToRuntimeSession ? (runtimeSessionId ?? runtime.sessionId ?? null) : null); - const resolvedSessionParams = resolvedSessionId - ? ({ - sessionId: resolvedSessionId, - cwd, - ...(workspaceId ? { workspaceId } : {}), - ...(workspaceRepoUrl ? { repoUrl: workspaceRepoUrl } : {}), - ...(workspaceRepoRef ? { repoRef: workspaceRepoRef } : {}), - } as Record) - : null; - const parsedError = typeof attempt.parsed.errorMessage === "string" ? attempt.parsed.errorMessage.trim() : ""; - const stderrLine = firstNonEmptyLine(attempt.proc.stderr); - const structuredFailure = attempt.parsed.resultEvent - ? describeGeminiFailure(attempt.parsed.resultEvent) - : null; - const fallbackErrorMessage = - parsedError || - structuredFailure || - stderrLine || - `Gemini exited with code ${attempt.proc.exitCode ?? -1}`; - - return { - exitCode: attempt.proc.exitCode, - signal: attempt.proc.signal, - timedOut: false, - errorMessage: (attempt.proc.exitCode ?? 0) === 0 ? null : fallbackErrorMessage, - errorCode: (attempt.proc.exitCode ?? 0) !== 0 && authMeta.requiresAuth ? "gemini_auth_required" : null, - usage: attempt.parsed.usage, - sessionId: resolvedSessionId, - sessionParams: resolvedSessionParams, - sessionDisplayId: resolvedSessionId, - provider: "google", - model, - billingType, - costUsd: attempt.parsed.costUsd, - resultJson: attempt.parsed.resultEvent ?? { - stdout: attempt.proc.stdout, - stderr: attempt.proc.stderr, - }, - summary: attempt.parsed.summary, - question: attempt.parsed.question, - clearSession: clearSessionForTurnLimit || Boolean(clearSessionOnMissingSession && !resolvedSessionId), - }; - }; - - try { - const initial = await runAttempt(sessionId); - if ( - sessionId && - !initial.proc.timedOut && - (initial.proc.exitCode ?? 0) !== 0 && - isGeminiUnknownSessionError(initial.proc.stdout, initial.proc.stderr) - ) { - await onLog( - "stderr", - `[agent-company] Gemini resume session "${sessionId}" is unavailable; retrying with a fresh session.\n`, - ); - const retry = await runAttempt(null); - return toResult(retry, true, true); - } - - return toResult(initial); - } finally { - if (promptFilePath) { - await fs.unlink(promptFilePath).catch(() => {}); - } - } -} diff --git a/packages/adapter-gemini-local/src/server/index.ts b/packages/adapter-gemini-local/src/server/index.ts deleted file mode 100644 index c4538a48..00000000 --- a/packages/adapter-gemini-local/src/server/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export { execute } from "./execute.js"; -export { testEnvironment } from "./test.js"; -export { - parseGeminiJsonl, - isGeminiUnknownSessionError, - describeGeminiFailure, - detectGeminiAuthRequired, - isGeminiTurnLimitResult, -} from "./parse.js"; -export { listGeminiSkills, syncGeminiSkills } from "./skills.js"; -import { createStandardSessionCodec } from "@agentcompany/adapter-utils/session-codec"; - -export const sessionCodec = createStandardSessionCodec({ extraSessionIdKeys: ["sessionID"] }); diff --git a/packages/adapter-gemini-local/src/server/parse.ts b/packages/adapter-gemini-local/src/server/parse.ts deleted file mode 100644 index 8321d1d3..00000000 --- a/packages/adapter-gemini-local/src/server/parse.ts +++ /dev/null @@ -1,263 +0,0 @@ -import { asNumber, asString, parseJson, parseObject } from "@agentcompany/adapter-utils/server-utils"; - -function collectMessageText(message: unknown): string[] { - if (typeof message === "string") { - const trimmed = message.trim(); - return trimmed ? [trimmed] : []; - } - - const record = parseObject(message); - const direct = asString(record.text, "").trim(); - const lines: string[] = direct ? [direct] : []; - const content = Array.isArray(record.content) ? record.content : []; - - for (const partRaw of content) { - const part = parseObject(partRaw); - const type = asString(part.type, "").trim(); - if (type === "output_text" || type === "text" || type === "content") { - const text = asString(part.text, "").trim() || asString(part.content, "").trim(); - if (text) lines.push(text); - } - } - - return lines; -} - -function readSessionId(event: Record): string | null { - return ( - asString(event.session_id, "").trim() || - asString(event.sessionId, "").trim() || - asString(event.sessionID, "").trim() || - asString(event.checkpoint_id, "").trim() || - asString(event.thread_id, "").trim() || - null - ); -} - -function asErrorText(value: unknown): string { - if (typeof value === "string") return value; - const rec = parseObject(value); - const message = - asString(rec.message, "") || - asString(rec.error, "") || - asString(rec.code, "") || - asString(rec.detail, ""); - if (message) return message; - try { - return JSON.stringify(rec); - } catch { - return ""; - } -} - -function accumulateUsage( - target: { inputTokens: number; cachedInputTokens: number; outputTokens: number }, - usageRaw: unknown, -) { - const usage = parseObject(usageRaw); - const usageMetadata = parseObject(usage.usageMetadata); - const source = Object.keys(usageMetadata).length > 0 ? usageMetadata : usage; - - target.inputTokens += asNumber( - source.input_tokens, - asNumber(source.inputTokens, asNumber(source.promptTokenCount, 0)), - ); - target.cachedInputTokens += asNumber( - source.cached_input_tokens, - asNumber(source.cachedInputTokens, asNumber(source.cachedContentTokenCount, 0)), - ); - target.outputTokens += asNumber( - source.output_tokens, - asNumber(source.outputTokens, asNumber(source.candidatesTokenCount, 0)), - ); -} - -export function parseGeminiJsonl(stdout: string) { - let sessionId: string | null = null; - const messages: string[] = []; - let errorMessage: string | null = null; - let costUsd: number | null = null; - let resultEvent: Record | null = null; - let question: { prompt: string; choices: Array<{ key: string; label: string; description?: string }> } | null = null; - const usage = { - inputTokens: 0, - cachedInputTokens: 0, - outputTokens: 0, - }; - - for (const rawLine of stdout.split(/\r?\n/)) { - const line = rawLine.trim(); - if (!line) continue; - - const event = parseJson(line); - if (!event) continue; - - const foundSessionId = readSessionId(event); - if (foundSessionId) sessionId = foundSessionId; - - const type = asString(event.type, "").trim(); - - if (type === "assistant") { - messages.push(...collectMessageText(event.message)); - const messageObj = parseObject(event.message); - const content = Array.isArray(messageObj.content) ? messageObj.content : []; - for (const partRaw of content) { - const part = parseObject(partRaw); - if (asString(part.type, "").trim() === "question") { - question = { - prompt: asString(part.prompt, "").trim(), - choices: (Array.isArray(part.choices) ? part.choices : []).map((choiceRaw) => { - const choice = parseObject(choiceRaw); - return { - key: asString(choice.key, "").trim(), - label: asString(choice.label, "").trim(), - description: asString(choice.description, "").trim() || undefined, - }; - }), - }; - break; // only one question per message - } - } - continue; - } - - if (type === "result") { - resultEvent = event; - accumulateUsage(usage, event.usage ?? event.usageMetadata); - const resultText = - asString(event.result, "").trim() || - asString(event.text, "").trim() || - asString(event.response, "").trim(); - if (resultText && messages.length === 0) messages.push(resultText); - costUsd = asNumber(event.total_cost_usd, asNumber(event.cost_usd, asNumber(event.cost, costUsd ?? 0))) || costUsd; - const isError = event.is_error === true || asString(event.subtype, "").toLowerCase() === "error"; - if (isError) { - const text = asErrorText(event.error ?? event.message ?? event.result).trim(); - if (text) errorMessage = text; - } - continue; - } - - if (type === "error") { - const text = asErrorText(event.error ?? event.message ?? event.detail).trim(); - if (text) errorMessage = text; - continue; - } - - if (type === "system") { - const subtype = asString(event.subtype, "").trim().toLowerCase(); - if (subtype === "error") { - const text = asErrorText(event.error ?? event.message ?? event.detail).trim(); - if (text) errorMessage = text; - } - continue; - } - - if (type === "text") { - const part = parseObject(event.part); - const text = asString(part.text, "").trim(); - if (text) messages.push(text); - continue; - } - - if (type === "step_finish" || event.usage || event.usageMetadata) { - accumulateUsage(usage, event.usage ?? event.usageMetadata); - costUsd = asNumber(event.total_cost_usd, asNumber(event.cost_usd, asNumber(event.cost, costUsd ?? 0))) || costUsd; - continue; - } - } - - return { - sessionId, - summary: messages.join("\n\n").trim(), - usage, - costUsd, - errorMessage, - resultEvent, - question, - }; -} - -export function isGeminiUnknownSessionError(stdout: string, stderr: string): boolean { - const haystack = `${stdout}\n${stderr}` - .split(/\r?\n/) - .map((line) => line.trim()) - .filter(Boolean) - .join("\n"); - - return /unknown\s+session|session\s+.*\s+not\s+found|resume\s+.*\s+not\s+found|checkpoint\s+.*\s+not\s+found|cannot\s+resume|failed\s+to\s+resume/i.test( - haystack, - ); -} - -function extractGeminiErrorMessages(parsed: Record): string[] { - const messages: string[] = []; - const errorMsg = asString(parsed.error, "").trim(); - if (errorMsg) messages.push(errorMsg); - - const raw = Array.isArray(parsed.errors) ? parsed.errors : []; - for (const entry of raw) { - if (typeof entry === "string") { - const msg = entry.trim(); - if (msg) messages.push(msg); - continue; - } - if (typeof entry !== "object" || entry === null || Array.isArray(entry)) continue; - const obj = entry as Record; - const msg = asString(obj.message, "") || asString(obj.error, "") || asString(obj.code, ""); - if (msg) { - messages.push(msg); - continue; - } - try { - messages.push(JSON.stringify(obj)); - } catch { - // skip non-serializable entry - } - } - - return messages; -} - -export function describeGeminiFailure(parsed: Record): string | null { - const status = asString(parsed.status, ""); - const errors = extractGeminiErrorMessages(parsed); - - const detail = errors[0] ?? ""; - const parts = ["Gemini run failed"]; - if (status) parts.push(`status=${status}`); - if (detail) parts.push(detail); - return parts.length > 1 ? parts.join(": ") : null; -} - -const GEMINI_AUTH_REQUIRED_RE = /(?:not\s+authenticated|please\s+authenticate|api[_ ]?key\s+(?:required|missing|invalid)|authentication\s+required|unauthorized|invalid\s+credentials|not\s+logged\s+in|login\s+required|run\s+`?gemini\s+auth(?:\s+login)?`?\s+first)/i; - -export function detectGeminiAuthRequired(input: { - parsed: Record | null; - stdout: string; - stderr: string; -}): { requiresAuth: boolean } { - const errors = extractGeminiErrorMessages(input.parsed ?? {}); - const messages = [...errors, input.stdout, input.stderr] - .join("\n") - .split(/\r?\n/) - .map((line) => line.trim()) - .filter(Boolean); - - const requiresAuth = messages.some((line) => GEMINI_AUTH_REQUIRED_RE.test(line)); - return { requiresAuth }; -} - -export function isGeminiTurnLimitResult( - parsed: Record | null | undefined, - exitCode?: number | null, -): boolean { - if (exitCode === 53) return true; - if (!parsed) return false; - - const status = asString(parsed.status, "").trim().toLowerCase(); - if (status === "turn_limit" || status === "max_turns") return true; - - const error = asString(parsed.error, "").trim(); - return /turn\s*limit|max(?:imum)?\s+turns?/i.test(error); -} diff --git a/packages/adapter-gemini-local/src/server/skills.ts b/packages/adapter-gemini-local/src/server/skills.ts deleted file mode 100644 index 415d8a8b..00000000 --- a/packages/adapter-gemini-local/src/server/skills.ts +++ /dev/null @@ -1,113 +0,0 @@ -// --------------------------------------------------------------------------- -// Gemini adapter skill listing / sync -- persistent mode -// Skills are symlinked into ~/.gemini/skills/ and persist across runs. -// --------------------------------------------------------------------------- - -import { promises as fs } from "node:fs"; -import path from "node:path"; -import type { - AdapterSkillContext, - AdapterSkillSnapshot, -} from "@agentcompany/adapter-utils"; -import { - parseObject, - asString, - readAgentCompanyRuntimeSkillEntries, - readInstalledSkillTargets, - resolveAgentCompanyDesiredSkillNames, - buildPersistentSkillSnapshot, - ensureAgentCompanySkillSymlink, - removeMaintainerOnlySkillSymlinks, -} from "@agentcompany/adapter-utils/server-utils"; - -function resolveGeminiSkillsHome(config: Record): string { - const env = parseObject(config.env); - const home = asString(env.HOME, asString(env.USERPROFILE, "")); - const base = home || (process.env.HOME ?? process.env.USERPROFILE ?? ""); - return path.join(base, ".gemini", "skills"); -} - -async function buildGeminiSkillSnapshot( - config: Record, -): Promise { - const moduleDir = path.resolve(import.meta.dirname ?? __dirname); - const availableEntries = await readAgentCompanyRuntimeSkillEntries(config, moduleDir); - const desiredSkills = resolveAgentCompanyDesiredSkillNames(config, availableEntries); - const skillsHome = resolveGeminiSkillsHome(config); - const installed = await readInstalledSkillTargets(skillsHome); - - return buildPersistentSkillSnapshot({ - adapterType: "gemini_local", - availableEntries, - desiredSkills, - installed, - skillsHome, - locationLabel: "~/.gemini/skills", - missingDetail: "Configured but not currently linked into the Gemini skills home.", - externalConflictDetail: "Skill name is occupied by an external installation.", - externalDetail: "Installed outside AgentCompany management.", - }); -} - -/** - * List the current skill state for the Gemini adapter. - * Persistent mode: reports actual installed state in ~/.gemini/skills/. - */ -export async function listGeminiSkills( - ctx: AdapterSkillContext, -): Promise { - return buildGeminiSkillSnapshot(ctx.config); -} - -/** - * Sync skills for the Gemini adapter. - * Persistent mode: creates symlinks for desired skills, removes stale ones, - * then returns a fresh snapshot. - */ -export async function syncGeminiSkills( - ctx: AdapterSkillContext, - desiredSkills: string[], -): Promise { - const moduleDir = path.resolve(import.meta.dirname ?? __dirname); - const config = ctx.config; - const availableEntries = await readAgentCompanyRuntimeSkillEntries(config, moduleDir); - const skillsHome = resolveGeminiSkillsHome(config); - - // Ensure the skills home directory exists - await fs.mkdir(skillsHome, { recursive: true }); - - // Build a set of desired skill keys for quick lookup - const desiredSet = new Set(desiredSkills); - - // Symlink type for Windows compatibility - const symlinkType = process.platform === "win32" ? ("junction" as const) : undefined; - const linkSkill = async (source: string, target: string) => { - await fs.symlink(source, target, symlinkType); - }; - - // Create/repair symlinks for desired skills - const syncedRuntimeNames = new Set(); - for (const available of availableEntries) { - if (!desiredSet.has(available.key)) continue; - const target = path.join(skillsHome, available.runtimeName); - await ensureAgentCompanySkillSymlink(available.source, target, linkSkill); - syncedRuntimeNames.add(available.runtimeName); - } - - // Remove stale maintainer-only symlinks that are no longer desired - await removeMaintainerOnlySkillSymlinks(skillsHome, syncedRuntimeNames); - - // Return fresh snapshot reflecting the new state - const installed = await readInstalledSkillTargets(skillsHome); - return buildPersistentSkillSnapshot({ - adapterType: "gemini_local", - availableEntries, - desiredSkills, - installed, - skillsHome, - locationLabel: "~/.gemini/skills", - missingDetail: "Configured but not currently linked into the Gemini skills home.", - externalConflictDetail: "Skill name is occupied by an external installation.", - externalDetail: "Installed outside AgentCompany management.", - }); -} diff --git a/packages/adapter-gemini-local/src/server/test.ts b/packages/adapter-gemini-local/src/server/test.ts deleted file mode 100644 index effd49ce..00000000 --- a/packages/adapter-gemini-local/src/server/test.ts +++ /dev/null @@ -1,152 +0,0 @@ -import type { - AdapterEnvironmentCheck, - AdapterEnvironmentTestContext, - AdapterEnvironmentTestResult, -} from "@agentcompany/adapter-utils"; -import { - asBoolean, - asString, - asStringArray, - ensureAbsoluteDirectory, - ensureCommandResolvable, - ensurePathInEnv, - parseObject, - runChildProcess, -} from "@agentcompany/adapter-utils/server-utils"; -import { summarizeStatus, isNonEmpty, commandLooksLike, summarizeProbeDetail } from "@agentcompany/adapter-utils/test-utils"; -import { DEFAULT_GEMINI_LOCAL_MODEL } from "../index.js"; -import { detectGeminiAuthRequired, parseGeminiJsonl } from "./parse.js"; - -export async function testEnvironment( - ctx: AdapterEnvironmentTestContext, -): Promise { - const checks: AdapterEnvironmentCheck[] = []; - const config = parseObject(ctx.config); - const command = asString(config.command, "gemini"); - const cwd = asString(config.cwd, process.cwd()); - - try { - await ensureAbsoluteDirectory(cwd, { createIfMissing: true }); - checks.push({ - code: "gemini_cwd_valid", - level: "info", - message: `Working directory is valid: ${cwd}`, - }); - } catch (err) { - checks.push({ - code: "gemini_cwd_invalid", - level: "error", - message: err instanceof Error ? err.message : "Invalid working directory", - detail: cwd, - }); - } - - const envConfig = parseObject(config.env); - const env: Record = {}; - for (const [key, value] of Object.entries(envConfig)) { - if (typeof value === "string") env[key] = value; - } - const runtimeEnv = ensurePathInEnv(env); - try { - await ensureCommandResolvable(command, cwd, runtimeEnv); - checks.push({ - code: "gemini_command_resolvable", - level: "info", - message: `Command is executable: ${command}`, - }); - } catch (err) { - checks.push({ - code: "gemini_command_unresolvable", - level: "error", - message: err instanceof Error ? err.message : "Command is not executable", - detail: command, - }); - } - - const configGeminiApiKey = env.GEMINI_API_KEY; - const configGoogleApiKey = env.GOOGLE_API_KEY; - const hasGca = env.GOOGLE_GENAI_USE_GCA === "true"; - if ( - isNonEmpty(configGeminiApiKey) || - isNonEmpty(configGoogleApiKey) || - hasGca - ) { - const source = hasGca - ? "Google account login (GCA)" - : "adapter runtime env"; - checks.push({ - code: "gemini_api_key_present", - level: "info", - message: "Gemini API credentials are set for CLI authentication.", - detail: `Detected in ${source}.`, - }); - } else { - checks.push({ - code: "gemini_api_key_missing", - level: "info", - message: "No explicit API key detected. Gemini CLI may still authenticate via `gemini auth login` (OAuth).", - hint: "If the hello probe fails with an auth error, set GEMINI_API_KEY or GOOGLE_API_KEY in connector secret bindings, or run `gemini auth login`.", - }); - } - - const canRunProbe = - checks.every((check) => check.code !== "gemini_cwd_invalid" && check.code !== "gemini_command_unresolvable"); - if (canRunProbe && commandLooksLike(command, "gemini")) { - try { - const model = asString(config.model, DEFAULT_GEMINI_LOCAL_MODEL).trim(); - const approvalMode = asString(config.approvalMode, asBoolean(config.yolo, false) ? "yolo" : "default"); - const sandbox = asBoolean(config.sandbox, false); - const extraArgs = (() => { - const fromExtraArgs = asStringArray(config.extraArgs); - if (fromExtraArgs.length > 0) return fromExtraArgs; - return asStringArray(config.args); - })(); - - const args = ["--output-format", "stream-json"]; - if (model && model !== DEFAULT_GEMINI_LOCAL_MODEL) args.push("--model", model); - if (approvalMode !== "default") args.push("--approval-mode", approvalMode); - if (sandbox) { - args.push("--sandbox"); - } else { - args.push("--sandbox=none"); - } - if (extraArgs.length > 0) args.push(...extraArgs); - args.push("Respond with hello."); - - const probe = await runChildProcess( - `gemini-envtest-${Date.now()}-${Math.random().toString(16).slice(2)}`, - command, - args, - { cwd, env, timeoutSec: 45, graceSec: 5, onLog: async () => { } }, - ); - const parsed = parseGeminiJsonl(probe.stdout); - const detail = summarizeProbeDetail(probe.stdout, probe.stderr, parsed.errorMessage); - const authMeta = detectGeminiAuthRequired({ parsed: parsed.resultEvent, stdout: probe.stdout, stderr: probe.stderr }); - - if (probe.timedOut) { - checks.push({ code: "gemini_hello_probe_timed_out", level: "info", message: "Gemini hello probe timed out." }); - } else if ((probe.exitCode ?? 1) === 0) { - const summary = parsed.summary.trim(); - checks.push({ code: "gemini_hello_probe_passed", level: "info", message: "Gemini probe completed.", ...(summary ? { detail: summary.replace(/\s+/g, " ").trim().slice(0, 240) } : {}) }); - } else if (authMeta.requiresAuth) { - checks.push({ - code: "gemini_hello_probe_auth_required", level: "warn", - message: "Gemini CLI is installed, but authentication is not ready.", - ...(detail ? { detail } : {}), - hint: "Run `gemini auth` or configure GEMINI_API_KEY / GOOGLE_API_KEY.", - }); - } else { - checks.push({ code: "gemini_hello_probe_failed", level: "info", message: "Gemini hello probe exited with non-zero code.", ...(detail ? { detail } : {}) }); - } - } catch { - checks.push({ code: "gemini_hello_probe_error", level: "info", message: "Gemini hello probe could not run." }); - } - } - - return { - adapterType: ctx.adapterType, - status: summarizeStatus(checks), - checks, - testedAt: new Date().toISOString(), - }; -} diff --git a/packages/adapter-gemini-local/src/ui/build-config.ts b/packages/adapter-gemini-local/src/ui/build-config.ts deleted file mode 100644 index d38af272..00000000 --- a/packages/adapter-gemini-local/src/ui/build-config.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { CreateConfigValues } from "@agentcompany/adapter-utils"; -import { parseCommaArgs, parseEnvVars, parseEnvBindings } from "@agentcompany/adapter-utils/config-utils"; -import { DEFAULT_GEMINI_LOCAL_MODEL } from "../index.js"; - -export function buildGeminiLocalConfig(v: CreateConfigValues): Record { - const ac: Record = {}; - if (v.cwd) ac.cwd = v.cwd; - if (v.instructionsFilePath) ac.instructionsFilePath = v.instructionsFilePath; - if (v.promptTemplate) ac.promptTemplate = v.promptTemplate; - ac.model = v.model || DEFAULT_GEMINI_LOCAL_MODEL; - ac.timeoutSec = 0; - ac.graceSec = 15; - const env = parseEnvBindings(v.envBindings); - const legacy = parseEnvVars(v.envVars); - for (const [key, value] of Object.entries(legacy)) { - if (!Object.prototype.hasOwnProperty.call(env, key)) { - env[key] = { type: "plain", value }; - } - } - if (Object.keys(env).length > 0) ac.env = env; - ac.sandbox = !v.dangerouslyBypassSandbox; - - if (v.command) ac.command = v.command; - if (v.extraArgs) ac.extraArgs = parseCommaArgs(v.extraArgs); - return ac; -} diff --git a/packages/adapter-gemini-local/src/ui/index.ts b/packages/adapter-gemini-local/src/ui/index.ts deleted file mode 100644 index 5d7708b1..00000000 --- a/packages/adapter-gemini-local/src/ui/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { parseGeminiStdoutLine } from "./parse-stdout.js"; -export { buildGeminiLocalConfig } from "./build-config.js"; diff --git a/packages/adapter-gemini-local/src/ui/parse-stdout.ts b/packages/adapter-gemini-local/src/ui/parse-stdout.ts deleted file mode 100644 index 79e7303a..00000000 --- a/packages/adapter-gemini-local/src/ui/parse-stdout.ts +++ /dev/null @@ -1,245 +0,0 @@ -import type { TranscriptEntry } from "@agentcompany/adapter-utils"; -import { asRecord, safeJsonParse, errorText } from "@agentcompany/adapter-utils/parse-utils"; - -function asString(value: unknown, fallback = ""): string { - return typeof value === "string" ? value : fallback; -} - -function asNumber(value: unknown, fallback = 0): number { - return typeof value === "number" && Number.isFinite(value) ? value : fallback; -} - -function stringifyUnknown(value: unknown): string { - if (typeof value === "string") return value; - if (value === null || value === undefined) return ""; - try { - return JSON.stringify(value, null, 2); - } catch { - return String(value); - } -} - -function collectTextEntries(messageRaw: unknown, ts: string, kind: "assistant" | "user"): TranscriptEntry[] { - if (typeof messageRaw === "string") { - const text = messageRaw.trim(); - return text ? [{ kind, ts, text }] : []; - } - - const message = asRecord(messageRaw); - if (!message) return []; - - const entries: TranscriptEntry[] = []; - const directText = asString(message.text).trim(); - if (directText) entries.push({ kind, ts, text: directText }); - - const content = Array.isArray(message.content) ? message.content : []; - for (const partRaw of content) { - const part = asRecord(partRaw); - if (!part) continue; - const type = asString(part.type).trim(); - if (type !== "output_text" && type !== "text" && type !== "content") continue; - const text = asString(part.text).trim() || asString(part.content).trim(); - if (text) entries.push({ kind, ts, text }); - } - - return entries; -} - -function parseAssistantMessage(messageRaw: unknown, ts: string): TranscriptEntry[] { - if (typeof messageRaw === "string") { - const text = messageRaw.trim(); - return text ? [{ kind: "assistant", ts, text }] : []; - } - - const message = asRecord(messageRaw); - if (!message) return []; - - const entries: TranscriptEntry[] = []; - const directText = asString(message.text).trim(); - if (directText) entries.push({ kind: "assistant", ts, text: directText }); - - const content = Array.isArray(message.content) ? message.content : []; - for (const partRaw of content) { - const part = asRecord(partRaw); - if (!part) continue; - const type = asString(part.type).trim(); - - if (type === "output_text" || type === "text" || type === "content") { - const text = asString(part.text).trim() || asString(part.content).trim(); - if (text) entries.push({ kind: "assistant", ts, text }); - continue; - } - - if (type === "thinking") { - const text = asString(part.text).trim(); - if (text) entries.push({ kind: "thinking", ts, text }); - continue; - } - - if (type === "tool_call") { - const name = asString(part.name, asString(part.tool, "tool")); - entries.push({ - kind: "tool_call", - ts, - name, - input: part.input ?? part.arguments ?? part.args ?? {}, - }); - continue; - } - - if (type === "tool_result" || type === "tool_response") { - const toolUseId = - asString(part.tool_use_id) || - asString(part.toolUseId) || - asString(part.call_id) || - asString(part.id) || - "tool_result"; - const contentText = - asString(part.output) || - asString(part.text) || - asString(part.result) || - stringifyUnknown(part.output ?? part.result ?? part.text ?? part.response); - const isError = part.is_error === true || asString(part.status).toLowerCase() === "error"; - entries.push({ - kind: "tool_result", - ts, - toolUseId, - content: contentText, - isError, - }); - } - } - - return entries; -} - -function parseTopLevelToolEvent(parsed: Record, ts: string): TranscriptEntry[] { - const subtype = asString(parsed.subtype).trim().toLowerCase(); - const callId = asString(parsed.call_id, asString(parsed.callId, asString(parsed.id, "tool_call"))); - const toolCall = asRecord(parsed.tool_call ?? parsed.toolCall); - if (!toolCall) { - return [{ kind: "system", ts, text: `tool_call${subtype ? ` (${subtype})` : ""}` }]; - } - - const [toolName] = Object.keys(toolCall); - if (!toolName) { - return [{ kind: "system", ts, text: `tool_call${subtype ? ` (${subtype})` : ""}` }]; - } - const payload = asRecord(toolCall[toolName]) ?? {}; - - if (subtype === "started" || subtype === "start") { - return [{ - kind: "tool_call", - ts, - name: toolName, - input: payload.args ?? payload.input ?? payload.arguments ?? payload, - }]; - } - - if (subtype === "completed" || subtype === "complete" || subtype === "finished") { - const result = payload.result ?? payload.output ?? payload.error; - const isError = - parsed.is_error === true || - payload.is_error === true || - payload.error !== undefined || - asString(payload.status).toLowerCase() === "error"; - return [{ - kind: "tool_result", - ts, - toolUseId: callId, - content: result !== undefined ? stringifyUnknown(result) : `${toolName} completed`, - isError, - }]; - } - - return [{ kind: "system", ts, text: `tool_call${subtype ? ` (${subtype})` : ""}: ${toolName}` }]; -} - -function readSessionId(parsed: Record): string { - return ( - asString(parsed.session_id) || - asString(parsed.sessionId) || - asString(parsed.sessionID) || - asString(parsed.checkpoint_id) || - asString(parsed.thread_id) - ); -} - -function readUsage(parsed: Record) { - const usage = asRecord(parsed.usage) ?? asRecord(parsed.usageMetadata); - const usageMetadata = asRecord(usage?.usageMetadata); - const source = usageMetadata ?? usage ?? {}; - return { - inputTokens: asNumber(source.input_tokens, asNumber(source.inputTokens, asNumber(source.promptTokenCount))), - outputTokens: asNumber(source.output_tokens, asNumber(source.outputTokens, asNumber(source.candidatesTokenCount))), - cachedTokens: asNumber( - source.cached_input_tokens, - asNumber(source.cachedInputTokens, asNumber(source.cachedContentTokenCount)), - ), - }; -} - -export function parseGeminiStdoutLine(line: string, ts: string): TranscriptEntry[] { - const parsed = asRecord(safeJsonParse(line)); - if (!parsed) { - return [{ kind: "stdout", ts, text: line }]; - } - - const type = asString(parsed.type); - - if (type === "system") { - const subtype = asString(parsed.subtype); - if (subtype === "init") { - const sessionId = readSessionId(parsed); - return [{ kind: "init", ts, model: asString(parsed.model, "gemini"), sessionId }]; - } - if (subtype === "error") { - const text = errorText(parsed.error ?? parsed.message ?? parsed.detail); - return [{ kind: "stderr", ts, text: text || "error" }]; - } - return [{ kind: "system", ts, text: `system: ${subtype || "event"}` }]; - } - - if (type === "assistant") { - return parseAssistantMessage(parsed.message, ts); - } - - if (type === "user") { - return collectTextEntries(parsed.message, ts, "user"); - } - - if (type === "thinking") { - const text = asString(parsed.text).trim() || asString(asRecord(parsed.delta)?.text).trim(); - return text ? [{ kind: "thinking", ts, text }] : []; - } - - if (type === "tool_call") { - return parseTopLevelToolEvent(parsed, ts); - } - - if (type === "result") { - const usage = readUsage(parsed); - const errors = parsed.is_error === true - ? [errorText(parsed.error ?? parsed.message ?? parsed.result)].filter(Boolean) - : []; - return [{ - kind: "result", - ts, - text: asString(parsed.result) || asString(parsed.text) || asString(parsed.response), - inputTokens: usage.inputTokens, - outputTokens: usage.outputTokens, - cachedTokens: usage.cachedTokens, - costUsd: asNumber(parsed.total_cost_usd, asNumber(parsed.cost_usd, asNumber(parsed.cost))), - subtype: asString(parsed.subtype, "result"), - isError: parsed.is_error === true, - errors, - }]; - } - - if (type === "error") { - const text = errorText(parsed.error ?? parsed.message ?? parsed.detail); - return [{ kind: "stderr", ts, text: text || "error" }]; - } - - return [{ kind: "stdout", ts, text: line }]; -} diff --git a/packages/adapter-gemini-local/tsconfig.json b/packages/adapter-gemini-local/tsconfig.json deleted file mode 100644 index 5a24989c..00000000 --- a/packages/adapter-gemini-local/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "dist", - "rootDir": "src" - }, - "include": ["src"] -} diff --git a/packages/adapter-utils/package.json b/packages/adapter-utils/package.json deleted file mode 100644 index 060936c7..00000000 --- a/packages/adapter-utils/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@agentcompany/adapter-utils", - "version": "0.3.0", - "type": "module", - "exports": { - ".": "./src/index.ts", - "./*": "./src/*.ts" - }, - "publishConfig": { - "access": "public", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - }, - "./*": { - "types": "./dist/*.d.ts", - "import": "./dist/*.js" - } - }, - "main": "./dist/index.js", - "types": "./dist/index.d.ts" - }, - "files": [ - "dist" - ], - "scripts": { - "build": "tsc", - "clean": "rm -rf dist", - "typecheck": "tsc --noEmit" - }, - "devDependencies": { - "@types/node": "^24.6.0", - "typescript": "^5.7.3" - } -} diff --git a/packages/adapter-utils/src/config-utils.ts b/packages/adapter-utils/src/config-utils.ts deleted file mode 100644 index cf5a26cf..00000000 --- a/packages/adapter-utils/src/config-utils.ts +++ /dev/null @@ -1,61 +0,0 @@ -export function parseCommaArgs(value: string): string[] { - return value - .split(",") - .map((item) => item.trim()) - .filter(Boolean); -} - -export function parseEnvVars(text: string): Record { - const env: Record = {}; - for (const line of text.split(/\r?\n/)) { - const trimmed = line.trim(); - if (!trimmed || trimmed.startsWith("#")) continue; - const eq = trimmed.indexOf("="); - if (eq <= 0) continue; - const key = trimmed.slice(0, eq).trim(); - const value = trimmed.slice(eq + 1); - if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) continue; - env[key] = value; - } - return env; -} - -export function parseEnvBindings(bindings: unknown): Record { - if (typeof bindings !== "object" || bindings === null || Array.isArray(bindings)) return {}; - const env: Record = {}; - for (const [key, raw] of Object.entries(bindings)) { - if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) continue; - if (typeof raw === "string") { - env[key] = { type: "plain", value: raw }; - continue; - } - if (typeof raw !== "object" || raw === null || Array.isArray(raw)) continue; - const rec = raw as Record; - if (rec.type === "plain" && typeof rec.value === "string") { - env[key] = { type: "plain", value: rec.value }; - continue; - } - if (rec.type === "secret_ref" && typeof rec.secretId === "string") { - env[key] = { - type: "secret_ref", - secretId: rec.secretId, - ...(typeof rec.version === "number" || rec.version === "latest" - ? { version: rec.version } - : {}), - }; - } - } - return env; -} - -export function parseJsonObject(text: string): Record | null { - const trimmed = text.trim(); - if (!trimmed) return null; - try { - const parsed = JSON.parse(trimmed); - if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return null; - return parsed as Record; - } catch { - return null; - } -} diff --git a/packages/adapter-utils/src/execute-helpers.ts b/packages/adapter-utils/src/execute-helpers.ts deleted file mode 100644 index 2db183f0..00000000 --- a/packages/adapter-utils/src/execute-helpers.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { fileURLToPath } from "node:url"; -import path from "node:path"; -import fs from "node:fs/promises"; -import type { ManagedSkillRef } from "./types.js"; -import { asString, asStringArray, parseObject } from "./server-utils-parsers.js"; -import { buildAgentCompanyEnv } from "./server-utils-parsers.js"; - -// --------------------------------------------------------------------------- -// hasNonEmptyEnvValue -// --------------------------------------------------------------------------- - -export function hasNonEmptyEnvValue(env: Record, key: string): boolean { - const raw = env[key]; - return typeof raw === "string" && raw.trim().length > 0; -} - -// --------------------------------------------------------------------------- -// Skills directory resolution -// --------------------------------------------------------------------------- - -/** - * Build the standard two-candidate list for a given adapter package. - * `importMetaUrl` should be `import.meta.url` from the adapter's execute-helpers.ts. - * - published: /dist/server/ -> /skills/ - * - dev: src/server/ -> repo root/skills/ - */ -export function buildSkillsCandidates(importMetaUrl: string): string[] { - const moduleDir = path.dirname(fileURLToPath(importMetaUrl)); - return [ - path.resolve(moduleDir, "../../skills"), - path.resolve(moduleDir, "../../../../../skills"), - ]; -} - -/** - * Resolve the first existing skills directory from the given candidates. - */ -export async function resolveSkillsDir(candidates: string[]): Promise { - for (const candidate of candidates) { - const isDir = await fs.stat(candidate).then((s) => s.isDirectory()).catch(() => false); - if (isDir) return candidate; - } - return null; -} - -// --------------------------------------------------------------------------- -// ManagedSkills type guard + parser -// --------------------------------------------------------------------------- - -export function parseManagedSkills(config: Record): ManagedSkillRef[] { - if (!Array.isArray(config.managedSkills)) return []; - return (config.managedSkills as ManagedSkillRef[]).filter( - (s) => typeof s.runtimeName === "string" && typeof s.sourcePath === "string", - ); -} - -// --------------------------------------------------------------------------- -// extraArgs parser -// --------------------------------------------------------------------------- - -export function parseExtraArgs(config: Record): string[] { - const fromExtraArgs = asStringArray(config.extraArgs); - if (fromExtraArgs.length > 0) return fromExtraArgs; - return asStringArray(config.args); -} - -// --------------------------------------------------------------------------- -// Common env building -// --------------------------------------------------------------------------- - -export interface CommonAgentCompanyEnvInput { - runId: string; - agent: { id: string; companyId: string }; - config: Record; - context: Record; - authToken?: string; -} - -export interface CommonAgentCompanyEnvResult { - env: Record; - cwd: string; - effectiveWorkspaceCwd: string; - workspaceId: string | null; - workspaceRepoUrl: string | null; - workspaceRepoRef: string | null; - hasExplicitApiKey: boolean; -} - -/** - * Build the AGENT_COMPANY_* environment block common to all local adapters. - * Returns the env map plus resolved workspace fields needed for session params. - */ -export async function buildCommonAgentCompanyEnv( - input: CommonAgentCompanyEnvInput, - opts: { - ensureAbsoluteDirectory: (dir: string, options: { createIfMissing: boolean }) => Promise; - }, -): Promise { - const { runId, agent, config, context, authToken } = input; - - const workspaceContext = parseObject(context.agentCompanyWorkspace); - const workspaceCwd = asString(workspaceContext.cwd, ""); - const workspaceSource = asString(workspaceContext.source, ""); - const workspaceStrategy = asString(workspaceContext.strategy, ""); - const workspaceId = asString(workspaceContext.workspaceId, "") || null; - const workspaceRepoUrl = asString(workspaceContext.repoUrl, "") || null; - const workspaceRepoRef = asString(workspaceContext.repoRef, "") || null; - const workspaceBranch = asString(workspaceContext.branchName, "") || null; - const workspaceWorktreePath = asString(workspaceContext.worktreePath, "") || null; - - const workspaceHints = Array.isArray(context.agentCompanyWorkspaces) - ? context.agentCompanyWorkspaces.filter( - (value): value is Record => typeof value === "object" && value !== null, - ) - : []; - const runtimeServiceIntents = Array.isArray(context.agentCompanyRuntimeServiceIntents) - ? context.agentCompanyRuntimeServiceIntents.filter( - (value): value is Record => typeof value === "object" && value !== null, - ) - : []; - const runtimeServices = Array.isArray(context.agentCompanyRuntimeServices) - ? context.agentCompanyRuntimeServices.filter( - (value): value is Record => typeof value === "object" && value !== null, - ) - : []; - const runtimePrimaryUrl = asString(context.agentCompanyRuntimePrimaryUrl as unknown, ""); - - const configuredCwd = asString(config.cwd, ""); - const useConfiguredInsteadOfAgentHome = workspaceSource === "agent_home" && configuredCwd.length > 0; - const effectiveWorkspaceCwd = useConfiguredInsteadOfAgentHome ? "" : workspaceCwd; - const cwd = effectiveWorkspaceCwd || configuredCwd || process.cwd(); - await opts.ensureAbsoluteDirectory(cwd, { createIfMissing: true }); - - const envConfig = parseObject(config.env); - const hasExplicitApiKey = - typeof envConfig.AGENT_COMPANY_API_KEY === "string" && envConfig.AGENT_COMPANY_API_KEY.trim().length > 0; - - const env: Record = { ...buildAgentCompanyEnv(agent) }; - env.AGENT_COMPANY_RUN_ID = runId; - - const wakeTaskId = - (typeof context.taskId === "string" && context.taskId.trim().length > 0 && context.taskId.trim()) || - (typeof context.issueId === "string" && context.issueId.trim().length > 0 && context.issueId.trim()) || - null; - const wakeReason = - typeof context.wakeReason === "string" && context.wakeReason.trim().length > 0 - ? context.wakeReason.trim() - : null; - const wakeCommentId = - (typeof context.wakeCommentId === "string" && context.wakeCommentId.trim().length > 0 && context.wakeCommentId.trim()) || - (typeof context.commentId === "string" && context.commentId.trim().length > 0 && context.commentId.trim()) || - null; - const approvalId = - typeof context.approvalId === "string" && context.approvalId.trim().length > 0 - ? context.approvalId.trim() - : null; - const approvalStatus = - typeof context.approvalStatus === "string" && context.approvalStatus.trim().length > 0 - ? context.approvalStatus.trim() - : null; - const linkedIssueIds = Array.isArray(context.issueIds) - ? context.issueIds.filter((value): value is string => typeof value === "string" && value.trim().length > 0) - : []; - - if (wakeTaskId) env.AGENT_COMPANY_TASK_ID = wakeTaskId; - if (wakeReason) env.AGENT_COMPANY_WAKE_REASON = wakeReason; - if (wakeCommentId) env.AGENT_COMPANY_WAKE_COMMENT_ID = wakeCommentId; - if (approvalId) env.AGENT_COMPANY_APPROVAL_ID = approvalId; - if (approvalStatus) env.AGENT_COMPANY_APPROVAL_STATUS = approvalStatus; - if (linkedIssueIds.length > 0) env.AGENT_COMPANY_LINKED_ISSUE_IDS = linkedIssueIds.join(","); - - if (effectiveWorkspaceCwd) env.AGENT_COMPANY_WORKSPACE_CWD = effectiveWorkspaceCwd; - if (workspaceSource) env.AGENT_COMPANY_WORKSPACE_SOURCE = workspaceSource; - if (workspaceStrategy) env.AGENT_COMPANY_WORKSPACE_STRATEGY = workspaceStrategy; - if (workspaceId) env.AGENT_COMPANY_WORKSPACE_ID = workspaceId; - if (workspaceRepoUrl) env.AGENT_COMPANY_WORKSPACE_REPO_URL = workspaceRepoUrl; - if (workspaceRepoRef) env.AGENT_COMPANY_WORKSPACE_REPO_REF = workspaceRepoRef; - if (workspaceBranch) env.AGENT_COMPANY_WORKSPACE_BRANCH = workspaceBranch; - if (workspaceWorktreePath) env.AGENT_COMPANY_WORKSPACE_WORKTREE_PATH = workspaceWorktreePath; - if (workspaceHints.length > 0) env.AGENT_COMPANY_WORKSPACES_JSON = JSON.stringify(workspaceHints); - if (runtimeServiceIntents.length > 0) env.AGENT_COMPANY_RUNTIME_SERVICE_INTENTS_JSON = JSON.stringify(runtimeServiceIntents); - if (runtimeServices.length > 0) env.AGENT_COMPANY_RUNTIME_SERVICES_JSON = JSON.stringify(runtimeServices); - if (runtimePrimaryUrl) env.AGENT_COMPANY_RUNTIME_PRIMARY_URL = runtimePrimaryUrl; - - // Merge caller-configured env overrides - for (const [key, value] of Object.entries(envConfig)) { - if (typeof value === "string") env[key] = value; - } - - if (!hasExplicitApiKey && authToken) { - env.AGENT_COMPANY_API_KEY = authToken; - } - - return { - env, - cwd, - effectiveWorkspaceCwd, - workspaceId, - workspaceRepoUrl, - workspaceRepoRef, - hasExplicitApiKey, - }; -} - -// --------------------------------------------------------------------------- -// Session resume validation -// --------------------------------------------------------------------------- - -export interface SessionResumeState { - sessionId: string | null; - runtimeSessionId: string; - runtimeSessionCwd: string; - canResumeSession: boolean; -} - -export function resolveSessionResumeState( - runtime: { sessionId?: string | null; sessionParams?: Record | null }, - cwd: string, -): SessionResumeState { - const runtimeSessionParams = parseObject(runtime.sessionParams); - const runtimeSessionId = asString(runtimeSessionParams.sessionId, runtime.sessionId ?? ""); - const runtimeSessionCwd = asString(runtimeSessionParams.cwd, ""); - const canResumeSession = - runtimeSessionId.length > 0 && - (runtimeSessionCwd.length === 0 || path.resolve(runtimeSessionCwd) === path.resolve(cwd)); - return { - sessionId: canResumeSession ? runtimeSessionId : null, - runtimeSessionId, - runtimeSessionCwd, - canResumeSession, - }; -} diff --git a/packages/adapter-utils/src/index.ts b/packages/adapter-utils/src/index.ts deleted file mode 100644 index a82746be..00000000 --- a/packages/adapter-utils/src/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -export type { - AdapterAgent, - AdapterRuntime, - UsageSummary, - AdapterBillingType, - AdapterRuntimeServiceReport, - AdapterExecutionResult, - AdapterInvocationMeta, - AdapterExecutionContext, - AdapterEnvironmentCheckLevel, - AdapterEnvironmentCheck, - AdapterEnvironmentTestStatus, - AdapterEnvironmentTestResult, - AdapterEnvironmentTestContext, - AdapterSkillSyncMode, - AdapterSkillState, - AdapterSkillOrigin, - AdapterSkillEntry, - AdapterSkillSnapshot, - AdapterSkillContext, - AdapterSessionCodec, - AdapterModel, - HireApprovedPayload, - HireApprovedHookResult, - ServerAdapterModule, - TranscriptEntry, - StdoutLineParser, - CLIAdapterModule, - CreateConfigValues, - ManagedSkillRef, -} from "./types.js"; -export { - REDACTED_HOME_PATH_USER, - redactHomePathUserSegments, - redactHomePathUserSegmentsInValue, -} from "./log-redaction.js"; -export type { - CommonAgentCompanyEnvInput, - CommonAgentCompanyEnvResult, - SessionResumeState, -} from "./execute-helpers.js"; -export { - hasNonEmptyEnvValue, - buildSkillsCandidates, - resolveSkillsDir, - parseManagedSkills, - parseExtraArgs, - buildCommonAgentCompanyEnv, - resolveSessionResumeState, -} from "./execute-helpers.js"; diff --git a/packages/adapter-utils/src/log-redaction.ts b/packages/adapter-utils/src/log-redaction.ts deleted file mode 100644 index 1d96ccbd..00000000 --- a/packages/adapter-utils/src/log-redaction.ts +++ /dev/null @@ -1,49 +0,0 @@ -export const REDACTED_HOME_PATH_USER = "[]"; - -const HOME_PATH_PATTERNS = [ - { - regex: /\/Users\/[^/\\\s]+/g, - replace: `/Users/${REDACTED_HOME_PATH_USER}`, - }, - { - regex: /\/home\/[^/\\\s]+/g, - replace: `/home/${REDACTED_HOME_PATH_USER}`, - }, - { - regex: /([A-Za-z]:\\Users\\)[^\\/\s]+/g, - replace: `$1${REDACTED_HOME_PATH_USER}`, - }, -] as const; - -function isPlainObject(value: unknown): value is Record { - if (typeof value !== "object" || value === null || Array.isArray(value)) return false; - const proto = Object.getPrototypeOf(value); - return proto === Object.prototype || proto === null; -} - -export function redactHomePathUserSegments(text: string): string { - let result = text; - for (const pattern of HOME_PATH_PATTERNS) { - result = result.replace(pattern.regex, pattern.replace); - } - return result; -} - -export function redactHomePathUserSegmentsInValue(value: T): T { - if (typeof value === "string") { - return redactHomePathUserSegments(value) as T; - } - if (Array.isArray(value)) { - return value.map((entry) => redactHomePathUserSegmentsInValue(entry)) as T; - } - if (!isPlainObject(value)) { - return value; - } - - const redacted: Record = {}; - for (const [key, entry] of Object.entries(value)) { - redacted[key] = redactHomePathUserSegmentsInValue(entry); - } - return redacted as T; -} - diff --git a/packages/adapter-utils/src/parse-utils.ts b/packages/adapter-utils/src/parse-utils.ts deleted file mode 100644 index a54ec734..00000000 --- a/packages/adapter-utils/src/parse-utils.ts +++ /dev/null @@ -1,47 +0,0 @@ -export function asRecord(value: unknown): Record | null { - if (typeof value !== "object" || value === null || Array.isArray(value)) return null; - return value as Record; -} - -export function safeJsonParse(text: string): unknown { - try { - return JSON.parse(text); - } catch { - return null; - } -} - -export function errorText(value: unknown): string { - if (typeof value === "string") return value; - const rec = asRecord(value); - if (!rec) return ""; - const msg = - (typeof rec.message === "string" && rec.message) || - (typeof rec.error === "string" && rec.error) || - (typeof rec.code === "string" && rec.code) || - ""; - if (msg) return msg; - try { - return JSON.stringify(rec); - } catch { - return ""; - } -} - -export function asString(value: unknown, fallback = ""): string { - return typeof value === "string" ? value : fallback; -} - -export function asNumber(value: unknown, fallback = 0): number { - return typeof value === "number" && Number.isFinite(value) ? value : fallback; -} - -export function stringifyUnknown(value: unknown): string { - if (typeof value === "string") return value; - if (value === null || value === undefined) return ""; - try { - return JSON.stringify(value, null, 2); - } catch { - return String(value); - } -} diff --git a/packages/adapter-utils/src/server-utils-parsers.ts b/packages/adapter-utils/src/server-utils-parsers.ts deleted file mode 100644 index 3c3391d2..00000000 --- a/packages/adapter-utils/src/server-utils-parsers.ts +++ /dev/null @@ -1,138 +0,0 @@ -export const MAX_CAPTURE_BYTES = 4 * 1024 * 1024; -export const MAX_EXCERPT_BYTES = 32 * 1024; - -const SENSITIVE_ENV_KEY = /(key|token|secret|password|passwd|authorization|cookie)/i; - -export function parseObject(value: unknown): Record { - if (typeof value !== "object" || value === null || Array.isArray(value)) { - return {}; - } - return value as Record; -} - -export function asString(value: unknown, fallback: string): string { - return typeof value === "string" && value.length > 0 ? value : fallback; -} - -export function asNumber(value: unknown, fallback: number): number { - return typeof value === "number" && Number.isFinite(value) ? value : fallback; -} - -export function asBoolean(value: unknown, fallback: boolean): boolean { - return typeof value === "boolean" ? value : fallback; -} - -export function asStringArray(value: unknown): string[] { - return Array.isArray(value) ? value.filter((item): item is string => typeof item === "string") : []; -} - -export function parseJson(value: string): Record | null { - try { - return JSON.parse(value) as Record; - } catch { - return null; - } -} - -export function appendWithCap(prev: string, chunk: string, cap = MAX_CAPTURE_BYTES) { - const combined = prev + chunk; - return combined.length > cap ? combined.slice(combined.length - cap) : combined; -} - -export function resolvePathValue(obj: Record, dottedPath: string) { - const parts = dottedPath.split("."); - let cursor: unknown = obj; - - for (const part of parts) { - if (typeof cursor !== "object" || cursor === null || Array.isArray(cursor)) { - return ""; - } - cursor = (cursor as Record)[part]; - } - - if (cursor === null || cursor === undefined) return ""; - if (typeof cursor === "string") return cursor; - if (typeof cursor === "number" || typeof cursor === "boolean") return String(cursor); - - try { - return JSON.stringify(cursor); - } catch { - return ""; - } -} - -export function renderTemplate(template: string, data: Record) { - return template.replace(/{{\s*([a-zA-Z0-9_.-]+)\s*}}/g, (_, path) => resolvePathValue(data, path)); -} - -/** - * Remove flags from `extraArgs` that the adapter will already add itself. - * Handles both `--flag value` pairs and `--flag=value` forms. - * This prevents duplicate/conflicting CLI arguments when users have shell - * aliases or wrapper functions that inject the same flags. - */ -export function filterConflictingArgs(extraArgs: string[], adapterFlags: string[]): string[] { - const flagSet = new Set(adapterFlags.map((f) => f.replace(/=.*$/, ""))); - const filtered: string[] = []; - for (let i = 0; i < extraArgs.length; i++) { - const arg = extraArgs[i]; - const bareFlag = arg.replace(/=.*$/, ""); - if (flagSet.has(bareFlag)) { - // Skip this flag and its value if the value is a separate argument - if (!arg.includes("=") && i + 1 < extraArgs.length && !extraArgs[i + 1].startsWith("-")) { - i++; // skip the value argument too - } - continue; - } - filtered.push(arg); - } - return filtered; -} - -export function redactEnvForLogs(env: Record): Record { - const redacted: Record = {}; - for (const [key, value] of Object.entries(env)) { - redacted[key] = SENSITIVE_ENV_KEY.test(key) ? "***REDACTED***" : value; - } - return redacted; -} - -export function buildAgentCompanyEnv(agent: { id: string; companyId: string }): Record { - const resolveHostForUrl = (rawHost: string): string => { - const host = rawHost.trim(); - if (!host || host === "0.0.0.0" || host === "::") return "localhost"; - if (host.includes(":") && !host.startsWith("[") && !host.endsWith("]")) return `[${host}]`; - return host; - }; - const vars: Record = { - AGENT_COMPANY_AGENT_ID: agent.id, - AGENT_COMPANY_COMPANY_ID: agent.companyId, - }; - const runtimeHost = resolveHostForUrl( - process.env.AGENT_COMPANY_LISTEN_HOST ?? process.env.HOST ?? "localhost", - ); - const runtimePort = process.env.AGENT_COMPANY_LISTEN_PORT ?? process.env.PORT ?? "3100"; - const apiUrl = process.env.AGENT_COMPANY_API_URL ?? `http://${runtimeHost}:${runtimePort}`; - vars.AGENT_COMPANY_API_URL = apiUrl; - return vars; -} - -export function defaultPathForPlatform() { - if (process.platform === "win32") { - const home = process.env.USERPROFILE ?? process.env.HOME ?? ""; - const appData = process.env.APPDATA ?? (home ? `${home}\\AppData\\Roaming` : ""); - const localAppData = process.env.LOCALAPPDATA ?? (home ? `${home}\\AppData\\Local` : ""); - const parts = [ - "C:\\Windows\\System32", - "C:\\Windows", - "C:\\Windows\\System32\\Wbem", - appData ? `${appData}\\npm` : "", - localAppData ? `${localAppData}\\pnpm` : "", - home ? `${home}\\.local\\bin` : "", - home ? `${home}\\.cargo\\bin` : "", - "C:\\Program Files\\nodejs", - ].filter(Boolean); - return parts.join(";"); - } - return "/usr/local/bin:/opt/homebrew/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin"; -} diff --git a/packages/adapter-utils/src/server-utils-process.ts b/packages/adapter-utils/src/server-utils-process.ts deleted file mode 100644 index f00b365f..00000000 --- a/packages/adapter-utils/src/server-utils-process.ts +++ /dev/null @@ -1,394 +0,0 @@ -import { spawn, spawnSync, type ChildProcess } from "node:child_process"; -import { constants as fsConstants, promises as fs } from "node:fs"; -import path from "node:path"; -import { StringDecoder } from "node:string_decoder"; -import { appendWithCap, defaultPathForPlatform } from "./server-utils-parsers.js"; - -/** - * Decode a Buffer as GBK (CP936). Used as a fallback when UTF-8 decoding - * produces replacement characters on Chinese Windows systems where the - * system ANSI code page is GBK and chcp 65001 is ineffective for piped I/O. - */ -function decodeGbkBuffer(buf: Buffer): string { - try { - return new TextDecoder("gbk").decode(buf); - } catch { - return buf.toString("utf8"); - } -} - -export interface RunProcessResult { - exitCode: number | null; - signal: string | null; - timedOut: boolean; - stdout: string; - stderr: string; -} - -interface RunningProcess { - child: ChildProcess; - graceSec: number; -} - -interface SpawnTarget { - command: string; - args: string[]; -} - -const WINDOWS_CMD_SCRIPT_EXTENSIONS = new Set([".bat", ".cmd"]); - -type ChildProcessWithEvents = ChildProcess & { - on(event: "error", listener: (err: Error) => void): ChildProcess; - on( - event: "close", - listener: (code: number | null, signal: NodeJS.Signals | null) => void, - ): ChildProcess; -}; - -export const runningProcesses = new Map(); - -export function normalizeCommandValue(command: string): string { - let normalized = command.trim(); - while (normalized.length >= 2) { - const quote = normalized[0]; - if ((quote !== '"' && quote !== "'") || normalized.at(-1) !== quote) { - break; - } - normalized = normalized.slice(1, -1).trim(); - } - return normalized; -} - -function windowsPathExts(env: NodeJS.ProcessEnv): string[] { - return (env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean); -} - -async function pathExists(candidate: string) { - try { - await fs.access(candidate, process.platform === "win32" ? fsConstants.F_OK : fsConstants.X_OK); - return true; - } catch { - return false; - } -} - -async function resolveCommandPath(command: string, cwd: string, env: NodeJS.ProcessEnv): Promise { - const normalizedCommand = normalizeCommandValue(command); - const hasPathSeparator = normalizedCommand.includes("/") || normalizedCommand.includes("\\"); - if (hasPathSeparator) { - const absolute = path.isAbsolute(normalizedCommand) ? normalizedCommand : path.resolve(cwd, normalizedCommand); - return (await pathExists(absolute)) ? absolute : null; - } - - const pathValue = env.PATH ?? env.Path ?? ""; - const delimiter = process.platform === "win32" ? ";" : ":"; - const dirs = pathValue.split(delimiter).filter(Boolean); - const exts = process.platform === "win32" ? windowsPathExts(env) : [""]; - const hasExtension = process.platform === "win32" && path.extname(command).length > 0; - - for (const dir of dirs) { - const candidates = - process.platform === "win32" - ? hasExtension - ? [path.join(dir, normalizedCommand)] - : exts.map((ext) => path.join(dir, `${normalizedCommand}${ext}`)) - : [path.join(dir, normalizedCommand)]; - for (const candidate of candidates) { - if (await pathExists(candidate)) return candidate; - } - } - - return null; -} - -function quoteForCmd(arg: string) { - if (!arg.length) return '""'; - const escaped = arg.replace(/"/g, '""'); - return /[\s"&<>|^()]/.test(escaped) ? `"${escaped}"` : escaped; -} - -export function buildWindowsSpawnTarget( - executable: string, - args: string[], - shell: string, -): SpawnTarget { - const extension = path.extname(executable).toLowerCase(); - if (!WINDOWS_CMD_SCRIPT_EXTENSIONS.has(extension)) { - return { command: executable, args }; - } - const commandLine = [quoteForCmd(executable), ...args.map(quoteForCmd)].join(" "); - return { - command: shell, - args: ["/d", "/c", `chcp 65001 >nul && ${commandLine}`], - }; -} - -export async function resolveSpawnTarget( - command: string, - args: string[], - cwd: string, - env: NodeJS.ProcessEnv, -): Promise { - const normalizedCommand = normalizeCommandValue(command); - const resolved = await resolveCommandPath(normalizedCommand, cwd, env); - const executable = resolved ?? normalizedCommand; - - if (process.platform !== "win32") { - return { command: executable, args }; - } - - // On Windows, ALL spawned processes need UTF-8 code page (65001) to prevent - // Chinese/CJK character corruption. The default Windows code page (e.g. 936/GBK) - // corrupts multi-byte UTF-8 characters passed through cmd.exe, curl, etc. - const shell = env.ComSpec || process.env.ComSpec || "cmd.exe"; - return buildWindowsSpawnTarget(executable, args, shell); -} - -export function ensurePathInEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv { - if (typeof env.PATH === "string" && env.PATH.length > 0) return env; - if (typeof env.Path === "string" && env.Path.length > 0) return env; - return { ...env, PATH: defaultPathForPlatform() }; -} - -export async function ensureAbsoluteDirectory( - cwd: string, - opts: { createIfMissing?: boolean } = {}, -) { - if (!path.isAbsolute(cwd)) { - throw new Error(`Working directory must be an absolute path: "${cwd}"`); - } - - const assertDirectory = async () => { - const stats = await fs.stat(cwd); - if (!stats.isDirectory()) { - throw new Error(`Working directory is not a directory: "${cwd}"`); - } - }; - - try { - await assertDirectory(); - return; - } catch (err) { - const code = (err as NodeJS.ErrnoException).code; - if (!opts.createIfMissing || code !== "ENOENT") { - if (code === "ENOENT") { - throw new Error(`Working directory does not exist: "${cwd}"`); - } - throw err instanceof Error ? err : new Error(String(err)); - } - } - - try { - await fs.mkdir(cwd, { recursive: true }); - await assertDirectory(); - } catch (err) { - const reason = err instanceof Error ? err.message : String(err); - throw new Error(`Could not create working directory "${cwd}": ${reason}`); - } -} - -export async function ensureCommandResolvable(command: string, cwd: string, env: NodeJS.ProcessEnv) { - const normalizedCommand = normalizeCommandValue(command); - const resolved = await resolveCommandPath(normalizedCommand, cwd, env); - if (resolved) return; - if (normalizedCommand.includes("/") || normalizedCommand.includes("\\")) { - const absolute = path.isAbsolute(normalizedCommand) ? normalizedCommand : path.resolve(cwd, normalizedCommand); - throw new Error(`Command is not executable: "${command}" (resolved: "${absolute}")`); - } - throw new Error(`Command not found in PATH: "${command}"`); -} - -export async function runChildProcess( - runId: string, - command: string, - args: string[], - opts: { - cwd: string; - env: Record; - timeoutSec: number; - graceSec: number; - onLog: (stream: "stdout" | "stderr", chunk: string) => Promise; - onLogError?: (err: unknown, runId: string, message: string) => void; - stdin?: string; - }, -): Promise { - const onLogError = opts.onLogError ?? ((err, id, msg) => console.warn({ err, runId: id }, msg)); - - return new Promise((resolve, reject) => { - const rawMerged: NodeJS.ProcessEnv = { ...opts.env }; - - // Strip Claude Code nesting-guard env vars so spawned `claude` processes - // don't refuse to start with "cannot be launched inside another session". - // These vars leak in when the AgentCompany server itself is started from - // within a Claude Code session (e.g. `npx agentcompany run` in a terminal - // owned by Claude Code) or when cron inherits a contaminated shell env. - const CLAUDE_CODE_NESTING_VARS = [ - "CLAUDECODE", - "CLAUDE_CODE_ENTRYPOINT", - "CLAUDE_CODE_SESSION", - "CLAUDE_CODE_PARENT_SESSION", - ] as const; - for (const key of CLAUDE_CODE_NESTING_VARS) { - delete rawMerged[key]; - } - - const mergedEnv = ensurePathInEnv(rawMerged); - // On Windows, force UTF-8 encoding in child processes to prevent Chinese/CJK - // character corruption caused by the default system code page (e.g. 936/GBK). - if (process.platform === "win32") { - mergedEnv.PYTHONUTF8 = "1"; - mergedEnv.PYTHONIOENCODING = "utf-8"; - if (!mergedEnv.LANG) mergedEnv.LANG = "en_US.UTF-8"; - } - - void resolveSpawnTarget(command, args, opts.cwd, mergedEnv) - .then((target) => { - const child = spawn(target.command, target.args, { - cwd: opts.cwd, - env: mergedEnv, - shell: false, - windowsHide: true, - stdio: [opts.stdin != null ? "pipe" : "ignore", "pipe", "pipe"], - }) as ChildProcessWithEvents; - - if (opts.stdin != null && child.stdin) { - child.stdin.write(opts.stdin); - child.stdin.end(); - } - - runningProcesses.set(runId, { child, graceSec: opts.graceSec }); - - let timedOut = false; - let stdout = ""; - let stderr = ""; - let logChain: Promise = Promise.resolve(); - - // Use StringDecoder to handle multi-byte characters split across chunks. - // On Windows, child process stdout may arrive in GBK (CP936) instead - // of UTF-8 when chcp 65001 is ineffective (piped stdout has no console). - // We detect this per-stream and fall back to GBK decoding if needed. - const stdoutDecoder = new StringDecoder("utf8"); - const stderrDecoder = new StringDecoder("utf8"); - let stdoutIsGbk = false; - let stderrIsGbk = false; - - const timeout = - opts.timeoutSec > 0 - ? setTimeout(() => { - timedOut = true; - child.kill("SIGTERM"); - setTimeout(() => { - if (!child.killed) { - child.kill("SIGKILL"); - } - }, Math.max(1, opts.graceSec) * 1000); - }, opts.timeoutSec * 1000) - : null; - - child.stdout?.on("data", (chunk: unknown) => { - let text: string; - if (chunk instanceof Buffer) { - if (stdoutIsGbk) { - text = decodeGbkBuffer(chunk); - } else { - text = stdoutDecoder.write(chunk); - if (text.includes("\ufffd") && chunk.length > 0) { - stdoutIsGbk = true; - text = decodeGbkBuffer(chunk); - } - } - } else { - text = String(chunk); - } - stdout = appendWithCap(stdout, text); - logChain = logChain - .then(() => opts.onLog("stdout", text)) - .catch((err) => onLogError(err, runId, "failed to append stdout log chunk")); - }); - - child.stderr?.on("data", (chunk: unknown) => { - let text: string; - if (chunk instanceof Buffer) { - if (stderrIsGbk) { - text = decodeGbkBuffer(chunk); - } else { - text = stderrDecoder.write(chunk); - if (text.includes("\ufffd") && chunk.length > 0) { - stderrIsGbk = true; - text = decodeGbkBuffer(chunk); - } - } - } else { - text = String(chunk); - } - stderr = appendWithCap(stderr, text); - logChain = logChain - .then(() => opts.onLog("stderr", text)) - .catch((err) => onLogError(err, runId, "failed to append stderr log chunk")); - }); - - child.on("error", (err: Error) => { - if (timeout) clearTimeout(timeout); - runningProcesses.delete(runId); - const errno = (err as NodeJS.ErrnoException).code; - const pathValue = mergedEnv.PATH ?? mergedEnv.Path ?? ""; - const msg = - errno === "ENOENT" - ? `Failed to start command "${command}" in "${opts.cwd}". Verify adapter command, working directory, and PATH (${pathValue}).` - : `Failed to start command "${command}" in "${opts.cwd}": ${err.message}`; - reject(new Error(msg)); - }); - - child.on("close", (code: number | null, signal: NodeJS.Signals | null) => { - if (timeout) clearTimeout(timeout); - runningProcesses.delete(runId); - // Flush any remaining partial multi-byte characters from the decoders. - const stdoutTail = stdoutDecoder.end(); - const stderrTail = stderrDecoder.end(); - if (stdoutTail) stdout = appendWithCap(stdout, stdoutTail); - if (stderrTail) stderr = appendWithCap(stderr, stderrTail); - void logChain.finally(() => { - resolve({ - exitCode: code, - signal, - timedOut, - stdout, - stderr, - }); - }); - }); - }) - .catch(reject); - }); -} - -/** - * Kill a process and all its descendants. - * Windows: `taskkill /T /F` kills the full process tree. - * Unix: SIGKILL the process directly (CLI tools are leaf processes). - */ -function killProcessTree(pid: number): void { - if (process.platform === "win32") { - try { - spawnSync("taskkill", ["/T", "/F", "/PID", String(pid)], { stdio: "ignore", timeout: 5000 }); - } catch { /* process already exited */ } - } else { - try { - process.kill(pid, "SIGKILL"); - } catch { /* already dead */ } - } -} - -/** - * Force-kill every child process tracked in `runningProcesses` and clear the map. - * Called by the worker during shutdown to ensure no CLI processes survive app quit. - */ -export function shutdownAllRunning(): void { - for (const [runId, entry] of runningProcesses) { - const pid = entry.child.pid; - if (pid != null) { - killProcessTree(pid); - } - runningProcesses.delete(runId); - } -} diff --git a/packages/adapter-utils/src/server-utils-skills-sync.ts b/packages/adapter-utils/src/server-utils-skills-sync.ts deleted file mode 100644 index 43a7cc78..00000000 --- a/packages/adapter-utils/src/server-utils-skills-sync.ts +++ /dev/null @@ -1,305 +0,0 @@ -import { promises as fs } from "node:fs"; -import path from "node:path"; -import type { AdapterSkillEntry, AdapterSkillSnapshot } from "./types.js"; -import type { AgentCompanySkillEntry, InstalledSkillTarget } from "./server-utils-skills.js"; - -interface PersistentSkillSnapshotOptions { - adapterType: string; - availableEntries: AgentCompanySkillEntry[]; - desiredSkills: string[]; - installed: Map; - skillsHome: string; - locationLabel?: string | null; - installedDetail?: string | null; - missingDetail: string; - externalConflictDetail: string; - externalDetail: string; - warnings?: string[]; -} - -function normalizePathSlashes(value: string): string { - return value.replaceAll("\\", "/"); -} - -function isMaintainerOnlySkillTarget(candidate: string): boolean { - return normalizePathSlashes(candidate).includes("/.agents/skills/"); -} - -function skillLocationLabel(value: string | null | undefined): string | null { - if (typeof value !== "string") return null; - const trimmed = value.trim(); - return trimmed.length > 0 ? trimmed : null; -} - -function buildManagedSkillOrigin(entry: { required?: boolean }): Pick< - AdapterSkillEntry, - "origin" | "originLabel" | "readOnly" -> { - if (entry.required) { - return { - origin: "paperclip_required", - originLabel: "Required by AgentCompany", - readOnly: false, - }; - } - return { - origin: "company_managed", - originLabel: "Managed by AgentCompany", - readOnly: false, - }; -} - -function canonicalizeDesiredAgentCompanySkillReference( - reference: string, - availableEntries: Array<{ key: string; runtimeName?: string | null }>, -): string { - const normalizedReference = reference.trim().toLowerCase(); - if (!normalizedReference) return ""; - - const exactKey = availableEntries.find((entry) => entry.key.trim().toLowerCase() === normalizedReference); - if (exactKey) return exactKey.key; - - const byRuntimeName = availableEntries.filter((entry) => - typeof entry.runtimeName === "string" && entry.runtimeName.trim().toLowerCase() === normalizedReference, - ); - if (byRuntimeName.length === 1) return byRuntimeName[0]!.key; - - const slugMatches = availableEntries.filter((entry) => - entry.key.trim().toLowerCase().split("/").pop() === normalizedReference, - ); - if (slugMatches.length === 1) return slugMatches[0]!.key; - - return normalizedReference; -} - -/** - * Build an AdapterSkillSnapshot for persistent-mode adapters (Gemini, Codex). - * Compares available entries against installed state and desired skill list. - */ -export function buildPersistentSkillSnapshot( - options: PersistentSkillSnapshotOptions, -): AdapterSkillSnapshot { - const { - adapterType, - availableEntries, - desiredSkills, - installed, - skillsHome, - locationLabel, - installedDetail, - missingDetail, - externalConflictDetail, - externalDetail, - } = options; - const availableByKey = new Map(availableEntries.map((entry) => [entry.key, entry])); - const desiredSet = new Set(desiredSkills); - const entries: AdapterSkillEntry[] = []; - const warnings = [...(options.warnings ?? [])]; - - for (const available of availableEntries) { - const installedEntry = installed.get(available.runtimeName) ?? null; - const desired = desiredSet.has(available.key); - let state: AdapterSkillEntry["state"] = "available"; - let managed = false; - let detail: string | null = null; - - if (installedEntry?.targetPath === available.source) { - managed = true; - state = desired ? "installed" : "stale"; - detail = installedDetail ?? null; - } else if (installedEntry) { - state = "external"; - detail = desired ? externalConflictDetail : externalDetail; - } else if (desired) { - state = "missing"; - detail = missingDetail; - } - - entries.push({ - key: available.key, - runtimeName: available.runtimeName, - desired, - managed, - state, - sourcePath: available.source, - targetPath: path.join(skillsHome, available.runtimeName), - detail, - required: Boolean(available.required), - requiredReason: available.requiredReason ?? null, - ...buildManagedSkillOrigin(available), - }); - } - - for (const desiredSkill of desiredSkills) { - if (availableByKey.has(desiredSkill)) continue; - warnings.push(`Desired skill "${desiredSkill}" is not available from the AgentCompany skills directory.`); - entries.push({ - key: desiredSkill, - runtimeName: null, - desired: true, - managed: true, - state: "missing", - sourcePath: null, - targetPath: null, - detail: "AgentCompany cannot find this skill in the local runtime skills directory.", - origin: "external_unknown", - originLabel: "External or unavailable", - readOnly: false, - }); - } - - for (const [name, installedEntry] of installed.entries()) { - if (availableEntries.some((entry) => entry.runtimeName === name)) continue; - entries.push({ - key: name, - runtimeName: name, - desired: false, - managed: false, - state: "external", - origin: "user_installed", - originLabel: "User-installed", - locationLabel: skillLocationLabel(locationLabel), - readOnly: true, - sourcePath: null, - targetPath: installedEntry.targetPath ?? path.join(skillsHome, name), - detail: externalDetail, - }); - } - - entries.sort((left, right) => left.key.localeCompare(right.key)); - - return { - adapterType, - supported: true, - mode: "persistent", - desiredSkills, - entries, - warnings, - }; -} - -/** - * Read the desired skill sync preference from adapter config. - */ -export function readAgentCompanySkillSyncPreference(config: Record): { - explicit: boolean; - desiredSkills: string[]; -} { - const raw = config.agentCompanySkillSync; - if (typeof raw !== "object" || raw === null || Array.isArray(raw)) { - return { explicit: false, desiredSkills: [] }; - } - const syncConfig = raw as Record; - const desiredValues = syncConfig.desiredSkills; - const desired = Array.isArray(desiredValues) - ? desiredValues - .filter((value): value is string => typeof value === "string") - .map((value) => value.trim()) - .filter(Boolean) - : []; - return { - explicit: Object.prototype.hasOwnProperty.call(raw, "desiredSkills"), - desiredSkills: Array.from(new Set(desired)), - }; -} - -/** - * Resolve the canonical desired skill list from config and available entries. - * Required skills are always included; explicit preferences are canonicalized. - */ -export function resolveAgentCompanyDesiredSkillNames( - config: Record, - availableEntries: Array<{ key: string; runtimeName?: string | null; required?: boolean }>, -): string[] { - const preference = readAgentCompanySkillSyncPreference(config); - const requiredSkills = availableEntries - .filter((entry) => entry.required) - .map((entry) => entry.key); - if (!preference.explicit) { - return Array.from(new Set(requiredSkills)); - } - const desiredSkills = preference.desiredSkills - .map((reference) => canonicalizeDesiredAgentCompanySkillReference(reference, availableEntries)) - .filter(Boolean); - return Array.from(new Set([...requiredSkills, ...desiredSkills])); -} - -/** - * Create or repair a symlink from source to target skill directory. - * Returns the action taken: "created", "repaired", or "skipped". - */ -export async function ensureAgentCompanySkillSymlink( - source: string, - target: string, - linkSkill: (source: string, target: string) => Promise = (linkSource, linkTarget) => - fs.symlink(linkSource, linkTarget), -): Promise<"created" | "repaired" | "skipped"> { - const existing = await fs.lstat(target).catch(() => null); - if (!existing) { - await linkSkill(source, target); - return "created"; - } - - if (!existing.isSymbolicLink()) { - return "skipped"; - } - - const linkedPath = await fs.readlink(target).catch(() => null); - if (!linkedPath) return "skipped"; - - const resolvedLinkedPath = path.resolve(path.dirname(target), linkedPath); - if (resolvedLinkedPath === source) { - return "skipped"; - } - - const linkedPathExists = await fs.stat(resolvedLinkedPath).then(() => true).catch(() => false); - if (linkedPathExists) { - return "skipped"; - } - - await fs.unlink(target); - await linkSkill(source, target); - return "repaired"; -} - -/** - * Remove symlinks in skillsHome that point to maintainer-only paths - * (.agents/skills/) and are not in the allowed set. - */ -export async function removeMaintainerOnlySkillSymlinks( - skillsHome: string, - allowedSkillNames: Iterable, -): Promise { - const allowed = new Set(Array.from(allowedSkillNames)); - try { - const entries = await fs.readdir(skillsHome, { withFileTypes: true }); - const removed: string[] = []; - for (const entry of entries) { - if (allowed.has(entry.name)) continue; - - const target = path.join(skillsHome, entry.name); - const existing = await fs.lstat(target).catch(() => null); - if (!existing?.isSymbolicLink()) continue; - - const linkedPath = await fs.readlink(target).catch(() => null); - if (!linkedPath) continue; - - const resolvedLinkedPath = path.isAbsolute(linkedPath) - ? linkedPath - : path.resolve(path.dirname(target), linkedPath); - if ( - !isMaintainerOnlySkillTarget(linkedPath) && - !isMaintainerOnlySkillTarget(resolvedLinkedPath) - ) { - continue; - } - - await fs.unlink(target); - removed.push(entry.name); - } - - return removed; - } catch { - return []; - } -} diff --git a/packages/adapter-utils/src/server-utils-skills.ts b/packages/adapter-utils/src/server-utils-skills.ts deleted file mode 100644 index f240b571..00000000 --- a/packages/adapter-utils/src/server-utils-skills.ts +++ /dev/null @@ -1,176 +0,0 @@ -import { promises as fs, type Dirent } from "node:fs"; -import path from "node:path"; -import type { ManagedSkillRef } from "./types.js"; -import { parseObject, asString, asBoolean } from "./server-utils-parsers.js"; - -/** - * Create symlinks for managed skills in the target directory. - * Per D-13: uses 'junction' type on Windows to avoid Developer Mode requirement. - * Individual skill symlink failures are logged and reported but do not block other skills. - */ -export async function createManagedSkillSymlinks( - managedSkills: ManagedSkillRef[], - targetDir: string, - onLog: (stream: "stdout" | "stderr", chunk: string) => Promise, -): Promise { - await fs.mkdir(targetDir, { recursive: true }); - const symlinkType = process.platform === "win32" ? ("junction" as const) : undefined; - for (const skill of managedSkills) { - const target = path.join(targetDir, skill.runtimeName); - const existing = await fs.lstat(target).catch(() => null); - if (existing) { - await fs.rm(target, { recursive: true, force: true }); - } - try { - await fs.symlink(skill.sourcePath, target, symlinkType); - await onLog("stderr", `[agent-company] Injected managed skill "${skill.runtimeName}"\n`); - } catch (err) { - await onLog( - "stderr", - `[agent-company] Failed to inject skill "${skill.runtimeName}": ${err instanceof Error ? err.message : String(err)}\n`, - ); - } - } -} - -// --------------------------------------------------------------------------- -// Skill resolution helpers -- ported from Paperclip reference with -// AgentCompany naming. These utilities let each adapter discover, list, -// resolve, and synchronize skills from a shared skills directory. -// --------------------------------------------------------------------------- - -export const AGENTCOMPANY_SKILL_ROOT_RELATIVE_CANDIDATES = [ - "../../skills", - "../../../../../skills", -]; - -export interface AgentCompanySkillEntry { - key: string; - runtimeName: string; - source: string; - required?: boolean; - requiredReason?: string | null; -} - -export interface InstalledSkillTarget { - targetPath: string | null; - kind: "symlink" | "directory" | "file"; -} - -export function resolveInstalledEntryTarget( - skillsHome: string, - entryName: string, - dirent: Dirent, - linkedPath: string | null, -): InstalledSkillTarget { - const fullPath = path.join(skillsHome, entryName); - if (dirent.isSymbolicLink()) { - return { - targetPath: linkedPath ? path.resolve(path.dirname(fullPath), linkedPath) : null, - kind: "symlink", - }; - } - if (dirent.isDirectory()) { - return { targetPath: fullPath, kind: "directory" }; - } - return { targetPath: fullPath, kind: "file" }; -} - -export function normalizeConfiguredAgentCompanyRuntimeSkills(value: unknown): AgentCompanySkillEntry[] { - if (!Array.isArray(value)) return []; - const out: AgentCompanySkillEntry[] = []; - for (const rawEntry of value) { - const entry = parseObject(rawEntry); - const key = asString(entry.key, asString(entry.name, "")).trim(); - const runtimeName = asString(entry.runtimeName, asString(entry.name, "")).trim(); - const source = asString(entry.source, "").trim(); - if (!key || !runtimeName || !source) continue; - out.push({ - key, - runtimeName, - source, - required: asBoolean(entry.required, false), - requiredReason: - typeof entry.requiredReason === "string" && entry.requiredReason.trim().length > 0 - ? entry.requiredReason.trim() - : null, - }); - } - return out; -} - -/** - * Resolve the AgentCompany skills root directory from relative path candidates. - */ -export async function resolveAgentCompanySkillsDir( - moduleDir: string, - additionalCandidates: string[] = [], -): Promise { - const candidates = [ - ...AGENTCOMPANY_SKILL_ROOT_RELATIVE_CANDIDATES.map((relativePath) => path.resolve(moduleDir, relativePath)), - ...additionalCandidates.map((candidate) => path.resolve(candidate)), - ]; - const seenRoots = new Set(); - - for (const root of candidates) { - if (seenRoots.has(root)) continue; - seenRoots.add(root); - const isDirectory = await fs.stat(root).then((stats) => stats.isDirectory()).catch(() => false); - if (isDirectory) return root; - } - - return null; -} - -/** - * List skill entries from the AgentCompany skills directory. - */ -export async function listAgentCompanySkillEntries( - moduleDir: string, - additionalCandidates: string[] = [], -): Promise { - const root = await resolveAgentCompanySkillsDir(moduleDir, additionalCandidates); - if (!root) return []; - - try { - const entries = await fs.readdir(root, { withFileTypes: true }); - return entries - .filter((entry) => entry.isDirectory()) - .map((entry) => ({ - key: `agentcompany/agentcompany/${entry.name}`, - runtimeName: entry.name, - source: path.join(root, entry.name), - required: true, - requiredReason: "Bundled AgentCompany skills are always available for local adapters.", - })); - } catch { - return []; - } -} - -/** - * Read installed skill targets from a skill home directory (symlinks, dirs, files). - */ -export async function readInstalledSkillTargets(skillsHome: string): Promise> { - const entries = await fs.readdir(skillsHome, { withFileTypes: true }).catch(() => []); - const out = new Map(); - for (const entry of entries) { - const fullPath = path.join(skillsHome, entry.name); - const linkedPath = entry.isSymbolicLink() ? await fs.readlink(fullPath).catch(() => null) : null; - out.set(entry.name, resolveInstalledEntryTarget(skillsHome, entry.name, entry, linkedPath)); - } - return out; -} - -/** - * Read runtime skill entries from adapter config or discover from module directory. - */ -export async function readAgentCompanyRuntimeSkillEntries( - config: Record, - moduleDir: string, - additionalCandidates: string[] = [], -): Promise { - const configuredEntries = normalizeConfiguredAgentCompanyRuntimeSkills(config.agentCompanyRuntimeSkills); - if (configuredEntries.length > 0) return configuredEntries; - return listAgentCompanySkillEntries(moduleDir, additionalCandidates); -} diff --git a/packages/adapter-utils/src/server-utils.ts b/packages/adapter-utils/src/server-utils.ts deleted file mode 100644 index bda42b6c..00000000 --- a/packages/adapter-utils/src/server-utils.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./server-utils-parsers.js"; -export * from "./server-utils-process.js"; -export * from "./server-utils-skills.js"; -export * from "./server-utils-skills-sync.js"; diff --git a/packages/adapter-utils/src/session-codec.ts b/packages/adapter-utils/src/session-codec.ts deleted file mode 100644 index d813984c..00000000 --- a/packages/adapter-utils/src/session-codec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { AdapterSessionCodec } from "./types.js"; - -function readNonEmptyString(value: unknown): string | null { - return typeof value === "string" && value.trim().length > 0 ? value.trim() : null; -} - -interface SessionCodecOptions { - /** Additional key aliases for sessionId beyond "sessionId" and "session_id" (e.g. "sessionID" for Gemini/OpenCode). */ - extraSessionIdKeys?: string[]; -} - -/** - * Creates a standard session codec shared across adapters. - * All adapters use the same serialize/deserialize/getDisplayId logic, - * differing only in which keys they accept for sessionId. - */ -export function createStandardSessionCodec(options?: SessionCodecOptions): AdapterSessionCodec { - const extraKeys = options?.extraSessionIdKeys ?? []; - - function readSessionId(record: Record): string | null { - return ( - readNonEmptyString(record.sessionId) ?? - readNonEmptyString(record.session_id) ?? - extraKeys.reduce((found, key) => found ?? readNonEmptyString(record[key]), null) - ); - } - - function extractFields(record: Record) { - const sessionId = readSessionId(record); - if (!sessionId) return null; - const cwd = - readNonEmptyString(record.cwd) ?? - readNonEmptyString(record.workdir) ?? - readNonEmptyString(record.folder); - const workspaceId = readNonEmptyString(record.workspaceId) ?? readNonEmptyString(record.workspace_id); - const repoUrl = readNonEmptyString(record.repoUrl) ?? readNonEmptyString(record.repo_url); - const repoRef = readNonEmptyString(record.repoRef) ?? readNonEmptyString(record.repo_ref); - return { - sessionId, - ...(cwd ? { cwd } : {}), - ...(workspaceId ? { workspaceId } : {}), - ...(repoUrl ? { repoUrl } : {}), - ...(repoRef ? { repoRef } : {}), - }; - } - - return { - deserialize(raw: unknown) { - if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null; - return extractFields(raw as Record); - }, - serialize(params: Record | null) { - if (!params) return null; - return extractFields(params); - }, - getDisplayId(params: Record | null) { - if (!params) return null; - return readSessionId(params); - }, - }; -} diff --git a/packages/adapter-utils/src/test-utils.ts b/packages/adapter-utils/src/test-utils.ts deleted file mode 100644 index d600b651..00000000 --- a/packages/adapter-utils/src/test-utils.ts +++ /dev/null @@ -1,37 +0,0 @@ -import path from "node:path"; -import type { AdapterEnvironmentCheck, AdapterEnvironmentTestResult } from "./types.js"; -import { normalizeCommandValue } from "./server-utils-process.js"; - -export function summarizeStatus(checks: AdapterEnvironmentCheck[]): AdapterEnvironmentTestResult["status"] { - if (checks.some((check) => check.level === "error")) return "fail"; - if (checks.some((check) => check.level === "warn")) return "warn"; - return "pass"; -} - -export function isNonEmpty(value: unknown): value is string { - return typeof value === "string" && value.trim().length > 0; -} - -export function firstNonEmptyLine(text: string): string { - return ( - text - .split(/\r?\n/) - .map((line) => line.trim()) - .find(Boolean) ?? "" - ); -} - -export function commandLooksLike(command: string, expected: string): boolean { - const normalized = normalizeCommandValue(command).replace(/\\/g, "/"); - const base = path.posix.basename(normalized).toLowerCase(); - return base === expected || base === `${expected}.cmd` || base === `${expected}.exe`; -} - -export function summarizeProbeDetail(stdout: string, stderr: string, parsedError?: string | null): string | null { - const raw = parsedError?.trim() || firstNonEmptyLine(stderr) || firstNonEmptyLine(stdout); - if (!raw) return null; - const clean = raw.replace(/\s+/g, " ").trim(); - const max = 240; - return clean.length > max ? `${clean.slice(0, max - 1)}…` : clean; -} - diff --git a/packages/adapter-utils/src/types.ts b/packages/adapter-utils/src/types.ts deleted file mode 100644 index 064a67bf..00000000 --- a/packages/adapter-utils/src/types.ts +++ /dev/null @@ -1,291 +0,0 @@ -export interface AdapterAgent { - id: string; - companyId: string; - name: string; - adapterType: string | null; - adapterConfig: unknown; -} - -export interface AdapterRuntime { - /** - * Legacy single session id view. Prefer `sessionParams` + `sessionDisplayId`. - */ - sessionId: string | null; - sessionParams: Record | null; - sessionDisplayId: string | null; - taskKey: string | null; -} - -export interface UsageSummary { - inputTokens: number; - outputTokens: number; - cachedInputTokens?: number; -} - -export type AdapterBillingType = "api" | "subscription" | "unknown"; - -export interface AdapterRuntimeServiceReport { - id?: string | null; - projectId?: string | null; - projectWorkspaceId?: string | null; - issueId?: string | null; - scopeType?: "project_workspace" | "execution_workspace" | "run" | "agent"; - scopeId?: string | null; - serviceName: string; - status?: "starting" | "running" | "stopped" | "failed"; - lifecycle?: "shared" | "ephemeral"; - reuseKey?: string | null; - command?: string | null; - cwd?: string | null; - port?: number | null; - url?: string | null; - providerRef?: string | null; - ownerAgentId?: string | null; - stopPolicy?: Record | null; - healthStatus?: "unknown" | "healthy" | "unhealthy"; -} - -export interface AdapterExecutionResult { - exitCode: number | null; - signal: string | null; - timedOut: boolean; - errorMessage?: string | null; - errorCode?: string | null; - errorMeta?: Record; - usage?: UsageSummary; - /** - * Legacy single session id output. Prefer `sessionParams` + `sessionDisplayId`. - */ - sessionId?: string | null; - sessionParams?: Record | null; - sessionDisplayId?: string | null; - provider?: string | null; - model?: string | null; - billingType?: AdapterBillingType | null; - costUsd?: number | null; - resultJson?: Record | null; - runtimeServices?: AdapterRuntimeServiceReport[]; - summary?: string | null; - clearSession?: boolean; - question?: { - prompt: string; - choices: Array<{ - key: string; - label: string; - description?: string; - }>; - } | null; -} - -export interface AdapterSessionCodec { - deserialize(raw: unknown): Record | null; - serialize(params: Record | null): Record | null; - getDisplayId?: (params: Record | null) => string | null; -} - -export interface AdapterInvocationMeta { - adapterType: string; - command: string; - cwd?: string; - commandArgs?: string[]; - commandNotes?: string[]; - env?: Record; - prompt?: string; - context?: Record; -} - -export interface AdapterExecutionContext { - runId: string; - agent: AdapterAgent; - runtime: AdapterRuntime; - config: Record; - context: Record; - onLog: (stream: "stdout" | "stderr", chunk: string) => Promise; - onMeta?: (meta: AdapterInvocationMeta) => Promise; - authToken?: string; -} - -export interface AdapterModel { - id: string; - label: string; -} - -export type AdapterEnvironmentCheckLevel = "info" | "warn" | "error"; - -export interface AdapterEnvironmentCheck { - code: string; - level: AdapterEnvironmentCheckLevel; - message: string; - detail?: string | null; - hint?: string | null; -} - -export type AdapterEnvironmentTestStatus = "pass" | "warn" | "fail"; - -export interface AdapterEnvironmentTestResult { - adapterType: string; - status: AdapterEnvironmentTestStatus; - checks: AdapterEnvironmentCheck[]; - testedAt: string; -} - -export type AdapterSkillSyncMode = "unsupported" | "persistent" | "ephemeral"; - -export type AdapterSkillState = - | "available" - | "configured" - | "installed" - | "missing" - | "stale" - | "external"; - -export type AdapterSkillOrigin = - | "company_managed" - | "paperclip_required" - | "user_installed" - | "external_unknown"; - -export interface AdapterSkillEntry { - key: string; - runtimeName: string | null; - desired: boolean; - managed: boolean; - required?: boolean; - requiredReason?: string | null; - state: AdapterSkillState; - origin?: AdapterSkillOrigin; - originLabel?: string | null; - locationLabel?: string | null; - readOnly?: boolean; - sourcePath?: string | null; - targetPath?: string | null; - detail?: string | null; -} - -export interface AdapterSkillSnapshot { - adapterType: string; - supported: boolean; - mode: AdapterSkillSyncMode; - desiredSkills: string[]; - entries: AdapterSkillEntry[]; - warnings: string[]; -} - -export interface AdapterSkillContext { - agentId: string; - companyId: string; - adapterType: string; - config: Record; -} - -export interface AdapterEnvironmentTestContext { - companyId: string; - adapterType: string; - config: Record; - deployment?: { - mode?: "local_trusted" | "authenticated"; - exposure?: "private" | "public"; - bindHost?: string | null; - allowedHostnames?: string[]; - }; -} - -/** Payload for the onHireApproved adapter lifecycle hook (e.g. join-request or hire_agent approval). */ -export interface HireApprovedPayload { - companyId: string; - agentId: string; - agentName: string; - adapterType: string; - /** "join_request" | "approval" */ - source: "join_request" | "approval"; - sourceId: string; - approvedAt: string; - /** Canonical operator-facing message for cloud adapters to show the user. */ - message: string; -} - -/** Result of onHireApproved hook; failures are non-fatal to the approval flow. */ -export interface HireApprovedHookResult { - ok: boolean; - error?: string; - detail?: Record; -} - -export interface ServerAdapterModule { - type: string; - execute(ctx: AdapterExecutionContext): Promise; - testEnvironment(ctx: AdapterEnvironmentTestContext): Promise; - listSkills?: (ctx: AdapterSkillContext) => Promise; - syncSkills?: (ctx: AdapterSkillContext, desiredSkills: string[]) => Promise; - sessionCodec?: AdapterSessionCodec; - supportsLocalAgentJwt?: boolean; - models?: AdapterModel[]; - listModels?: () => Promise; - agentConfigurationDoc?: string; - /** Per D-04: If true, adapter manages its own context window (e.g. Claude, Codex). Session rotation is skipped but usage is still tracked. */ - nativeContextManagement?: boolean; - /** - * Optional lifecycle hook when an agent is approved/hired (join-request or hire_agent approval). - * adapterConfig is the agent's adapter config so the adapter can e.g. send a callback to a configured URL. - */ - onHireApproved?: ( - payload: HireApprovedPayload, - adapterConfig: Record, - ) => Promise; -} - -export type TranscriptEntry = - | { kind: "assistant"; ts: string; text: string; delta?: boolean } - | { kind: "thinking"; ts: string; text: string; delta?: boolean } - | { kind: "user"; ts: string; text: string } - | { kind: "tool_call"; ts: string; name: string; input: unknown; toolUseId?: string } - | { kind: "tool_result"; ts: string; toolUseId: string; content: string; isError: boolean } - | { kind: "init"; ts: string; model: string; sessionId: string } - | { kind: "result"; ts: string; text: string; inputTokens: number; outputTokens: number; cachedTokens: number; costUsd: number; subtype: string; isError: boolean; errors: string[] } - | { kind: "stderr"; ts: string; text: string } - | { kind: "system"; ts: string; text: string } - | { kind: "stdout"; ts: string; text: string }; - -export type StdoutLineParser = (line: string, ts: string) => TranscriptEntry[]; - -export interface CLIAdapterModule { - type: string; - formatStdoutEvent: (line: string, debug: boolean) => void; -} - -/** Skill reference passed from main process to worker for adapter injection. */ -export interface ManagedSkillRef { - /** Skill slug used as directory name in the adapter's skill directory */ - runtimeName: string; - /** Absolute path to the materialized skill directory on disk */ - sourcePath: string; -} - -export interface CreateConfigValues { - adapterType: string; - cwd: string; - instructionsFilePath?: string; - promptTemplate: string; - model: string; - thinkingEffort: string; - chrome: boolean; - dangerouslySkipPermissions: boolean; - search: boolean; - dangerouslyBypassSandbox: boolean; - command: string; - args: string; - extraArgs: string; - envVars: string; - envBindings: Record; - url: string; - bootstrapPrompt: string; - payloadTemplateJson?: string; - workspaceStrategyType?: string; - workspaceBaseRef?: string; - workspaceBranchTemplate?: string; - worktreeParentDir?: string; - runtimeServicesJson?: string; - maxTurnsPerRun: number; - heartbeatEnabled: boolean; - intervalSec: number; -} diff --git a/packages/adapter-utils/tsconfig.json b/packages/adapter-utils/tsconfig.json deleted file mode 100644 index 5a24989c..00000000 --- a/packages/adapter-utils/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "dist", - "rootDir": "src" - }, - "include": ["src"] -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e1526861..459dbc5c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,18 +8,15 @@ importers: .: dependencies: - '@agentcompany/adapter-claude-local': - specifier: workspace:* - version: link:packages/adapter-claude-local - '@agentcompany/adapter-codex-local': - specifier: workspace:* - version: link:packages/adapter-codex-local - '@agentcompany/adapter-gemini-local': - specifier: workspace:* - version: link:packages/adapter-gemini-local - '@agentcompany/adapter-utils': - specifier: workspace:* - version: link:packages/adapter-utils + '@mariozechner/pi-agent-core': + specifier: ^0.67.6 + version: 0.67.6(ws@8.20.0)(zod@4.3.6) + '@mariozechner/pi-ai': + specifier: ^0.67.6 + version: 0.67.6(ws@8.20.0)(zod@4.3.6) + '@mariozechner/pi-coding-agent': + specifier: ^0.67.6 + version: 0.67.6(ws@8.20.0)(zod@4.3.6) '@phosphor-icons/react': specifier: 2.1.10 version: 2.1.10(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -62,7 +59,7 @@ importers: version: 0.5.19(tailwindcss@4.2.1) '@tailwindcss/vite': specifier: 4.2.1 - version: 4.2.1(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)) + version: 4.2.1(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)) '@types/node': specifier: ^25.2.3 version: 25.5.0 @@ -74,7 +71,7 @@ importers: version: 19.2.3(@types/react@19.2.14) '@vitejs/plugin-react': specifier: ^5.0.0 - version: 5.2.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)) + version: 5.2.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)) electron: specifier: 39.8.0 version: 39.8.0 @@ -83,7 +80,7 @@ importers: version: 26.8.1(electron-builder-squirrel-windows@26.8.1) electron-vite: specifier: 5.0.0 - version: 5.0.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)) + version: 5.0.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)) eslint: specifier: 9.38.0 version: 9.38.0(jiti@2.6.1) @@ -107,73 +104,158 @@ importers: version: 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) vite: specifier: ^7.0.0 - version: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1) + version: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3) vitest: specifier: 4.1.0 - version: 4.1.0(@types/node@25.5.0)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)) - - packages/adapter-claude-local: - dependencies: - '@agentcompany/adapter-utils': - specifier: workspace:* - version: link:../adapter-utils - picocolors: - specifier: ^1.1.1 - version: 1.1.1 - devDependencies: - '@types/node': - specifier: ^24.6.0 - version: 24.12.0 - typescript: - specifier: ^5.7.3 - version: 5.9.3 - - packages/adapter-codex-local: - dependencies: - '@agentcompany/adapter-utils': - specifier: workspace:* - version: link:../adapter-utils - picocolors: - specifier: ^1.1.1 - version: 1.1.1 - devDependencies: - '@types/node': - specifier: ^24.6.0 - version: 24.12.0 - typescript: - specifier: ^5.7.3 - version: 5.9.3 - - packages/adapter-gemini-local: - dependencies: - '@agentcompany/adapter-utils': - specifier: workspace:* - version: link:../adapter-utils - picocolors: - specifier: ^1.1.1 - version: 1.1.1 - devDependencies: - '@types/node': - specifier: ^24.6.0 - version: 24.12.0 - typescript: - specifier: ^5.7.3 - version: 5.9.3 - - packages/adapter-utils: - devDependencies: - '@types/node': - specifier: ^24.6.0 - version: 24.12.0 - typescript: - specifier: ^5.7.3 - version: 5.9.3 + version: 4.1.0(@types/node@25.5.0)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)) packages: 7zip-bin@5.2.0: resolution: {integrity: sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==} + '@anthropic-ai/sdk@0.90.0': + resolution: {integrity: sha512-MzZtPabJF1b0FTDl6Z6H5ljphPwACLGP13lu8MTiB8jXaW/YXlpOp+Po2cVou3MPM5+f5toyLnul9whKCy7fBg==} + hasBin: true + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-bedrock-runtime@3.1031.0': + resolution: {integrity: sha512-ZgiSo2wslPXlv7wK4m2ULu2VfimbVRRlho0DqXhlvZGEqvtC209cMOxfPZWJ79Fz9sf0IzmWFkDtvMYjnwyLfw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.974.0': + resolution: {integrity: sha512-8j+dMtyDqNXFmi09CBdz8TY6Ltf2jhfHuP6ZvG4zVjndRc6JF0aeBUbRwQLndbptFCsdctRQgdNWecy4TIfXAw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.26': + resolution: {integrity: sha512-WBHAMxyPdgeJY6ZGLvq9mJwzZ+GaNUROQbfdVshtMsDVBrZTj5ZuFjKclSjSHvKSHJ4Y4O2yvI/aA/hrJbYfng==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-http@3.972.28': + resolution: {integrity: sha512-+1DwCjjpo1WoiZTN08yGitI3nUwZUSQWVWFrW4C46HqZwACjcUQ7C66tnKPBTVxrEYYDOP11A6Afmu1L6ylt3g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-ini@3.972.30': + resolution: {integrity: sha512-Fg1oJcoijwOZjTxdbx+ubqbQl8YEQ4Cwhjw6TWzQjuDEvQYNhnCXW2pN7eKtdTrdE4a6+5TVKGSm2I+i2BKIQg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.30': + resolution: {integrity: sha512-nchIrrI/7dgjG1bW/DEWOJc00K9n+kkl6B8Mk0KO6d4GfWBOXlVr9uHp7CJR9FIrjmov5SGjHXG2q9XAtkRw6Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-node@3.972.31': + resolution: {integrity: sha512-99OHVQ6eZ5DTxiOWgHdjBMvLqv7xoY4jLK6nZ1NcNSQbAnYZkQNIHi/VqInc9fnmg7of9si/z+waE6YL9OQIlw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-process@3.972.26': + resolution: {integrity: sha512-jibxNld3m+vbmQwn98hcQ+fLIVrx3cQuhZlSs1/hix48SjDS5/pjMLwpmtLD/lFnd6ve1AL4o1bZg3X1WRa2SQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-sso@3.972.30': + resolution: {integrity: sha512-honYIM17F/+QSWJRE84T4u//ofqEi7rLbnwmIpu7fgFX5PML78wbtdSAy5Xwyve3TLpE9/f9zQx0aBVxSjAOPw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.972.30': + resolution: {integrity: sha512-CyL4oWUlONQRN2SsYMVrA9Z3i3QfLWTQctI8tuKbjNGCVVDCnJf/yMbSJCOZgpPFRtxh7dgQwvpqwmJm+iytmw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/eventstream-handler-node@3.972.14': + resolution: {integrity: sha512-m4X56gxG76/CKfxNVbOFuYwnAZcHgS6HOH8lgp15HoGHIAVTcZfZrXvcYzJFOMLEJgVn+JHBu6EiNV+xSNXXFg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-eventstream@3.972.10': + resolution: {integrity: sha512-QUqLs7Af1II9X4fCRAu+EGHG3KHyOp4RkuLhRKoA3NuFlh6TL8i+zXBl8w2LUxqm44B/Kom45hgSlwA1SpTsXQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-host-header@3.972.10': + resolution: {integrity: sha512-IJSsIMeVQ8MMCPbuh1AbltkFhLBLXn7aejzfX5YKT/VLDHn++Dcz8886tXckE+wQssyPUhaXrJhdakO2VilRhg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-logger@3.972.10': + resolution: {integrity: sha512-OOuGvvz1Dm20SjZo5oEBePFqxt5nf8AwkNDSyUHvD9/bfNASmstcYxFAHUowy4n6Io7mWUZ04JURZwSBvyQanQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.972.11': + resolution: {integrity: sha512-+zz6f79Kj9V5qFK2P+D8Ehjnw4AhphAlCAsPjUqEcInA9umtSSKMrHbSagEeOIsDNuvVrH98bjRHcyQukTrhaQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-user-agent@3.972.30': + resolution: {integrity: sha512-lCz6JfelhjD6Eco1urXM2rOYRaxROSqeoY6IEKx+soegFJOajmIBCMHTAWuJl25Wf9IAST+i0/yOk9G3rMV26A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-websocket@3.972.16': + resolution: {integrity: sha512-86+S9oCyRVGzoMRpQhxkArp7kD2K75GPmaNevd9B6EyNhWoNvnCZZ3WbgN4j7ZT+jvtvBCGZvI2XHsWZJ+BRIg==} + engines: {node: '>= 14.0.0'} + + '@aws-sdk/nested-clients@3.996.20': + resolution: {integrity: sha512-bzPdsNQnCh6TvvUmTHLZlL8qgyME6mNiUErcRMyJPywIl1BEu2VZRShel3mUoSh89bOBEXEWtjocDMolFxd/9A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/region-config-resolver@3.972.12': + resolution: {integrity: sha512-QQI43Mxd53nBij0pm8HXC+t4IOC6gnhhZfzxE0OATQyO6QfPV4e+aTIRRuAJKA6Nig/cR8eLwPryqYTX9ZrjAQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1031.0': + resolution: {integrity: sha512-zj/PvnbQK/2KJNln5K2QRI9HSsy+B4emz2gbQyUHkk6l7Lidu83P/9tfmC2cJXkcC3vdmyKH2DP3Iw/FDfKQuQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.973.8': + resolution: {integrity: sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-endpoints@3.996.7': + resolution: {integrity: sha512-ty4LQxN1QC+YhUP28NfEgZDEGXkyqOQy+BDriBozqHsrYO4JMgiPhfizqOGF7P+euBTZ5Ez6SKlLAMCLo8tzmw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-format-url@3.972.10': + resolution: {integrity: sha512-DEKiHNJVtNxdyTeQspzY+15Po/kHm6sF0Cs4HV9Q2+lplB63+DrvdeiSoOSdWEWAoO2RcY1veoXVDz2tWxWCgQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-locate-window@3.965.5': + resolution: {integrity: sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/util-user-agent-browser@3.972.10': + resolution: {integrity: sha512-FAzqXvfEssGdSIz8ejatan0bOdx1qefBWKF/gWmVBXIP1HkS7v/wjjaqrAGGKvyihrXTXW00/2/1nTJtxpXz7g==} + + '@aws-sdk/util-user-agent-node@3.973.16': + resolution: {integrity: sha512-ccvu0FNCI0C6OqmxI/tWn7BD8qGooWuURssiIM+6vbksFO8opXR4JOGtGYPj8QYzN/vfwNYrcK344PPbYuvzRg==} + engines: {node: '>=20.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.972.18': + resolution: {integrity: sha512-BMDNVG1ETXRhl1tnisQiYBef3RShJ1kfZA7x7afivTFMLirfHNTb6U71K569HNXhSXbQZsweHvSDZ6euBw8hPA==} + engines: {node: '>=20.0.0'} + + '@aws/lambda-invoke-store@0.2.4': + resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.29.0': resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} @@ -251,6 +333,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + '@babel/template@7.28.6': resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} @@ -263,6 +349,9 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} + '@borewit/text-codec@0.2.2': + resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + '@develar/schema-utils@2.6.5': resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==} engines: {node: '>= 8.9.0'} @@ -661,6 +750,15 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@google/genai@1.50.1': + resolution: {integrity: sha512-YbkX7H9+1Pt8wOt7DDREy8XSoiL6fRDzZQRyaVBarFf8MR3zHGqVdvM4cLbDXqPhxqvegZShgfxb8kw9C7YhAQ==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@modelcontextprotocol/sdk': ^1.25.2 + peerDependenciesMeta: + '@modelcontextprotocol/sdk': + optional: true + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -709,6 +807,94 @@ packages: resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==} engines: {node: '>= 10.0.0'} + '@mariozechner/clipboard-darwin-arm64@0.3.2': + resolution: {integrity: sha512-uBf6K7Je1ihsgvmWxA8UCGCeI+nbRVRXoarZdLjl6slz94Zs1tNKFZqx7aCI5O1i3e0B6ja82zZ06BWrl0MCVw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@mariozechner/clipboard-darwin-universal@0.3.2': + resolution: {integrity: sha512-mxSheKTW2U9LsBdXy0SdmdCAE5HqNS9QUmpNHLnfJ+SsbFKALjEZc5oRrVMXxGQSirDvYf5bjmRyT0QYYonnlg==} + engines: {node: '>= 10'} + os: [darwin] + + '@mariozechner/clipboard-darwin-x64@0.3.2': + resolution: {integrity: sha512-U1BcVEoidvwIp95+HJswSW+xr28EQiHR7rZjH6pn8Sja5yO4Yoe3yCN0Zm8Lo72BbSOK/fTSq0je7CJpaPCspg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@mariozechner/clipboard-linux-arm64-gnu@0.3.2': + resolution: {integrity: sha512-BsinwG3yWTIjdgNCxsFlip7LkfwPk+ruw/aFCXHUg/fb5XC/Ksp+YMQ7u0LUtiKzIv/7LMXgZInJQH6gxbAaqQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@mariozechner/clipboard-linux-arm64-musl@0.3.2': + resolution: {integrity: sha512-0/Gi5Xq2V6goXBop19ePoHvXsmJD9SzFlO3S+d6+T2b+BlPcpOu3Oa0wTjl+cZrLAAEzA86aPNBI+VVAFDFPKw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@mariozechner/clipboard-linux-riscv64-gnu@0.3.2': + resolution: {integrity: sha512-2AFFiXB24qf0zOZsxI1GJGb9wQGlOJyN6UwoXqmKS3dpQi/l6ix30IzDDA4c4ZcCcx4D+9HLYXhC1w7Sov8pXA==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + + '@mariozechner/clipboard-linux-x64-gnu@0.3.2': + resolution: {integrity: sha512-v6fVnsn7WMGg73Dab8QMwyFce7tzGfgEixKgzLP8f1GJqkJZi5zO4k4FOHzSgUufgLil63gnxvMpjWkgfeQN7A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@mariozechner/clipboard-linux-x64-musl@0.3.2': + resolution: {integrity: sha512-xVUtnoMQ8v2JVyfJLKKXACA6avdnchdbBkTsZs8BgJQo29qwCp5NIHAUO8gbJ40iaEGToW5RlmVk2M9V0HsHEw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@mariozechner/clipboard-win32-arm64-msvc@0.3.2': + resolution: {integrity: sha512-AEgg95TNi8TGgak2wSXZkXKCvAUTjWoU1Pqb0ON7JHrX78p616XUFNTJohtIon3e0w6k0pYPZeCuqRCza/Tqeg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@mariozechner/clipboard-win32-x64-msvc@0.3.2': + resolution: {integrity: sha512-tGRuYpZwDOD7HBrCpyRuhGnHHSCknELvqwKKUG4JSfSB7JIU7LKRh6zx6fMUOQd8uISK35TjFg5UcNih+vJhFA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@mariozechner/clipboard@0.3.2': + resolution: {integrity: sha512-IHQpksNjo7EAtGuHFU+tbWDp5LarH3HU/8WiB9O70ZEoBPHOg0/6afwSLK0QyNMMmx4Bpi/zl6+DcBXe95nWYA==} + engines: {node: '>= 10'} + + '@mariozechner/jiti@2.6.5': + resolution: {integrity: sha512-faGUlTcXka5l7rv0lP3K3vGW/ejRuOS24RR2aSFWREUQqzjgdsuWNo/IiPqL3kWRGt6Ahl2+qcDAwtdeWeuGUw==} + hasBin: true + + '@mariozechner/pi-agent-core@0.67.6': + resolution: {integrity: sha512-ww342P+gyRiZ7I6+dWvHtEO94AQFgA54ONXEvQ12txpZ9eJtC/DuH6nh8brKHSvLsl6U0RDeBy/GKAsKN0FOHw==} + engines: {node: '>=20.0.0'} + + '@mariozechner/pi-ai@0.67.6': + resolution: {integrity: sha512-muGq9wG+nOjuJrk4nCy3FWUfK2MPQMmGS6yVApVZB8A6R/4HyiSBRHOafnh1nfamudkcy90lDqUtVfLfwpHSFQ==} + engines: {node: '>=20.0.0'} + hasBin: true + + '@mariozechner/pi-coding-agent@0.67.6': + resolution: {integrity: sha512-OIUT8mzsWsdD0eoZS5cOdRnVuKPx6HjAK4paN2IHrPwULLjqsB/5cTivWWEqBohxapth8yGCJE2XP4+feXa6Tg==} + engines: {node: '>=20.6.0'} + hasBin: true + + '@mariozechner/pi-tui@0.67.6': + resolution: {integrity: sha512-eO5XYizj9aCEgh4wqbDERFGd5wFH94+23t91fYZQ5plV++L4K3EH4XLdjF3eg69bw36L30FyESfxmaMDlXIShw==} + engines: {node: '>=20.0.0'} + + '@mistralai/mistralai@1.14.1': + resolution: {integrity: sha512-IiLmmZFCCTReQgPAT33r7KQ1nYo5JPdvGkrkZqA8qQ2qB1GHgs5LoP5K2ICyrjnpw2n8oSxMM/VP+liiKcGNlQ==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -745,6 +931,36 @@ packages: engines: {node: '>=18'} hasBin: true + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@reduxjs/toolkit@2.11.2': resolution: {integrity: sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==} peerDependencies: @@ -884,10 +1100,204 @@ packages: cpu: [x64] os: [win32] + '@silvia-odwyer/photon-node@0.3.4': + resolution: {integrity: sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==} + + '@sinclair/typebox@0.34.49': + resolution: {integrity: sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==} + '@sindresorhus/is@4.6.0': resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} + '@smithy/config-resolver@4.4.16': + resolution: {integrity: sha512-GFlGPNLZKrGfqWpqVb31z7hvYCA9ZscfX1buYnvvMGcRYsQQnhH+4uN6mWWflcD5jB4OXP/LBrdpukEdjl41tg==} + engines: {node: '>=18.0.0'} + + '@smithy/core@3.23.15': + resolution: {integrity: sha512-E7GVCgsQttzfujEZb6Qep005wWf4xiL4x06apFEtzQMWYBPggZh/0cnOxPficw5cuK/YjjkehKoIN4YUaSh0UQ==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.2.14': + resolution: {integrity: sha512-Au28zBN48ZAoXdooGUHemuVBrkE+Ie6RPmGNIAJsFqj33Vhb6xAgRifUydZ2aY+M+KaMAETAlKk5NC5h1G7wpg==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-codec@4.2.14': + resolution: {integrity: sha512-erZq0nOIpzfeZdCyzZjdJb4nVSKLUmSkaQUVkRGQTXs30gyUGeKnrYEg+Xe1W5gE3aReS7IgsvANwVPxSzY6Pw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-browser@4.2.14': + resolution: {integrity: sha512-8IelTCtTctWRbb+0Dcy+C0aICh1qa0qWXqgjcXDmMuCvPJRnv26hiDZoAau2ILOniki65mCPKqOQs/BaWvO4CQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-config-resolver@4.3.14': + resolution: {integrity: sha512-sqHiHpYRYo3FJlaIxD1J8PhbcmJAm7IuM16mVnwSkCToD7g00IBZzKuiLNMGmftULmEUX6/UAz8/NN5uMP8bVA==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-node@4.2.14': + resolution: {integrity: sha512-Ht/8BuGlKfFTy0H3+8eEu0vdpwGztCnaLLXtpXNdQqiR7Hj4vFScU3T436vRAjATglOIPjJXronY+1WxxNLSiw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-universal@4.2.14': + resolution: {integrity: sha512-lWyt4T2XQZUZgK3tQ3Wn0w3XBvZsK/vjTuJl6bXbnGZBHH0ZUSONTYiK9TgjTTzU54xQr3DRFwpjmhp0oLm3gg==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.3.17': + resolution: {integrity: sha512-bXOvQzaSm6MnmLaWA1elgfQcAtN4UP3vXqV97bHuoOrHQOJiLT3ds6o9eo5bqd0TJfRFpzdGnDQdW3FACiAVdw==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-node@4.2.14': + resolution: {integrity: sha512-8ZBDY2DD4wr+GGjTpPtiglEsqr0lUP+KHqgZcWczFf6qeZ/YRjMIOoQWVQlmwu7EtxKTd8YXD8lblmYcpBIA1g==} + engines: {node: '>=18.0.0'} + + '@smithy/invalid-dependency@4.2.14': + resolution: {integrity: sha512-c21qJiTSb25xvvOp+H2TNZzPCngrvl5vIPqPB8zQ/DmJF4QWXO19x1dWfMJZ6wZuuWUPPm0gV8C0cU3+ifcWuw==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.2.2': + resolution: {integrity: sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.2.14': + resolution: {integrity: sha512-xhHq7fX4/3lv5NHxLUk3OeEvl0xZ+Ek3qIbWaCL4f9JwgDZEclPBElljaZCAItdGPQl/kSM4LPMOpy1MYgprpw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.4.30': + resolution: {integrity: sha512-qS2XqhKeXmdZ4nEQ4cOxIczSP/Y91wPAHYuRwmWDCh975B7/57uxsm5d6sisnUThn2u2FwzMdJNM7AbO1YPsPg==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.5.3': + resolution: {integrity: sha512-TE8dJNi6JuxzGSxMCVd3i9IEWDndCl3bmluLsBNDWok8olgj65OfkndMhl9SZ7m14c+C5SQn/PcUmrDl57rSFw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.2.18': + resolution: {integrity: sha512-M6CSgnp3v4tYz9ynj2JHbA60woBZcGqEwNjTKjBsNHPV26R1ZX52+0wW8WsZU18q45jD0tw2wL22S17Ze9LpEw==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.2.14': + resolution: {integrity: sha512-2dvkUKLuFdKsCRmOE4Mn63co0Djtsm+JMh0bYZQupN1pJwMeE8FmQmRLLzzEMN0dnNi7CDCYYH8F0EVwWiPBeA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.3.14': + resolution: {integrity: sha512-S+gFjyo/weSVL0P1b9Ts8C/CwIfNCgUPikk3sl6QVsfE/uUuO+QsF+NsE/JkpvWqqyz1wg7HFdiaZuj5CoBMRg==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.5.3': + resolution: {integrity: sha512-lc5jFL++x17sPhIwMWJ3YOnqmSjw/2Po6VLDlUIXvxVWRuJwRXnJ4jOBBLB0cfI5BB5ehIl02Fxr1PDvk/kxDw==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.2.14': + resolution: {integrity: sha512-WuM31CgfsnQ/10i7NYr0PyxqknD72Y5uMfUMVSniPjbEPceiTErb4eIqJQ+pdxNEAUEWrewrGjIRjVbVHsxZiQ==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.3.14': + resolution: {integrity: sha512-dN5F8kHx8RNU0r+pCwNmFZyz6ChjMkzShy/zup6MtkRmmix4vZzJdW+di7x//b1LiynIev88FM18ie+wwPcQtQ==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.2.14': + resolution: {integrity: sha512-XYA5Z0IqTeF+5XDdh4BBmSA0HvbgVZIyv4cmOoUheDNR57K1HgBp9ukUMx3Cr3XpDHHpLBnexPE3LAtDsZkj2A==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.2.14': + resolution: {integrity: sha512-hr+YyqBD23GVvRxGGrcc/oOeNlK3PzT5Fu4dzrDXxzS1LpFiuL2PQQqKPs87M79aW7ziMs+nvB3qdw77SqE7Lw==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.2.14': + resolution: {integrity: sha512-vVimoUnGxlx4eLLQbZImdOZFOe+Zh+5ACntv8VxZuGP72LdWu5GV3oEmCahSEReBgRJoWjypFkrehSj7BWx1HQ==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.4.9': + resolution: {integrity: sha512-495/V2I15SHgedSJoDPD23JuSfKAp726ZI1V0wtjB07Wh7q/0tri/0e0DLefZCHgxZonrGKt/OCTpAtP1wE1kQ==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.3.14': + resolution: {integrity: sha512-1D9Y/nmlVjCeSivCbhZ7hgEpmHyY1h0GvpSZt3l0xcD9JjmjVC1CHOozS6+Gh+/ldMH8JuJ6cujObQqfayAVFA==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.12.11': + resolution: {integrity: sha512-wzz/Wa1CH/Tlhxh0s4DQPEcXSxSVfJ59AZcUh9Gu0c6JTlKuwGf4o/3P2TExv0VbtPFt8odIBG+eQGK2+vTECg==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.14.1': + resolution: {integrity: sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.2.14': + resolution: {integrity: sha512-p06BiBigJ8bTA3MgnOfCtDUWnAMY0YfedO/GRpmc7p+wg3KW8vbXy1xwSu5ASy0wV7rRYtlfZOIKH4XqfhjSQQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.3.2': + resolution: {integrity: sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.2.2': + resolution: {integrity: sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.2.3': + resolution: {integrity: sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.2.2': + resolution: {integrity: sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-config-provider@4.2.2': + resolution: {integrity: sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.3.47': + resolution: {integrity: sha512-zlIuXai3/SHjQUQ8y3g/woLvrH573SK2wNjcDaHu5e9VOcC0JwM1MI0Sq0GZJyN3BwSUneIhpjZ18nsiz5AtQw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.2.52': + resolution: {integrity: sha512-cQBz8g68Vnw1W2meXlkb3D/hXJU+Taiyj9P8qLJtjREEV9/Td65xi4A/H1sRQ8EIgX5qbZbvdYPKygKLholZ3w==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.4.1': + resolution: {integrity: sha512-wMxNDZJrgS5mQV9oxCs4TWl5767VMgOfqfZ3JHyCkMtGC2ykW9iPqMvFur695Otcc5yxLG8OKO/80tsQBxrhXg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@4.2.2': + resolution: {integrity: sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-middleware@4.2.14': + resolution: {integrity: sha512-1Su2vj9RYNDEv/V+2E+jXkkwGsgR7dc4sfHn9Z7ruzQHJIEni9zzw5CauvRXlFJfmgcqYP8fWa0dkh2Q2YaQyw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.3.2': + resolution: {integrity: sha512-2+KTsJEwTi63NUv4uR9IQ+IFT1yu6Rf6JuoBK2WKaaJ/TRvOiOVGcXAsEqX/TQN2thR9yII21kPUJq1UV/WI2A==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.5.23': + resolution: {integrity: sha512-N6on1+ngJ3RznZOnDWNveIwnTSlqxNnXuNAh7ez889ZZaRdXoNRTXKgmYOLe6dB0gCmAVtuRScE1hymQFl4hpg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-uri-escape@4.2.2': + resolution: {integrity: sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.2.2': + resolution: {integrity: sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==} + engines: {node: '>=18.0.0'} + + '@smithy/uuid@1.1.2': + resolution: {integrity: sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==} + engines: {node: '>=18.0.0'} + '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -1002,6 +1412,16 @@ packages: '@tanstack/virtual-core@3.13.23': resolution: {integrity: sha512-zSz2Z2HNyLjCplANTDyl3BcdQJc2k1+yyFoKhNRmCr7V7dY8o8q5m8uFTI1/Pg1kL+Hgrz6u3Xo6eFUB7l66cg==} + '@tokenizer/inflate@0.4.1': + resolution: {integrity: sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==} + engines: {node: '>=18'} + + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -1068,15 +1488,15 @@ packages: '@types/keyv@3.1.4': resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + '@types/mime-types@2.1.4': + resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} '@types/node@22.19.15': resolution: {integrity: sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==} - '@types/node@24.12.0': - resolution: {integrity: sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==} - '@types/node@25.5.0': resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} @@ -1094,6 +1514,9 @@ packages: '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + '@types/use-sync-external-store@0.0.6': resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} @@ -1220,6 +1643,14 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv-keywords@3.5.2: resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: @@ -1228,6 +1659,9 @@ packages: ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1244,6 +1678,9 @@ packages: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + app-builder-bin@5.0.0-alpha.12: resolution: {integrity: sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==} @@ -1265,6 +1702,10 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} @@ -1298,6 +1739,13 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + basic-ftp@5.3.0: + resolution: {integrity: sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==} + engines: {node: '>=10.0.0'} + + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -1305,6 +1753,9 @@ packages: resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + bowser@2.14.1: + resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -1327,6 +1778,9 @@ packages: buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -1375,6 +1829,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chownr@3.0.0: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} @@ -1394,6 +1852,11 @@ packages: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} + cli-highlight@2.1.11: + resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + cli-spinners@2.9.2: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} @@ -1402,6 +1865,9 @@ packages: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} engines: {node: '>=8'} + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1511,6 +1977,14 @@ packages: resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} engines: {node: '>=12'} + data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1545,6 +2019,10 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -1556,6 +2034,10 @@ packages: detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} + engines: {node: '>=0.3.1'} + dir-compare@4.2.0: resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==} @@ -1583,6 +2065,9 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + ejs@3.1.10: resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} @@ -1695,6 +2180,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + eslint-plugin-react-hooks@7.0.0: resolution: {integrity: sha512-fNXaOwvKwq2+pXiRpXc825Vd63+KM4DLL40Rtlycb8m7fYpp6efrTp1sa6ZbP/Ap58K2bEKFXRmhURE+CJAQWw==} engines: {node: '>=18'} @@ -1732,6 +2222,11 @@ packages: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esquery@1.7.0: resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} @@ -1761,6 +2256,9 @@ packages: exponential-backoff@3.1.3: resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + extract-zip@2.0.1: resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} engines: {node: '>= 10.17.0'} @@ -1783,6 +2281,16 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + + fast-xml-builder@1.1.4: + resolution: {integrity: sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==} + + fast-xml-parser@5.5.8: + resolution: {integrity: sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==} + hasBin: true + fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -1798,10 +2306,18 @@ packages: picomatch: optional: true + fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + file-type@21.3.4: + resolution: {integrity: sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==} + engines: {node: '>=20'} + filelist@1.0.6: resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} @@ -1828,6 +2344,10 @@ packages: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} + formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + framer-motion@12.36.0: resolution: {integrity: sha512-4PqYHAT7gev0ke0wos+PyrcFxI0HScjm3asgU8nSYa8YzJFuwgIvdj3/s3ZaxLq0bUSboIn19A2WS/MHwLCvfw==} peerDependencies: @@ -1882,6 +2402,14 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gaxios@7.1.4: + resolution: {integrity: sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==} + engines: {node: '>=18'} + + gcp-metadata@8.1.2: + resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} + engines: {node: '>=18'} + gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -1890,6 +2418,10 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -1902,6 +2434,10 @@ packages: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} engines: {node: '>=8'} + get-uri@6.0.5: + resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} + engines: {node: '>= 14'} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1915,6 +2451,10 @@ packages: deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me @@ -1935,6 +2475,14 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} + google-auth-library@10.6.2: + resolution: {integrity: sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==} + engines: {node: '>=18'} + + google-logging-utils@1.1.3: + resolution: {integrity: sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==} + engines: {node: '>=14'} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -1974,10 +2522,17 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} + hosted-git-info@9.0.2: + resolution: {integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==} + engines: {node: ^20.17.0 || >=22.9.0} + http-cache-semantics@4.2.0: resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} @@ -2105,12 +2660,22 @@ packages: engines: {node: '>=6'} hasBin: true + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + json-schema-to-ts@3.1.1: + resolution: {integrity: sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==} + engines: {node: '>=16'} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -2128,9 +2693,18 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + koffi@2.16.0: + resolution: {integrity: sha512-h/2NJueOKWd0YYycEOWDspomizgNfuOKf/V7ZE2fytvuRtHoY9Tb+y4x6GJ6pFqaVndWn9dLK+sCI14eWtu5rA==} + lazy-val@1.0.5: resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} @@ -2229,6 +2803,9 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + lowercase-keys@2.0.0: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} @@ -2236,6 +2813,10 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.3.5: + resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -2243,6 +2824,10 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -2250,6 +2835,11 @@ packages: resolution: {integrity: sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==} engines: {node: ^18.17.0 || >=20.5.0} + marked@15.0.12: + resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==} + engines: {node: '>= 18'} + hasBin: true + matcher@3.0.0: resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} engines: {node: '>=10'} @@ -2270,10 +2860,18 @@ packages: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + mime@2.6.0: resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} engines: {node: '>=4.0.0'} @@ -2354,6 +2952,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2366,6 +2967,10 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} + netmask@2.1.1: + resolution: {integrity: sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==} + engines: {node: '>= 0.4.0'} + node-abi@4.27.0: resolution: {integrity: sha512-M6PypnnjGwr6Wv1O7twPpnJiie8MeLoBSh99zF1jnRRU2NLgxO/fUEQW1rfAhAKzPa/fvQ4PKitt1O+c8l243Q==} engines: {node: '>=22.12.0'} @@ -2376,6 +2981,15 @@ packages: node-api-version@0.2.1: resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + node-gyp@11.5.0: resolution: {integrity: sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==} engines: {node: ^18.17.0 || >=20.5.0} @@ -2393,6 +3007,10 @@ packages: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -2407,6 +3025,18 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + openai@6.26.0: + resolution: {integrity: sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.25 || ^4.0 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2431,6 +3061,18 @@ packages: resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} engines: {node: '>=18'} + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + pac-proxy-agent@7.2.0: + resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -2438,10 +3080,26 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse5-htmlparser2-tree-adapter@6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + + parse5@5.1.1: + resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} + + parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + + partial-json@0.1.7: + resolution: {integrity: sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-expression-matcher@1.5.0: + resolution: {integrity: sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==} + engines: {node: '>=14.0.0'} + path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -2454,6 +3112,10 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -2521,6 +3183,17 @@ packages: proper-lockfile@4.1.2: resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + protobufjs@7.5.5: + resolution: {integrity: sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==} + engines: {node: '>=12.0.0'} + + proxy-agent@6.5.0: + resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} + engines: {node: '>= 14'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} @@ -2591,6 +3264,10 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + resedit@1.7.2: resolution: {integrity: sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==} engines: {node: '>=12', npm: '>=6'} @@ -2616,6 +3293,10 @@ packages: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -2736,6 +3417,9 @@ packages: resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==} engines: {node: '>= 6'} + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.0.0: resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==} @@ -2762,6 +3446,13 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strnum@2.2.3: + resolution: {integrity: sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==} + + strtok3@10.3.5: + resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} + engines: {node: '>=18'} + sumchecker@3.0.1: resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} engines: {node: '>= 8.0'} @@ -2788,6 +3479,13 @@ packages: resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} engines: {node: '>=6.0.0'} + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + tiny-async-pool@1.3.0: resolution: {integrity: sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==} @@ -2823,9 +3521,16 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + token-types@6.1.2: + resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} + engines: {node: '>=14.16'} + truncate-utf8-bytes@1.0.2: resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==} + ts-algebra@2.0.0: + resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} + ts-api-utils@2.4.0: resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} engines: {node: '>=18.12'} @@ -2855,15 +3560,20 @@ packages: engines: {node: '>=14.17'} hasBin: true + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} + undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@7.16.0: - resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + undici@7.25.0: + resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} + engines: {node: '>=20.18.1'} + unique-filename@4.0.0: resolution: {integrity: sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==} engines: {node: ^18.17.0 || >=20.5.0} @@ -2900,6 +3610,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@11.1.0: + resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} + hasBin: true + verror@1.10.1: resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} engines: {node: '>=0.6.0'} @@ -2985,6 +3699,10 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + web-streams-polyfill@3.3.3: + resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} + engines: {node: '>= 8'} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -3015,6 +3733,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xmlbuilder@15.1.1: resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} engines: {node: '>=8.0'} @@ -3033,10 +3763,23 @@ packages: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} + yaml@2.8.3: + resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -3048,6 +3791,15 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + engines: {node: '>=18'} + + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + zod-validation-error@4.0.2: resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} engines: {node: '>=18.0.0'} @@ -3079,6 +3831,388 @@ snapshots: 7zip-bin@5.2.0: {} + '@anthropic-ai/sdk@0.90.0(zod@4.3.6)': + dependencies: + json-schema-to-ts: 3.1.1 + optionalDependencies: + zod: 4.3.6 + + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.8 + tslib: 2.8.1 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-locate-window': 3.965.5 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.8 + tslib: 2.8.1 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.8.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/client-bedrock-runtime@3.1031.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.0 + '@aws-sdk/credential-provider-node': 3.972.31 + '@aws-sdk/eventstream-handler-node': 3.972.14 + '@aws-sdk/middleware-eventstream': 3.972.10 + '@aws-sdk/middleware-host-header': 3.972.10 + '@aws-sdk/middleware-logger': 3.972.10 + '@aws-sdk/middleware-recursion-detection': 3.972.11 + '@aws-sdk/middleware-user-agent': 3.972.30 + '@aws-sdk/middleware-websocket': 3.972.16 + '@aws-sdk/region-config-resolver': 3.972.12 + '@aws-sdk/token-providers': 3.1031.0 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-endpoints': 3.996.7 + '@aws-sdk/util-user-agent-browser': 3.972.10 + '@aws-sdk/util-user-agent-node': 3.973.16 + '@smithy/config-resolver': 4.4.16 + '@smithy/core': 3.23.15 + '@smithy/eventstream-serde-browser': 4.2.14 + '@smithy/eventstream-serde-config-resolver': 4.3.14 + '@smithy/eventstream-serde-node': 4.2.14 + '@smithy/fetch-http-handler': 5.3.17 + '@smithy/hash-node': 4.2.14 + '@smithy/invalid-dependency': 4.2.14 + '@smithy/middleware-content-length': 4.2.14 + '@smithy/middleware-endpoint': 4.4.30 + '@smithy/middleware-retry': 4.5.3 + '@smithy/middleware-serde': 4.2.18 + '@smithy/middleware-stack': 4.2.14 + '@smithy/node-config-provider': 4.3.14 + '@smithy/node-http-handler': 4.5.3 + '@smithy/protocol-http': 5.3.14 + '@smithy/smithy-client': 4.12.11 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 + '@smithy/util-base64': 4.3.2 + '@smithy/util-body-length-browser': 4.2.2 + '@smithy/util-body-length-node': 4.2.3 + '@smithy/util-defaults-mode-browser': 4.3.47 + '@smithy/util-defaults-mode-node': 4.2.52 + '@smithy/util-endpoints': 3.4.1 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-retry': 4.3.2 + '@smithy/util-stream': 4.5.23 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.974.0': + dependencies: + '@aws-sdk/types': 3.973.8 + '@aws-sdk/xml-builder': 3.972.18 + '@smithy/core': 3.23.15 + '@smithy/node-config-provider': 4.3.14 + '@smithy/property-provider': 4.2.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/signature-v4': 5.3.14 + '@smithy/smithy-client': 4.12.11 + '@smithy/types': 4.14.1 + '@smithy/util-base64': 4.3.2 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.26': + dependencies: + '@aws-sdk/core': 3.974.0 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.28': + dependencies: + '@aws-sdk/core': 3.974.0 + '@aws-sdk/types': 3.973.8 + '@smithy/fetch-http-handler': 5.3.17 + '@smithy/node-http-handler': 4.5.3 + '@smithy/property-provider': 4.2.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/smithy-client': 4.12.11 + '@smithy/types': 4.14.1 + '@smithy/util-stream': 4.5.23 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.972.30': + dependencies: + '@aws-sdk/core': 3.974.0 + '@aws-sdk/credential-provider-env': 3.972.26 + '@aws-sdk/credential-provider-http': 3.972.28 + '@aws-sdk/credential-provider-login': 3.972.30 + '@aws-sdk/credential-provider-process': 3.972.26 + '@aws-sdk/credential-provider-sso': 3.972.30 + '@aws-sdk/credential-provider-web-identity': 3.972.30 + '@aws-sdk/nested-clients': 3.996.20 + '@aws-sdk/types': 3.973.8 + '@smithy/credential-provider-imds': 4.2.14 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-login@3.972.30': + dependencies: + '@aws-sdk/core': 3.974.0 + '@aws-sdk/nested-clients': 3.996.20 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.972.31': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.26 + '@aws-sdk/credential-provider-http': 3.972.28 + '@aws-sdk/credential-provider-ini': 3.972.30 + '@aws-sdk/credential-provider-process': 3.972.26 + '@aws-sdk/credential-provider-sso': 3.972.30 + '@aws-sdk/credential-provider-web-identity': 3.972.30 + '@aws-sdk/types': 3.973.8 + '@smithy/credential-provider-imds': 4.2.14 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.972.26': + dependencies: + '@aws-sdk/core': 3.974.0 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.972.30': + dependencies: + '@aws-sdk/core': 3.974.0 + '@aws-sdk/nested-clients': 3.996.20 + '@aws-sdk/token-providers': 3.1031.0 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.972.30': + dependencies: + '@aws-sdk/core': 3.974.0 + '@aws-sdk/nested-clients': 3.996.20 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/eventstream-handler-node@3.972.14': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/eventstream-codec': 4.2.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-eventstream@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-host-header@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.972.11': + dependencies: + '@aws-sdk/types': 3.973.8 + '@aws/lambda-invoke-store': 0.2.4 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.972.30': + dependencies: + '@aws-sdk/core': 3.974.0 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-endpoints': 3.996.7 + '@smithy/core': 3.23.15 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + '@smithy/util-retry': 4.3.2 + tslib: 2.8.1 + + '@aws-sdk/middleware-websocket@3.972.16': + dependencies: + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-format-url': 3.972.10 + '@smithy/eventstream-codec': 4.2.14 + '@smithy/eventstream-serde-browser': 4.2.14 + '@smithy/fetch-http-handler': 5.3.17 + '@smithy/protocol-http': 5.3.14 + '@smithy/signature-v4': 5.3.14 + '@smithy/types': 4.14.1 + '@smithy/util-base64': 4.3.2 + '@smithy/util-hex-encoding': 4.2.2 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.996.20': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.0 + '@aws-sdk/middleware-host-header': 3.972.10 + '@aws-sdk/middleware-logger': 3.972.10 + '@aws-sdk/middleware-recursion-detection': 3.972.11 + '@aws-sdk/middleware-user-agent': 3.972.30 + '@aws-sdk/region-config-resolver': 3.972.12 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-endpoints': 3.996.7 + '@aws-sdk/util-user-agent-browser': 3.972.10 + '@aws-sdk/util-user-agent-node': 3.973.16 + '@smithy/config-resolver': 4.4.16 + '@smithy/core': 3.23.15 + '@smithy/fetch-http-handler': 5.3.17 + '@smithy/hash-node': 4.2.14 + '@smithy/invalid-dependency': 4.2.14 + '@smithy/middleware-content-length': 4.2.14 + '@smithy/middleware-endpoint': 4.4.30 + '@smithy/middleware-retry': 4.5.3 + '@smithy/middleware-serde': 4.2.18 + '@smithy/middleware-stack': 4.2.14 + '@smithy/node-config-provider': 4.3.14 + '@smithy/node-http-handler': 4.5.3 + '@smithy/protocol-http': 5.3.14 + '@smithy/smithy-client': 4.12.11 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 + '@smithy/util-base64': 4.3.2 + '@smithy/util-body-length-browser': 4.2.2 + '@smithy/util-body-length-node': 4.2.3 + '@smithy/util-defaults-mode-browser': 4.3.47 + '@smithy/util-defaults-mode-node': 4.2.52 + '@smithy/util-endpoints': 3.4.1 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-retry': 4.3.2 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.972.12': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/config-resolver': 4.4.16 + '@smithy/node-config-provider': 4.3.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1031.0': + dependencies: + '@aws-sdk/core': 3.974.0 + '@aws-sdk/nested-clients': 3.996.20 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.973.8': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.996.7': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 + '@smithy/util-endpoints': 3.4.1 + tslib: 2.8.1 + + '@aws-sdk/util-format-url@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/querystring-builder': 4.2.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.965.5': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.972.10': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 + bowser: 2.14.1 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.973.16': + dependencies: + '@aws-sdk/middleware-user-agent': 3.972.30 + '@aws-sdk/types': 3.973.8 + '@smithy/node-config-provider': 4.3.14 + '@smithy/types': 4.14.1 + '@smithy/util-config-provider': 4.2.2 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.972.18': + dependencies: + '@smithy/types': 4.14.1 + fast-xml-parser: 5.5.8 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.2.4': {} + '@babel/code-frame@7.29.0': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -3173,6 +4307,8 @@ snapshots: '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 + '@babel/runtime@7.29.2': {} + '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 @@ -3196,6 +4332,8 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@borewit/text-codec@0.2.2': {} + '@develar/schema-utils@2.6.5': dependencies: ajv: 6.14.0 @@ -3507,6 +4645,17 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@google/genai@1.50.1': + dependencies: + google-auth-library: 10.6.2 + p-retry: 4.6.2 + protobufjs: 7.5.5 + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -3563,6 +4712,144 @@ snapshots: transitivePeerDependencies: - supports-color + '@mariozechner/clipboard-darwin-arm64@0.3.2': + optional: true + + '@mariozechner/clipboard-darwin-universal@0.3.2': + optional: true + + '@mariozechner/clipboard-darwin-x64@0.3.2': + optional: true + + '@mariozechner/clipboard-linux-arm64-gnu@0.3.2': + optional: true + + '@mariozechner/clipboard-linux-arm64-musl@0.3.2': + optional: true + + '@mariozechner/clipboard-linux-riscv64-gnu@0.3.2': + optional: true + + '@mariozechner/clipboard-linux-x64-gnu@0.3.2': + optional: true + + '@mariozechner/clipboard-linux-x64-musl@0.3.2': + optional: true + + '@mariozechner/clipboard-win32-arm64-msvc@0.3.2': + optional: true + + '@mariozechner/clipboard-win32-x64-msvc@0.3.2': + optional: true + + '@mariozechner/clipboard@0.3.2': + optionalDependencies: + '@mariozechner/clipboard-darwin-arm64': 0.3.2 + '@mariozechner/clipboard-darwin-universal': 0.3.2 + '@mariozechner/clipboard-darwin-x64': 0.3.2 + '@mariozechner/clipboard-linux-arm64-gnu': 0.3.2 + '@mariozechner/clipboard-linux-arm64-musl': 0.3.2 + '@mariozechner/clipboard-linux-riscv64-gnu': 0.3.2 + '@mariozechner/clipboard-linux-x64-gnu': 0.3.2 + '@mariozechner/clipboard-linux-x64-musl': 0.3.2 + '@mariozechner/clipboard-win32-arm64-msvc': 0.3.2 + '@mariozechner/clipboard-win32-x64-msvc': 0.3.2 + optional: true + + '@mariozechner/jiti@2.6.5': + dependencies: + std-env: 3.10.0 + yoctocolors: 2.1.2 + + '@mariozechner/pi-agent-core@0.67.6(ws@8.20.0)(zod@4.3.6)': + dependencies: + '@mariozechner/pi-ai': 0.67.6(ws@8.20.0)(zod@4.3.6) + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@mariozechner/pi-ai@0.67.6(ws@8.20.0)(zod@4.3.6)': + dependencies: + '@anthropic-ai/sdk': 0.90.0(zod@4.3.6) + '@aws-sdk/client-bedrock-runtime': 3.1031.0 + '@google/genai': 1.50.1 + '@mistralai/mistralai': 1.14.1 + '@sinclair/typebox': 0.34.49 + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + chalk: 5.6.2 + openai: 6.26.0(ws@8.20.0)(zod@4.3.6) + partial-json: 0.1.7 + proxy-agent: 6.5.0 + undici: 7.25.0 + zod-to-json-schema: 3.25.2(zod@4.3.6) + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@mariozechner/pi-coding-agent@0.67.6(ws@8.20.0)(zod@4.3.6)': + dependencies: + '@mariozechner/jiti': 2.6.5 + '@mariozechner/pi-agent-core': 0.67.6(ws@8.20.0)(zod@4.3.6) + '@mariozechner/pi-ai': 0.67.6(ws@8.20.0)(zod@4.3.6) + '@mariozechner/pi-tui': 0.67.6 + '@silvia-odwyer/photon-node': 0.3.4 + ajv: 8.18.0 + chalk: 5.6.2 + cli-highlight: 2.1.11 + diff: 8.0.4 + extract-zip: 2.0.1 + file-type: 21.3.4 + glob: 13.0.6 + hosted-git-info: 9.0.2 + ignore: 7.0.5 + marked: 15.0.12 + minimatch: 10.2.4 + proper-lockfile: 4.1.2 + strip-ansi: 7.2.0 + undici: 7.25.0 + uuid: 11.1.0 + yaml: 2.8.3 + optionalDependencies: + '@mariozechner/clipboard': 0.3.2 + transitivePeerDependencies: + - '@modelcontextprotocol/sdk' + - aws-crt + - bufferutil + - supports-color + - utf-8-validate + - ws + - zod + + '@mariozechner/pi-tui@0.67.6': + dependencies: + '@types/mime-types': 2.1.4 + chalk: 5.6.2 + get-east-asian-width: 1.5.0 + marked: 15.0.12 + mime-types: 3.0.2 + optionalDependencies: + koffi: 2.16.0 + + '@mistralai/mistralai@1.14.1': + dependencies: + ws: 8.20.0 + zod: 4.3.6 + zod-to-json-schema: 3.25.2(zod@4.3.6) + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -3601,6 +4888,29 @@ snapshots: dependencies: playwright: 1.58.2 + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1))(react@19.2.4)': dependencies: '@standard-schema/spec': 1.1.0 @@ -3690,8 +5000,312 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.59.0': optional: true + '@silvia-odwyer/photon-node@0.3.4': {} + + '@sinclair/typebox@0.34.49': {} + '@sindresorhus/is@4.6.0': {} + '@smithy/config-resolver@4.4.16': + dependencies: + '@smithy/node-config-provider': 4.3.14 + '@smithy/types': 4.14.1 + '@smithy/util-config-provider': 4.2.2 + '@smithy/util-endpoints': 3.4.1 + '@smithy/util-middleware': 4.2.14 + tslib: 2.8.1 + + '@smithy/core@3.23.15': + dependencies: + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 + '@smithy/util-base64': 4.3.2 + '@smithy/util-body-length-browser': 4.2.2 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-stream': 4.5.23 + '@smithy/util-utf8': 4.2.2 + '@smithy/uuid': 1.1.2 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.2.14': + dependencies: + '@smithy/node-config-provider': 4.3.14 + '@smithy/property-provider': 4.2.14 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 + tslib: 2.8.1 + + '@smithy/eventstream-codec@4.2.14': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.14.1 + '@smithy/util-hex-encoding': 4.2.2 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.2.14': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.3.14': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.2.14': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-universal@4.2.14': + dependencies: + '@smithy/eventstream-codec': 4.2.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.3.17': + dependencies: + '@smithy/protocol-http': 5.3.14 + '@smithy/querystring-builder': 4.2.14 + '@smithy/types': 4.14.1 + '@smithy/util-base64': 4.3.2 + tslib: 2.8.1 + + '@smithy/hash-node@4.2.14': + dependencies: + '@smithy/types': 4.14.1 + '@smithy/util-buffer-from': 4.2.2 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.2.14': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/is-array-buffer@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.2.14': + dependencies: + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.4.30': + dependencies: + '@smithy/core': 3.23.15 + '@smithy/middleware-serde': 4.2.18 + '@smithy/node-config-provider': 4.3.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 + '@smithy/util-middleware': 4.2.14 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.5.3': + dependencies: + '@smithy/core': 3.23.15 + '@smithy/node-config-provider': 4.3.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/service-error-classification': 4.2.14 + '@smithy/smithy-client': 4.12.11 + '@smithy/types': 4.14.1 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-retry': 4.3.2 + '@smithy/uuid': 1.1.2 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.2.18': + dependencies: + '@smithy/core': 3.23.15 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.2.14': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.3.14': + dependencies: + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.5.3': + dependencies: + '@smithy/protocol-http': 5.3.14 + '@smithy/querystring-builder': 4.2.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/property-provider@4.2.14': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/protocol-http@5.3.14': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.2.14': + dependencies: + '@smithy/types': 4.14.1 + '@smithy/util-uri-escape': 4.2.2 + tslib: 2.8.1 + + '@smithy/querystring-parser@4.2.14': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/service-error-classification@4.2.14': + dependencies: + '@smithy/types': 4.14.1 + + '@smithy/shared-ini-file-loader@4.4.9': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/signature-v4@5.3.14': + dependencies: + '@smithy/is-array-buffer': 4.2.2 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + '@smithy/util-hex-encoding': 4.2.2 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-uri-escape': 4.2.2 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@smithy/smithy-client@4.12.11': + dependencies: + '@smithy/core': 3.23.15 + '@smithy/middleware-endpoint': 4.4.30 + '@smithy/middleware-stack': 4.2.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + '@smithy/util-stream': 4.5.23 + tslib: 2.8.1 + + '@smithy/types@4.14.1': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.2.14': + dependencies: + '@smithy/querystring-parser': 4.2.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/util-base64@4.3.2': + dependencies: + '@smithy/util-buffer-from': 4.2.2 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@smithy/util-body-length-browser@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/util-body-length-node@4.2.3': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-buffer-from@4.2.2': + dependencies: + '@smithy/is-array-buffer': 4.2.2 + tslib: 2.8.1 + + '@smithy/util-config-provider@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/util-defaults-mode-browser@4.3.47': + dependencies: + '@smithy/property-provider': 4.2.14 + '@smithy/smithy-client': 4.12.11 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/util-defaults-mode-node@4.2.52': + dependencies: + '@smithy/config-resolver': 4.4.16 + '@smithy/credential-provider-imds': 4.2.14 + '@smithy/node-config-provider': 4.3.14 + '@smithy/property-provider': 4.2.14 + '@smithy/smithy-client': 4.12.11 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/util-endpoints@3.4.1': + dependencies: + '@smithy/node-config-provider': 4.3.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/util-middleware@4.2.14': + dependencies: + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/util-retry@4.3.2': + dependencies: + '@smithy/service-error-classification': 4.2.14 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@smithy/util-stream@4.5.23': + dependencies: + '@smithy/fetch-http-handler': 5.3.17 + '@smithy/node-http-handler': 4.5.3 + '@smithy/types': 4.14.1 + '@smithy/util-base64': 4.3.2 + '@smithy/util-buffer-from': 4.2.2 + '@smithy/util-hex-encoding': 4.2.2 + '@smithy/util-utf8': 4.2.2 + tslib: 2.8.1 + + '@smithy/util-uri-escape@4.2.2': + dependencies: + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.2.2': + dependencies: + '@smithy/util-buffer-from': 4.2.2 + tslib: 2.8.1 + + '@smithy/uuid@1.1.2': + dependencies: + tslib: 2.8.1 + '@standard-schema/spec@1.1.0': {} '@standard-schema/utils@0.3.0': {} @@ -3766,12 +5380,12 @@ snapshots: postcss-selector-parser: 6.0.10 tailwindcss: 4.2.1 - '@tailwindcss/vite@4.2.1(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1))': + '@tailwindcss/vite@4.2.1(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))': dependencies: '@tailwindcss/node': 4.2.1 '@tailwindcss/oxide': 4.2.1 tailwindcss: 4.2.1 - vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3) '@tanstack/react-virtual@3.13.23(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: @@ -3781,6 +5395,17 @@ snapshots: '@tanstack/virtual-core@3.13.23': {} + '@tokenizer/inflate@0.4.1': + dependencies: + debug: 4.4.3 + token-types: 6.1.2 + transitivePeerDependencies: + - supports-color + + '@tokenizer/token@0.3.0': {} + + '@tootallnate/quickjs-emscripten@0.23.0': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.29.0 @@ -3858,16 +5483,14 @@ snapshots: dependencies: '@types/node': 25.5.0 + '@types/mime-types@2.1.4': {} + '@types/ms@2.1.0': {} '@types/node@22.19.15': dependencies: undici-types: 6.21.0 - '@types/node@24.12.0': - dependencies: - undici-types: 7.16.0 - '@types/node@25.5.0': dependencies: undici-types: 7.18.2 @@ -3890,6 +5513,8 @@ snapshots: dependencies: '@types/node': 25.5.0 + '@types/retry@0.12.0': {} + '@types/use-sync-external-store@0.0.6': {} '@types/verror@1.10.11': @@ -3993,7 +5618,7 @@ snapshots: '@typescript-eslint/types': 8.46.1 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@5.2.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1))': + '@vitejs/plugin-react@5.2.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) @@ -4001,7 +5626,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-rc.3 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3) transitivePeerDependencies: - supports-color @@ -4014,13 +5639,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1))': + '@vitest/mocker@4.1.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.0 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3) '@vitest/pretty-format@4.1.0': dependencies: @@ -4058,6 +5683,10 @@ snapshots: agent-base@7.1.4: {} + ajv-formats@3.0.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + ajv-keywords@3.5.2(ajv@6.14.0): dependencies: ajv: 6.14.0 @@ -4069,6 +5698,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-regex@5.0.1: {} ansi-regex@6.2.2: {} @@ -4079,6 +5715,8 @@ snapshots: ansi-styles@6.2.3: {} + any-promise@1.3.0: {} + app-builder-bin@5.0.0-alpha.12: {} app-builder-lib@26.8.1(dmg-builder@26.8.1)(electron-builder-squirrel-windows@26.8.1): @@ -4131,6 +5769,10 @@ snapshots: assertion-error@2.0.1: {} + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + astral-regex@2.0.0: optional: true @@ -4150,6 +5792,10 @@ snapshots: baseline-browser-mapping@2.10.7: {} + basic-ftp@5.3.0: {} + + bignumber.js@9.3.1: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -4159,6 +5805,8 @@ snapshots: boolean@3.2.0: optional: true + bowser@2.14.1: {} + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -4186,6 +5834,8 @@ snapshots: buffer-crc32@0.2.13: {} + buffer-equal-constant-time@1.0.1: {} + buffer-from@1.1.2: {} buffer@5.7.1: @@ -4266,6 +5916,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chalk@5.6.2: {} + chownr@3.0.0: {} chromium-pickle-js@0.2.0: {} @@ -4278,6 +5930,15 @@ snapshots: dependencies: restore-cursor: 3.1.0 + cli-highlight@2.1.11: + dependencies: + chalk: 4.1.2 + highlight.js: 10.7.3 + mz: 2.7.0 + parse5: 5.1.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + yargs: 16.2.0 + cli-spinners@2.9.2: {} cli-truncate@2.1.0: @@ -4286,6 +5947,12 @@ snapshots: string-width: 4.2.3 optional: true + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -4380,6 +6047,10 @@ snapshots: d3-timer@3.0.1: {} + data-uri-to-buffer@4.0.1: {} + + data-uri-to-buffer@6.0.2: {} + debug@4.4.3: dependencies: ms: 2.1.3 @@ -4412,6 +6083,12 @@ snapshots: object-keys: 1.1.1 optional: true + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + delayed-stream@1.0.0: {} detect-libc@2.1.2: {} @@ -4419,6 +6096,8 @@ snapshots: detect-node@2.1.0: optional: true + diff@8.0.4: {} + dir-compare@4.2.0: dependencies: minimatch: 3.1.5 @@ -4463,6 +6142,10 @@ snapshots: eastasianwidth@0.2.0: {} + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + ejs@3.1.10: dependencies: jake: 10.9.4 @@ -4522,7 +6205,7 @@ snapshots: transitivePeerDependencies: - supports-color - electron-vite@5.0.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)): + electron-vite@5.0.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)): dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) @@ -4530,7 +6213,7 @@ snapshots: esbuild: 0.25.12 magic-string: 0.30.21 picocolors: 1.1.1 - vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3) transitivePeerDependencies: - supports-color @@ -4660,6 +6343,14 @@ snapshots: escape-string-regexp@4.0.0: {} + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + eslint-plugin-react-hooks@7.0.0(eslint@9.38.0(jiti@2.6.1)): dependencies: '@babel/core': 7.29.0 @@ -4731,6 +6422,8 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.16.0) eslint-visitor-keys: 4.2.1 + esprima@4.0.1: {} + esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -4753,6 +6446,8 @@ snapshots: exponential-backoff@3.1.3: {} + extend@3.0.2: {} + extract-zip@2.0.1: dependencies: debug: 4.4.3 @@ -4780,6 +6475,18 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-uri@3.1.0: {} + + fast-xml-builder@1.1.4: + dependencies: + path-expression-matcher: 1.5.0 + + fast-xml-parser@5.5.8: + dependencies: + fast-xml-builder: 1.1.4 + path-expression-matcher: 1.5.0 + strnum: 2.2.3 + fastq@1.20.1: dependencies: reusify: 1.1.0 @@ -4792,10 +6499,24 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fetch-blob@3.2.0: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.3 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 + file-type@21.3.4: + dependencies: + '@tokenizer/inflate': 0.4.1 + strtok3: 10.3.5 + token-types: 6.1.2 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + filelist@1.0.6: dependencies: minimatch: 5.1.9 @@ -4829,6 +6550,10 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + formdata-polyfill@4.0.10: + dependencies: + fetch-blob: 3.2.0 + framer-motion@12.36.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: motion-dom: 12.36.0 @@ -4883,10 +6608,28 @@ snapshots: function-bind@1.1.2: {} + gaxios@7.1.4: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.6 + node-fetch: 3.3.2 + transitivePeerDependencies: + - supports-color + + gcp-metadata@8.1.2: + dependencies: + gaxios: 7.1.4 + google-logging-utils: 1.1.3 + json-bigint: 1.0.0 + transitivePeerDependencies: + - supports-color + gensync@1.0.0-beta.2: {} get-caller-file@2.0.5: {} + get-east-asian-width@1.5.0: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -4909,6 +6652,14 @@ snapshots: dependencies: pump: 3.0.4 + get-uri@6.0.5: + dependencies: + basic-ftp: 5.3.0 + data-uri-to-buffer: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -4926,6 +6677,12 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + glob@13.0.6: + dependencies: + minimatch: 10.2.4 + minipass: 7.1.3 + path-scurry: 2.0.2 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -4955,6 +6712,19 @@ snapshots: gopd: 1.2.0 optional: true + google-auth-library@10.6.2: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 7.1.4 + gcp-metadata: 8.1.2 + google-logging-utils: 1.1.3 + jws: 4.0.1 + transitivePeerDependencies: + - supports-color + + google-logging-utils@1.1.3: {} + gopd@1.2.0: {} got@11.8.6: @@ -4998,10 +6768,16 @@ snapshots: dependencies: hermes-estree: 0.25.1 + highlight.js@10.7.3: {} + hosted-git-info@4.1.0: dependencies: lru-cache: 6.0.0 + hosted-git-info@9.0.2: + dependencies: + lru-cache: 11.3.5 + http-cache-semantics@4.2.0: {} http-proxy-agent@7.0.2: @@ -5105,10 +6881,21 @@ snapshots: jsesc@3.1.0: {} + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.3.1 + json-buffer@3.0.1: {} + json-schema-to-ts@3.1.1: + dependencies: + '@babel/runtime': 7.29.2 + ts-algebra: 2.0.0 + json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json-stringify-safe@5.0.1: @@ -5126,10 +6913,24 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.1: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 + koffi@2.16.0: + optional: true + lazy-val@1.0.5: {} levn@0.4.1: @@ -5203,10 +7004,14 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + long@5.3.2: {} + lowercase-keys@2.0.0: {} lru-cache@10.4.3: {} + lru-cache@11.3.5: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -5215,6 +7020,8 @@ snapshots: dependencies: yallist: 4.0.0 + lru-cache@7.18.3: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -5235,6 +7042,8 @@ snapshots: transitivePeerDependencies: - supports-color + marked@15.0.12: {} + matcher@3.0.0: dependencies: escape-string-regexp: 4.0.0 @@ -5251,10 +7060,16 @@ snapshots: mime-db@1.52.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + mime@2.6.0: {} mimic-fn@2.1.0: {} @@ -5327,12 +7142,20 @@ snapshots: ms@2.1.3: {} + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + nanoid@3.3.11: {} natural-compare@1.4.0: {} negotiator@1.0.0: {} + netmask@2.1.1: {} + node-abi@4.27.0: dependencies: semver: 7.7.4 @@ -5344,6 +7167,14 @@ snapshots: dependencies: semver: 7.7.4 + node-domexception@1.0.0: {} + + node-fetch@3.3.2: + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + node-gyp@11.5.0: dependencies: env-paths: 2.2.1 @@ -5367,6 +7198,8 @@ snapshots: normalize-url@6.1.0: {} + object-assign@4.1.1: {} + object-keys@1.1.1: optional: true @@ -5380,6 +7213,11 @@ snapshots: dependencies: mimic-fn: 2.1.0 + openai@6.26.0(ws@8.20.0)(zod@4.3.6): + optionalDependencies: + ws: 8.20.0 + zod: 4.3.6 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -5413,14 +7251,49 @@ snapshots: p-map@7.0.4: {} + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + pac-proxy-agent@7.2.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.4 + debug: 4.4.3 + get-uri: 6.0.5 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.1.1 + package-json-from-dist@1.0.1: {} parent-module@1.0.1: dependencies: callsites: 3.1.0 + parse5-htmlparser2-tree-adapter@6.0.1: + dependencies: + parse5: 6.0.1 + + parse5@5.1.1: {} + + parse5@6.0.1: {} + + partial-json@0.1.7: {} + path-exists@4.0.0: {} + path-expression-matcher@1.5.0: {} + path-is-absolute@1.0.1: {} path-key@3.1.1: {} @@ -5430,6 +7303,11 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.3 + path-scurry@2.0.2: + dependencies: + lru-cache: 11.3.5 + minipass: 7.1.3 + pathe@2.0.3: {} pe-library@0.4.1: {} @@ -5489,6 +7367,36 @@ snapshots: retry: 0.12.0 signal-exit: 3.0.7 + protobufjs@7.5.5: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 25.5.0 + long: 5.3.2 + + proxy-agent@6.5.0: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 7.18.3 + pac-proxy-agent: 7.2.0 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + pump@3.0.4: dependencies: end-of-stream: 1.4.5 @@ -5560,6 +7468,8 @@ snapshots: require-directory@2.1.1: {} + require-from-string@2.0.2: {} + resedit@1.7.2: dependencies: pe-library: 0.4.1 @@ -5581,6 +7491,8 @@ snapshots: retry@0.12.0: {} + retry@0.13.1: {} + reusify@1.1.0: {} rimraf@2.6.3: @@ -5716,6 +7628,8 @@ snapshots: stat-mode@1.0.0: {} + std-env@3.10.0: {} + std-env@4.0.0: {} string-width@4.2.3: @@ -5744,6 +7658,12 @@ snapshots: strip-json-comments@3.1.1: {} + strnum@2.2.3: {} + + strtok3@10.3.5: + dependencies: + '@tokenizer/token': 0.3.0 + sumchecker@3.0.1: dependencies: debug: 4.4.3 @@ -5776,6 +7696,14 @@ snapshots: mkdirp: 0.5.6 rimraf: 2.6.3 + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + tiny-async-pool@1.3.0: dependencies: semver: 5.7.2 @@ -5805,10 +7733,18 @@ snapshots: dependencies: is-number: 7.0.0 + token-types@6.1.2: + dependencies: + '@borewit/text-codec': 0.2.2 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + truncate-utf8-bytes@1.0.2: dependencies: utf8-byte-length: 1.0.5 + ts-algebra@2.0.0: {} + ts-api-utils@2.4.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -5835,12 +7771,14 @@ snapshots: typescript@5.9.3: {} + uint8array-extras@1.5.0: {} + undici-types@6.21.0: {} - undici-types@7.16.0: {} - undici-types@7.18.2: {} + undici@7.25.0: {} + unique-filename@4.0.0: dependencies: unique-slug: 5.0.0 @@ -5871,6 +7809,8 @@ snapshots: util-deprecate@1.0.2: {} + uuid@11.1.0: {} + verror@1.10.1: dependencies: assert-plus: 1.0.0 @@ -5895,7 +7835,7 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1): + vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3): dependencies: esbuild: 0.27.4 fdir: 6.5.0(picomatch@4.0.3) @@ -5908,11 +7848,12 @@ snapshots: fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.31.1 + yaml: 2.8.3 - vitest@4.1.0(@types/node@25.5.0)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)): + vitest@4.1.0(@types/node@25.5.0)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.0 - '@vitest/mocker': 4.1.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)) + '@vitest/mocker': 4.1.0(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3)) '@vitest/pretty-format': 4.1.0 '@vitest/runner': 4.1.0 '@vitest/snapshot': 4.1.0 @@ -5929,7 +7870,7 @@ snapshots: tinyexec: 1.0.4 tinyglobby: 0.2.15 tinyrainbow: 3.1.0 - vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.5.0 @@ -5940,6 +7881,8 @@ snapshots: dependencies: defaults: 1.0.4 + web-streams-polyfill@3.3.3: {} + which@2.0.2: dependencies: isexe: 2.0.0 @@ -5969,6 +7912,8 @@ snapshots: wrappy@1.0.2: {} + ws@8.20.0: {} + xmlbuilder@15.1.1: {} y18n@5.0.8: {} @@ -5979,8 +7924,22 @@ snapshots: yallist@5.0.0: {} + yaml@2.8.3: {} + + yargs-parser@20.2.9: {} + yargs-parser@21.1.1: {} + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + yargs@17.7.2: dependencies: cliui: 8.0.1 @@ -5998,6 +7957,12 @@ snapshots: yocto-queue@0.1.0: {} + yoctocolors@2.1.2: {} + + zod-to-json-schema@3.25.2(zod@4.3.6): + dependencies: + zod: 4.3.6 + zod-validation-error@4.0.2(zod@4.3.6): dependencies: zod: 4.3.6