diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index e665cfc..83ffc5a 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -1,33 +1,33 @@ name: PR Checks on: - pull_request: - branches: [master, dev] + pull_request: + branches: [master, dev] jobs: - validate: - name: Type Check, Build & Audit - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Type check - run: npm run typecheck - - - name: Build - run: npm run build - - - name: Security audit - run: npm audit --audit-level=high - continue-on-error: false + validate: + name: Type Check, Build & Audit + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "npm" + + - name: Install dependencies + run: npm ci + + - name: Type check + run: npm run typecheck + + - name: Build + run: npm run build + + - name: Security audit + run: npm audit --audit-level=high + continue-on-error: false diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..3325b6e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,10 @@ +{ + "semi": false, + "singleQuote": false, + "tabWidth": 4, + "useTabs": false, + "trailingComma": "all", + "printWidth": 100, + "bracketSpacing": true, + "arrowParens": "always" +} diff --git a/README.md b/README.md index 9d15e73..f0af36f 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Add to your OpenCode config: ```jsonc // opencode.jsonc { - "plugin": ["@tarquinen/opencode-dcp@latest"] + "plugin": ["@tarquinen/opencode-dcp@latest"], } ``` @@ -54,53 +54,53 @@ DCP uses its own config file: ```jsonc { - // Enable or disable the plugin - "enabled": true, - // Enable debug logging to ~/.config/opencode/logs/dcp/ - "debug": false, - // Summary display: "off", "minimal", or "detailed" - "pruningSummary": "detailed", - // Strategies for pruning tokens from chat history - "strategies": { - // Remove duplicate tool calls (same tool with same arguments) - "deduplication": { - "enabled": true, - // Additional tools to protect from pruning - "protectedTools": [] + // Enable or disable the plugin + "enabled": true, + // Enable debug logging to ~/.config/opencode/logs/dcp/ + "debug": false, + // Summary display: "off", "minimal", or "detailed" + "pruningSummary": "detailed", + // Strategies for pruning tokens from chat history + "strategies": { + // Remove duplicate tool calls (same tool with same arguments) + "deduplication": { + "enabled": true, + // Additional tools to protect from pruning + "protectedTools": [], + }, + // Prune write tool inputs when the file has been subsequently read + "supersedeWrites": { + "enabled": true, + }, + // Exposes a prune tool to your LLM to call when it determines pruning is necessary + "pruneTool": { + "enabled": true, + // Additional tools to protect from pruning + "protectedTools": [], + // Protect from pruning for message turns + "turnProtection": { + "enabled": false, + "turns": 4, + }, + // Nudge the LLM to use the prune tool (every tool results) + "nudge": { + "enabled": true, + "frequency": 10, + }, + }, + // (Legacy) Run an LLM to analyze what tool calls are no longer relevant on idle + "onIdle": { + "enabled": false, + // Additional tools to protect from pruning + "protectedTools": [], + // Override model for analysis (format: "provider/model") + // "model": "anthropic/claude-haiku-4-5", + // Show toast notifications when model selection fails + "showModelErrorToasts": true, + // When true, fallback models are not permitted + "strictModelSelection": false, + }, }, - // Prune write tool inputs when the file has been subsequently read - "supersedeWrites": { - "enabled": true - }, - // Exposes a prune tool to your LLM to call when it determines pruning is necessary - "pruneTool": { - "enabled": true, - // Additional tools to protect from pruning - "protectedTools": [], - // Protect from pruning for message turns - "turnProtection": { - "enabled": false, - "turns": 4 - }, - // Nudge the LLM to use the prune tool (every tool results) - "nudge": { - "enabled": true, - "frequency": 10 - } - }, - // (Legacy) Run an LLM to analyze what tool calls are no longer relevant on idle - "onIdle": { - "enabled": false, - // Additional tools to protect from pruning - "protectedTools": [], - // Override model for analysis (format: "provider/model") - // "model": "anthropic/claude-haiku-4-5", - // Show toast notifications when model selection fails - "showModelErrorToasts": true, - // When true, fallback models are not permitted - "strictModelSelection": false - } - } } ``` diff --git a/index.ts b/index.ts index ac87705..224b7cd 100644 --- a/index.ts +++ b/index.ts @@ -5,6 +5,7 @@ import { loadPrompt } from "./lib/prompt" import { createSessionState } from "./lib/state" import { createPruneTool } from "./lib/strategies" import { createChatMessageTransformHandler, createEventHandler } from "./lib/hooks" +import { getPendingPrune, setPendingPrune, setAutoConfirm } from "./lib/ui/confirmation" const plugin: Plugin = (async (ctx) => { const config = getConfig(ctx) @@ -14,8 +15,8 @@ const plugin: Plugin = (async (ctx) => { } // Suppress AI SDK warnings - if (typeof globalThis !== 'undefined') { - (globalThis as any).AI_SDK_LOG_WARNINGS = false + if (typeof globalThis !== "undefined") { + ;(globalThis as any).AI_SDK_LOG_WARNINGS = false } // Initialize core components @@ -28,7 +29,227 @@ const plugin: Plugin = (async (ctx) => { }) return { - "experimental.chat.system.transform": async (_input: unknown, output: { system: string[] }) => { + ui: [ + { + name: "dcp-prune-summary", + inline: true, + template: { + type: "box", + direction: "column", + gap: 0, + children: [ + { + type: "box", + direction: "row", + gap: 1, + children: [ + { + type: "text", + content: "▣", + fg: "textMuted", + }, + { + type: "text", + content: "DCP", + fg: "text", + bold: true, + }, + { + type: "text", + content: "{{saved}} saved", + fg: "textMuted", + }, + ], + }, + { + type: "collapsible", + title: "{{count}} items pruned", + expanded: false, + fg: "textMuted", + fgExpanded: "text", + icon: "▶", + iconExpanded: "▼", + children: [ + { + type: "text", + content: "{{itemsList}}", + fg: "textMuted", + }, + ], + }, + ], + }, + }, + { + name: "dcp-confirm", + replaceInput: true, + modals: [ + { + name: "dcp-settings", + template: { + type: "box", + direction: "column", + gap: 1, + children: [ + { + type: "text", + content: "DCP Settings", + fg: "text", + bold: true, + }, + { + type: "text", + content: "Configure pruning behavior", + fg: "textMuted", + }, + ], + }, + }, + ], + template: { + type: "box", + direction: "column", + bg: "backgroundPanel", + paddingY: 0, + gap: 0, + children: [ + { + type: "box", + direction: "row", + gap: 1, + paddingX: 2, + paddingY: 1, + justifyContent: "space-between", + children: [ + { + type: "text", + content: "Select files to prune", + fg: "text", + bold: true, + }, + { + type: "icon", + icon: "⚙", + fg: "textMuted", + fgHover: "warning", + onModal: "dcp-settings", + }, + ], + }, + { + type: "box", + direction: "column", + paddingX: 2, + paddingBottom: 1, + children: [ + { + type: "checklist", + items: "{{items}}", + fg: "textMuted", + fgChecked: "text", + borderColorChecked: "warning", + onToggle: "item-toggled", + }, + ], + }, + { + type: "box", + direction: "row", + gap: 0, + justifyContent: "space-between", + bg: "backgroundElement", + paddingY: 1, + paddingX: 2, + children: [ + { + type: "box", + direction: "row", + gap: 0, + children: [ + { + type: "text", + content: "click items to select", + fg: "textMuted", + }, + ], + }, + { + type: "button-group", + gap: 1, + defaultIndex: 2, + bgColor: "backgroundElement", + children: [ + { + type: "confirm-button", + label: "Reject", + fg: "textMuted", + bg: "backgroundPanel", + fgHover: "warning", + borderColorHover: "warning", + onConfirm: "cancel-prune", + }, + { + type: "confirm-button", + label: "Auto", + fg: "textMuted", + bg: "backgroundPanel", + fgHover: "warning", + borderColorHover: "warning", + onConfirm: "auto-prune", + }, + { + type: "confirm-button", + label: "Confirm", + fg: "textMuted", + bg: "backgroundPanel", + fgHover: "warning", + borderColorHover: "warning", + onConfirm: "confirm-prune", + }, + ], + }, + ], + }, + ], + }, + }, + ], + "ui.event": async (event: { + component: string + event: string + data: Record + }) => { + logger.info("UI Event received", event) + + if (event.component === "dcp-confirm") { + const pending = getPendingPrune() + if (event.event === "item-toggled" && event.data.items && pending) { + // Update the pending items state + pending.items = event.data.items + } else if (event.event === "confirm-prune" && pending) { + const confirmed = pending.items + .filter((i: { checked: boolean }) => i.checked) + .map((i: { id: string }) => i.id) + pending.resolve(confirmed) + setPendingPrune(null) + } else if (event.event === "cancel-prune" && pending) { + pending.resolve([]) + setPendingPrune(null) + } else if (event.event === "auto-prune" && pending) { + // Enable auto-confirm and confirm this one + setAutoConfirm(true) + const confirmed = pending.items + .filter((i: { checked: boolean }) => i.checked) + .map((i: { id: string }) => i.id) + pending.resolve(confirmed) + setPendingPrune(null) + } + } + }, + "experimental.chat.system.transform": async ( + _input: unknown, + output: { system: string[] }, + ) => { const syntheticPrompt = loadPrompt("prune-system-prompt") output.system.push(syntheticPrompt) }, @@ -36,17 +257,19 @@ const plugin: Plugin = (async (ctx) => { ctx.client, state, logger, - config + config, ), - tool: config.strategies.pruneTool.enabled ? { - prune: createPruneTool({ - client: ctx.client, - state, - logger, - config, - workingDirectory: ctx.directory - }), - } : undefined, + tool: config.strategies.pruneTool.enabled + ? { + prune: createPruneTool({ + client: ctx.client, + state, + logger, + config, + workingDirectory: ctx.directory, + }), + } + : undefined, config: async (opencodeConfig) => { // Add prune to primary_tools by mutating the opencode config // This works because config is cached and passed by reference @@ -59,7 +282,9 @@ const plugin: Plugin = (async (ctx) => { logger.info("Added 'prune' to experimental.primary_tools via config mutation") } }, - event: createEventHandler(ctx.client, config, state, logger, ctx.directory), + event: createEventHandler(ctx.client, config, state, logger, ctx.directory, () => + setAutoConfirm(false), + ), } }) satisfies Plugin diff --git a/lib/config.ts b/lib/config.ts index 9a670fe..8e30119 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -1,8 +1,8 @@ -import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync } from 'fs' -import { join, dirname } from 'path' -import { homedir } from 'os' -import { parse } from 'jsonc-parser' -import type { PluginInput } from '@opencode-ai/plugin' +import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync } from "fs" +import { join, dirname } from "path" +import { homedir } from "os" +import { parse } from "jsonc-parser" +import type { PluginInput } from "@opencode-ai/plugin" export interface Deduplication { enabled: boolean @@ -50,49 +50,49 @@ export interface PluginConfig { } } -const DEFAULT_PROTECTED_TOOLS = ['task', 'todowrite', 'todoread', 'prune', 'batch'] +const DEFAULT_PROTECTED_TOOLS = ["task", "todowrite", "todoread", "prune", "batch"] // Valid config keys for validation against user config export const VALID_CONFIG_KEYS = new Set([ // Top-level keys - 'enabled', - 'debug', - 'showUpdateToasts', // Deprecated but kept for backwards compatibility - 'pruningSummary', - 'strategies', + "enabled", + "debug", + "showUpdateToasts", // Deprecated but kept for backwards compatibility + "pruningSummary", + "strategies", // strategies.deduplication - 'strategies.deduplication', - 'strategies.deduplication.enabled', - 'strategies.deduplication.protectedTools', + "strategies.deduplication", + "strategies.deduplication.enabled", + "strategies.deduplication.protectedTools", // strategies.supersedeWrites - 'strategies.supersedeWrites', - 'strategies.supersedeWrites.enabled', + "strategies.supersedeWrites", + "strategies.supersedeWrites.enabled", // strategies.onIdle - 'strategies.onIdle', - 'strategies.onIdle.enabled', - 'strategies.onIdle.model', - 'strategies.onIdle.showModelErrorToasts', - 'strategies.onIdle.strictModelSelection', - 'strategies.onIdle.protectedTools', + "strategies.onIdle", + "strategies.onIdle.enabled", + "strategies.onIdle.model", + "strategies.onIdle.showModelErrorToasts", + "strategies.onIdle.strictModelSelection", + "strategies.onIdle.protectedTools", // strategies.pruneTool - 'strategies.pruneTool', - 'strategies.pruneTool.enabled', - 'strategies.pruneTool.protectedTools', - 'strategies.pruneTool.turnProtection', - 'strategies.pruneTool.turnProtection.enabled', - 'strategies.pruneTool.turnProtection.turns', - 'strategies.pruneTool.nudge', - 'strategies.pruneTool.nudge.enabled', - 'strategies.pruneTool.nudge.frequency' + "strategies.pruneTool", + "strategies.pruneTool.enabled", + "strategies.pruneTool.protectedTools", + "strategies.pruneTool.turnProtection", + "strategies.pruneTool.turnProtection.enabled", + "strategies.pruneTool.turnProtection.turns", + "strategies.pruneTool.nudge", + "strategies.pruneTool.nudge.enabled", + "strategies.pruneTool.nudge.frequency", ]) // Extract all key paths from a config object for validation -function getConfigKeyPaths(obj: Record, prefix = ''): string[] { +function getConfigKeyPaths(obj: Record, prefix = ""): string[] { const keys: string[] = [] for (const key of Object.keys(obj)) { const fullKey = prefix ? `${prefix}.${key}` : key keys.push(fullKey) - if (obj[key] && typeof obj[key] === 'object' && !Array.isArray(obj[key])) { + if (obj[key] && typeof obj[key] === "object" && !Array.isArray(obj[key])) { keys.push(...getConfigKeyPaths(obj[key], fullKey)) } } @@ -102,7 +102,7 @@ function getConfigKeyPaths(obj: Record, prefix = ''): string[] { // Returns invalid keys found in user config export function getInvalidConfigKeys(userConfig: Record): string[] { const userKeys = getConfigKeyPaths(userConfig) - return userKeys.filter(key => !VALID_CONFIG_KEYS.has(key)) + return userKeys.filter((key) => !VALID_CONFIG_KEYS.has(key)) } // Type validators for config values @@ -116,16 +116,20 @@ function validateConfigTypes(config: Record): ValidationError[] { const errors: ValidationError[] = [] // Top-level validators - if (config.enabled !== undefined && typeof config.enabled !== 'boolean') { - errors.push({ key: 'enabled', expected: 'boolean', actual: typeof config.enabled }) + if (config.enabled !== undefined && typeof config.enabled !== "boolean") { + errors.push({ key: "enabled", expected: "boolean", actual: typeof config.enabled }) } - if (config.debug !== undefined && typeof config.debug !== 'boolean') { - errors.push({ key: 'debug', expected: 'boolean', actual: typeof config.debug }) + if (config.debug !== undefined && typeof config.debug !== "boolean") { + errors.push({ key: "debug", expected: "boolean", actual: typeof config.debug }) } if (config.pruningSummary !== undefined) { - const validValues = ['off', 'minimal', 'detailed'] + const validValues = ["off", "minimal", "detailed"] if (!validValues.includes(config.pruningSummary)) { - errors.push({ key: 'pruningSummary', expected: '"off" | "minimal" | "detailed"', actual: JSON.stringify(config.pruningSummary) }) + errors.push({ + key: "pruningSummary", + expected: '"off" | "minimal" | "detailed"', + actual: JSON.stringify(config.pruningSummary), + }) } } @@ -133,62 +137,160 @@ function validateConfigTypes(config: Record): ValidationError[] { const strategies = config.strategies if (strategies) { // deduplication - if (strategies.deduplication?.enabled !== undefined && typeof strategies.deduplication.enabled !== 'boolean') { - errors.push({ key: 'strategies.deduplication.enabled', expected: 'boolean', actual: typeof strategies.deduplication.enabled }) + if ( + strategies.deduplication?.enabled !== undefined && + typeof strategies.deduplication.enabled !== "boolean" + ) { + errors.push({ + key: "strategies.deduplication.enabled", + expected: "boolean", + actual: typeof strategies.deduplication.enabled, + }) } - if (strategies.deduplication?.protectedTools !== undefined && !Array.isArray(strategies.deduplication.protectedTools)) { - errors.push({ key: 'strategies.deduplication.protectedTools', expected: 'string[]', actual: typeof strategies.deduplication.protectedTools }) + if ( + strategies.deduplication?.protectedTools !== undefined && + !Array.isArray(strategies.deduplication.protectedTools) + ) { + errors.push({ + key: "strategies.deduplication.protectedTools", + expected: "string[]", + actual: typeof strategies.deduplication.protectedTools, + }) } // onIdle if (strategies.onIdle) { - if (strategies.onIdle.enabled !== undefined && typeof strategies.onIdle.enabled !== 'boolean') { - errors.push({ key: 'strategies.onIdle.enabled', expected: 'boolean', actual: typeof strategies.onIdle.enabled }) + if ( + strategies.onIdle.enabled !== undefined && + typeof strategies.onIdle.enabled !== "boolean" + ) { + errors.push({ + key: "strategies.onIdle.enabled", + expected: "boolean", + actual: typeof strategies.onIdle.enabled, + }) } - if (strategies.onIdle.model !== undefined && typeof strategies.onIdle.model !== 'string') { - errors.push({ key: 'strategies.onIdle.model', expected: 'string', actual: typeof strategies.onIdle.model }) + if ( + strategies.onIdle.model !== undefined && + typeof strategies.onIdle.model !== "string" + ) { + errors.push({ + key: "strategies.onIdle.model", + expected: "string", + actual: typeof strategies.onIdle.model, + }) } - if (strategies.onIdle.showModelErrorToasts !== undefined && typeof strategies.onIdle.showModelErrorToasts !== 'boolean') { - errors.push({ key: 'strategies.onIdle.showModelErrorToasts', expected: 'boolean', actual: typeof strategies.onIdle.showModelErrorToasts }) + if ( + strategies.onIdle.showModelErrorToasts !== undefined && + typeof strategies.onIdle.showModelErrorToasts !== "boolean" + ) { + errors.push({ + key: "strategies.onIdle.showModelErrorToasts", + expected: "boolean", + actual: typeof strategies.onIdle.showModelErrorToasts, + }) } - if (strategies.onIdle.strictModelSelection !== undefined && typeof strategies.onIdle.strictModelSelection !== 'boolean') { - errors.push({ key: 'strategies.onIdle.strictModelSelection', expected: 'boolean', actual: typeof strategies.onIdle.strictModelSelection }) + if ( + strategies.onIdle.strictModelSelection !== undefined && + typeof strategies.onIdle.strictModelSelection !== "boolean" + ) { + errors.push({ + key: "strategies.onIdle.strictModelSelection", + expected: "boolean", + actual: typeof strategies.onIdle.strictModelSelection, + }) } - if (strategies.onIdle.protectedTools !== undefined && !Array.isArray(strategies.onIdle.protectedTools)) { - errors.push({ key: 'strategies.onIdle.protectedTools', expected: 'string[]', actual: typeof strategies.onIdle.protectedTools }) + if ( + strategies.onIdle.protectedTools !== undefined && + !Array.isArray(strategies.onIdle.protectedTools) + ) { + errors.push({ + key: "strategies.onIdle.protectedTools", + expected: "string[]", + actual: typeof strategies.onIdle.protectedTools, + }) } } // pruneTool if (strategies.pruneTool) { - if (strategies.pruneTool.enabled !== undefined && typeof strategies.pruneTool.enabled !== 'boolean') { - errors.push({ key: 'strategies.pruneTool.enabled', expected: 'boolean', actual: typeof strategies.pruneTool.enabled }) + if ( + strategies.pruneTool.enabled !== undefined && + typeof strategies.pruneTool.enabled !== "boolean" + ) { + errors.push({ + key: "strategies.pruneTool.enabled", + expected: "boolean", + actual: typeof strategies.pruneTool.enabled, + }) } - if (strategies.pruneTool.protectedTools !== undefined && !Array.isArray(strategies.pruneTool.protectedTools)) { - errors.push({ key: 'strategies.pruneTool.protectedTools', expected: 'string[]', actual: typeof strategies.pruneTool.protectedTools }) + if ( + strategies.pruneTool.protectedTools !== undefined && + !Array.isArray(strategies.pruneTool.protectedTools) + ) { + errors.push({ + key: "strategies.pruneTool.protectedTools", + expected: "string[]", + actual: typeof strategies.pruneTool.protectedTools, + }) } if (strategies.pruneTool.turnProtection) { - if (strategies.pruneTool.turnProtection.enabled !== undefined && typeof strategies.pruneTool.turnProtection.enabled !== 'boolean') { - errors.push({ key: 'strategies.pruneTool.turnProtection.enabled', expected: 'boolean', actual: typeof strategies.pruneTool.turnProtection.enabled }) + if ( + strategies.pruneTool.turnProtection.enabled !== undefined && + typeof strategies.pruneTool.turnProtection.enabled !== "boolean" + ) { + errors.push({ + key: "strategies.pruneTool.turnProtection.enabled", + expected: "boolean", + actual: typeof strategies.pruneTool.turnProtection.enabled, + }) } - if (strategies.pruneTool.turnProtection.turns !== undefined && typeof strategies.pruneTool.turnProtection.turns !== 'number') { - errors.push({ key: 'strategies.pruneTool.turnProtection.turns', expected: 'number', actual: typeof strategies.pruneTool.turnProtection.turns }) + if ( + strategies.pruneTool.turnProtection.turns !== undefined && + typeof strategies.pruneTool.turnProtection.turns !== "number" + ) { + errors.push({ + key: "strategies.pruneTool.turnProtection.turns", + expected: "number", + actual: typeof strategies.pruneTool.turnProtection.turns, + }) } } if (strategies.pruneTool.nudge) { - if (strategies.pruneTool.nudge.enabled !== undefined && typeof strategies.pruneTool.nudge.enabled !== 'boolean') { - errors.push({ key: 'strategies.pruneTool.nudge.enabled', expected: 'boolean', actual: typeof strategies.pruneTool.nudge.enabled }) + if ( + strategies.pruneTool.nudge.enabled !== undefined && + typeof strategies.pruneTool.nudge.enabled !== "boolean" + ) { + errors.push({ + key: "strategies.pruneTool.nudge.enabled", + expected: "boolean", + actual: typeof strategies.pruneTool.nudge.enabled, + }) } - if (strategies.pruneTool.nudge.frequency !== undefined && typeof strategies.pruneTool.nudge.frequency !== 'number') { - errors.push({ key: 'strategies.pruneTool.nudge.frequency', expected: 'number', actual: typeof strategies.pruneTool.nudge.frequency }) + if ( + strategies.pruneTool.nudge.frequency !== undefined && + typeof strategies.pruneTool.nudge.frequency !== "number" + ) { + errors.push({ + key: "strategies.pruneTool.nudge.frequency", + expected: "number", + actual: typeof strategies.pruneTool.nudge.frequency, + }) } } } // supersedeWrites if (strategies.supersedeWrites) { - if (strategies.supersedeWrites.enabled !== undefined && typeof strategies.supersedeWrites.enabled !== 'boolean') { - errors.push({ key: 'strategies.supersedeWrites.enabled', expected: 'boolean', actual: typeof strategies.supersedeWrites.enabled }) + if ( + strategies.supersedeWrites.enabled !== undefined && + typeof strategies.supersedeWrites.enabled !== "boolean" + ) { + errors.push({ + key: "strategies.supersedeWrites.enabled", + expected: "boolean", + actual: typeof strategies.supersedeWrites.enabled, + }) } } } @@ -201,7 +303,7 @@ function showConfigValidationWarnings( ctx: PluginInput, configPath: string, configData: Record, - isProject: boolean + isProject: boolean, ): void { const invalidKeys = getInvalidConfigKeys(configData) const typeErrors = validateConfigTypes(configData) @@ -210,12 +312,12 @@ function showConfigValidationWarnings( return } - const configType = isProject ? 'project config' : 'config' + const configType = isProject ? "project config" : "config" const messages: string[] = [] if (invalidKeys.length > 0) { - const keyList = invalidKeys.slice(0, 3).join(', ') - const suffix = invalidKeys.length > 3 ? ` (+${invalidKeys.length - 3} more)` : '' + const keyList = invalidKeys.slice(0, 3).join(", ") + const suffix = invalidKeys.length > 3 ? ` (+${invalidKeys.length - 3} more)` : "" messages.push(`Unknown keys: ${keyList}${suffix}`) } @@ -233,10 +335,10 @@ function showConfigValidationWarnings( ctx.client.tui.showToast({ body: { title: `DCP: Invalid ${configType}`, - message: `${configPath}\n${messages.join('\n')}`, + message: `${configPath}\n${messages.join("\n")}`, variant: "warning", - duration: 7000 - } + duration: 7000, + }, }) } catch {} }, 7000) @@ -245,44 +347,44 @@ function showConfigValidationWarnings( const defaultConfig: PluginConfig = { enabled: true, debug: false, - pruningSummary: 'detailed', + pruningSummary: "detailed", strategies: { deduplication: { enabled: true, - protectedTools: [...DEFAULT_PROTECTED_TOOLS] + protectedTools: [...DEFAULT_PROTECTED_TOOLS], }, supersedeWrites: { - enabled: true + enabled: true, }, pruneTool: { enabled: true, protectedTools: [...DEFAULT_PROTECTED_TOOLS], turnProtection: { enabled: false, - turns: 4 + turns: 4, }, nudge: { enabled: true, - frequency: 10 - } + frequency: 10, + }, }, onIdle: { enabled: false, protectedTools: [...DEFAULT_PROTECTED_TOOLS], showModelErrorToasts: true, - strictModelSelection: false - } - } + strictModelSelection: false, + }, + }, } -const GLOBAL_CONFIG_DIR = join(homedir(), '.config', 'opencode') -const GLOBAL_CONFIG_PATH_JSONC = join(GLOBAL_CONFIG_DIR, 'dcp.jsonc') -const GLOBAL_CONFIG_PATH_JSON = join(GLOBAL_CONFIG_DIR, 'dcp.json') +const GLOBAL_CONFIG_DIR = join(homedir(), ".config", "opencode") +const GLOBAL_CONFIG_PATH_JSONC = join(GLOBAL_CONFIG_DIR, "dcp.jsonc") +const GLOBAL_CONFIG_PATH_JSON = join(GLOBAL_CONFIG_DIR, "dcp.json") function findOpencodeDir(startDir: string): string | null { let current = startDir - while (current !== '/') { - const candidate = join(current, '.opencode') + while (current !== "/") { + const candidate = join(current, ".opencode") if (existsSync(candidate) && statSync(candidate).isDirectory()) { return candidate } @@ -293,7 +395,11 @@ function findOpencodeDir(startDir: string): string | null { return null } -function getConfigPaths(ctx?: PluginInput): { global: string | null, configDir: string | null, project: string | null} { +function getConfigPaths(ctx?: PluginInput): { + global: string | null + configDir: string | null + project: string | null +} { // Global: ~/.config/opencode/dcp.jsonc|json let globalPath: string | null = null if (existsSync(GLOBAL_CONFIG_PATH_JSONC)) { @@ -306,8 +412,8 @@ function getConfigPaths(ctx?: PluginInput): { global: string | null, configDir: let configDirPath: string | null = null const opencodeConfigDir = process.env.OPENCODE_CONFIG_DIR if (opencodeConfigDir) { - const configJsonc = join(opencodeConfigDir, 'dcp.jsonc') - const configJson = join(opencodeConfigDir, 'dcp.json') + const configJsonc = join(opencodeConfigDir, "dcp.jsonc") + const configJson = join(opencodeConfigDir, "dcp.json") if (existsSync(configJsonc)) { configDirPath = configJsonc } else if (existsSync(configJson)) { @@ -320,8 +426,8 @@ function getConfigPaths(ctx?: PluginInput): { global: string | null, configDir: if (ctx?.directory) { const opencodeDir = findOpencodeDir(ctx.directory) if (opencodeDir) { - const projectJsonc = join(opencodeDir, 'dcp.jsonc') - const projectJson = join(opencodeDir, 'dcp.json') + const projectJsonc = join(opencodeDir, "dcp.jsonc") + const projectJson = join(opencodeDir, "dcp.json") if (existsSync(projectJsonc)) { projectPath = projectJsonc } else if (existsSync(projectJson)) { @@ -388,7 +494,7 @@ function createDefaultConfig(): void { } } ` - writeFileSync(GLOBAL_CONFIG_PATH_JSONC, configContent, 'utf-8') + writeFileSync(GLOBAL_CONFIG_PATH_JSONC, configContent, "utf-8") } interface ConfigLoadResult { @@ -399,7 +505,7 @@ interface ConfigLoadResult { function loadConfigFile(configPath: string): ConfigLoadResult { let fileContent: string try { - fileContent = readFileSync(configPath, 'utf-8') + fileContent = readFileSync(configPath, "utf-8") } catch { // File doesn't exist or can't be read - not a parse error return { data: null } @@ -408,18 +514,18 @@ function loadConfigFile(configPath: string): ConfigLoadResult { try { const parsed = parse(fileContent) if (parsed === undefined || parsed === null) { - return { data: null, parseError: 'Config file is empty or invalid' } + return { data: null, parseError: "Config file is empty or invalid" } } return { data: parsed } } catch (error: any) { - return { data: null, parseError: error.message || 'Failed to parse config' } + return { data: null, parseError: error.message || "Failed to parse config" } } } function mergeStrategies( - base: PluginConfig['strategies'], - override?: Partial -): PluginConfig['strategies'] { + base: PluginConfig["strategies"], + override?: Partial, +): PluginConfig["strategies"] { if (!override) return base return { @@ -428,42 +534,48 @@ function mergeStrategies( protectedTools: [ ...new Set([ ...base.deduplication.protectedTools, - ...(override.deduplication?.protectedTools ?? []) - ]) - ] + ...(override.deduplication?.protectedTools ?? []), + ]), + ], }, onIdle: { enabled: override.onIdle?.enabled ?? base.onIdle.enabled, model: override.onIdle?.model ?? base.onIdle.model, - showModelErrorToasts: override.onIdle?.showModelErrorToasts ?? base.onIdle.showModelErrorToasts, - strictModelSelection: override.onIdle?.strictModelSelection ?? base.onIdle.strictModelSelection, + showModelErrorToasts: + override.onIdle?.showModelErrorToasts ?? base.onIdle.showModelErrorToasts, + strictModelSelection: + override.onIdle?.strictModelSelection ?? base.onIdle.strictModelSelection, protectedTools: [ ...new Set([ ...base.onIdle.protectedTools, - ...(override.onIdle?.protectedTools ?? []) - ]) - ] + ...(override.onIdle?.protectedTools ?? []), + ]), + ], }, pruneTool: { enabled: override.pruneTool?.enabled ?? base.pruneTool.enabled, protectedTools: [ ...new Set([ ...base.pruneTool.protectedTools, - ...(override.pruneTool?.protectedTools ?? []) - ]) + ...(override.pruneTool?.protectedTools ?? []), + ]), ], turnProtection: { - enabled: override.pruneTool?.turnProtection?.enabled ?? base.pruneTool.turnProtection.enabled, - turns: override.pruneTool?.turnProtection?.turns ?? base.pruneTool.turnProtection.turns + enabled: + override.pruneTool?.turnProtection?.enabled ?? + base.pruneTool.turnProtection.enabled, + turns: + override.pruneTool?.turnProtection?.turns ?? + base.pruneTool.turnProtection.turns, }, nudge: { enabled: override.pruneTool?.nudge?.enabled ?? base.pruneTool.nudge.enabled, - frequency: override.pruneTool?.nudge?.frequency ?? base.pruneTool.nudge.frequency - } + frequency: override.pruneTool?.nudge?.frequency ?? base.pruneTool.nudge.frequency, + }, }, supersedeWrites: { - enabled: override.supersedeWrites?.enabled ?? base.supersedeWrites.enabled - } + enabled: override.supersedeWrites?.enabled ?? base.supersedeWrites.enabled, + }, } } @@ -473,26 +585,25 @@ function deepCloneConfig(config: PluginConfig): PluginConfig { strategies: { deduplication: { ...config.strategies.deduplication, - protectedTools: [...config.strategies.deduplication.protectedTools] + protectedTools: [...config.strategies.deduplication.protectedTools], }, onIdle: { ...config.strategies.onIdle, - protectedTools: [...config.strategies.onIdle.protectedTools] + protectedTools: [...config.strategies.onIdle.protectedTools], }, pruneTool: { ...config.strategies.pruneTool, protectedTools: [...config.strategies.pruneTool.protectedTools], turnProtection: { ...config.strategies.pruneTool.turnProtection }, - nudge: { ...config.strategies.pruneTool.nudge } + nudge: { ...config.strategies.pruneTool.nudge }, }, supersedeWrites: { - ...config.strategies.supersedeWrites - } - } + ...config.strategies.supersedeWrites, + }, + }, } } - export function getConfig(ctx: PluginInput): PluginConfig { let config = deepCloneConfig(defaultConfig) const configPaths = getConfigPaths(ctx) @@ -508,8 +619,8 @@ export function getConfig(ctx: PluginInput): PluginConfig { title: "DCP: Invalid config", message: `${configPaths.global}\n${result.parseError}\nUsing default values`, variant: "warning", - duration: 7000 - } + duration: 7000, + }, }) } catch {} }, 7000) @@ -520,7 +631,7 @@ export function getConfig(ctx: PluginInput): PluginConfig { enabled: result.data.enabled ?? config.enabled, debug: result.data.debug ?? config.debug, pruningSummary: result.data.pruningSummary ?? config.pruningSummary, - strategies: mergeStrategies(config.strategies, result.data.strategies as any) + strategies: mergeStrategies(config.strategies, result.data.strategies as any), } } } else { @@ -539,8 +650,8 @@ export function getConfig(ctx: PluginInput): PluginConfig { title: "DCP: Invalid configDir config", message: `${configPaths.configDir}\n${result.parseError}\nUsing global/default values`, variant: "warning", - duration: 7000 - } + duration: 7000, + }, }) } catch {} }, 7000) @@ -551,7 +662,7 @@ export function getConfig(ctx: PluginInput): PluginConfig { enabled: result.data.enabled ?? config.enabled, debug: result.data.debug ?? config.debug, pruningSummary: result.data.pruningSummary ?? config.pruningSummary, - strategies: mergeStrategies(config.strategies, result.data.strategies as any) + strategies: mergeStrategies(config.strategies, result.data.strategies as any), } } } @@ -567,8 +678,8 @@ export function getConfig(ctx: PluginInput): PluginConfig { title: "DCP: Invalid project config", message: `${configPaths.project}\n${result.parseError}\nUsing global/default values`, variant: "warning", - duration: 7000 - } + duration: 7000, + }, }) } catch {} }, 7000) @@ -579,7 +690,7 @@ export function getConfig(ctx: PluginInput): PluginConfig { enabled: result.data.enabled ?? config.enabled, debug: result.data.debug ?? config.debug, pruningSummary: result.data.pruningSummary ?? config.pruningSummary, - strategies: mergeStrategies(config.strategies, result.data.strategies as any) + strategies: mergeStrategies(config.strategies, result.data.strategies as any), } } } diff --git a/lib/hooks.ts b/lib/hooks.ts index c578e4b..b163ad6 100644 --- a/lib/hooks.ts +++ b/lib/hooks.ts @@ -7,24 +7,20 @@ import { prune, insertPruneToolContext } from "./messages" import { checkSession } from "./state" import { runOnIdle } from "./strategies/on-idle" - export function createChatMessageTransformHandler( client: any, state: SessionState, logger: Logger, - config: PluginConfig + config: PluginConfig, ) { - return async ( - input: {}, - output: { messages: WithParts[] } - ) => { + return async (input: {}, output: { messages: WithParts[] }) => { await checkSession(client, state, logger, output.messages) if (state.isSubAgent) { return } - syncToolCache(state, config, logger, output.messages); + syncToolCache(state, config, logger, output.messages) deduplicate(state, logger, config, output.messages) supersedeWrites(state, logger, config, output.messages) @@ -40,15 +36,22 @@ export function createEventHandler( config: PluginConfig, state: SessionState, logger: Logger, - workingDirectory?: string + workingDirectory?: string, + onUserMessage?: () => void, ) { - return async ( - { event }: { event: any } - ) => { + return async ({ event }: { event: any }) => { if (state.sessionId === null || state.isSubAgent) { return } + // Reset auto-confirm on user message + if (event.type === "message.part.added" && event.properties?.part?.type === "text") { + const role = event.properties?.role + if (role === "user" && onUserMessage) { + onUserMessage() + } + } + if (event.type === "session.status" && event.properties.status.type === "idle") { if (!config.strategies.onIdle.enabled) { return @@ -59,13 +62,7 @@ export function createEventHandler( } try { - await runOnIdle( - client, - state, - logger, - config, - workingDirectory - ) + await runOnIdle(client, state, logger, config, workingDirectory) } catch (err: any) { logger.error("OnIdle pruning failed", { error: err.message }) } diff --git a/lib/logger.ts b/lib/logger.ts index 0081db1..d101c67 100644 --- a/lib/logger.ts +++ b/lib/logger.ts @@ -29,15 +29,15 @@ export class Logger { // Format arrays compactly if (Array.isArray(value)) { if (value.length === 0) continue - parts.push(`${key}=[${value.slice(0, 3).join(",")}${value.length > 3 ? `...+${value.length - 3}` : ""}]`) - } - else if (typeof value === 'object') { + parts.push( + `${key}=[${value.slice(0, 3).join(",")}${value.length > 3 ? `...+${value.length - 3}` : ""}]`, + ) + } else if (typeof value === "object") { const str = JSON.stringify(value) if (str.length < 50) { parts.push(`${key}=${str}`) } - } - else { + } else { parts.push(`${key}=${value}`) } } @@ -55,15 +55,15 @@ export class Logger { // Skip specified number of frames to get to actual caller for (let i = skipFrames; i < stack.length; i++) { const filename = stack[i]?.getFileName() - if (filename && !filename.includes('/logger.')) { + if (filename && !filename.includes("/logger.")) { // Extract just the filename without path and extension const match = filename.match(/([^/\\]+)\.[tj]s$/) return match ? match[1] : filename } } - return 'unknown' + return "unknown" } catch { - return 'unknown' + return "unknown" } } @@ -83,10 +83,9 @@ export class Logger { await mkdir(dailyLogDir, { recursive: true }) } - const logFile = join(dailyLogDir, `${new Date().toISOString().split('T')[0]}.log`) + const logFile = join(dailyLogDir, `${new Date().toISOString().split("T")[0]}.log`) await writeFile(logFile, logLine, { flag: "a" }) - } catch (error) { - } + } catch (error) {} } info(message: string, data?: any) { diff --git a/lib/messages/prune.ts b/lib/messages/prune.ts index f9348bf..2d52ebb 100644 --- a/lib/messages/prune.ts +++ b/lib/messages/prune.ts @@ -6,8 +6,9 @@ import { extractParameterKey, buildToolIdList } from "./utils" import { getLastUserMessage, isMessageCompacted } from "../shared-utils" import { UserMessage } from "@opencode-ai/sdk" -const PRUNED_TOOL_INPUT_REPLACEMENT = '[Input removed to save context]' -const PRUNED_TOOL_OUTPUT_REPLACEMENT = '[Output removed to save context - information superseded or no longer needed]' +const PRUNED_TOOL_INPUT_REPLACEMENT = "[Input removed to save context]" +const PRUNED_TOOL_OUTPUT_REPLACEMENT = + "[Output removed to save context - information superseded or no longer needed]" const NUDGE_STRING = loadPrompt("prune-nudge") const wrapPrunableTools = (content: string): string => ` @@ -39,27 +40,34 @@ const buildPrunableToolsList = ( } const numericId = toolIdList.indexOf(toolCallId) if (numericId === -1) { - logger.warn(`Tool in cache but not in toolIdList - possible stale entry`, { toolCallId, tool: toolParameterEntry.tool }) + logger.warn(`Tool in cache but not in toolIdList - possible stale entry`, { + toolCallId, + tool: toolParameterEntry.tool, + }) return } const paramKey = extractParameterKey(toolParameterEntry.tool, toolParameterEntry.parameters) - const description = paramKey ? `${toolParameterEntry.tool}, ${paramKey}` : toolParameterEntry.tool + const description = paramKey + ? `${toolParameterEntry.tool}, ${paramKey}` + : toolParameterEntry.tool lines.push(`${numericId}: ${description}`) - logger.debug(`Prunable tool found - ID: ${numericId}, Tool: ${toolParameterEntry.tool}, Call ID: ${toolCallId}`) + logger.debug( + `Prunable tool found - ID: ${numericId}, Tool: ${toolParameterEntry.tool}, Call ID: ${toolCallId}`, + ) }) if (lines.length === 0) { return "" } - return wrapPrunableTools(lines.join('\n')) + return wrapPrunableTools(lines.join("\n")) } export const insertPruneToolContext = ( state: SessionState, config: PluginConfig, logger: Logger, - messages: WithParts[] + messages: WithParts[], ): void => { if (!config.strategies.pruneTool.enabled) { return @@ -101,8 +109,8 @@ export const insertPruneToolContext = ( agent: (lastUserMessage.info as UserMessage).agent || "build", model: { providerID: (lastUserMessage.info as UserMessage).model.providerID, - modelID: (lastUserMessage.info as UserMessage).model.modelID - } + modelID: (lastUserMessage.info as UserMessage).model.modelID, + }, }, parts: [ { @@ -111,8 +119,8 @@ export const insertPruneToolContext = ( messageID: SYNTHETIC_MESSAGE_ID, type: "text", text: prunableToolsContent, - } - ] + }, + ], } messages.push(userMessage) @@ -122,55 +130,47 @@ export const prune = ( state: SessionState, logger: Logger, config: PluginConfig, - messages: WithParts[] + messages: WithParts[], ): void => { pruneToolOutputs(state, logger, messages) pruneToolInputs(state, logger, messages) } -const pruneToolOutputs = ( - state: SessionState, - logger: Logger, - messages: WithParts[] -): void => { +const pruneToolOutputs = (state: SessionState, logger: Logger, messages: WithParts[]): void => { for (const msg of messages) { if (isMessageCompacted(state, msg)) { continue } for (const part of msg.parts) { - if (part.type !== 'tool') { + if (part.type !== "tool") { continue } if (!state.prune.toolIds.includes(part.callID)) { continue } // Skip write and edit tools - their inputs are pruned instead - if (part.tool === 'write' || part.tool === 'edit') { + if (part.tool === "write" || part.tool === "edit") { continue } - if (part.state.status === 'completed') { + if (part.state.status === "completed") { part.state.output = PRUNED_TOOL_OUTPUT_REPLACEMENT } } } } -const pruneToolInputs = ( - state: SessionState, - logger: Logger, - messages: WithParts[] -): void => { +const pruneToolInputs = (state: SessionState, logger: Logger, messages: WithParts[]): void => { for (const msg of messages) { for (const part of msg.parts) { - if (part.type !== 'tool') { + if (part.type !== "tool") { continue } if (!state.prune.toolIds.includes(part.callID)) { continue } // Only prune inputs for write and edit tools - if (part.tool !== 'write' && part.tool !== 'edit') { + if (part.tool !== "write" && part.tool !== "edit") { continue } // Don't prune yet if tool is still pending or running diff --git a/lib/messages/utils.ts b/lib/messages/utils.ts index 48f453c..cbf497d 100644 --- a/lib/messages/utils.ts +++ b/lib/messages/utils.ts @@ -6,7 +6,7 @@ import type { SessionState, WithParts } from "../state" * Extracts a human-readable key from tool metadata for display purposes. */ export const extractParameterKey = (tool: string, parameters: any): string => { - if (!parameters) return '' + if (!parameters) return "" if (tool === "read" && parameters.filePath) { return parameters.filePath @@ -19,21 +19,21 @@ export const extractParameterKey = (tool: string, parameters: any): string => { } if (tool === "list") { - return parameters.path || '(current directory)' + return parameters.path || "(current directory)" } if (tool === "glob") { if (parameters.pattern) { const pathInfo = parameters.path ? ` in ${parameters.path}` : "" return `"${parameters.pattern}"${pathInfo}` } - return '(unknown pattern)' + return "(unknown pattern)" } if (tool === "grep") { if (parameters.pattern) { const pathInfo = parameters.path ? ` in ${parameters.path}` : "" return `"${parameters.pattern}"${pathInfo}` } - return '(unknown pattern)' + return "(unknown pattern)" } if (tool === "bash") { @@ -67,8 +67,8 @@ export const extractParameterKey = (tool: string, parameters: any): string => { } const paramStr = JSON.stringify(parameters) - if (paramStr === '{}' || paramStr === '[]' || paramStr === 'null') { - return '' + if (paramStr === "{}" || paramStr === "[]" || paramStr === "null") { + return "" } return paramStr.substring(0, 50) } @@ -76,7 +76,7 @@ export const extractParameterKey = (tool: string, parameters: any): string => { export function buildToolIdList( state: SessionState, messages: WithParts[], - logger: Logger + logger: Logger, ): string[] { const toolIds: string[] = [] for (const msg of messages) { @@ -85,7 +85,7 @@ export function buildToolIdList( } if (msg.parts) { for (const part of msg.parts) { - if (part.type === 'tool' && part.callID && part.tool) { + if (part.type === "tool" && part.callID && part.tool) { toolIds.push(part.callID) } } diff --git a/lib/model-selector.ts b/lib/model-selector.ts index d1499eb..efa8e87 100644 --- a/lib/model-selector.ts +++ b/lib/model-selector.ts @@ -1,107 +1,112 @@ -import type { LanguageModel } from 'ai'; -import type { Logger } from './logger'; +import type { LanguageModel } from "ai" +import type { Logger } from "./logger" export interface ModelInfo { - providerID: string; - modelID: string; + providerID: string + modelID: string } export const FALLBACK_MODELS: Record = { - openai: 'gpt-5-mini', - anthropic: 'claude-haiku-4-5', //This model isn't broken in opencode-auth-provider - google: 'gemini-2.5-flash', - deepseek: 'deepseek-chat', - xai: 'grok-4-fast', - alibaba: 'qwen3-coder-flash', - zai: 'glm-4.5-flash', - opencode: 'big-pickle' -}; + openai: "gpt-5-mini", + anthropic: "claude-haiku-4-5", //This model isn't broken in opencode-auth-provider + google: "gemini-2.5-flash", + deepseek: "deepseek-chat", + xai: "grok-4-fast", + alibaba: "qwen3-coder-flash", + zai: "glm-4.5-flash", + opencode: "big-pickle", +} const PROVIDER_PRIORITY = [ - 'openai', - 'anthropic', - 'google', - 'deepseek', - 'xai', - 'alibaba', - 'zai', - 'opencode' -]; + "openai", + "anthropic", + "google", + "deepseek", + "xai", + "alibaba", + "zai", + "opencode", +] // TODO: some anthropic provided models aren't supported by the opencode-auth-provider package, so this provides a temporary workaround -const SKIP_PROVIDERS = ['github-copilot', 'anthropic']; +const SKIP_PROVIDERS = ["github-copilot", "anthropic"] export interface ModelSelectionResult { - model: LanguageModel; - modelInfo: ModelInfo; - source: 'user-model' | 'config' | 'fallback'; - reason?: string; - failedModel?: ModelInfo; + model: LanguageModel + modelInfo: ModelInfo + source: "user-model" | "config" | "fallback" + reason?: string + failedModel?: ModelInfo } function shouldSkipProvider(providerID: string): boolean { - const normalized = providerID.toLowerCase().trim(); - return SKIP_PROVIDERS.some(skip => normalized.includes(skip.toLowerCase())); + const normalized = providerID.toLowerCase().trim() + return SKIP_PROVIDERS.some((skip) => normalized.includes(skip.toLowerCase())) } -async function importOpencodeAI(logger?: Logger, maxRetries: number = 3, delayMs: number = 100, workspaceDir?: string): Promise { - let lastError: Error | undefined; +async function importOpencodeAI( + logger?: Logger, + maxRetries: number = 3, + delayMs: number = 100, + workspaceDir?: string, +): Promise { + let lastError: Error | undefined for (let attempt = 1; attempt <= maxRetries; attempt++) { try { - const { OpencodeAI } = await import('@tarquinen/opencode-auth-provider'); - return new OpencodeAI({ workspaceDir }); + const { OpencodeAI } = await import("@tarquinen/opencode-auth-provider") + return new OpencodeAI({ workspaceDir }) } catch (error: any) { - lastError = error; + lastError = error - if (error.message?.includes('before initialization')) { + if (error.message?.includes("before initialization")) { logger?.debug(`Import attempt ${attempt}/${maxRetries} failed, will retry`, { - error: error.message - }); + error: error.message, + }) if (attempt < maxRetries) { - await new Promise(resolve => setTimeout(resolve, delayMs * attempt)); - continue; + await new Promise((resolve) => setTimeout(resolve, delayMs * attempt)) + continue } } - throw error; + throw error } } - throw lastError; + throw lastError } export async function selectModel( currentModel?: ModelInfo, logger?: Logger, configModel?: string, - workspaceDir?: string + workspaceDir?: string, ): Promise { - const opencodeAI = await importOpencodeAI(logger, 3, 100, workspaceDir); + const opencodeAI = await importOpencodeAI(logger, 3, 100, workspaceDir) - let failedModelInfo: ModelInfo | undefined; + let failedModelInfo: ModelInfo | undefined if (configModel) { - const parts = configModel.split('/'); + const parts = configModel.split("/") if (parts.length !== 2) { - logger?.warn('Invalid config model format', { configModel }); + logger?.warn("Invalid config model format", { configModel }) } else { - const [providerID, modelID] = parts; + const [providerID, modelID] = parts try { - const model = await opencodeAI.getLanguageModel(providerID, modelID); + const model = await opencodeAI.getLanguageModel(providerID, modelID) return { model, modelInfo: { providerID, modelID }, - source: 'config', - reason: 'Using model specified in dcp.jsonc config' - }; + source: "config", + reason: "Using model specified in dcp.jsonc config", + } } catch (error: any) { logger?.warn(`Config model failed: ${providerID}/${modelID}`, { - error: error.message - }); - failedModelInfo = { providerID, modelID }; + error: error.message, + }) + failedModelInfo = { providerID, modelID } } } } @@ -109,67 +114,72 @@ export async function selectModel( if (currentModel) { if (shouldSkipProvider(currentModel.providerID)) { if (!failedModelInfo) { - failedModelInfo = currentModel; + failedModelInfo = currentModel } } else { try { - const model = await opencodeAI.getLanguageModel(currentModel.providerID, currentModel.modelID); + const model = await opencodeAI.getLanguageModel( + currentModel.providerID, + currentModel.modelID, + ) return { model, modelInfo: currentModel, - source: 'user-model', - reason: 'Using current session model' - }; + source: "user-model", + reason: "Using current session model", + } } catch (error: any) { if (!failedModelInfo) { - failedModelInfo = currentModel; + failedModelInfo = currentModel } } } } - const providers = await opencodeAI.listProviders(); + const providers = await opencodeAI.listProviders() for (const providerID of PROVIDER_PRIORITY) { - if (!providers[providerID]) continue; + if (!providers[providerID]) continue - const fallbackModelID = FALLBACK_MODELS[providerID]; - if (!fallbackModelID) continue; + const fallbackModelID = FALLBACK_MODELS[providerID] + if (!fallbackModelID) continue try { - const model = await opencodeAI.getLanguageModel(providerID, fallbackModelID); + const model = await opencodeAI.getLanguageModel(providerID, fallbackModelID) return { model, modelInfo: { providerID, modelID: fallbackModelID }, - source: 'fallback', + source: "fallback", reason: `Using ${providerID}/${fallbackModelID}`, - failedModel: failedModelInfo - }; + failedModel: failedModelInfo, + } } catch (error: any) { - continue; + continue } } - throw new Error('No available models for analysis. Please authenticate with at least one provider.'); + throw new Error( + "No available models for analysis. Please authenticate with at least one provider.", + ) } export function extractModelFromSession(sessionState: any, logger?: Logger): ModelInfo | undefined { if (sessionState?.model?.providerID && sessionState?.model?.modelID) { return { providerID: sessionState.model.providerID, - modelID: sessionState.model.modelID - }; + modelID: sessionState.model.modelID, + } } if (sessionState?.messages && Array.isArray(sessionState.messages)) { - const lastMessage = sessionState.messages[sessionState.messages.length - 1]; + const lastMessage = sessionState.messages[sessionState.messages.length - 1] if (lastMessage?.model?.providerID && lastMessage?.model?.modelID) { return { providerID: lastMessage.model.providerID, - modelID: lastMessage.model.modelID - }; + modelID: lastMessage.model.modelID, + } } } - return undefined; + return undefined } diff --git a/lib/prompt.ts b/lib/prompt.ts index 33a490f..0f2bad3 100644 --- a/lib/prompt.ts +++ b/lib/prompt.ts @@ -6,129 +6,144 @@ export function loadPrompt(name: string, vars?: Record): string let content = readFileSync(filePath, "utf8").trim() if (vars) { for (const [key, value] of Object.entries(vars)) { - content = content.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value) + content = content.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), value) } } return content } -function minimizeMessages(messages: any[], alreadyPrunedIds?: string[], protectedToolCallIds?: string[]): any[] { - const prunedIdsSet = alreadyPrunedIds ? new Set(alreadyPrunedIds.map(id => id.toLowerCase())) : new Set() - const protectedIdsSet = protectedToolCallIds ? new Set(protectedToolCallIds.map(id => id.toLowerCase())) : new Set() - - return messages.map(msg => { - const minimized: any = { - role: msg.info?.role - } - - if (msg.parts) { - minimized.parts = msg.parts - .filter((part: any) => { - if (part.type === 'step-start' || part.type === 'step-finish') { - return false - } - return true - }) - .map((part: any) => { - if (part.type === 'text') { - if (part.ignored) { - return null - } - return { - type: 'text', - text: part.text +function minimizeMessages( + messages: any[], + alreadyPrunedIds?: string[], + protectedToolCallIds?: string[], +): any[] { + const prunedIdsSet = alreadyPrunedIds + ? new Set(alreadyPrunedIds.map((id) => id.toLowerCase())) + : new Set() + const protectedIdsSet = protectedToolCallIds + ? new Set(protectedToolCallIds.map((id) => id.toLowerCase())) + : new Set() + + return messages + .map((msg) => { + const minimized: any = { + role: msg.info?.role, + } + + if (msg.parts) { + minimized.parts = msg.parts + .filter((part: any) => { + if (part.type === "step-start" || part.type === "step-finish") { + return false } - } - - // TODO: This should use the opencode normalized system instead of per provider settings - if (part.type === 'reasoning') { - // Calculate encrypted content size if present - let encryptedContentLength = 0 - if (part.metadata?.openai?.reasoningEncryptedContent) { - encryptedContentLength = part.metadata.openai.reasoningEncryptedContent.length - } else if (part.metadata?.anthropic?.signature) { - encryptedContentLength = part.metadata.anthropic.signature.length - } else if (part.metadata?.google?.thoughtSignature) { - encryptedContentLength = part.metadata.google.thoughtSignature.length + return true + }) + .map((part: any) => { + if (part.type === "text") { + if (part.ignored) { + return null + } + return { + type: "text", + text: part.text, + } } - return { - type: 'reasoning', - text: part.text, - textLength: part.text?.length || 0, - encryptedContentLength, - ...(part.time && { time: part.time }), - ...(part.metadata && { metadataKeys: Object.keys(part.metadata) }) - } - } - - if (part.type === 'tool') { - const callIDLower = part.callID?.toLowerCase() - const isAlreadyPruned = prunedIdsSet.has(callIDLower) - const isProtected = protectedIdsSet.has(callIDLower) - - let displayCallID = part.callID - if (isAlreadyPruned) { - displayCallID = '' - } else if (isProtected) { - displayCallID = '' - } + // TODO: This should use the opencode normalized system instead of per provider settings + if (part.type === "reasoning") { + // Calculate encrypted content size if present + let encryptedContentLength = 0 + if (part.metadata?.openai?.reasoningEncryptedContent) { + encryptedContentLength = + part.metadata.openai.reasoningEncryptedContent.length + } else if (part.metadata?.anthropic?.signature) { + encryptedContentLength = part.metadata.anthropic.signature.length + } else if (part.metadata?.google?.thoughtSignature) { + encryptedContentLength = + part.metadata.google.thoughtSignature.length + } - const toolPart: any = { - type: 'tool', - toolCallID: displayCallID, - tool: part.tool + return { + type: "reasoning", + text: part.text, + textLength: part.text?.length || 0, + encryptedContentLength, + ...(part.time && { time: part.time }), + ...(part.metadata && { metadataKeys: Object.keys(part.metadata) }), + } } - if (part.state?.output) { - toolPart.output = part.state.output - } + if (part.type === "tool") { + const callIDLower = part.callID?.toLowerCase() + const isAlreadyPruned = prunedIdsSet.has(callIDLower) + const isProtected = protectedIdsSet.has(callIDLower) - if (part.state?.input) { - const input = part.state.input + let displayCallID = part.callID + if (isAlreadyPruned) { + displayCallID = "" + } else if (isProtected) { + displayCallID = "" + } - if (input.filePath && (part.tool === 'write' || part.tool === 'edit' || part.tool === 'multiedit' || part.tool === 'patch')) { - toolPart.input = input + const toolPart: any = { + type: "tool", + toolCallID: displayCallID, + tool: part.tool, } - else if (input.filePath) { - toolPart.input = { filePath: input.filePath } + + if (part.state?.output) { + toolPart.output = part.state.output } - else if (input.tool_calls && Array.isArray(input.tool_calls)) { - toolPart.input = { - batch_summary: `${input.tool_calls.length} tool calls`, - tools: input.tool_calls.map((tc: any) => tc.tool) + + if (part.state?.input) { + const input = part.state.input + + if ( + input.filePath && + (part.tool === "write" || + part.tool === "edit" || + part.tool === "multiedit" || + part.tool === "patch") + ) { + toolPart.input = input + } else if (input.filePath) { + toolPart.input = { filePath: input.filePath } + } else if (input.tool_calls && Array.isArray(input.tool_calls)) { + toolPart.input = { + batch_summary: `${input.tool_calls.length} tool calls`, + tools: input.tool_calls.map((tc: any) => tc.tool), + } + } else { + toolPart.input = input } } - else { - toolPart.input = input - } + + return toolPart } - return toolPart - } + return null + }) + .filter(Boolean) + } - return null - }) - .filter(Boolean) - } - - return minimized - }).filter(msg => { - return msg.parts && msg.parts.length > 0 - }) + return minimized + }) + .filter((msg) => { + return msg.parts && msg.parts.length > 0 + }) } export function buildAnalysisPrompt( unprunedToolCallIds: string[], messages: any[], alreadyPrunedIds?: string[], - protectedToolCallIds?: string[] + protectedToolCallIds?: string[], ): string { const minimizedMessages = minimizeMessages(messages, alreadyPrunedIds, protectedToolCallIds) - const messagesJson = JSON.stringify(minimizedMessages, null, 2).replace(/\\n/g, '\n') + const messagesJson = JSON.stringify(minimizedMessages, null, 2).replace(/\\n/g, "\n") return loadPrompt("on-idle-analysis", { available_tool_call_ids: unprunedToolCallIds.join(", "), - session_history: messagesJson + session_history: messagesJson, }) } diff --git a/lib/shared-utils.ts b/lib/shared-utils.ts index fe6fbd6..ce3be56 100644 --- a/lib/shared-utils.ts +++ b/lib/shared-utils.ts @@ -1,22 +1,15 @@ import { SessionState, WithParts } from "./state" -export const isMessageCompacted = ( - state: SessionState, - msg: WithParts -): boolean => { +export const isMessageCompacted = (state: SessionState, msg: WithParts): boolean => { return msg.info.time.created < state.lastCompaction } -export const getLastUserMessage = ( - messages: WithParts[] -): WithParts | null => { +export const getLastUserMessage = (messages: WithParts[]): WithParts | null => { for (let i = messages.length - 1; i >= 0; i--) { const msg = messages[i] - if (msg.info.role === 'user') { + if (msg.info.role === "user") { return msg } } return null } - - diff --git a/lib/state/persistence.ts b/lib/state/persistence.ts index eb97551..ccd4859 100644 --- a/lib/state/persistence.ts +++ b/lib/state/persistence.ts @@ -4,110 +4,98 @@ * Storage location: ~/.local/share/opencode/storage/plugin/dcp/{sessionId}.json */ -import * as fs from "fs/promises"; -import { existsSync } from "fs"; -import { homedir } from "os"; -import { join } from "path"; +import * as fs from "fs/promises" +import { existsSync } from "fs" +import { homedir } from "os" +import { join } from "path" import type { SessionState, SessionStats, Prune } from "./types" -import type { Logger } from "../logger"; +import type { Logger } from "../logger" export interface PersistedSessionState { - sessionName?: string; + sessionName?: string prune: Prune - stats: SessionStats; - lastUpdated: string; + stats: SessionStats + lastUpdated: string } -const STORAGE_DIR = join( - homedir(), - ".local", - "share", - "opencode", - "storage", - "plugin", - "dcp" -); +const STORAGE_DIR = join(homedir(), ".local", "share", "opencode", "storage", "plugin", "dcp") async function ensureStorageDir(): Promise { if (!existsSync(STORAGE_DIR)) { - await fs.mkdir(STORAGE_DIR, { recursive: true }); + await fs.mkdir(STORAGE_DIR, { recursive: true }) } } function getSessionFilePath(sessionId: string): string { - return join(STORAGE_DIR, `${sessionId}.json`); + return join(STORAGE_DIR, `${sessionId}.json`) } export async function saveSessionState( sessionState: SessionState, logger: Logger, - sessionName?: string + sessionName?: string, ): Promise { try { if (!sessionState.sessionId) { - return; + return } - await ensureStorageDir(); + await ensureStorageDir() const state: PersistedSessionState = { sessionName: sessionName, prune: sessionState.prune, stats: sessionState.stats, - lastUpdated: new Date().toISOString() - }; + lastUpdated: new Date().toISOString(), + } - const filePath = getSessionFilePath(sessionState.sessionId); - const content = JSON.stringify(state, null, 2); - await fs.writeFile(filePath, content, "utf-8"); + const filePath = getSessionFilePath(sessionState.sessionId) + const content = JSON.stringify(state, null, 2) + await fs.writeFile(filePath, content, "utf-8") logger.info("Saved session state to disk", { sessionId: sessionState.sessionId, - totalTokensSaved: state.stats.totalPruneTokens - }); + totalTokensSaved: state.stats.totalPruneTokens, + }) } catch (error: any) { logger.error("Failed to save session state", { sessionId: sessionState.sessionId, error: error?.message, - }); + }) } } export async function loadSessionState( sessionId: string, - logger: Logger + logger: Logger, ): Promise { try { - const filePath = getSessionFilePath(sessionId); + const filePath = getSessionFilePath(sessionId) if (!existsSync(filePath)) { - return null; + return null } - const content = await fs.readFile(filePath, "utf-8"); - const state = JSON.parse(content) as PersistedSessionState; + const content = await fs.readFile(filePath, "utf-8") + const state = JSON.parse(content) as PersistedSessionState - if (!state || - !state.prune || - !Array.isArray(state.prune.toolIds) || - !state.stats - ) { + if (!state || !state.prune || !Array.isArray(state.prune.toolIds) || !state.stats) { logger.warn("Invalid session state file, ignoring", { sessionId: sessionId, - }); - return null; + }) + return null } logger.info("Loaded session state from disk", { - sessionId: sessionId - }); + sessionId: sessionId, + }) - return state; + return state } catch (error: any) { logger.warn("Failed to load session state", { sessionId: sessionId, error: error?.message, - }); - return null; + }) + return null } } diff --git a/lib/state/state.ts b/lib/state/state.ts index e33f4c8..956ac9d 100644 --- a/lib/state/state.ts +++ b/lib/state/state.ts @@ -8,9 +8,8 @@ export const checkSession = async ( client: any, state: SessionState, logger: Logger, - messages: WithParts[] + messages: WithParts[], ): Promise => { - const lastUserMessage = getLastUserMessage(messages) if (!lastUserMessage) { return @@ -32,7 +31,9 @@ export const checkSession = async ( state.lastCompaction = lastCompactionTimestamp state.toolParameters.clear() state.prune.toolIds = [] - logger.info("Detected compaction from messages - cleared tool cache", { timestamp: lastCompactionTimestamp }) + logger.info("Detected compaction from messages - cleared tool cache", { + timestamp: lastCompactionTimestamp, + }) } state.currentTurn = countTurns(state, messages) @@ -43,7 +44,7 @@ export function createSessionState(): SessionState { sessionId: null, isSubAgent: false, prune: { - toolIds: [] + toolIds: [], }, stats: { pruneTokenCounter: 0, @@ -53,7 +54,7 @@ export function createSessionState(): SessionState { nudgeCounter: 0, lastToolPrune: false, lastCompaction: 0, - currentTurn: 0 + currentTurn: 0, } } @@ -61,7 +62,7 @@ export function resetSessionState(state: SessionState): void { state.sessionId = null state.isSubAgent = false state.prune = { - toolIds: [] + toolIds: [], } state.stats = { pruneTokenCounter: 0, @@ -79,10 +80,10 @@ export async function ensureSessionInitialized( state: SessionState, sessionId: string, logger: Logger, - messages: WithParts[] + messages: WithParts[], ): Promise { if (state.sessionId === sessionId) { - return; + return } logger.info("session ID = " + sessionId) @@ -100,11 +101,11 @@ export async function ensureSessionInitialized( const persisted = await loadSessionState(sessionId, logger) if (persisted === null) { - return; + return } state.prune = { - toolIds: persisted.prune.toolIds || [] + toolIds: persisted.prune.toolIds || [], } state.stats = { pruneTokenCounter: persisted.stats?.pruneTokenCounter || 0, diff --git a/lib/state/tool-cache.ts b/lib/state/tool-cache.ts index f8ad2b3..55a94f4 100644 --- a/lib/state/tool-cache.ts +++ b/lib/state/tool-cache.ts @@ -35,9 +35,11 @@ export async function syncToolCache( continue } - const isProtectedByTurn = config.strategies.pruneTool.turnProtection.enabled && + const isProtectedByTurn = + config.strategies.pruneTool.turnProtection.enabled && config.strategies.pruneTool.turnProtection.turns > 0 && - (state.currentTurn - turnCounter) < config.strategies.pruneTool.turnProtection.turns + state.currentTurn - turnCounter < + config.strategies.pruneTool.turnProtection.turns state.lastToolPrune = part.tool === "prune" @@ -58,25 +60,24 @@ export async function syncToolCache( continue } - state.toolParameters.set( - part.callID, - { - tool: part.tool, - parameters: part.state?.input ?? {}, - status: part.state.status as ToolStatus | undefined, - error: part.state.status === "error" ? part.state.error : undefined, - turn: turnCounter, - } - ) + state.toolParameters.set(part.callID, { + tool: part.tool, + parameters: part.state?.input ?? {}, + status: part.state.status as ToolStatus | undefined, + error: part.state.status === "error" ? part.state.error : undefined, + turn: turnCounter, + }) logger.info(`Cached tool id: ${part.callID} (created on turn ${turnCounter})`) } } - logger.info(`Synced cache - size: ${state.toolParameters.size}, currentTurn: ${state.currentTurn}, nudgeCounter: ${state.nudgeCounter}`) + logger.info( + `Synced cache - size: ${state.toolParameters.size}, currentTurn: ${state.currentTurn}, nudgeCounter: ${state.nudgeCounter}`, + ) trimToolParametersCache(state) } catch (error) { logger.warn("Failed to sync tool parameters from OpenCode", { - error: error instanceof Error ? error.message : String(error) + error: error instanceof Error ? error.message : String(error), }) } } @@ -90,8 +91,10 @@ export function trimToolParametersCache(state: SessionState): void { return } - const keysToRemove = Array.from(state.toolParameters.keys()) - .slice(0, state.toolParameters.size - MAX_TOOL_CACHE_SIZE) + const keysToRemove = Array.from(state.toolParameters.keys()).slice( + 0, + state.toolParameters.size - MAX_TOOL_CACHE_SIZE, + ) for (const key of keysToRemove) { state.toolParameters.delete(key) diff --git a/lib/state/types.ts b/lib/state/types.ts index 04847d5..9a6de02 100644 --- a/lib/state/types.ts +++ b/lib/state/types.ts @@ -12,7 +12,7 @@ export interface ToolParameterEntry { parameters: any status?: ToolStatus error?: string - turn: number // Which turn (step-start count) this tool was called on + turn: number // Which turn (step-start count) this tool was called on } export interface SessionStats { @@ -33,5 +33,5 @@ export interface SessionState { nudgeCounter: number lastToolPrune: boolean lastCompaction: number - currentTurn: number // Current turn count derived from step-start parts + currentTurn: number // Current turn count derived from step-start parts } diff --git a/lib/strategies/deduplication.ts b/lib/strategies/deduplication.ts index 11462a8..101e664 100644 --- a/lib/strategies/deduplication.ts +++ b/lib/strategies/deduplication.ts @@ -13,7 +13,7 @@ export const deduplicate = ( state: SessionState, logger: Logger, config: PluginConfig, - messages: WithParts[] + messages: WithParts[], ): void => { if (!config.strategies.deduplication.enabled) { return @@ -27,7 +27,7 @@ export const deduplicate = ( // Filter out IDs already pruned const alreadyPruned = new Set(state.prune.toolIds) - const unprunedIds = allToolIds.filter(id => !alreadyPruned.has(id)) + const unprunedIds = allToolIds.filter((id) => !alreadyPruned.has(id)) if (unprunedIds.length === 0) { return @@ -86,7 +86,7 @@ function createToolSignature(tool: string, parameters?: any): string { } function normalizeParameters(params: any): any { - if (typeof params !== 'object' || params === null) return params + if (typeof params !== "object" || params === null) return params if (Array.isArray(params)) return params const normalized: any = {} @@ -99,7 +99,7 @@ function normalizeParameters(params: any): any { } function sortObjectKeys(obj: any): any { - if (typeof obj !== 'object' || obj === null) return obj + if (typeof obj !== "object" || obj === null) return obj if (Array.isArray(obj)) return obj.map(sortObjectKeys) const sorted: any = {} diff --git a/lib/strategies/on-idle.ts b/lib/strategies/on-idle.ts index 602298e..43f481c 100644 --- a/lib/strategies/on-idle.ts +++ b/lib/strategies/on-idle.ts @@ -21,7 +21,7 @@ export interface OnIdleResult { function parseMessages( state: SessionState, messages: WithParts[], - toolParametersCache: Map + toolParametersCache: Map, ): { toolCallIds: string[] toolMetadata: Map @@ -46,7 +46,7 @@ function parseMessages( parameters: parameters, status: part.state?.status, error: part.state?.status === "error" ? part.state.error : undefined, - turn: cachedData?.turn ?? 0 + turn: cachedData?.turn ?? 0, }) } } @@ -64,26 +64,28 @@ function replacePrunedToolOutputs(messages: WithParts[], prunedIds: string[]): W const prunedIdsSet = new Set(prunedIds) - return messages.map(msg => { + return messages.map((msg) => { if (!msg.parts) return msg return { ...msg, parts: msg.parts.map((part: any) => { - if (part.type === 'tool' && + if ( + part.type === "tool" && part.callID && prunedIdsSet.has(part.callID) && - part.state?.output) { + part.state?.output + ) { return { ...part, state: { ...part.state, - output: '[Output removed to save context - information superseded or no longer needed]' - } + output: "[Output removed to save context - information superseded or no longer needed]", + }, } } return part - }) + }), } }) as WithParts[] } @@ -100,10 +102,10 @@ async function runLlmAnalysis( unprunedToolCallIds: string[], alreadyPrunedIds: string[], toolMetadata: Map, - workingDirectory?: string + workingDirectory?: string, ): Promise { const protectedToolCallIds: string[] = [] - const prunableToolCallIds = unprunedToolCallIds.filter(id => { + const prunableToolCallIds = unprunedToolCallIds.filter((id) => { const metadata = toolMetadata.get(id) if (metadata && config.strategies.onIdle.protectedTools.includes(metadata.tool)) { protectedToolCallIds.push(id) @@ -124,7 +126,7 @@ async function runLlmAnalysis( if (model?.providerID && model?.modelID) { validModelInfo = { providerID: model.providerID, - modelID: model.modelID + modelID: model.modelID, } } } @@ -133,15 +135,19 @@ async function runLlmAnalysis( validModelInfo, logger, config.strategies.onIdle.model, - workingDirectory + workingDirectory, ) - logger.info(`OnIdle Model: ${modelSelection.modelInfo.providerID}/${modelSelection.modelInfo.modelID}`, { - source: modelSelection.source - }) + logger.info( + `OnIdle Model: ${modelSelection.modelInfo.providerID}/${modelSelection.modelInfo.modelID}`, + { + source: modelSelection.source, + }, + ) if (modelSelection.failedModel && config.strategies.onIdle.showModelErrorToasts) { - const skipAi = modelSelection.source === 'fallback' && config.strategies.onIdle.strictModelSelection + const skipAi = + modelSelection.source === "fallback" && config.strategies.onIdle.strictModelSelection try { await client.tui.showToast({ body: { @@ -150,20 +156,20 @@ async function runLlmAnalysis( ? `${modelSelection.failedModel.providerID}/${modelSelection.failedModel.modelID} failed\nAI analysis skipped (strictModelSelection enabled)` : `${modelSelection.failedModel.providerID}/${modelSelection.failedModel.modelID} failed\nUsing ${modelSelection.modelInfo.providerID}/${modelSelection.modelInfo.modelID}`, variant: "info", - duration: 5000 - } + duration: 5000, + }, }) } catch { // Ignore toast errors } } - if (modelSelection.source === 'fallback' && config.strategies.onIdle.strictModelSelection) { + if (modelSelection.source === "fallback" && config.strategies.onIdle.strictModelSelection) { logger.info("Skipping AI analysis (fallback model, strictModelSelection enabled)") return [] } - const { generateObject } = await import('ai') + const { generateObject } = await import("ai") const sanitizedMessages = replacePrunedToolOutputs(messages, alreadyPrunedIds) @@ -171,7 +177,7 @@ async function runLlmAnalysis( prunableToolCallIds, sanitizedMessages, alreadyPrunedIds, - protectedToolCallIds + protectedToolCallIds, ) const result = await generateObject({ @@ -180,19 +186,17 @@ async function runLlmAnalysis( pruned_tool_call_ids: z.array(z.string()), reasoning: z.string(), }), - prompt: analysisPrompt + prompt: analysisPrompt, }) const rawLlmPrunedIds = result.object.pruned_tool_call_ids - const llmPrunedIds = rawLlmPrunedIds.filter(id => - prunableToolCallIds.includes(id) - ) + const llmPrunedIds = rawLlmPrunedIds.filter((id) => prunableToolCallIds.includes(id)) // Always log LLM output as debug - const reasoning = result.object.reasoning.replace(/\n+/g, ' ').replace(/\s+/g, ' ').trim() + const reasoning = result.object.reasoning.replace(/\n+/g, " ").replace(/\s+/g, " ").trim() logger.debug(`OnIdle LLM output`, { pruned_tool_call_ids: rawLlmPrunedIds, - reasoning: reasoning + reasoning: reasoning, }) return llmPrunedIds @@ -207,7 +211,7 @@ export async function runOnIdle( state: SessionState, logger: Logger, config: PluginConfig, - workingDirectory?: string + workingDirectory?: string, ): Promise { try { if (!state.sessionId) { @@ -219,7 +223,7 @@ export async function runOnIdle( // Fetch session info and messages const [sessionInfoResponse, messagesResponse] = await Promise.all([ client.session.get({ path: { id: sessionId } }), - client.session.messages({ path: { id: sessionId }}) + client.session.messages({ path: { id: sessionId } }), ]) const sessionInfo = sessionInfoResponse.data @@ -233,14 +237,14 @@ export async function runOnIdle( const { toolCallIds, toolMetadata } = parseMessages(state, messages, state.toolParameters) const alreadyPrunedIds = state.prune.toolIds - const unprunedToolCallIds = toolCallIds.filter(id => !alreadyPrunedIds.includes(id)) + const unprunedToolCallIds = toolCallIds.filter((id) => !alreadyPrunedIds.includes(id)) if (unprunedToolCallIds.length === 0) { return null } // Count prunable tools (excluding protected) - const candidateCount = unprunedToolCallIds.filter(id => { + const candidateCount = unprunedToolCallIds.filter((id) => { const metadata = toolMetadata.get(id) return !metadata || !config.strategies.onIdle.protectedTools.includes(metadata.tool) }).length @@ -259,10 +263,10 @@ export async function runOnIdle( unprunedToolCallIds, alreadyPrunedIds, toolMetadata, - workingDirectory + workingDirectory, ) - const newlyPrunedIds = llmPrunedIds.filter(id => !alreadyPrunedIds.includes(id)) + const newlyPrunedIds = llmPrunedIds.filter((id) => !alreadyPrunedIds.includes(id)) if (newlyPrunedIds.length === 0) { return null @@ -271,7 +275,7 @@ export async function runOnIdle( // Log the tool IDs being pruned with their tool names for (const id of newlyPrunedIds) { const metadata = toolMetadata.get(id) - const toolName = metadata?.tool || 'unknown' + const toolName = metadata?.tool || "unknown" logger.info(`OnIdle pruning tool: ${toolName}`, { callID: id }) } @@ -301,7 +305,7 @@ export async function runOnIdle( prunedToolMetadata, undefined, // reason currentParams, - workingDirectory || "" + workingDirectory || "", ) state.stats.totalPruneTokens += state.stats.pruneTokenCounter @@ -311,7 +315,7 @@ export async function runOnIdle( // Persist state const sessionName = sessionInfo?.title - saveSessionState(state, logger, sessionName).catch(err => { + saveSessionState(state, logger, sessionName).catch((err) => { logger.error("Failed to persist state", { error: err.message }) }) diff --git a/lib/strategies/prune-tool.ts b/lib/strategies/prune-tool.ts index 285a88d..94de456 100644 --- a/lib/strategies/prune-tool.ts +++ b/lib/strategies/prune-tool.ts @@ -9,6 +9,7 @@ import { saveSessionState } from "../state/persistence" import type { Logger } from "../logger" import { loadPrompt } from "../prompt" import { calculateTokensSaved, getCurrentParams } from "./utils" +import { requestPruneConfirmation } from "../ui/confirmation" /** Tool description loaded from prompts/prune-tool-spec.txt */ const TOOL_DESCRIPTION = loadPrompt("prune-tool-spec") @@ -25,23 +26,26 @@ export interface PruneToolContext { * Creates the prune tool definition. * Accepts numeric IDs from the list and prunes those tool outputs. */ -export function createPruneTool( - ctx: PruneToolContext, -): ReturnType { +export function createPruneTool(ctx: PruneToolContext): ReturnType { return tool({ description: TOOL_DESCRIPTION, args: { - ids: tool.schema.array( - tool.schema.string() - ).describe( - "Numeric IDs as strings to prune from the list" - ), - metadata: tool.schema.object({ - reason: tool.schema.enum(["completion", "noise", "consolidation"]).describe("The reason for pruning"), - distillation: tool.schema.record(tool.schema.string(), tool.schema.any()).optional().describe( - "An object containing detailed summaries or extractions of the key findings from the tools being pruned. This is REQUIRED for 'consolidation'." - ), - }).describe("Metadata about the pruning operation."), + ids: tool.schema + .array(tool.schema.string()) + .describe("Numeric IDs as strings to prune from the list"), + metadata: tool.schema + .object({ + reason: tool.schema + .enum(["completion", "noise", "consolidation"]) + .describe("The reason for pruning"), + distillation: tool.schema + .record(tool.schema.string(), tool.schema.any()) + .optional() + .describe( + "An object containing detailed summaries or extractions of the key findings from the tools being pruned. This is REQUIRED for 'consolidation'.", + ), + }) + .describe("Metadata about the pruning operation."), }, async execute(args, toolCtx) { const { client, state, logger, config, workingDirectory } = ctx @@ -51,7 +55,9 @@ export function createPruneTool( logger.info(JSON.stringify(args)) if (!args.ids || args.ids.length === 0) { - logger.debug("Prune tool called but args.ids is empty or undefined: " + JSON.stringify(args)) + logger.debug( + "Prune tool called but args.ids is empty or undefined: " + JSON.stringify(args), + ) return "No IDs provided. Check the list for available IDs to prune." } @@ -60,20 +66,23 @@ export function createPruneTool( return "Missing metadata.reason. Provide metadata: { reason: 'completion' | 'noise' | 'consolidation' }" } - const { reason, distillation } = args.metadata; + const { reason, distillation } = args.metadata const numericToolIds: number[] = args.ids - .map(id => parseInt(id, 10)) + .map((id) => parseInt(id, 10)) .filter((n): n is number => !isNaN(n)) if (numericToolIds.length === 0) { - logger.debug("No numeric tool IDs provided for pruning, yet prune tool was called: " + JSON.stringify(args)) + logger.debug( + "No numeric tool IDs provided for pruning, yet prune tool was called: " + + JSON.stringify(args), + ) return "No numeric IDs provided. Format: ids: [id1, id2, ...]" } // Fetch messages to calculate tokens and find current agent const messagesResponse = await client.session.messages({ - path: { id: sessionId } + path: { id: sessionId }, }) const messages: WithParts[] = messagesResponse.data || messagesResponse @@ -83,7 +92,7 @@ export function createPruneTool( const toolIdList: string[] = buildToolIdList(state, messages, logger) // Validate that all numeric IDs are within bounds - if (numericToolIds.some(id => id < 0 || id >= toolIdList.length)) { + if (numericToolIds.some((id) => id < 0 || id >= toolIdList.length)) { logger.debug("Invalid tool IDs provided: " + numericToolIds.join(", ")) return "Invalid IDs provided. Only use numeric IDs from the list." } @@ -94,17 +103,23 @@ export function createPruneTool( const id = toolIdList[index] const metadata = state.toolParameters.get(id) if (!metadata) { - logger.debug("Rejecting prune request - ID not in cache (turn-protected or hallucinated)", { index, id }) + logger.debug( + "Rejecting prune request - ID not in cache (turn-protected or hallucinated)", + { index, id }, + ) return "Invalid IDs provided. Only use numeric IDs from the list." } if (config.strategies.pruneTool.protectedTools.includes(metadata.tool)) { - logger.debug("Rejecting prune request - protected tool", { index, id, tool: metadata.tool }) + logger.debug("Rejecting prune request - protected tool", { + index, + id, + tool: metadata.tool, + }) return "Invalid IDs provided. Only use numeric IDs from the list." } } - const pruneToolIds: string[] = numericToolIds.map(index => toolIdList[index]) - state.prune.toolIds.push(...pruneToolIds) + const pruneToolIds: string[] = numericToolIds.map((index) => toolIdList[index]) const toolMetadata = new Map() for (const id of pruneToolIds) { @@ -116,7 +131,34 @@ export function createPruneTool( } } - state.stats.pruneTokenCounter += calculateTokensSaved(state, messages, pruneToolIds) + // Request user confirmation before pruning + const confirmedIds = await requestPruneConfirmation( + client, + sessionId, + pruneToolIds, + toolMetadata, + currentParams, + logger, + workingDirectory, + ) + + if (confirmedIds.length === 0) { + logger.info("Prune cancelled by user") + return "Prune cancelled by user." + } + + // Use only the confirmed IDs + const finalPruneIds = confirmedIds + state.prune.toolIds.push(...finalPruneIds) + + // Recalculate metadata for confirmed IDs only + const finalMetadata = new Map() + for (const id of finalPruneIds) { + const entry = toolMetadata.get(id) + if (entry) finalMetadata.set(id, entry) + } + + state.stats.pruneTokenCounter += calculateTokensSaved(state, messages, finalPruneIds) await sendUnifiedNotification( client, @@ -124,24 +166,25 @@ export function createPruneTool( config, state, sessionId, - pruneToolIds, - toolMetadata, + finalPruneIds, + finalMetadata, reason as PruneReason, currentParams, - workingDirectory + workingDirectory, ) state.stats.totalPruneTokens += state.stats.pruneTokenCounter state.stats.pruneTokenCounter = 0 state.nudgeCounter = 0 - saveSessionState(state, logger) - .catch(err => logger.error("Failed to persist state", { error: err.message })) + saveSessionState(state, logger).catch((err) => + logger.error("Failed to persist state", { error: err.message }), + ) const result = formatPruningResultForTool( - pruneToolIds, - toolMetadata, - workingDirectory + finalPruneIds, + finalMetadata, + workingDirectory, ) if (distillation) { @@ -152,4 +195,3 @@ export function createPruneTool( }, }) } - diff --git a/lib/strategies/supersede-writes.ts b/lib/strategies/supersede-writes.ts index b8bb847..327cb58 100644 --- a/lib/strategies/supersede-writes.ts +++ b/lib/strategies/supersede-writes.ts @@ -16,7 +16,7 @@ export const supersedeWrites = ( state: SessionState, logger: Logger, config: PluginConfig, - messages: WithParts[] + messages: WithParts[], ): void => { if (!config.strategies.supersedeWrites.enabled) { return @@ -31,14 +31,14 @@ export const supersedeWrites = ( // Filter out IDs already pruned const alreadyPruned = new Set(state.prune.toolIds) - const unprunedIds = allToolIds.filter(id => !alreadyPruned.has(id)) + const unprunedIds = allToolIds.filter((id) => !alreadyPruned.has(id)) if (unprunedIds.length === 0) { return } // Track write tools by file path: filePath -> [{ id, index }] // We track index to determine chronological order - const writesByFile = new Map() + const writesByFile = new Map() // Track read file paths with their index const readsByFile = new Map() @@ -55,12 +55,12 @@ export const supersedeWrites = ( continue } - if (metadata.tool === 'write') { + if (metadata.tool === "write") { if (!writesByFile.has(filePath)) { writesByFile.set(filePath, []) } writesByFile.get(filePath)!.push({ id, index: i }) - } else if (metadata.tool === 'read') { + } else if (metadata.tool === "read") { if (!readsByFile.has(filePath)) { readsByFile.set(filePath, []) } @@ -85,7 +85,7 @@ export const supersedeWrites = ( } // Check if any read comes after this write - const hasSubsequentRead = reads.some(readIndex => readIndex > write.index) + const hasSubsequentRead = reads.some((readIndex) => readIndex > write.index) if (hasSubsequentRead) { newPruneIds.push(write.id) } diff --git a/lib/strategies/utils.ts b/lib/strategies/utils.ts index 3c6a1b1..85d750e 100644 --- a/lib/strategies/utils.ts +++ b/lib/strategies/utils.ts @@ -1,15 +1,15 @@ import { SessionState, WithParts } from "../state" import { UserMessage } from "@opencode-ai/sdk" import { Logger } from "../logger" -import { encode } from 'gpt-tokenizer' +import { encode } from "gpt-tokenizer" import { getLastUserMessage, isMessageCompacted } from "../shared-utils" export function getCurrentParams( messages: WithParts[], - logger: Logger + logger: Logger, ): { - providerId: string | undefined, - modelId: string | undefined, + providerId: string | undefined + modelId: string | undefined agent: string | undefined } { const userMsg = getLastUserMessage(messages) @@ -29,9 +29,9 @@ export function getCurrentParams( */ function estimateTokensBatch(texts: string[]): number[] { try { - return texts.map(text => encode(text).length) + return texts.map((text) => encode(text).length) } catch { - return texts.map(text => Math.round(text.length / 4)) + return texts.map((text) => Math.round(text.length / 4)) } } @@ -42,7 +42,7 @@ function estimateTokensBatch(texts: string[]): number[] { export const calculateTokensSaved = ( state: SessionState, messages: WithParts[], - pruneToolIds: string[] + pruneToolIds: string[], ): number => { try { const contents: string[] = [] @@ -51,29 +51,32 @@ export const calculateTokensSaved = ( continue } for (const part of msg.parts) { - if (part.type !== 'tool' || !pruneToolIds.includes(part.callID)) { + if (part.type !== "tool" || !pruneToolIds.includes(part.callID)) { continue } // For write and edit tools, count input content as that is all we prune for these tools // (input is present in both completed and error states) if (part.tool === "write" || part.tool === "edit") { const inputContent = part.state.input?.content - const content = typeof inputContent === 'string' - ? inputContent - : JSON.stringify(inputContent ?? '') + const content = + typeof inputContent === "string" + ? inputContent + : JSON.stringify(inputContent ?? "") contents.push(content) continue } // For other tools, count output or error based on status if (part.state.status === "completed") { - const content = typeof part.state.output === 'string' - ? part.state.output - : JSON.stringify(part.state.output) + const content = + typeof part.state.output === "string" + ? part.state.output + : JSON.stringify(part.state.output) contents.push(content) } else if (part.state.status === "error") { - const content = typeof part.state.error === 'string' - ? part.state.error - : JSON.stringify(part.state.error) + const content = + typeof part.state.error === "string" + ? part.state.error + : JSON.stringify(part.state.error) contents.push(content) } } diff --git a/lib/ui/confirmation.ts b/lib/ui/confirmation.ts new file mode 100644 index 0000000..2e6d0f9 --- /dev/null +++ b/lib/ui/confirmation.ts @@ -0,0 +1,114 @@ +import type { Logger } from "../logger" +import type { ToolParameterEntry } from "../state" +import { extractParameterKey } from "../messages/utils" +import { shortenPath, truncate } from "./utils" + +export interface PendingConfirmation { + resolve: (confirmedIds: string[]) => void + items: Array<{ id: string; label: string; checked: boolean }> +} + +// Shared state for pending confirmations +let pendingPrune: PendingConfirmation | null = null + +// Auto-confirm mode - when true, automatically confirms all prunes +let autoConfirmEnabled = false + +export function getPendingPrune(): PendingConfirmation | null { + return pendingPrune +} + +export function setPendingPrune(pending: PendingConfirmation | null): void { + pendingPrune = pending +} + +export function isAutoConfirmEnabled(): boolean { + return autoConfirmEnabled +} + +export function setAutoConfirm(enabled: boolean): void { + autoConfirmEnabled = enabled +} + +export function resolvePendingPrune(confirmedIds: string[]): void { + if (pendingPrune) { + pendingPrune.resolve(confirmedIds) + pendingPrune = null + } +} + +/** + * Shows a confirmation UI for pruning and returns a Promise that resolves + * with the list of confirmed tool IDs (or empty array if cancelled). + * If auto-confirm is enabled, immediately returns all IDs without showing UI. + */ +export async function requestPruneConfirmation( + client: any, + sessionId: string, + pruneToolIds: string[], + toolMetadata: Map, + params: any, + logger: Logger, + workingDirectory: string, +): Promise { + // If auto-confirm is enabled, immediately return all IDs + if (autoConfirmEnabled) { + logger.info("Auto-confirming prune", { itemCount: pruneToolIds.length }) + return pruneToolIds + } + + // Build checklist items from the tool metadata + const items = pruneToolIds.map((id) => { + const meta = toolMetadata.get(id) + let label = id + if (meta) { + const toolName = meta.tool.charAt(0).toUpperCase() + meta.tool.slice(1) + const paramKey = extractParameterKey(meta.tool, meta.parameters) + if (paramKey) { + label = `${toolName} ${truncate(shortenPath(paramKey, workingDirectory), 50)}` + } else { + label = `${toolName}` + } + } + return { id, label, checked: true } + }) + + logger.info("Requesting prune confirmation", { itemCount: items.length }) + + // Create the promise that will be resolved by UI events + return new Promise((resolve) => { + setPendingPrune({ resolve, items }) + + const agent = params.agent || undefined + const model = + params.providerId && params.modelId + ? { providerID: params.providerId, modelID: params.modelId } + : undefined + + // Send the confirmation UI message + client.session + .prompt({ + path: { id: sessionId }, + body: { + noReply: true, + agent, + model, + parts: [ + { + type: "text", + text: "dcp-confirm", + plugin: true, + metadata: { items }, + }, + ], + }, + }) + .catch((error: any) => { + logger.error("Failed to send confirmation UI", { + error: error.message, + }) + resolve([]) // Resolve with empty on error + setPendingPrune(null) + }) + }) +} diff --git a/lib/ui/notification.ts b/lib/ui/notification.ts index ead50ac..e2b415b 100644 --- a/lib/ui/notification.ts +++ b/lib/ui/notification.ts @@ -1,57 +1,10 @@ import type { Logger } from "../logger" import type { SessionState } from "../state" -import { formatPrunedItemsList, formatTokenCount } from "./utils" +import { formatPrunedItemsList } from "./utils" import { ToolParameterEntry } from "../state" import { PluginConfig } from "../config" export type PruneReason = "completion" | "noise" | "consolidation" -export const PRUNE_REASON_LABELS: Record = { - completion: "Task Complete", - noise: "Noise Removal", - consolidation: "Consolidation" -} - -function formatStatsHeader( - totalTokensSaved: number, - pruneTokenCounter: number -): string { - const totalTokensSavedStr = `~${formatTokenCount(totalTokensSaved + pruneTokenCounter)}` - return [ - `▣ DCP | ${totalTokensSavedStr} saved total`, - ].join('\n') -} - -function buildMinimalMessage( - state: SessionState, - reason: PruneReason | undefined -): string { - const reasonSuffix = reason ? ` [${PRUNE_REASON_LABELS[reason]}]` : '' - return formatStatsHeader( - state.stats.totalPruneTokens, - state.stats.pruneTokenCounter - ) + reasonSuffix -} - -function buildDetailedMessage( - state: SessionState, - reason: PruneReason | undefined, - pruneToolIds: string[], - toolMetadata: Map, - workingDirectory?: string -): string { - let message = formatStatsHeader(state.stats.totalPruneTokens, state.stats.pruneTokenCounter) - - if (pruneToolIds.length > 0) { - const pruneTokenCounterStr = `~${formatTokenCount(state.stats.pruneTokenCounter)}` - const reasonLabel = reason ? ` — ${PRUNE_REASON_LABELS[reason]}` : '' - message += `\n\n▣ Pruning (${pruneTokenCounterStr})${reasonLabel}` - - const itemLines = formatPrunedItemsList(pruneToolIds, toolMetadata, workingDirectory) - message += '\n' + itemLines.join('\n') - } - - return message.trim() -} export async function sendUnifiedNotification( client: any, @@ -63,56 +16,78 @@ export async function sendUnifiedNotification( toolMetadata: Map, reason: PruneReason | undefined, params: any, - workingDirectory: string + workingDirectory: string, ): Promise { const hasPruned = pruneToolIds.length > 0 if (!hasPruned) { return false } - if (config.pruningSummary === 'off') { + if (config.pruningSummary === "off") { return false } - const message = config.pruningSummary === 'minimal' - ? buildMinimalMessage(state, reason) - : buildDetailedMessage(state, reason, pruneToolIds, toolMetadata, workingDirectory) + const totalSaved = state.stats.totalPruneTokens + state.stats.pruneTokenCounter + const itemLines = formatPrunedItemsList(pruneToolIds, toolMetadata, workingDirectory) - await sendIgnoredMessage(client, sessionId, message, params, logger) + await sendPruneSummary( + client, + sessionId, + params, + logger, + totalSaved, + pruneToolIds.length, + itemLines, + ) return true } -export async function sendIgnoredMessage( +export async function sendPruneSummary( client: any, - sessionID: string, - text: string, + sessionId: string, params: any, - logger: Logger + logger: Logger, + totalSaved: number, + count: number, + itemLines: string[], ): Promise { const agent = params.agent || undefined - const model = params.providerId && params.modelId ? { - providerID: params.providerId, - modelID: params.modelId - } : undefined + const model = + params.providerId && params.modelId + ? { + providerID: params.providerId, + modelID: params.modelId, + } + : undefined + + const formatted = totalSaved >= 1000 ? `~${(totalSaved / 1000).toFixed(1)}K` : `${totalSaved}` + + const parts: any[] = [ + { + type: "text", + text: "dcp-prune-summary", + plugin: true, + metadata: { + saved: formatted, + count: String(count), + itemsList: itemLines.join("\n"), + }, + }, + ] try { await client.session.prompt({ path: { - id: sessionID + id: sessionId, }, body: { noReply: true, agent: agent, model: model, - parts: [{ - type: 'text', - text: text, - ignored: true - }] - } + parts: parts, + }, }) } catch (error: any) { - logger.error("Failed to send notification", { error: error.message }) + logger.error("Failed to send prune summary", { error: error.message }) } } - diff --git a/lib/ui/utils.ts b/lib/ui/utils.ts index 11335fa..539bc77 100644 --- a/lib/ui/utils.ts +++ b/lib/ui/utils.ts @@ -3,14 +3,14 @@ import { extractParameterKey } from "../messages/utils" export function formatTokenCount(tokens: number): string { if (tokens >= 1000) { - return `${(tokens / 1000).toFixed(1)}K`.replace('.0K', 'K') + ' tokens' + return `${(tokens / 1000).toFixed(1)}K`.replace(".0K", "K") + " tokens" } - return tokens.toString() + ' tokens' + return tokens.toString() + " tokens" } export function truncate(str: string, maxLen: number = 60): string { if (str.length <= maxLen) return str - return str.slice(0, maxLen - 3) + '...' + return str.slice(0, maxLen - 3) + "..." } export function shortenPath(input: string, workingDirectory?: string): string { @@ -27,11 +27,11 @@ export function shortenPath(input: string, workingDirectory?: string): string { function shortenSinglePath(path: string, workingDirectory?: string): string { if (workingDirectory) { - if (path.startsWith(workingDirectory + '/')) { + if (path.startsWith(workingDirectory + "/")) { return path.slice(workingDirectory.length + 1) } if (path === workingDirectory) { - return '.' + return "." } } @@ -39,12 +39,12 @@ function shortenSinglePath(path: string, workingDirectory?: string): string { } /** - * Formats a list of pruned items in the style: "→ tool: parameter" + * Formats a list of pruned items in the style: "tool: parameter" */ export function formatPrunedItemsList( pruneToolIds: string[], toolMetadata: Map, - workingDirectory?: string + workingDirectory?: string, ): string[] { const lines: string[] = [] @@ -56,20 +56,20 @@ export function formatPrunedItemsList( if (paramKey) { // Use 60 char limit to match notification style const displayKey = truncate(shortenPath(paramKey, workingDirectory), 60) - lines.push(`→ ${metadata.tool}: ${displayKey}`) + const toolName = metadata.tool.charAt(0).toUpperCase() + metadata.tool.slice(1) + lines.push(`${toolName}: ${displayKey}`) } else { - lines.push(`→ ${metadata.tool}`) + const toolName = metadata.tool.charAt(0).toUpperCase() + metadata.tool.slice(1) + lines.push(`${toolName}`) } } } - const knownCount = pruneToolIds.filter(id => - toolMetadata.has(id) - ).length + const knownCount = pruneToolIds.filter((id) => toolMetadata.has(id)).length const unknownCount = pruneToolIds.length - knownCount if (unknownCount > 0) { - lines.push(`→ (${unknownCount} tool${unknownCount > 1 ? 's' : ''} with unknown metadata)`) + lines.push(`(${unknownCount} tool${unknownCount > 1 ? "s" : ""} with unknown metadata)`) } return lines @@ -81,16 +81,16 @@ export function formatPrunedItemsList( export function formatPruningResultForTool( prunedIds: string[], toolMetadata: Map, - workingDirectory?: string + workingDirectory?: string, ): string { const lines: string[] = [] lines.push(`Context pruning complete. Pruned ${prunedIds.length} tool outputs.`) - lines.push('') + lines.push("") if (prunedIds.length > 0) { lines.push(`Semantically pruned (${prunedIds.length}):`) lines.push(...formatPrunedItemsList(prunedIds, toolMetadata, workingDirectory)) } - return lines.join('\n').trim() + return lines.join("\n").trim() } diff --git a/package-lock.json b/package-lock.json index 42b0ebd..d7e73c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,2309 +1,2309 @@ { - "name": "@tarquinen/opencode-dcp", - "version": "1.0.4", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@tarquinen/opencode-dcp", - "version": "1.0.4", - "license": "MIT", - "dependencies": { - "@ai-sdk/openai-compatible": "^1.0.28", - "@opencode-ai/sdk": "latest", - "@tarquinen/opencode-auth-provider": "^0.1.7", - "ai": "^5.0.106", - "gpt-tokenizer": "^3.4.0", - "jsonc-parser": "^3.3.1", - "zod": "^4.1.13" - }, - "devDependencies": { - "@opencode-ai/plugin": "^1.0.143", - "@types/node": "^24.10.1", - "tsx": "^4.21.0", - "typescript": "^5.9.3" - }, - "peerDependencies": { - "@opencode-ai/plugin": ">=0.13.7" - } - }, - "node_modules/@ai-sdk/gateway": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.18.tgz", - "integrity": "sha512-sDQcW+6ck2m0pTIHW6BPHD7S125WD3qNkx/B8sEzJp/hurocmJ5Cni0ybExg6sQMGo+fr/GWOwpHF1cmCdg5rQ==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.18", - "@vercel/oidc": "3.0.5" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/openai-compatible": { - "version": "1.0.28", - "resolved": "https://registry.npmjs.org/@ai-sdk/openai-compatible/-/openai-compatible-1.0.28.tgz", - "integrity": "sha512-yKubDxLYtXyGUzkr9lNStf/lE/I+Okc8tmotvyABhsQHHieLKk6oV5fJeRJxhr67Ejhg+FRnwUOxAmjRoFM4dA==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.18" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz", - "integrity": "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@ai-sdk/provider-utils": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.18.tgz", - "integrity": "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@standard-schema/spec": "^1.0.0", - "eventsource-parser": "^3.0.6" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@aws-crypto/sha256-browser": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", - "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", - "license": "Apache-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.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/sha256-js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", - "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/util": "^5.2.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@aws-crypto/supports-web-crypto": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", - "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-crypto/util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", - "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "^3.222.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", - "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", - "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", - "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^2.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.943.0.tgz", - "integrity": "sha512-XkuokRF2IQ+VLBn0AwrwfFOkZ2c1IXACwQdn3CDnpBZpT1s2hgH3MX0DoH9+41w4ar2QCSI09uAJiv9PX4DLoQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.943.0", - "@aws-sdk/credential-provider-node": "3.943.0", - "@aws-sdk/middleware-host-header": "3.936.0", - "@aws-sdk/middleware-logger": "3.936.0", - "@aws-sdk/middleware-recursion-detection": "3.936.0", - "@aws-sdk/middleware-user-agent": "3.943.0", - "@aws-sdk/region-config-resolver": "3.936.0", - "@aws-sdk/types": "3.936.0", - "@aws-sdk/util-endpoints": "3.936.0", - "@aws-sdk/util-user-agent-browser": "3.936.0", - "@aws-sdk/util-user-agent-node": "3.943.0", - "@smithy/config-resolver": "^4.4.3", - "@smithy/core": "^3.18.5", - "@smithy/fetch-http-handler": "^5.3.6", - "@smithy/hash-node": "^4.2.5", - "@smithy/invalid-dependency": "^4.2.5", - "@smithy/middleware-content-length": "^4.2.5", - "@smithy/middleware-endpoint": "^4.3.12", - "@smithy/middleware-retry": "^4.4.12", - "@smithy/middleware-serde": "^4.2.6", - "@smithy/middleware-stack": "^4.2.5", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/node-http-handler": "^4.4.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/smithy-client": "^4.9.8", - "@smithy/types": "^4.9.0", - "@smithy/url-parser": "^4.2.5", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.11", - "@smithy/util-defaults-mode-node": "^4.2.14", - "@smithy/util-endpoints": "^3.2.5", - "@smithy/util-middleware": "^4.2.5", - "@smithy/util-retry": "^4.2.5", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.943.0.tgz", - "integrity": "sha512-kOTO2B8Ks2qX73CyKY8PAajtf5n39aMe2spoiOF5EkgSzGV7hZ/HONRDyADlyxwfsX39Q2F2SpPUaXzon32IGw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.943.0", - "@aws-sdk/middleware-host-header": "3.936.0", - "@aws-sdk/middleware-logger": "3.936.0", - "@aws-sdk/middleware-recursion-detection": "3.936.0", - "@aws-sdk/middleware-user-agent": "3.943.0", - "@aws-sdk/region-config-resolver": "3.936.0", - "@aws-sdk/types": "3.936.0", - "@aws-sdk/util-endpoints": "3.936.0", - "@aws-sdk/util-user-agent-browser": "3.936.0", - "@aws-sdk/util-user-agent-node": "3.943.0", - "@smithy/config-resolver": "^4.4.3", - "@smithy/core": "^3.18.5", - "@smithy/fetch-http-handler": "^5.3.6", - "@smithy/hash-node": "^4.2.5", - "@smithy/invalid-dependency": "^4.2.5", - "@smithy/middleware-content-length": "^4.2.5", - "@smithy/middleware-endpoint": "^4.3.12", - "@smithy/middleware-retry": "^4.4.12", - "@smithy/middleware-serde": "^4.2.6", - "@smithy/middleware-stack": "^4.2.5", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/node-http-handler": "^4.4.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/smithy-client": "^4.9.8", - "@smithy/types": "^4.9.0", - "@smithy/url-parser": "^4.2.5", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.11", - "@smithy/util-defaults-mode-node": "^4.2.14", - "@smithy/util-endpoints": "^3.2.5", - "@smithy/util-middleware": "^4.2.5", - "@smithy/util-retry": "^4.2.5", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/core": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.943.0.tgz", - "integrity": "sha512-8CBy2hI9ABF7RBVQuY1bgf/ue+WPmM/hl0adrXFlhnhkaQP0tFY5zhiy1Y+n7V+5f3/ORoHBmCCQmcHDDYJqJQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.936.0", - "@aws-sdk/xml-builder": "3.930.0", - "@smithy/core": "^3.18.5", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/property-provider": "^4.2.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/signature-v4": "^5.3.5", - "@smithy/smithy-client": "^4.9.8", - "@smithy/types": "^4.9.0", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-middleware": "^4.2.5", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.943.0.tgz", - "integrity": "sha512-jZJ0uHjNlhfjx2ZX7YVYnh1wfSkLAvQmecGCSl9C6LJRNXy4uWFPbGjPqcA0tWp0WWIsUYhqjasgvCOMZIY8nw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/property-provider": "^4.2.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.943.0.tgz", - "integrity": "sha512-WnS5w9fK9CTuoZRVSIHLOMcI63oODg9qd1vXMYb7QGLGlfwUm4aG3hdu7i9XvYrpkQfE3dzwWLtXF4ZBuL1Tew==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/property-provider": "^4.2.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.943.0.tgz", - "integrity": "sha512-SA8bUcYDEACdhnhLpZNnWusBpdmj4Vl67Vxp3Zke7SvoWSYbuxa+tiDiC+c92Z4Yq6xNOuLPW912ZPb9/NsSkA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/fetch-http-handler": "^5.3.6", - "@smithy/node-http-handler": "^4.4.5", - "@smithy/property-provider": "^4.2.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/smithy-client": "^4.9.8", - "@smithy/types": "^4.9.0", - "@smithy/util-stream": "^4.5.6", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.943.0.tgz", - "integrity": "sha512-BcLDb8l4oVW+NkuqXMlO7TnM6lBOWW318ylf4FRED/ply5eaGxkQYqdGvHSqGSN5Rb3vr5Ek0xpzSjeYD7C8Kw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.943.0", - "@aws-sdk/credential-provider-env": "3.943.0", - "@aws-sdk/credential-provider-http": "3.943.0", - "@aws-sdk/credential-provider-login": "3.943.0", - "@aws-sdk/credential-provider-process": "3.943.0", - "@aws-sdk/credential-provider-sso": "3.943.0", - "@aws-sdk/credential-provider-web-identity": "3.943.0", - "@aws-sdk/nested-clients": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/credential-provider-imds": "^4.2.5", - "@smithy/property-provider": "^4.2.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.943.0.tgz", - "integrity": "sha512-9iCOVkiRW+evxiJE94RqosCwRrzptAVPhRhGWv4osfYDhjNAvUMyrnZl3T1bjqCoKNcETRKEZIU3dqYHnUkcwQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.943.0", - "@aws-sdk/nested-clients": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/property-provider": "^4.2.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.943.0.tgz", - "integrity": "sha512-14eddaH/gjCWoLSAELVrFOQNyswUYwWphIt+PdsJ/FqVfP4ay2HsiZVEIYbQtmrKHaoLJhiZKwBQRjcqJDZG0w==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.943.0", - "@aws-sdk/credential-provider-http": "3.943.0", - "@aws-sdk/credential-provider-ini": "3.943.0", - "@aws-sdk/credential-provider-process": "3.943.0", - "@aws-sdk/credential-provider-sso": "3.943.0", - "@aws-sdk/credential-provider-web-identity": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/credential-provider-imds": "^4.2.5", - "@smithy/property-provider": "^4.2.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.943.0.tgz", - "integrity": "sha512-GIY/vUkthL33AdjOJ8r9vOosKf/3X+X7LIiACzGxvZZrtoOiRq0LADppdiKIB48vTL63VvW+eRIOFAxE6UDekw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/property-provider": "^4.2.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.943.0.tgz", - "integrity": "sha512-1c5G11syUrru3D9OO6Uk+ul5e2lX1adb+7zQNyluNaLPXP6Dina6Sy6DFGRLu7tM8+M7luYmbS3w63rpYpaL+A==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-sso": "3.943.0", - "@aws-sdk/core": "3.943.0", - "@aws-sdk/token-providers": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/property-provider": "^4.2.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.943.0.tgz", - "integrity": "sha512-VtyGKHxICSb4kKGuaqotxso8JVM8RjCS3UYdIMOxUt9TaFE/CZIfZKtjTr+IJ7M0P7t36wuSUb/jRLyNmGzUUA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.943.0", - "@aws-sdk/nested-clients": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/property-provider": "^4.2.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-providers": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.943.0.tgz", - "integrity": "sha512-uZurSNsS01ehhrSwEPwcKdqp9lmd/x9q++BYO351bXyjSj1LzA/2lfUIxI2tCz/wAjJWOdnnlUdJj6P9I1uNvw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.943.0", - "@aws-sdk/core": "3.943.0", - "@aws-sdk/credential-provider-cognito-identity": "3.943.0", - "@aws-sdk/credential-provider-env": "3.943.0", - "@aws-sdk/credential-provider-http": "3.943.0", - "@aws-sdk/credential-provider-ini": "3.943.0", - "@aws-sdk/credential-provider-login": "3.943.0", - "@aws-sdk/credential-provider-node": "3.943.0", - "@aws-sdk/credential-provider-process": "3.943.0", - "@aws-sdk/credential-provider-sso": "3.943.0", - "@aws-sdk/credential-provider-web-identity": "3.943.0", - "@aws-sdk/nested-clients": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/config-resolver": "^4.4.3", - "@smithy/core": "^3.18.5", - "@smithy/credential-provider-imds": "^4.2.5", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/property-provider": "^4.2.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.936.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.936.0.tgz", - "integrity": "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.936.0", - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.936.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.936.0.tgz", - "integrity": "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.936.0", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.936.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.936.0.tgz", - "integrity": "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.936.0", - "@aws/lambda-invoke-store": "^0.2.0", - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.943.0.tgz", - "integrity": "sha512-956n4kVEwFNXndXfhSAN5wO+KRgqiWEEY+ECwLvxmmO8uQ0NWOa8l6l65nTtyuiWzMX81c9BvlyNR5EgUeeUvA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@aws-sdk/util-endpoints": "3.936.0", - "@smithy/core": "^3.18.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.943.0.tgz", - "integrity": "sha512-anFtB0p2FPuyUnbOULwGmKYqYKSq1M73c9uZ08jR/NCq6Trjq9cuF5TFTeHwjJyPRb4wMf2Qk859oiVfFqnQiw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.943.0", - "@aws-sdk/middleware-host-header": "3.936.0", - "@aws-sdk/middleware-logger": "3.936.0", - "@aws-sdk/middleware-recursion-detection": "3.936.0", - "@aws-sdk/middleware-user-agent": "3.943.0", - "@aws-sdk/region-config-resolver": "3.936.0", - "@aws-sdk/types": "3.936.0", - "@aws-sdk/util-endpoints": "3.936.0", - "@aws-sdk/util-user-agent-browser": "3.936.0", - "@aws-sdk/util-user-agent-node": "3.943.0", - "@smithy/config-resolver": "^4.4.3", - "@smithy/core": "^3.18.5", - "@smithy/fetch-http-handler": "^5.3.6", - "@smithy/hash-node": "^4.2.5", - "@smithy/invalid-dependency": "^4.2.5", - "@smithy/middleware-content-length": "^4.2.5", - "@smithy/middleware-endpoint": "^4.3.12", - "@smithy/middleware-retry": "^4.4.12", - "@smithy/middleware-serde": "^4.2.6", - "@smithy/middleware-stack": "^4.2.5", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/node-http-handler": "^4.4.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/smithy-client": "^4.9.8", - "@smithy/types": "^4.9.0", - "@smithy/url-parser": "^4.2.5", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.11", - "@smithy/util-defaults-mode-node": "^4.2.14", - "@smithy/util-endpoints": "^3.2.5", - "@smithy/util-middleware": "^4.2.5", - "@smithy/util-retry": "^4.2.5", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.936.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.936.0.tgz", - "integrity": "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.936.0", - "@smithy/config-resolver": "^4.4.3", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.943.0.tgz", - "integrity": "sha512-cRKyIzwfkS+XztXIFPoWORuaxlIswP+a83BJzelX4S1gUZ7FcXB4+lj9Jxjn8SbQhR4TPU3Owbpu+S7pd6IRbQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.943.0", - "@aws-sdk/nested-clients": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/property-provider": "^4.2.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/types": { - "version": "3.936.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz", - "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.936.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.936.0.tgz", - "integrity": "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.936.0", - "@smithy/types": "^4.9.0", - "@smithy/url-parser": "^4.2.5", - "@smithy/util-endpoints": "^3.2.5", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.893.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.893.0.tgz", - "integrity": "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.936.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.936.0.tgz", - "integrity": "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.936.0", - "@smithy/types": "^4.9.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.943.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.943.0.tgz", - "integrity": "sha512-gn+ILprVRrgAgTIBk2TDsJLRClzIOdStQFeFTcN0qpL8Z4GBCqMFhw7O7X+MM55Stt5s4jAauQ/VvoqmCADnQg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/middleware-user-agent": "3.943.0", - "@aws-sdk/types": "3.936.0", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } - } - }, - "node_modules/@aws-sdk/xml-builder": { - "version": "3.930.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.930.0.tgz", - "integrity": "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "fast-xml-parser": "5.2.5", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws/lambda-invoke-store": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.1.tgz", - "integrity": "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", - "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", - "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", - "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", - "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", - "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", - "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", - "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", - "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", - "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", - "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", - "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", - "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", - "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", - "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", - "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", - "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", - "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", - "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", - "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", - "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", - "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", - "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", - "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", - "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", - "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", - "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@openauthjs/openauth": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@openauthjs/openauth/-/openauth-0.4.3.tgz", - "integrity": "sha512-RlnjqvHzqcbFVymEwhlUEuac4utA5h4nhSK/i2szZuQmxTIqbGUxZ+nM+avM+VV4Ing+/ZaNLKILoXS3yrkOOw==", - "dependencies": { - "@standard-schema/spec": "1.0.0-beta.3", - "aws4fetch": "1.0.20", - "jose": "5.9.6" - }, - "peerDependencies": { - "arctic": "^2.2.2", - "hono": "^4.0.0" - } - }, - "node_modules/@openauthjs/openauth/node_modules/@standard-schema/spec": { - "version": "1.0.0-beta.3", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0-beta.3.tgz", - "integrity": "sha512-0ifF3BjA1E8SY9C+nUew8RefNOIq0cDlYALPty4rhUm8Rrl6tCM8hBT4bhGhx7I7iXD0uAgt50lgo8dD73ACMw==", - "license": "MIT" - }, - "node_modules/@opencode-ai/plugin": { - "version": "1.0.143", - "resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.0.143.tgz", - "integrity": "sha512-yzaCmdazVJMDADJLbMM8KGp1X+Hd/HVyIXMlNt9qcvz/fcs/ET4EwHJsJaQi/9m/jLJ+plwBJAeIW08BMrECPg==", - "dev": true, - "dependencies": { - "@opencode-ai/sdk": "1.0.143", - "zod": "4.1.8" - } - }, - "node_modules/@opencode-ai/plugin/node_modules/zod": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.8.tgz", - "integrity": "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/@opencode-ai/sdk": { - "version": "1.0.143", - "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.0.143.tgz", - "integrity": "sha512-dtmkBfJ7IIAHzL6KCzAlwc9GybfJONVeCsF6ePYySpkuhslDbRkZBJYb5vqGd1H5zdsgjc6JjuvmOf0rPWUL6A==" - }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@oslojs/asn1": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@oslojs/asn1/-/asn1-1.0.0.tgz", - "integrity": "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@oslojs/binary": "1.0.0" - } - }, - "node_modules/@oslojs/binary": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@oslojs/binary/-/binary-1.0.0.tgz", - "integrity": "sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ==", - "license": "MIT", - "peer": true - }, - "node_modules/@oslojs/crypto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@oslojs/crypto/-/crypto-1.0.1.tgz", - "integrity": "sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@oslojs/asn1": "1.0.0", - "@oslojs/binary": "1.0.0" - } - }, - "node_modules/@oslojs/encoding": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", - "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", - "license": "MIT", - "peer": true - }, - "node_modules/@oslojs/jwt": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@oslojs/jwt/-/jwt-0.2.0.tgz", - "integrity": "sha512-bLE7BtHrURedCn4Mco3ma9L4Y1GR2SMBuIvjWr7rmQ4/W/4Jy70TIAgZ+0nIlk0xHz1vNP8x8DCns45Sb2XRbg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@oslojs/encoding": "0.4.1" - } - }, - "node_modules/@oslojs/jwt/node_modules/@oslojs/encoding": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-0.4.1.tgz", - "integrity": "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q==", - "license": "MIT", - "peer": true - }, - "node_modules/@smithy/abort-controller": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz", - "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz", - "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/types": "^4.9.0", - "@smithy/util-config-provider": "^4.2.0", - "@smithy/util-endpoints": "^3.2.5", - "@smithy/util-middleware": "^4.2.5", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/core": { - "version": "3.18.6", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.6.tgz", - "integrity": "sha512-8Q/ugWqfDUEU1Exw71+DoOzlONJ2Cn9QA8VeeDzLLjzO/qruh9UKFzbszy4jXcIYgGofxYiT0t1TT6+CT/GupQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/middleware-serde": "^4.2.6", - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-middleware": "^4.2.5", - "@smithy/util-stream": "^4.5.6", - "@smithy/util-utf8": "^4.2.0", - "@smithy/uuid": "^1.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz", - "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/property-provider": "^4.2.5", - "@smithy/types": "^4.9.0", - "@smithy/url-parser": "^4.2.5", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz", - "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.3.5", - "@smithy/querystring-builder": "^4.2.5", - "@smithy/types": "^4.9.0", - "@smithy/util-base64": "^4.3.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/hash-node": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz", - "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "@smithy/util-buffer-from": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz", - "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", - "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz", - "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "4.3.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.13.tgz", - "integrity": "sha512-X4za1qCdyx1hEVVXuAWlZuK6wzLDv1uw1OY9VtaYy1lULl661+frY7FeuHdYdl7qAARUxH2yvNExU2/SmRFfcg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.18.6", - "@smithy/middleware-serde": "^4.2.6", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "@smithy/url-parser": "^4.2.5", - "@smithy/util-middleware": "^4.2.5", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.13.tgz", - "integrity": "sha512-RzIDF9OrSviXX7MQeKOm8r/372KTyY8Jmp6HNKOOYlrguHADuM3ED/f4aCyNhZZFLG55lv5beBin7nL0Nzy1Dw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/service-error-classification": "^4.2.5", - "@smithy/smithy-client": "^4.9.9", - "@smithy/types": "^4.9.0", - "@smithy/util-middleware": "^4.2.5", - "@smithy/util-retry": "^4.2.5", - "@smithy/uuid": "^1.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.6.tgz", - "integrity": "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.5.tgz", - "integrity": "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.5.tgz", - "integrity": "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.2.5", - "@smithy/shared-ini-file-loader": "^4.4.0", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz", - "integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/abort-controller": "^4.2.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/querystring-builder": "^4.2.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/property-provider": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.5.tgz", - "integrity": "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.5.tgz", - "integrity": "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/querystring-builder": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz", - "integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "@smithy/util-uri-escape": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/querystring-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz", - "integrity": "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/service-error-classification": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.5.tgz", - "integrity": "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.0.tgz", - "integrity": "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz", - "integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.2.0", - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "@smithy/util-hex-encoding": "^4.2.0", - "@smithy/util-middleware": "^4.2.5", - "@smithy/util-uri-escape": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/smithy-client": { - "version": "4.9.9", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.9.tgz", - "integrity": "sha512-SUnZJMMo5yCmgjopJbiNeo1vlr8KvdnEfIHV9rlD77QuOGdRotIVBcOrBuMr+sI9zrnhtDtLP054bZVbpZpiQA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.18.6", - "@smithy/middleware-endpoint": "^4.3.13", - "@smithy/middleware-stack": "^4.2.5", - "@smithy/protocol-http": "^5.3.5", - "@smithy/types": "^4.9.0", - "@smithy/util-stream": "^4.5.6", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz", - "integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/url-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.5.tgz", - "integrity": "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/querystring-parser": "^4.2.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-base64": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz", - "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-browser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz", - "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-body-length-node": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz", - "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-buffer-from": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz", - "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-config-provider": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz", - "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.3.12", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.12.tgz", - "integrity": "sha512-TKc6FnOxFULKxLgTNHYjcFqdOYzXVPFFVm5JhI30F3RdhT7nYOtOsjgaOwfDRmA/3U66O9KaBQ3UHoXwayRhAg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.2.5", - "@smithy/smithy-client": "^4.9.9", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.15", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.15.tgz", - "integrity": "sha512-94NqfQVo+vGc5gsQ9SROZqOvBkGNMQu6pjXbnn8aQvBUhc31kx49gxlkBEqgmaZQHUUfdRUin5gK/HlHKmbAwg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/config-resolver": "^4.4.3", - "@smithy/credential-provider-imds": "^4.2.5", - "@smithy/node-config-provider": "^4.3.5", - "@smithy/property-provider": "^4.2.5", - "@smithy/smithy-client": "^4.9.9", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-endpoints": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.5.tgz", - "integrity": "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.3.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-hex-encoding": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz", - "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-middleware": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.5.tgz", - "integrity": "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-retry": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.5.tgz", - "integrity": "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/service-error-classification": "^4.2.5", - "@smithy/types": "^4.9.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-stream": { - "version": "4.5.6", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.6.tgz", - "integrity": "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/fetch-http-handler": "^5.3.6", - "@smithy/node-http-handler": "^4.4.5", - "@smithy/types": "^4.9.0", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-buffer-from": "^4.2.0", - "@smithy/util-hex-encoding": "^4.2.0", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-uri-escape": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz", - "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/util-utf8": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", - "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/uuid": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz", - "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", - "license": "MIT" - }, - "node_modules/@tarquinen/opencode-auth-provider": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@tarquinen/opencode-auth-provider/-/opencode-auth-provider-0.1.7.tgz", - "integrity": "sha512-FH1QEyoirr2e8b48Z6HrjioIZIZUIM9zOpYmku1ad+c4Nv70F37fSWhcObyIdZo4Ly3OntpKPWjadyRhd/kQcg==", - "license": "MIT", - "dependencies": { - "@aws-sdk/credential-providers": "^3.936.0", - "ai": "^5.0.98", - "jsonc-parser": "^3.3.1", - "opencode-anthropic-auth": "0.0.2", - "opencode-copilot-auth": "0.0.5", - "opencode-gemini-auth": "^1.1.4", - "remeda": "^2.32.0", - "xdg-basedir": "^5.1.0", - "zod": "^4.1.12" - }, - "peerDependencies": { - "@ai-sdk/amazon-bedrock": ">=1.0.0", - "@ai-sdk/anthropic": ">=1.0.0", - "@ai-sdk/azure": ">=1.0.0", - "@ai-sdk/google": ">=1.0.0", - "@ai-sdk/google-vertex": ">=1.0.0", - "@ai-sdk/openai": ">=1.0.0", - "@ai-sdk/openai-compatible": ">=0.1.0", - "@openrouter/ai-sdk-provider": ">=0.1.0" - }, - "peerDependenciesMeta": { - "@ai-sdk/amazon-bedrock": { - "optional": true - }, - "@ai-sdk/anthropic": { - "optional": true - }, - "@ai-sdk/azure": { - "optional": true - }, - "@ai-sdk/google": { - "optional": true - }, - "@ai-sdk/google-vertex": { - "optional": true - }, - "@ai-sdk/openai": { - "optional": true - }, - "@ai-sdk/openai-compatible": { - "optional": true - }, - "@openrouter/ai-sdk-provider": { - "optional": true - } - } - }, - "node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@vercel/oidc": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.0.5.tgz", - "integrity": "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==", - "license": "Apache-2.0", - "engines": { - "node": ">= 20" - } - }, - "node_modules/ai": { - "version": "5.0.106", - "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.106.tgz", - "integrity": "sha512-M5obwavxSJJ3tGlAFqI6eltYNJB0D20X6gIBCFx/KVorb/X1fxVVfiZZpZb+Gslu4340droSOjT0aKQFCarNVg==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/gateway": "2.0.18", - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.18", - "@opentelemetry/api": "1.9.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/arctic": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/arctic/-/arctic-2.3.4.tgz", - "integrity": "sha512-+p30BOWsctZp+CVYCt7oAean/hWGW42sH5LAcRQX56ttEkFJWbzXBhmSpibbzwSJkRrotmsA+oAoJoVsU0f5xA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@oslojs/crypto": "1.0.1", - "@oslojs/encoding": "1.1.0", - "@oslojs/jwt": "0.2.0" - } - }, - "node_modules/aws4fetch": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/aws4fetch/-/aws4fetch-1.0.20.tgz", - "integrity": "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g==", - "license": "MIT" - }, - "node_modules/bowser": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.13.1.tgz", - "integrity": "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==", - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", - "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.0", - "@esbuild/android-arm": "0.27.0", - "@esbuild/android-arm64": "0.27.0", - "@esbuild/android-x64": "0.27.0", - "@esbuild/darwin-arm64": "0.27.0", - "@esbuild/darwin-x64": "0.27.0", - "@esbuild/freebsd-arm64": "0.27.0", - "@esbuild/freebsd-x64": "0.27.0", - "@esbuild/linux-arm": "0.27.0", - "@esbuild/linux-arm64": "0.27.0", - "@esbuild/linux-ia32": "0.27.0", - "@esbuild/linux-loong64": "0.27.0", - "@esbuild/linux-mips64el": "0.27.0", - "@esbuild/linux-ppc64": "0.27.0", - "@esbuild/linux-riscv64": "0.27.0", - "@esbuild/linux-s390x": "0.27.0", - "@esbuild/linux-x64": "0.27.0", - "@esbuild/netbsd-arm64": "0.27.0", - "@esbuild/netbsd-x64": "0.27.0", - "@esbuild/openbsd-arm64": "0.27.0", - "@esbuild/openbsd-x64": "0.27.0", - "@esbuild/openharmony-arm64": "0.27.0", - "@esbuild/sunos-x64": "0.27.0", - "@esbuild/win32-arm64": "0.27.0", - "@esbuild/win32-ia32": "0.27.0", - "@esbuild/win32-x64": "0.27.0" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", - "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/fast-xml-parser": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", - "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "strnum": "^2.1.0" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/gpt-tokenizer": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/gpt-tokenizer/-/gpt-tokenizer-3.4.0.tgz", - "integrity": "sha512-wxFLnhIXTDjYebd9A9pGl3e31ZpSypbpIJSOswbgop5jLte/AsZVDvjlbEuVFlsqZixVKqbcoNmRlFDf6pz/UQ==", - "license": "MIT" - }, - "node_modules/hono": { - "version": "4.10.7", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.10.7.tgz", - "integrity": "sha512-icXIITfw/07Q88nLSkB9aiUrd8rYzSweK681Kjo/TSggaGbOX4RRyxxm71v+3PC8C/j+4rlxGeoTRxQDkaJkUw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/jose": { - "version": "5.9.6", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.9.6.tgz", - "integrity": "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "license": "MIT" - }, - "node_modules/opencode-anthropic-auth": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/opencode-anthropic-auth/-/opencode-anthropic-auth-0.0.2.tgz", - "integrity": "sha512-m8dcEKtq2ExGLV7n4BMr1H5UimDaABV6aG82IDMcp1xmXUaO1K20/hess0s8cwvv6MFmJk4//2wbWZkzoOtirA==", - "dependencies": { - "@openauthjs/openauth": "^0.4.3" - } - }, - "node_modules/opencode-copilot-auth": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/opencode-copilot-auth/-/opencode-copilot-auth-0.0.5.tgz", - "integrity": "sha512-aOna2jy3BnaEpVJkeF32joUzI8DcpbBMWjd7zW6sgX4t58AnxaEB5sDadLsxRfcxJdhmABd5k6QSww5LcJ4e9Q==" - }, - "node_modules/opencode-gemini-auth": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/opencode-gemini-auth/-/opencode-gemini-auth-1.1.6.tgz", - "integrity": "sha512-7WxOEwYMqXeCD2jf/Wj+8yBS3qwnRxHKt/sWhn2ZBDgz+dVwrC/SpTNvpva1fF8KSgVVG8tS9yvDQXM0JcVGoQ==", - "license": "MIT", - "dependencies": { - "@openauthjs/openauth": "^0.4.3" - }, - "peerDependencies": { - "typescript": "^5" - } - }, - "node_modules/remeda": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.32.0.tgz", - "integrity": "sha512-BZx9DsT4FAgXDTOdgJIc5eY6ECIXMwtlSPQoPglF20ycSWigttDDe88AozEsPPT4OWk5NujroGSBC1phw5uU+w==", - "license": "MIT", - "dependencies": { - "type-fest": "^4.41.0" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/strnum": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", - "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" + "name": "@tarquinen/opencode-dcp", + "version": "1.0.4", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@tarquinen/opencode-dcp", + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "@ai-sdk/openai-compatible": "^1.0.28", + "@opencode-ai/sdk": "latest", + "@tarquinen/opencode-auth-provider": "^0.1.7", + "ai": "^5.0.106", + "gpt-tokenizer": "^3.4.0", + "jsonc-parser": "^3.3.1", + "zod": "^4.1.13" + }, + "devDependencies": { + "@opencode-ai/plugin": "^1.0.143", + "@types/node": "^24.10.1", + "tsx": "^4.21.0", + "typescript": "^5.9.3" + }, + "peerDependencies": { + "@opencode-ai/plugin": ">=0.13.7" + } + }, + "node_modules/@ai-sdk/gateway": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-2.0.18.tgz", + "integrity": "sha512-sDQcW+6ck2m0pTIHW6BPHD7S125WD3qNkx/B8sEzJp/hurocmJ5Cni0ybExg6sQMGo+fr/GWOwpHF1cmCdg5rQ==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "2.0.0", + "@ai-sdk/provider-utils": "3.0.18", + "@vercel/oidc": "3.0.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/openai-compatible": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/@ai-sdk/openai-compatible/-/openai-compatible-1.0.28.tgz", + "integrity": "sha512-yKubDxLYtXyGUzkr9lNStf/lE/I+Okc8tmotvyABhsQHHieLKk6oV5fJeRJxhr67Ejhg+FRnwUOxAmjRoFM4dA==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "2.0.0", + "@ai-sdk/provider-utils": "3.0.18" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz", + "integrity": "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==", + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/provider-utils": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.18.tgz", + "integrity": "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "2.0.0", + "@standard-schema/spec": "^1.0.0", + "eventsource-parser": "^3.0.6" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "license": "Apache-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.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-cognito-identity": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.943.0.tgz", + "integrity": "sha512-XkuokRF2IQ+VLBn0AwrwfFOkZ2c1IXACwQdn3CDnpBZpT1s2hgH3MX0DoH9+41w4ar2QCSI09uAJiv9PX4DLoQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/credential-provider-node": "3.943.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.943.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.943.0.tgz", + "integrity": "sha512-kOTO2B8Ks2qX73CyKY8PAajtf5n39aMe2spoiOF5EkgSzGV7hZ/HONRDyADlyxwfsX39Q2F2SpPUaXzon32IGw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.943.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.943.0.tgz", + "integrity": "sha512-8CBy2hI9ABF7RBVQuY1bgf/ue+WPmM/hl0adrXFlhnhkaQP0tFY5zhiy1Y+n7V+5f3/ORoHBmCCQmcHDDYJqJQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@aws-sdk/xml-builder": "3.930.0", + "@smithy/core": "^3.18.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/signature-v4": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-cognito-identity": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.943.0.tgz", + "integrity": "sha512-jZJ0uHjNlhfjx2ZX7YVYnh1wfSkLAvQmecGCSl9C6LJRNXy4uWFPbGjPqcA0tWp0WWIsUYhqjasgvCOMZIY8nw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.943.0.tgz", + "integrity": "sha512-WnS5w9fK9CTuoZRVSIHLOMcI63oODg9qd1vXMYb7QGLGlfwUm4aG3hdu7i9XvYrpkQfE3dzwWLtXF4ZBuL1Tew==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.943.0.tgz", + "integrity": "sha512-SA8bUcYDEACdhnhLpZNnWusBpdmj4Vl67Vxp3Zke7SvoWSYbuxa+tiDiC+c92Z4Yq6xNOuLPW912ZPb9/NsSkA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.943.0.tgz", + "integrity": "sha512-BcLDb8l4oVW+NkuqXMlO7TnM6lBOWW318ylf4FRED/ply5eaGxkQYqdGvHSqGSN5Rb3vr5Ek0xpzSjeYD7C8Kw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/credential-provider-env": "3.943.0", + "@aws-sdk/credential-provider-http": "3.943.0", + "@aws-sdk/credential-provider-login": "3.943.0", + "@aws-sdk/credential-provider-process": "3.943.0", + "@aws-sdk/credential-provider-sso": "3.943.0", + "@aws-sdk/credential-provider-web-identity": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.943.0.tgz", + "integrity": "sha512-9iCOVkiRW+evxiJE94RqosCwRrzptAVPhRhGWv4osfYDhjNAvUMyrnZl3T1bjqCoKNcETRKEZIU3dqYHnUkcwQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.943.0.tgz", + "integrity": "sha512-14eddaH/gjCWoLSAELVrFOQNyswUYwWphIt+PdsJ/FqVfP4ay2HsiZVEIYbQtmrKHaoLJhiZKwBQRjcqJDZG0w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.943.0", + "@aws-sdk/credential-provider-http": "3.943.0", + "@aws-sdk/credential-provider-ini": "3.943.0", + "@aws-sdk/credential-provider-process": "3.943.0", + "@aws-sdk/credential-provider-sso": "3.943.0", + "@aws-sdk/credential-provider-web-identity": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.943.0.tgz", + "integrity": "sha512-GIY/vUkthL33AdjOJ8r9vOosKf/3X+X7LIiACzGxvZZrtoOiRq0LADppdiKIB48vTL63VvW+eRIOFAxE6UDekw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.943.0.tgz", + "integrity": "sha512-1c5G11syUrru3D9OO6Uk+ul5e2lX1adb+7zQNyluNaLPXP6Dina6Sy6DFGRLu7tM8+M7luYmbS3w63rpYpaL+A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.943.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/token-providers": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.943.0.tgz", + "integrity": "sha512-VtyGKHxICSb4kKGuaqotxso8JVM8RjCS3UYdIMOxUt9TaFE/CZIfZKtjTr+IJ7M0P7t36wuSUb/jRLyNmGzUUA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-providers": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.943.0.tgz", + "integrity": "sha512-uZurSNsS01ehhrSwEPwcKdqp9lmd/x9q++BYO351bXyjSj1LzA/2lfUIxI2tCz/wAjJWOdnnlUdJj6P9I1uNvw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.943.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/credential-provider-cognito-identity": "3.943.0", + "@aws-sdk/credential-provider-env": "3.943.0", + "@aws-sdk/credential-provider-http": "3.943.0", + "@aws-sdk/credential-provider-ini": "3.943.0", + "@aws-sdk/credential-provider-login": "3.943.0", + "@aws-sdk/credential-provider-node": "3.943.0", + "@aws-sdk/credential-provider-process": "3.943.0", + "@aws-sdk/credential-provider-sso": "3.943.0", + "@aws-sdk/credential-provider-web-identity": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.936.0.tgz", + "integrity": "sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.936.0.tgz", + "integrity": "sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.936.0.tgz", + "integrity": "sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@aws/lambda-invoke-store": "^0.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.943.0.tgz", + "integrity": "sha512-956n4kVEwFNXndXfhSAN5wO+KRgqiWEEY+ECwLvxmmO8uQ0NWOa8l6l65nTtyuiWzMX81c9BvlyNR5EgUeeUvA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@smithy/core": "^3.18.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.943.0.tgz", + "integrity": "sha512-anFtB0p2FPuyUnbOULwGmKYqYKSq1M73c9uZ08jR/NCq6Trjq9cuF5TFTeHwjJyPRb4wMf2Qk859oiVfFqnQiw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.943.0", + "@aws-sdk/middleware-host-header": "3.936.0", + "@aws-sdk/middleware-logger": "3.936.0", + "@aws-sdk/middleware-recursion-detection": "3.936.0", + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/region-config-resolver": "3.936.0", + "@aws-sdk/types": "3.936.0", + "@aws-sdk/util-endpoints": "3.936.0", + "@aws-sdk/util-user-agent-browser": "3.936.0", + "@aws-sdk/util-user-agent-node": "3.943.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/core": "^3.18.5", + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/hash-node": "^4.2.5", + "@smithy/invalid-dependency": "^4.2.5", + "@smithy/middleware-content-length": "^4.2.5", + "@smithy/middleware-endpoint": "^4.3.12", + "@smithy/middleware-retry": "^4.4.12", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/smithy-client": "^4.9.8", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.11", + "@smithy/util-defaults-mode-node": "^4.2.14", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.936.0.tgz", + "integrity": "sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/config-resolver": "^4.4.3", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.943.0.tgz", + "integrity": "sha512-cRKyIzwfkS+XztXIFPoWORuaxlIswP+a83BJzelX4S1gUZ7FcXB4+lj9Jxjn8SbQhR4TPU3Owbpu+S7pd6IRbQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.943.0", + "@aws-sdk/nested-clients": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.936.0.tgz", + "integrity": "sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.936.0.tgz", + "integrity": "sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-endpoints": "^3.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.893.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.893.0.tgz", + "integrity": "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.936.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.936.0.tgz", + "integrity": "sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.936.0", + "@smithy/types": "^4.9.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.943.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.943.0.tgz", + "integrity": "sha512-gn+ILprVRrgAgTIBk2TDsJLRClzIOdStQFeFTcN0qpL8Z4GBCqMFhw7O7X+MM55Stt5s4jAauQ/VvoqmCADnQg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.943.0", + "@aws-sdk/types": "3.936.0", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.930.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.930.0.tgz", + "integrity": "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.1.tgz", + "integrity": "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", + "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", + "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", + "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", + "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", + "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", + "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", + "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", + "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", + "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", + "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", + "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", + "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", + "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", + "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", + "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", + "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", + "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", + "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", + "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", + "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", + "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", + "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", + "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", + "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", + "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", + "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@openauthjs/openauth": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@openauthjs/openauth/-/openauth-0.4.3.tgz", + "integrity": "sha512-RlnjqvHzqcbFVymEwhlUEuac4utA5h4nhSK/i2szZuQmxTIqbGUxZ+nM+avM+VV4Ing+/ZaNLKILoXS3yrkOOw==", + "dependencies": { + "@standard-schema/spec": "1.0.0-beta.3", + "aws4fetch": "1.0.20", + "jose": "5.9.6" + }, + "peerDependencies": { + "arctic": "^2.2.2", + "hono": "^4.0.0" + } + }, + "node_modules/@openauthjs/openauth/node_modules/@standard-schema/spec": { + "version": "1.0.0-beta.3", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0-beta.3.tgz", + "integrity": "sha512-0ifF3BjA1E8SY9C+nUew8RefNOIq0cDlYALPty4rhUm8Rrl6tCM8hBT4bhGhx7I7iXD0uAgt50lgo8dD73ACMw==", + "license": "MIT" + }, + "node_modules/@opencode-ai/plugin": { + "version": "1.0.143", + "resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.0.143.tgz", + "integrity": "sha512-yzaCmdazVJMDADJLbMM8KGp1X+Hd/HVyIXMlNt9qcvz/fcs/ET4EwHJsJaQi/9m/jLJ+plwBJAeIW08BMrECPg==", + "dev": true, + "dependencies": { + "@opencode-ai/sdk": "1.0.143", + "zod": "4.1.8" + } + }, + "node_modules/@opencode-ai/plugin/node_modules/zod": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.8.tgz", + "integrity": "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@opencode-ai/sdk": { + "version": "1.0.143", + "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.0.143.tgz", + "integrity": "sha512-dtmkBfJ7IIAHzL6KCzAlwc9GybfJONVeCsF6ePYySpkuhslDbRkZBJYb5vqGd1H5zdsgjc6JjuvmOf0rPWUL6A==" + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oslojs/asn1": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@oslojs/asn1/-/asn1-1.0.0.tgz", + "integrity": "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@oslojs/binary": "1.0.0" + } + }, + "node_modules/@oslojs/binary": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@oslojs/binary/-/binary-1.0.0.tgz", + "integrity": "sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@oslojs/crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@oslojs/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@oslojs/asn1": "1.0.0", + "@oslojs/binary": "1.0.0" + } + }, + "node_modules/@oslojs/encoding": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@oslojs/jwt": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@oslojs/jwt/-/jwt-0.2.0.tgz", + "integrity": "sha512-bLE7BtHrURedCn4Mco3ma9L4Y1GR2SMBuIvjWr7rmQ4/W/4Jy70TIAgZ+0nIlk0xHz1vNP8x8DCns45Sb2XRbg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@oslojs/encoding": "0.4.1" + } + }, + "node_modules/@oslojs/jwt/node_modules/@oslojs/encoding": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-0.4.1.tgz", + "integrity": "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q==", + "license": "MIT", + "peer": true + }, + "node_modules/@smithy/abort-controller": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.5.tgz", + "integrity": "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.3.tgz", + "integrity": "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-endpoints": "^3.2.5", + "@smithy/util-middleware": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "3.18.6", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.18.6.tgz", + "integrity": "sha512-8Q/ugWqfDUEU1Exw71+DoOzlONJ2Cn9QA8VeeDzLLjzO/qruh9UKFzbszy4jXcIYgGofxYiT0t1TT6+CT/GupQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/middleware-serde": "^4.2.6", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-stream": "^4.5.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.5.tgz", + "integrity": "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.6.tgz", + "integrity": "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.5.tgz", + "integrity": "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.5.tgz", + "integrity": "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz", + "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.5.tgz", + "integrity": "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.3.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.3.13.tgz", + "integrity": "sha512-X4za1qCdyx1hEVVXuAWlZuK6wzLDv1uw1OY9VtaYy1lULl661+frY7FeuHdYdl7qAARUxH2yvNExU2/SmRFfcg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.18.6", + "@smithy/middleware-serde": "^4.2.6", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "@smithy/url-parser": "^4.2.5", + "@smithy/util-middleware": "^4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.13.tgz", + "integrity": "sha512-RzIDF9OrSviXX7MQeKOm8r/372KTyY8Jmp6HNKOOYlrguHADuM3ED/f4aCyNhZZFLG55lv5beBin7nL0Nzy1Dw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/service-error-classification": "^4.2.5", + "@smithy/smithy-client": "^4.9.9", + "@smithy/types": "^4.9.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-retry": "^4.2.5", + "@smithy/uuid": "^1.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.6.tgz", + "integrity": "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.5.tgz", + "integrity": "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.5.tgz", + "integrity": "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.5", + "@smithy/shared-ini-file-loader": "^4.4.0", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.5.tgz", + "integrity": "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/querystring-builder": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.5.tgz", + "integrity": "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.5.tgz", + "integrity": "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.5.tgz", + "integrity": "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "@smithy/util-uri-escape": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.5.tgz", + "integrity": "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.5.tgz", + "integrity": "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.0.tgz", + "integrity": "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.5.tgz", + "integrity": "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-middleware": "^4.2.5", + "@smithy/util-uri-escape": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "4.9.9", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.9.9.tgz", + "integrity": "sha512-SUnZJMMo5yCmgjopJbiNeo1vlr8KvdnEfIHV9rlD77QuOGdRotIVBcOrBuMr+sI9zrnhtDtLP054bZVbpZpiQA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.18.6", + "@smithy/middleware-endpoint": "^4.3.13", + "@smithy/middleware-stack": "^4.2.5", + "@smithy/protocol-http": "^5.3.5", + "@smithy/types": "^4.9.0", + "@smithy/util-stream": "^4.5.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.9.0.tgz", + "integrity": "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.5.tgz", + "integrity": "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/querystring-parser": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz", + "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz", + "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz", + "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz", + "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz", + "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.12.tgz", + "integrity": "sha512-TKc6FnOxFULKxLgTNHYjcFqdOYzXVPFFVm5JhI30F3RdhT7nYOtOsjgaOwfDRmA/3U66O9KaBQ3UHoXwayRhAg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.2.5", + "@smithy/smithy-client": "^4.9.9", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "4.2.15", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.15.tgz", + "integrity": "sha512-94NqfQVo+vGc5gsQ9SROZqOvBkGNMQu6pjXbnn8aQvBUhc31kx49gxlkBEqgmaZQHUUfdRUin5gK/HlHKmbAwg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/config-resolver": "^4.4.3", + "@smithy/credential-provider-imds": "^4.2.5", + "@smithy/node-config-provider": "^4.3.5", + "@smithy/property-provider": "^4.2.5", + "@smithy/smithy-client": "^4.9.9", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.5.tgz", + "integrity": "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^4.3.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz", + "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.5.tgz", + "integrity": "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.5.tgz", + "integrity": "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/service-error-classification": "^4.2.5", + "@smithy/types": "^4.9.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.6.tgz", + "integrity": "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/fetch-http-handler": "^5.3.6", + "@smithy/node-http-handler": "^4.4.5", + "@smithy/types": "^4.9.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-buffer-from": "^4.2.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz", + "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz", + "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/uuid": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz", + "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT" + }, + "node_modules/@tarquinen/opencode-auth-provider": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@tarquinen/opencode-auth-provider/-/opencode-auth-provider-0.1.7.tgz", + "integrity": "sha512-FH1QEyoirr2e8b48Z6HrjioIZIZUIM9zOpYmku1ad+c4Nv70F37fSWhcObyIdZo4Ly3OntpKPWjadyRhd/kQcg==", + "license": "MIT", + "dependencies": { + "@aws-sdk/credential-providers": "^3.936.0", + "ai": "^5.0.98", + "jsonc-parser": "^3.3.1", + "opencode-anthropic-auth": "0.0.2", + "opencode-copilot-auth": "0.0.5", + "opencode-gemini-auth": "^1.1.4", + "remeda": "^2.32.0", + "xdg-basedir": "^5.1.0", + "zod": "^4.1.12" + }, + "peerDependencies": { + "@ai-sdk/amazon-bedrock": ">=1.0.0", + "@ai-sdk/anthropic": ">=1.0.0", + "@ai-sdk/azure": ">=1.0.0", + "@ai-sdk/google": ">=1.0.0", + "@ai-sdk/google-vertex": ">=1.0.0", + "@ai-sdk/openai": ">=1.0.0", + "@ai-sdk/openai-compatible": ">=0.1.0", + "@openrouter/ai-sdk-provider": ">=0.1.0" + }, + "peerDependenciesMeta": { + "@ai-sdk/amazon-bedrock": { + "optional": true + }, + "@ai-sdk/anthropic": { + "optional": true + }, + "@ai-sdk/azure": { + "optional": true + }, + "@ai-sdk/google": { + "optional": true + }, + "@ai-sdk/google-vertex": { + "optional": true + }, + "@ai-sdk/openai": { + "optional": true + }, + "@ai-sdk/openai-compatible": { + "optional": true + }, + "@openrouter/ai-sdk-provider": { + "optional": true + } + } + }, + "node_modules/@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@vercel/oidc": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.0.5.tgz", + "integrity": "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==", + "license": "Apache-2.0", + "engines": { + "node": ">= 20" + } + }, + "node_modules/ai": { + "version": "5.0.106", + "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.106.tgz", + "integrity": "sha512-M5obwavxSJJ3tGlAFqI6eltYNJB0D20X6gIBCFx/KVorb/X1fxVVfiZZpZb+Gslu4340droSOjT0aKQFCarNVg==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/gateway": "2.0.18", + "@ai-sdk/provider": "2.0.0", + "@ai-sdk/provider-utils": "3.0.18", + "@opentelemetry/api": "1.9.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/arctic": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/arctic/-/arctic-2.3.4.tgz", + "integrity": "sha512-+p30BOWsctZp+CVYCt7oAean/hWGW42sH5LAcRQX56ttEkFJWbzXBhmSpibbzwSJkRrotmsA+oAoJoVsU0f5xA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@oslojs/crypto": "1.0.1", + "@oslojs/encoding": "1.1.0", + "@oslojs/jwt": "0.2.0" + } + }, + "node_modules/aws4fetch": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/aws4fetch/-/aws4fetch-1.0.20.tgz", + "integrity": "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g==", + "license": "MIT" + }, + "node_modules/bowser": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.13.1.tgz", + "integrity": "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", + "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.0", + "@esbuild/android-arm": "0.27.0", + "@esbuild/android-arm64": "0.27.0", + "@esbuild/android-x64": "0.27.0", + "@esbuild/darwin-arm64": "0.27.0", + "@esbuild/darwin-x64": "0.27.0", + "@esbuild/freebsd-arm64": "0.27.0", + "@esbuild/freebsd-x64": "0.27.0", + "@esbuild/linux-arm": "0.27.0", + "@esbuild/linux-arm64": "0.27.0", + "@esbuild/linux-ia32": "0.27.0", + "@esbuild/linux-loong64": "0.27.0", + "@esbuild/linux-mips64el": "0.27.0", + "@esbuild/linux-ppc64": "0.27.0", + "@esbuild/linux-riscv64": "0.27.0", + "@esbuild/linux-s390x": "0.27.0", + "@esbuild/linux-x64": "0.27.0", + "@esbuild/netbsd-arm64": "0.27.0", + "@esbuild/netbsd-x64": "0.27.0", + "@esbuild/openbsd-arm64": "0.27.0", + "@esbuild/openbsd-x64": "0.27.0", + "@esbuild/openharmony-arm64": "0.27.0", + "@esbuild/sunos-x64": "0.27.0", + "@esbuild/win32-arm64": "0.27.0", + "@esbuild/win32-ia32": "0.27.0", + "@esbuild/win32-x64": "0.27.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/fast-xml-parser": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^2.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/gpt-tokenizer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/gpt-tokenizer/-/gpt-tokenizer-3.4.0.tgz", + "integrity": "sha512-wxFLnhIXTDjYebd9A9pGl3e31ZpSypbpIJSOswbgop5jLte/AsZVDvjlbEuVFlsqZixVKqbcoNmRlFDf6pz/UQ==", + "license": "MIT" + }, + "node_modules/hono": { + "version": "4.10.7", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.10.7.tgz", + "integrity": "sha512-icXIITfw/07Q88nLSkB9aiUrd8rYzSweK681Kjo/TSggaGbOX4RRyxxm71v+3PC8C/j+4rlxGeoTRxQDkaJkUw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/jose": { + "version": "5.9.6", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.9.6.tgz", + "integrity": "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "license": "MIT" + }, + "node_modules/opencode-anthropic-auth": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/opencode-anthropic-auth/-/opencode-anthropic-auth-0.0.2.tgz", + "integrity": "sha512-m8dcEKtq2ExGLV7n4BMr1H5UimDaABV6aG82IDMcp1xmXUaO1K20/hess0s8cwvv6MFmJk4//2wbWZkzoOtirA==", + "dependencies": { + "@openauthjs/openauth": "^0.4.3" + } + }, + "node_modules/opencode-copilot-auth": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/opencode-copilot-auth/-/opencode-copilot-auth-0.0.5.tgz", + "integrity": "sha512-aOna2jy3BnaEpVJkeF32joUzI8DcpbBMWjd7zW6sgX4t58AnxaEB5sDadLsxRfcxJdhmABd5k6QSww5LcJ4e9Q==" + }, + "node_modules/opencode-gemini-auth": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/opencode-gemini-auth/-/opencode-gemini-auth-1.1.6.tgz", + "integrity": "sha512-7WxOEwYMqXeCD2jf/Wj+8yBS3qwnRxHKt/sWhn2ZBDgz+dVwrC/SpTNvpva1fF8KSgVVG8tS9yvDQXM0JcVGoQ==", + "license": "MIT", + "dependencies": { + "@openauthjs/openauth": "^0.4.3" + }, + "peerDependencies": { + "typescript": "^5" + } + }, + "node_modules/remeda": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.32.0.tgz", + "integrity": "sha512-BZx9DsT4FAgXDTOdgJIc5eY6ECIXMwtlSPQoPglF20ycSWigttDDe88AozEsPPT4OWk5NujroGSBC1phw5uU+w==", + "license": "MIT", + "dependencies": { + "type-fest": "^4.41.0" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/strnum": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", + "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } - ], - "license": "MIT" - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "license": "MIT" - }, - "node_modules/xdg-basedir": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", - "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", - "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } - } } diff --git a/package.json b/package.json index 3732f49..2527951 100644 --- a/package.json +++ b/package.json @@ -1,60 +1,60 @@ { - "$schema": "https://json.schemastore.org/package.json", - "name": "@tarquinen/opencode-dcp", - "version": "1.0.4", - "type": "module", - "description": "OpenCode plugin that optimizes token usage by pruning obsolete tool outputs from conversation context", - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "scripts": { - "clean": "rm -rf dist", - "build": "npm run clean && tsc && cp -r lib/prompts dist/lib/prompts", - "postbuild": "rm -rf dist/logs", - "prepublishOnly": "npm run build", - "dev": "opencode plugin dev", - "typecheck": "tsc --noEmit", - "test": "node --import tsx --test tests/*.test.ts" - }, - "keywords": [ - "opencode", - "opencode-plugin", - "plugin", - "context", - "pruning", - "optimization", - "tokens" - ], - "repository": { - "type": "git", - "url": "git+https://github.com/Tarquinen/opencode-dynamic-context-pruning.git" - }, - "bugs": { - "url": "https://github.com/Tarquinen/opencode-dynamic-context-pruning/issues" - }, - "homepage": "https://github.com/Tarquinen/opencode-dynamic-context-pruning#readme", - "author": "tarquinen", - "license": "MIT", - "peerDependencies": { - "@opencode-ai/plugin": ">=0.13.7" - }, - "dependencies": { - "@ai-sdk/openai-compatible": "^1.0.28", - "@opencode-ai/sdk": "latest", - "@tarquinen/opencode-auth-provider": "^0.1.7", - "ai": "^5.0.106", - "gpt-tokenizer": "^3.4.0", - "jsonc-parser": "^3.3.1", - "zod": "^4.1.13" - }, - "devDependencies": { - "@opencode-ai/plugin": "^1.0.143", - "@types/node": "^24.10.1", - "tsx": "^4.21.0", - "typescript": "^5.9.3" - }, - "files": [ - "dist/", - "README.md", - "LICENSE" - ] + "$schema": "https://json.schemastore.org/package.json", + "name": "@tarquinen/opencode-dcp", + "version": "1.0.4", + "type": "module", + "description": "OpenCode plugin that optimizes token usage by pruning obsolete tool outputs from conversation context", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "clean": "rm -rf dist", + "build": "npm run clean && tsc && cp -r lib/prompts dist/lib/prompts", + "postbuild": "rm -rf dist/logs", + "prepublishOnly": "npm run build", + "dev": "opencode plugin dev", + "typecheck": "tsc --noEmit", + "test": "node --import tsx --test tests/*.test.ts" + }, + "keywords": [ + "opencode", + "opencode-plugin", + "plugin", + "context", + "pruning", + "optimization", + "tokens" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/Tarquinen/opencode-dynamic-context-pruning.git" + }, + "bugs": { + "url": "https://github.com/Tarquinen/opencode-dynamic-context-pruning/issues" + }, + "homepage": "https://github.com/Tarquinen/opencode-dynamic-context-pruning#readme", + "author": "tarquinen", + "license": "MIT", + "peerDependencies": { + "@opencode-ai/plugin": ">=0.13.7" + }, + "dependencies": { + "@ai-sdk/openai-compatible": "^1.0.28", + "@opencode-ai/sdk": "latest", + "@tarquinen/opencode-auth-provider": "^0.1.7", + "ai": "^5.0.106", + "gpt-tokenizer": "^3.4.0", + "jsonc-parser": "^3.3.1", + "zod": "^4.1.13" + }, + "devDependencies": { + "@opencode-ai/plugin": "^1.0.143", + "@types/node": "^24.10.1", + "tsx": "^4.21.0", + "typescript": "^5.9.3" + }, + "files": [ + "dist/", + "README.md", + "LICENSE" + ] } diff --git a/tsconfig.json b/tsconfig.json index e4fdca1..b30286c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,31 +1,24 @@ { - "$schema": "https://json.schemastore.org/tsconfig", - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "resolveJsonModule": true, - "allowJs": true, - "checkJs": false, - "outDir": "./dist", - "rootDir": ".", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "types": ["node"] - }, - "include": [ - "index.ts", - "lib/**/*" - ], - "exclude": [ - "node_modules", - "dist", - "logs" - ] + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "lib": ["ES2022"], + "moduleResolution": "bundler", + "resolveJsonModule": true, + "allowJs": true, + "checkJs": false, + "outDir": "./dist", + "rootDir": ".", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "types": ["node"] + }, + "include": ["index.ts", "lib/**/*"], + "exclude": ["node_modules", "dist", "logs"] }