From b6232472a74627f0aa3f95d149cbe5fcdaa51c4f Mon Sep 17 00:00:00 2001 From: dengmik-commits <270912164+dengmik-commits@users.noreply.github.com> Date: Fri, 29 May 2026 16:37:41 +0800 Subject: [PATCH 01/72] fix(mcp): fix Windows MCP spawn double-quoting that breaks all MCP servers The quoteWindowsShellArg function wrapped every argument in double quotes unconditionally, producing command strings like '"npx" "-y" "@playwright/mcp"'. When passed to spawn() with shell:true, Node.js wraps the entire string again for cmd.exe, causing double-quoting that breaks command parsing. All MCP servers (playwright, fetch, memory, github) failed to start on Windows. Fix: only quote arguments that contain spaces or double-quotes, leaving simple args unquoted. --- src/mcp/mcp-client.ts | 15 ++++++++++----- src/tests/mcp-client.test.ts | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/mcp/mcp-client.ts b/src/mcp/mcp-client.ts index 26a7a321..d2ef1c88 100644 --- a/src/mcp/mcp-client.ts +++ b/src/mcp/mcp-client.ts @@ -425,9 +425,11 @@ export function createMcpSpawnSpec( if (platform === "win32") { return { // On Windows, shell: true lets cmd.exe resolve the command via PATHEXT - // (npx -> npx.cmd, etc.). Pass one quoted command line with no spawn - // args to avoid Node 24 DEP0190. - command: [command, ...args].map(quoteWindowsShellArg).join(" "), + // (npx -> npx.cmd, etc.). Join command and args into a single string + // with empty spawn args to avoid Node 24 DEP0190. + // Only quote arguments that contain spaces or double-quotes to prevent + // double-wrapping by Node.js's own shell quoting. + command: [command, ...args].map(quoteWindowsArgIfNeeded).join(" "), args: [], shell: true, windowsHide: true, @@ -441,6 +443,9 @@ export function createMcpSpawnSpec( }; } -function quoteWindowsShellArg(arg: string): string { - return `"${arg.replace(/(\\*)"/g, '$1$1\\"').replace(/\\+$/g, "$&$&")}"`; +function quoteWindowsArgIfNeeded(arg: string): string { + if (arg.includes(" ") || arg.includes('"')) { + return `"${arg.replace(/(\\*)"/g, '$1$1\\"').replace(/\\+$/g, "$&$&")}"`; + } + return arg; } diff --git a/src/tests/mcp-client.test.ts b/src/tests/mcp-client.test.ts index e161aad3..29151d3a 100644 --- a/src/tests/mcp-client.test.ts +++ b/src/tests/mcp-client.test.ts @@ -10,9 +10,9 @@ test("createMcpSpawnSpec keeps non-Windows MCP launches shell-free", () => { }); }); -test("createMcpSpawnSpec avoids Windows shell args for Node 24", () => { +test("createMcpSpawnSpec joins args without quoting when spaces are absent (Windows)", () => { assert.deepEqual(createMcpSpawnSpec("npx", ["-y", "@playwright/mcp@latest"], "win32"), { - command: '"npx" "-y" "@playwright/mcp@latest"', + command: "npx -y @playwright/mcp@latest", args: [], shell: true, windowsHide: true, From 4b3339261548ed614a5f51c811a7e4626a328e80 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Mon, 8 Jun 2026 13:42:32 +0800 Subject: [PATCH 02/72] feat: implement `enabledSkills` support in settings.json --- docs/configuration.md | 18 +++++++++ docs/configuration_en.md | 18 +++++++++ src/session.ts | 9 ++++- src/settings.ts | 29 ++++++++++++++ src/tests/session.test.ts | 54 +++++++++++++++++++++++++++ src/tests/settings-and-notify.test.ts | 33 ++++++++++++++++ 6 files changed, 160 insertions(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index 752f7ab7..2f198b10 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -36,6 +36,7 @@ Deep Code 使用 `settings.json` 设置文件进行持久化配置,支持两 | `webSearchTool` | string | 自定义联网搜索脚本的完整路径 | | `mcpServers` | object | MCP 服务器配置(键为服务名,值为 McpServerConfig 对象) | | `temperature` | number | 模型采样温度,范围 `0` 到 `2` | +| `enabledSkills` | object | 按 skill 名称启用或禁用 skill 的配置 | #### `env` 子字段 @@ -101,6 +102,23 @@ Deep Code 内置免费可用的 Web Search 工具。如果需要自定义搜索 脚本接收一个搜索查询参数,输出 JSON 格式的结果供 AI 使用。 +#### `enabledSkills` — Skill 启用配置 + +控制 skill 扫描时是否包含指定 skill。键是解析后的 skill 名称,值必须是布尔值: + +```json +{ + "enabledSkills": { + "skill-writer": false, + "code-review": true + } +} +``` + +- 未配置的 skill 默认启用。 +- 将某个 skill 设置为 `false` 后,所有项目级和用户级目录中解析名称相同的 skill 都会被隐藏。 +- 项目设置会按 skill 覆盖用户设置。如果项目设置没有配置某个 skill,则使用用户设置。 + #### `mcpServers` — MCP 服务器 MCP(Model Context Protocol)服务器配置。值是键值对,键为服务名称,值为服务器配置对象。 diff --git a/docs/configuration_en.md b/docs/configuration_en.md index 8634992c..fac8c349 100644 --- a/docs/configuration_en.md +++ b/docs/configuration_en.md @@ -36,6 +36,7 @@ The following are all the top-level fields supported in `settings.json`, along w | `webSearchTool` | string | Full path to a custom web search script | | `mcpServers` | object | MCP server configurations (keys are service names, values are McpServerConfig objects) | | `temperature` | number | Sampling temperature for LLM, from `0` to `2` | +| `enabledSkills` | object | Per-skill enable/disable map, keyed by skill name | #### `env` Sub-fields @@ -101,6 +102,23 @@ Deep Code has a built-in, free-to-use Web Search tool. If you need custom search The script receives a search query as an argument and outputs results in JSON format for the AI. +#### `enabledSkills` — Skill Enablement + +Controls whether skills are included during skill scanning. Keys are resolved skill names, and values must be booleans: + +```json +{ + "enabledSkills": { + "skill-writer": false, + "code-review": true + } +} +``` + +- Missing entries are enabled by default. +- Setting a skill to `false` hides every skill with that resolved `name`, across project and user skill roots. +- Project settings override user settings per skill. If the project setting omits a skill, the user setting is used. + #### `mcpServers` — MCP Servers Configuration for MCP (Model Context Protocol) servers. The value is a key-value pair, where the key is the service name and the value is a server configuration object. diff --git a/src/session.ts b/src/session.ts index 9432a74d..7c479c8c 100644 --- a/src/session.ts +++ b/src/session.ts @@ -298,6 +298,7 @@ type SessionManagerOptions = { webSearchTool?: string; mcpServers?: Record; permissions?: Required; + enabledSkills?: Record; }; renderMarkdown: (text: string) => string; onAssistantMessage: (message: SessionMessage, shouldConnect: boolean) => void; @@ -324,6 +325,7 @@ export class SessionManager { webSearchTool?: string; mcpServers?: Record; permissions?: Required; + enabledSkills?: Record; }; private readonly onAssistantMessage: (message: SessionMessage, shouldConnect: boolean) => void; private readonly onSessionEntryUpdated?: (entry: SessionEntry) => void; @@ -808,6 +810,7 @@ ${agentInstructions} async listSkills(sessionId?: string): Promise { const skillRoots = this.getSkillScanRoots(); + const enabledSkills = this.getResolvedSettings().enabledSkills ?? {}; const skillsByName = new Map(); const collectSkills = (root: string, displayRoot: string): SkillInfo[] => { @@ -839,7 +842,11 @@ ${agentInstructions} } catch { continue; } - results.push(this.readSkillInfo(skillPath, `${displayRoot}/${skillName}/SKILL.md`, skillName)); + const skill = this.readSkillInfo(skillPath, `${displayRoot}/${skillName}/SKILL.md`, skillName); + if (enabledSkills[skill.name] === false) { + continue; + } + results.push(skill); } return results; }; diff --git a/src/settings.ts b/src/settings.ts index deb90344..c91f0306 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -43,6 +43,8 @@ export type PermissionSettings = { defaultMode?: PermissionDefaultMode; }; +export type EnabledSkillsSettings = Record; + export type DeepcodingSettings = { env?: DeepcodingEnv; model?: string; @@ -55,6 +57,7 @@ export type DeepcodingSettings = { webSearchTool?: string; mcpServers?: Record; permissions?: PermissionSettings; + enabledSkills?: EnabledSkillsSettings; }; export type ResolvedDeepcodingSettings = { @@ -71,6 +74,7 @@ export type ResolvedDeepcodingSettings = { webSearchTool?: string; mcpServers?: Record; permissions: Required; + enabledSkills: EnabledSkillsSettings; }; export type ModelConfigSelection = { @@ -188,6 +192,30 @@ function mergePermissions( }; } +function normalizeEnabledSkills(value: unknown): EnabledSkillsSettings { + if (!value || typeof value !== "object" || Array.isArray(value)) { + return {}; + } + const result: EnabledSkillsSettings = {}; + for (const [name, enabled] of Object.entries(value)) { + if (!name || typeof enabled !== "boolean") { + continue; + } + result[name] = enabled; + } + return result; +} + +function mergeEnabledSkills( + userSettings: DeepcodingSettings | null | undefined, + projectSettings: DeepcodingSettings | null | undefined +): EnabledSkillsSettings { + return { + ...normalizeEnabledSkills(userSettings?.enabledSkills), + ...normalizeEnabledSkills(projectSettings?.enabledSkills), + }; +} + function normalizeEnv(env: DeepcodingSettings["env"]): Record { const result: Record = {}; if (!env) { @@ -364,6 +392,7 @@ export function resolveSettingsSources( webSearchTool: webSearchTool || undefined, mcpServers: mergeMcpServers(userSettings, projectSettings, userEnv, projectEnv, systemEnv), permissions: mergePermissions(userSettings, projectSettings), + enabledSkills: mergeEnabledSkills(userSettings, projectSettings), }; } diff --git a/src/tests/session.test.ts b/src/tests/session.test.ts index b7660644..e22067fe 100644 --- a/src/tests/session.test.ts +++ b/src/tests/session.test.ts @@ -471,6 +471,60 @@ test("SessionManager lists skills from Deep Code and .agents roots by priority", assert.equal(sharedSkill?.description, "Project .deepcode skill"); }); +test("SessionManager excludes disabled skills by resolved skill name", async () => { + const workspace = createTempDir("deepcode-disabled-skills-workspace-"); + const home = createTempDir("deepcode-disabled-skills-home-"); + setHomeDir(home); + + const writeSkill = (root: string, dirName: string, skillName: string): void => { + const skillDir = path.join(root, dirName); + fs.mkdirSync(skillDir, { recursive: true }); + fs.writeFileSync( + path.join(skillDir, "SKILL.md"), + `---\nname: ${skillName}\ndescription: ${skillName} description\n---\n# ${skillName}\n`, + "utf8" + ); + }; + + for (const root of [ + path.join(workspace, ".deepcode", "skills"), + path.join(workspace, ".agents", "skills"), + path.join(home, ".deepcode", "skills"), + path.join(home, ".agents", "skills"), + ]) { + writeSkill(root, "skill-writer", "skill-writer"); + } + writeSkill(path.join(workspace, ".deepcode", "skills"), "frontmatter-disabled", "renamed-disabled"); + writeSkill(path.join(workspace, ".deepcode", "skills"), "enabled-skill", "enabled-skill"); + + const manager = new SessionManager({ + projectRoot: workspace, + createOpenAIClient: () => ({ + client: null, + model: "test-model", + baseURL: "https://api.deepseek.com", + thinkingEnabled: false, + machineId: "machine-id-disabled-skills", + }), + getResolvedSettings: () => ({ + model: "test-model", + enabledSkills: { + "skill-writer": false, + "renamed-disabled": false, + "enabled-skill": true, + }, + }), + renderMarkdown: (text) => text, + onAssistantMessage: () => {}, + }); + + const skills = await manager.listSkills(); + const skillNames = skills.map((skill) => skill.name); + + assert.deepEqual(skillNames, ["enabled-skill"]); + assert.equal(skills[0]?.path, "./.deepcode/skills/enabled-skill/SKILL.md"); +}); + test("SessionManager dispose disconnects MCP servers", async () => { const workspace = createTempDir("deepcode-mcp-dispose-workspace-"); const serverPath = path.join(workspace, "mcp-server.cjs"); diff --git a/src/tests/settings-and-notify.test.ts b/src/tests/settings-and-notify.test.ts index 5bc81cc9..ceddc43e 100644 --- a/src/tests/settings-and-notify.test.ts +++ b/src/tests/settings-and-notify.test.ts @@ -220,6 +220,39 @@ test("resolveSettingsSources merges permission settings", () => { assert.equal(resolved.permissions.defaultMode, "allowAll"); }); +test("resolveSettingsSources merges enabledSkills with project precedence", () => { + const resolved = resolveSettingsSources( + { + enabledSkills: { + inherited: false, + "project-enabled": false, + "project-disabled": true, + invalid: "false" as never, + }, + }, + { + enabledSkills: { + "project-enabled": true, + "project-disabled": false, + projectOnly: true, + ignored: null as never, + }, + }, + { + model: "default-model", + baseURL: "https://default.example.com", + }, + TEST_PROCESS_ENV + ); + + assert.deepEqual(resolved.enabledSkills, { + inherited: false, + "project-enabled": true, + "project-disabled": false, + projectOnly: true, + }); +}); + test("resolveSettingsSources merges MCP env with documented priority", () => { const resolved = resolveSettingsSources( { From 7fa00dcf4d1cb5be1daadba1103fb19f1808e9a0 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Mon, 8 Jun 2026 23:43:13 +0800 Subject: [PATCH 03/72] fix(ui): stabilize prompt cursor wrapping --- src/tests/message-view.test.ts | 23 +++ src/tests/prompt-input-keys.test.ts | 83 ++++++++-- src/ui/components/MessageView/index.tsx | 58 ++++--- src/ui/hooks/cursor.ts | 204 +++++++++++------------- src/ui/hooks/index.ts | 2 + src/ui/index.ts | 8 +- src/ui/views/PromptInput.tsx | 53 ++++-- 7 files changed, 274 insertions(+), 157 deletions(-) diff --git a/src/tests/message-view.test.ts b/src/tests/message-view.test.ts index ba1a9152..7d6b781c 100644 --- a/src/tests/message-view.test.ts +++ b/src/tests/message-view.test.ts @@ -1,6 +1,9 @@ import { test } from "node:test"; import assert from "node:assert/strict"; +import React from "react"; +import { renderToString } from "ink"; import { parseDiffPreview } from "../ui"; +import { MessageView, getPromptEchoContentWidth } from "../ui/components/MessageView"; import { buildThinkingSummary, formatBashStatusParams, @@ -119,6 +122,26 @@ test("renderMessageToStdout shows (no content) for empty user messages", () => { assert.ok(output.includes("(no content)")); }); +test("MessageView echoes submitted user prompts with live prompt wrapping width", () => { + assert.equal(getPromptEchoContentWidth(8), 6); + + const msg = makeSessionMessage({ role: "user", content: "abcdefg" }); + const output = renderToString(React.createElement(MessageView, { message: msg, width: 8 }), { columns: 8 }); + + assert.equal(output, "> abcdef\n g\n"); +}); + +test("MessageView echoes model changes with submitted prompt wrapping", () => { + const msg = makeSessionMessage({ + role: "system", + content: "abcdefgh", + meta: { isModelChange: true }, + }); + const output = renderToString(React.createElement(MessageView, { message: msg, width: 8 }), { columns: 8 }); + + assert.equal(output, "> abcdef\n gh\n"); +}); + test("renderMessageToStdout renders assistant non-thinking messages with ✦", () => { const msg = makeSessionMessage({ role: "assistant", content: "Here is the fix" }); const output = renderMessageToStdout(msg, RawMode.Raw); diff --git a/src/tests/prompt-input-keys.test.ts b/src/tests/prompt-input-keys.test.ts index 4ca564f9..a8999b6b 100644 --- a/src/tests/prompt-input-keys.test.ts +++ b/src/tests/prompt-input-keys.test.ts @@ -13,8 +13,10 @@ import { formatSelectedSkillsStatus, getPromptCursorPlacement, getPromptReturnKeyAction, + isPromptCursorAtWrapBoundary, isClearImageAttachmentsShortcut, removeCurrentSlashToken, + resolvePromptTerminalCursorPosition, toggleSkillSelection, renderBufferWithCursor, buildInitPromptSubmission, @@ -294,24 +296,83 @@ test("renderBufferWithCursor styles exactly one simulated cursor", () => { assert.equal((renderBufferWithCursor({ text: "hello\nworld", cursor: 6 }, true).match(ANSI_RE) ?? []).length, 2); }); -test("getPromptCursorPlacement targets the prompt row above divider and footer", () => { - const placement = getPromptCursorPlacement({ text: "hello", cursor: 5 }, 80, 2, "Enter send"); - assert.deepEqual(placement, { rowsUp: 3, column: 7 }); +test("renderBufferWithCursor can suppress the simulated cursor for real terminal cursor mode", () => { + assert.equal( + (renderBufferWithCursor({ text: "", cursor: 0 }, true, undefined, undefined, false).match(ANSI_RE) ?? []).length, + 0 + ); + assert.equal( + stripAnsi(renderBufferWithCursor({ text: "", cursor: 0 }, true, "Ask anything", undefined, false)), + " Ask anything" + ); + assert.equal( + (renderBufferWithCursor({ text: "hello", cursor: 1 }, true, undefined, undefined, false).match(ANSI_RE) ?? []) + .length, + 0 + ); + assert.equal( + stripAnsi(renderBufferWithCursor({ text: "hello\n", cursor: 6 }, true, undefined, undefined, false)), + "hello\n " + ); +}); + +test("getPromptCursorPlacement targets an Ink-relative prompt cell", () => { + const placement = getPromptCursorPlacement({ text: "hello", cursor: 5 }, 80); + assert.deepEqual(placement, { row: 0, column: 5 }); }); test("getPromptCursorPlacement targets the reserved row after a trailing newline", () => { - const placement = getPromptCursorPlacement({ text: "hello\n", cursor: 6 }, 80, 2, "Enter send"); - assert.deepEqual(placement, { rowsUp: 3, column: 2 }); + const placement = getPromptCursorPlacement({ text: "hello\n", cursor: 6 }, 80); + assert.deepEqual(placement, { row: 1, column: 0 }); }); test("getPromptCursorPlacement accounts for CJK character width", () => { - const placement = getPromptCursorPlacement({ text: "你好", cursor: 2 }, 80, 2, "Enter send"); - assert.equal(placement.column, 6); + const placement = getPromptCursorPlacement({ text: "你好", cursor: 2 }, 80); + assert.equal(placement.column, 4); }); test("getPromptCursorPlacement accounts for multiline buffer rows", () => { - const placement = getPromptCursorPlacement({ text: "hello\nworld", cursor: 11 }, 80, 2, "Enter send"); - assert.deepEqual(placement, { rowsUp: 3, column: 7 }); - const middle = getPromptCursorPlacement({ text: "hello\nworld", cursor: 2 }, 80, 2, "Enter send"); - assert.deepEqual(middle, { rowsUp: 4, column: 4 }); + const placement = getPromptCursorPlacement({ text: "hello\nworld", cursor: 11 }, 80); + assert.deepEqual(placement, { row: 1, column: 5 }); + const middle = getPromptCursorPlacement({ text: "hello\nworld", cursor: 2 }, 80); + assert.deepEqual(middle, { row: 0, column: 2 }); +}); + +test("getPromptCursorPlacement accounts for wrapped input rows", () => { + const placement = getPromptCursorPlacement({ text: "hello", cursor: 5 }, 5); + assert.deepEqual(placement, { row: 1, column: 0 }); + const cursorBeforeWrappedChar = getPromptCursorPlacement({ text: "hello!", cursor: 5 }, 5); + assert.deepEqual(cursorBeforeWrappedChar, { row: 1, column: 0 }); + const secondLine = getPromptCursorPlacement({ text: "hello!", cursor: 6 }, 5); + assert.deepEqual(secondLine, { row: 1, column: 1 }); +}); + +test("isPromptCursorAtWrapBoundary detects hard-wrapped cursor positions", () => { + assert.equal(isPromptCursorAtWrapBoundary({ text: "hell", cursor: 4 }, 5), false); + assert.equal(isPromptCursorAtWrapBoundary({ text: "hello", cursor: 5 }, 5), true); + assert.equal(isPromptCursorAtWrapBoundary({ text: "hello!", cursor: 6 }, 5), true); + assert.equal(isPromptCursorAtWrapBoundary({ text: "hello world", cursor: 6 }, 5), true); + assert.equal(isPromptCursorAtWrapBoundary({ text: "hello\n", cursor: 6 }, 5), false); + assert.equal(isPromptCursorAtWrapBoundary({ text: "hello\nworld", cursor: 11 }, 5), true); +}); + +test("resolvePromptTerminalCursorPosition requires matching measured layout", () => { + const placement = { row: 1, column: 4 }; + const origin = { layoutKey: "skills:1", left: 2, top: 3 }; + + assert.deepEqual(resolvePromptTerminalCursorPosition(placement, true, "skills:1", origin), { x: 6, y: 4 }); + assert.equal(resolvePromptTerminalCursorPosition(placement, true, "skills:0", origin), undefined); + assert.equal(resolvePromptTerminalCursorPosition(placement, false, "skills:1", origin), undefined); + assert.equal(resolvePromptTerminalCursorPosition(placement, true, "skills:1", null), undefined); +}); + +test("resolvePromptTerminalCursorPosition clamps negative terminal cells", () => { + assert.deepEqual( + resolvePromptTerminalCursorPosition({ row: 0, column: 1 }, true, "current", { + layoutKey: "current", + left: -5, + top: -1, + }), + { x: 0, y: 0 } + ); }); diff --git a/src/ui/components/MessageView/index.tsx b/src/ui/components/MessageView/index.tsx index 9c315516..66df9625 100644 --- a/src/ui/components/MessageView/index.tsx +++ b/src/ui/components/MessageView/index.tsx @@ -12,6 +12,8 @@ import { import type { DiffPreviewLine, MessageViewProps } from "./types"; import { RawMode, useRawModeContext } from "../../contexts"; +const PROMPT_ECHO_PREFIX_WIDTH = 2; + export function MessageView({ message, collapsed, width = 80 }: MessageViewProps): React.ReactElement | null { const { mode } = useRawModeContext(); if (!message.visible) { @@ -21,17 +23,11 @@ export function MessageView({ message, collapsed, width = 80 }: MessageViewProps if (message.role === "user") { const text = message.content || "(no content)"; return ( - - - {`>`} - - - {text} - {Array.isArray(message.contentParams) && message.contentParams.length > 0 ? ( - {` 📎 ${message.contentParams.length} image attachment(s)`} - ) : null} - - + ); } @@ -109,16 +105,7 @@ export function MessageView({ message, collapsed, width = 80 }: MessageViewProps if (message.role === "system") { // Render model change messages in the same style as user commands. if (message.meta?.isModelChange) { - return ( - - - {`>`} - - - {message.content} - - - ); + return ; } if (message.meta?.skill) { @@ -143,6 +130,35 @@ export function MessageView({ message, collapsed, width = 80 }: MessageViewProps return null; } +export function getPromptEchoContentWidth(width: number): number { + return Math.max(1, width - PROMPT_ECHO_PREFIX_WIDTH); +} + +function PromptEchoLine({ + text, + width, + attachmentCount = 0, +}: { + text: string; + width: number; + attachmentCount?: number; +}): React.ReactElement { + const contentWidth = getPromptEchoContentWidth(width); + return ( + + + {"> "} + + + + {text} + + {attachmentCount > 0 ? {` 📎 ${attachmentCount} image attachment(s)`} : null} + + + ); +} + function StatusLine({ bulletColor, name, diff --git a/src/ui/hooks/cursor.ts b/src/ui/hooks/cursor.ts index 07cc5779..677fa810 100644 --- a/src/ui/hooks/cursor.ts +++ b/src/ui/hooks/cursor.ts @@ -1,28 +1,19 @@ -import { useLayoutEffect, useRef } from "react"; +import { useCursor, useBoxMetrics } from "ink"; +import { useLayoutEffect, useState } from "react"; +import type { RefObject } from "react"; +import type { DOMElement } from "ink"; import type { PromptBufferState } from "../core/prompt-buffer"; -type CursorPlacement = { - rowsUp: number; +export type CursorPlacement = { + row: number; column: number; }; -type WriteFn = ( - chunk: string | Uint8Array, - encodingOrCallback?: BufferEncoding | ((error?: Error | null) => void), - callback?: (error?: Error | null) => void -) => boolean; - -function cursorUp(rows: number): string { - return rows > 0 ? `\u001B[${rows}A` : ""; -} - -function cursorDown(rows: number): string { - return rows > 0 ? `\u001B[${rows}B` : ""; -} - -function cursorForward(columns: number): string { - return columns > 0 ? `\u001B[${columns}C` : ""; -} +export type PromptCursorOrigin = { + layoutKey: string; + left: number; + top: number; +}; function showCursor(): string { return "\u001B[?25h"; @@ -59,44 +50,42 @@ export function disableTerminalExtendedKeys(): string { export function getPromptCursorPlacement( state: PromptBufferState, screenWidth: number, - prefixWidth: number, - footerText: string + initialColumn = 0 ): CursorPlacement { const width = Math.max(1, screenWidth); const cursor = Math.max(0, Math.min(state.cursor, state.text.length)); const beforeCursor = state.text.slice(0, cursor); - const at = state.text[cursor]; - const displayText = - beforeCursor + - (typeof at === "undefined" || at === "\n" ? " " : at) + - (at === "\n" ? "\n" : "") + - (typeof at === "undefined" ? "" : state.text.slice(cursor + 1)); - - const cursorPosition = measureTextPosition(beforeCursor, width, prefixWidth); - const promptRows = measureTextRows(displayText, width, prefixWidth); - const footerRows = 1 + measureTextRows(footerText, width, 0); - - return { - rowsUp: promptRows - 1 - cursorPosition.row + footerRows + 1, - column: cursorPosition.column, - }; + const cursorPosition = measureTextPosition(beforeCursor, width, initialColumn); + return { row: cursorPosition.row, column: cursorPosition.column }; } -function measureTextRows(text: string, width: number, initialColumn: number): number { - return measureTextPosition(text, width, initialColumn).row + 1; +export function isPromptCursorAtWrapBoundary(state: PromptBufferState, screenWidth: number): boolean { + const width = Math.max(1, screenWidth); + const cursor = Math.max(0, Math.min(state.cursor, state.text.length)); + const currentLineStart = state.text.lastIndexOf("\n", Math.max(0, cursor - 1)) + 1; + const currentLineBeforeCursor = state.text.slice(currentLineStart, cursor); + return measureTextPosition(currentLineBeforeCursor, width, 0).row > 0; } function measureTextPosition(text: string, width: number, initialColumn: number): { row: number; column: number } { let row = 0; let column = Math.min(initialColumn, width - 1); + let pendingWrap = false; for (const char of Array.from(text)) { if (char === "\n") { row++; column = Math.min(initialColumn, width - 1); + pendingWrap = false; continue; } + if (pendingWrap) { + row++; + column = Math.min(initialColumn, width - 1); + pendingWrap = false; + } + const charColumns = textWidth(char); if (column + charColumns > width) { row++; @@ -104,11 +93,15 @@ function measureTextPosition(text: string, width: number, initialColumn: number) } column += charColumns; if (column >= width) { - row++; - column = Math.min(initialColumn, width - 1); + column = width; + pendingWrap = true; } } + if (pendingWrap) { + return { row: row + 1, column: Math.min(initialColumn, width - 1) }; + } + return { row, column }; } @@ -144,90 +137,79 @@ function characterWidth(char: string): number { } export function usePromptTerminalCursor( - stdout: NodeJS.WriteStream | undefined, + targetRef: RefObject, placement: CursorPlacement, - isActive: boolean -): void { - const directWriteRef = useRef<((data: string) => void) | null>(null); - const activePlacementRef = useRef(null); - const lastPlacementRef = useRef(null); - const unmountingRef = useRef(false); + isActive: boolean, + layoutKey = "default" +): boolean { + const { setCursorPosition } = useCursor(); + const metrics = useBoxMetrics(targetRef as RefObject); + const [origin, setOrigin] = useState(null); useLayoutEffect(() => { - if (!stdout?.isTTY) { + if (!isActive || !metrics.hasMeasured) { return; } - const stream = stdout as NodeJS.WriteStream & { write: WriteFn }; - const originalWrite = stream.write; - const directWrite = (data: string) => { - originalWrite.call(stdout, data); - }; - const restorePromptCursor = () => { - if (unmountingRef.current) { - return; + const absolutePosition = getAbsoluteElementPosition(targetRef.current); + setOrigin((previous) => { + if (!absolutePosition) { + return previous === null ? previous : null; } - const activePlacement = activePlacementRef.current; - if (!activePlacement) { - return; + + if ( + previous?.layoutKey === layoutKey && + previous.left === absolutePosition.left && + previous.top === absolutePosition.top + ) { + return previous; } - directWrite("\r" + cursorDown(activePlacement.rowsUp) + hideCursor()); - activePlacementRef.current = null; - // Schedule a deferred re-position in case the layout effect does not - // re-run (e.g. a dropdown closed without changing the buffer). - Promise.resolve().then(() => { - if (unmountingRef.current || activePlacementRef.current) { - return; - } - const latest = directWriteRef.current; - const p = lastPlacementRef.current; - if (latest && p) { - latest(showCursor() + cursorUp(p.rowsUp) + "\r" + cursorForward(p.column)); - activePlacementRef.current = p; - } - }); - }; - const patchedWrite: WriteFn = (...args) => { - restorePromptCursor(); - return originalWrite.apply(stdout, args); - }; - directWriteRef.current = directWrite; - stream.write = patchedWrite; + return { + layoutKey, + left: absolutePosition.left, + top: absolutePosition.top, + }; + }); + }, [isActive, layoutKey, metrics.hasMeasured, metrics.height, metrics.left, metrics.top, metrics.width, targetRef]); + + const cursorPosition = resolvePromptTerminalCursorPosition(placement, isActive, layoutKey, origin); + setCursorPosition(cursorPosition); + return cursorPosition !== undefined; +} - return () => { - restorePromptCursor(); - stream.write = originalWrite; - directWriteRef.current = null; - }; - }, [stdout]); +export function resolvePromptTerminalCursorPosition( + placement: CursorPlacement, + isActive: boolean, + layoutKey: string, + origin: PromptCursorOrigin | null +): { x: number; y: number } | undefined { + if (!isActive || origin?.layoutKey !== layoutKey) { + return undefined; + } - useLayoutEffect(() => { - if (!isActive || !stdout?.isTTY) { - return; - } + return { + x: Math.max(0, Math.round(origin.left + placement.column)), + y: Math.max(0, Math.round(origin.top + placement.row)), + }; +} - unmountingRef.current = false; - const directWrite = directWriteRef.current; - if (!directWrite) { - return; - } +function getAbsoluteElementPosition(element: DOMElement | null): { left: number; top: number } | null { + let current: DOMElement | undefined = element ?? undefined; + let left = 0; + let top = 0; - directWrite(showCursor() + cursorUp(placement.rowsUp) + "\r" + cursorForward(placement.column)); - activePlacementRef.current = placement; - lastPlacementRef.current = placement; + while (current) { + const layout = current.yogaNode?.getComputedLayout(); + if (!layout) { + return null; + } + left += layout.left; + top += layout.top; + current = current.parentNode; + } - return () => { - unmountingRef.current = true; - lastPlacementRef.current = null; - const activePlacement = activePlacementRef.current; - if (!activePlacement) { - return; - } - directWrite("\r" + cursorDown(activePlacement.rowsUp) + hideCursor()); - activePlacementRef.current = null; - }; - }, [isActive, placement, stdout]); + return { left, top }; } export function useHiddenTerminalCursor(stdout: NodeJS.WriteStream | undefined, isActive: boolean): void { diff --git a/src/ui/hooks/index.ts b/src/ui/hooks/index.ts index 86245b65..226a6e98 100644 --- a/src/ui/hooks/index.ts +++ b/src/ui/hooks/index.ts @@ -8,6 +8,8 @@ export { usePromptTerminalCursor, useTerminalFocusReporting, getPromptCursorPlacement, + isPromptCursorAtWrapBoundary, + resolvePromptTerminalCursorPosition, } from "./cursor"; export { usePasteHandling } from "./usePasteHandling"; diff --git a/src/ui/index.ts b/src/ui/index.ts index ae1109ad..2504bbd8 100644 --- a/src/ui/index.ts +++ b/src/ui/index.ts @@ -6,7 +6,13 @@ import { export { getThinkingOptionIndex, MODEL_COMMAND_MODELS, MODEL_COMMAND_THINKING_OPTIONS }; export { buildPromptDraftFromSessionMessage } from "./utils"; -export { disableTerminalExtendedKeys, enableTerminalExtendedKeys, getPromptCursorPlacement } from "./hooks/cursor"; +export { + disableTerminalExtendedKeys, + enableTerminalExtendedKeys, + getPromptCursorPlacement, + isPromptCursorAtWrapBoundary, + resolvePromptTerminalCursorPosition, +} from "./hooks/cursor"; export { default as AppContainer } from "./views/AppContainer"; export { AskUserQuestionPrompt } from "./views/AskUserQuestionPrompt"; export { MessageView } from "./components"; diff --git a/src/ui/views/PromptInput.tsx b/src/ui/views/PromptInput.tsx index 48eb659a..f550afa9 100644 --- a/src/ui/views/PromptInput.tsx +++ b/src/ui/views/PromptInput.tsx @@ -1,5 +1,6 @@ -import React, { useEffect, useMemo, useState } from "react"; +import React, { useEffect, useMemo, useRef, useState } from "react"; import { Box, Text, useApp, useStdout } from "ink"; +import type { DOMElement } from "ink"; import chalk from "chalk"; import { ARGS_SEPARATOR } from "../constants"; import { @@ -48,6 +49,7 @@ import { usePasteHandling, useHistoryNavigation, getPromptCursorPlacement, + isPromptCursorAtWrapBoundary, usePromptTerminalCursor, } from "../hooks"; import type { InputKey } from "../hooks"; @@ -98,6 +100,7 @@ type Props = { }; const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; +const PROMPT_PREFIX_WIDTH = 2; const PromptPrefixLine = React.memo(function PromptPrefixLine({ busy }: { busy: boolean }): React.ReactElement { const [spinnerIndex, setSpinnerIndex] = useState(0); @@ -141,6 +144,7 @@ export const PromptInput = React.memo(function PromptInput({ }: Props): React.ReactElement { const { exit } = useApp(); const { stdout } = useStdout(); + const inputTextRef = useRef(null); const [buffer, setBuffer] = useState(EMPTY_BUFFER); const [imageUrls, setImageUrls] = useState([]); const [selectedSkills, setSelectedSkills] = useState([]); @@ -212,17 +216,28 @@ export const PromptInput = React.memo(function PromptInput({ () => showMenu || showSkillsDropdown || openRawModelDropdown || showModelDropdown || showFileMentionMenu, [showMenu, showSkillsDropdown, showModelDropdown, openRawModelDropdown, showFileMentionMenu] ); + const inputContentWidth = Math.max(1, screenWidth - PROMPT_PREFIX_WIDTH); const cursorPlacement = useMemo( - () => getPromptCursorPlacement(buffer, screenWidth, 2, footerText), - [buffer, footerText, screenWidth] + () => getPromptCursorPlacement(buffer, inputContentWidth), + [buffer, inputContentWidth] + ); + const useInlineCursor = isPromptCursorAtWrapBoundary(buffer, inputContentWidth); + const usePositionedCursor = !disabled && hasTerminalFocus && !showFooterText && stdout.isTTY && !useInlineCursor; + const promptCursorLayoutKey = useMemo( + () => [screenWidth, imageUrls.length, selectedSkills.map((skill) => skill.name).join("\u001F")].join("\u001E"), + [imageUrls.length, screenWidth, selectedSkills] ); - const usePositionedCursor = !disabled && hasTerminalFocus && !showFooterText; useTerminalFocusReporting(stdout, !disabled); useTerminalExtendedKeys(stdout, !disabled); useBracketedPaste(stdout, !disabled); - usePromptTerminalCursor(stdout, cursorPlacement, usePositionedCursor); - useHiddenTerminalCursor(stdout, !disabled && !usePositionedCursor); + const terminalCursorActive = usePromptTerminalCursor( + inputTextRef, + cursorPlacement, + usePositionedCursor, + promptCursorLayoutKey + ); + useHiddenTerminalCursor(stdout, !disabled && !terminalCursorActive); const refreshFileMentionItems = React.useCallback(() => { setFileMentionItems(scanFileMentionItems(projectRoot)); @@ -765,8 +780,16 @@ export const PromptInput = React.memo(function PromptInput({ borderDimColor > - - {renderBufferWithCursor(buffer, !disabled && hasTerminalFocus, placeholder, pastesRef.current)} + + + {renderBufferWithCursor( + buffer, + !disabled && hasTerminalFocus, + placeholder, + pastesRef.current, + !terminalCursorActive + )} + {inlineHint ? {inlineHint} : null} @@ -885,24 +908,28 @@ export function renderBufferWithCursor( state: PromptBufferState, isFocused: boolean, placeholder?: string, - validPastes?: Map + validPastes?: Map, + showSimulatedCursor = true ): string { const text = state.text || ""; const cursor = Math.max(0, Math.min(state.cursor, text.length)); const validIds = validPastes ?? new Map(); if (text.length === 0 && placeholder) { - if (!isFocused) { + if (!isFocused || !showSimulatedCursor) { return chalk.dim(` ${placeholder}`); } return renderCursorCell(" ") + chalk.dim(` ${placeholder}`); } if (text.length === 0) { - return isFocused ? renderCursorCell(" ") : ""; + if (!isFocused) { + return ""; + } + return showSimulatedCursor ? renderCursorCell(" ") : " "; } - if (!isFocused) { + if (!isFocused || !showSimulatedCursor) { return highlightPasteMarkersInText(text, validIds); } @@ -910,7 +937,7 @@ export function renderBufferWithCursor( } function highlightPasteMarkersInText(s: string, validIds: Map): string { - if (!s.includes("[paste #")) return s; + if (!s.includes("[paste #")) return s.endsWith("\n") ? `${s} ` : s; PASTE_MARKER_REGEX.lastIndex = 0; let result = ""; let pos = 0; From ffc7682c9cd00ab1e299d8a1e7e396926175b88c Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Tue, 9 Jun 2026 10:12:52 +0800 Subject: [PATCH 04/72] feat: add docs/session-persistence.md --- docs/session-persistence.md | 139 +++++++++++++++++++++++++++++++++ docs/session-persistence_en.md | 139 +++++++++++++++++++++++++++++++++ 2 files changed, 278 insertions(+) create mode 100644 docs/session-persistence.md create mode 100644 docs/session-persistence_en.md diff --git a/docs/session-persistence.md b/docs/session-persistence.md new file mode 100644 index 00000000..835d2881 --- /dev/null +++ b/docs/session-persistence.md @@ -0,0 +1,139 @@ +# 会话持久化机制 + +Deep Code 会把每个项目的会话记录保存在本机用户目录中。会话历史用于 `/resume`、`/continue` 和 `/undo`,不依赖当前终端进程是否仍在运行。 + +## 存储位置 + +每个项目都有独立的存储目录: + +```text +~/.deepcode/projects// +``` + +`` 由项目根目录路径生成。普通路径会转换为安全的目录名;路径过长时,Deep Code 会保留项目名的一部分,并追加稳定哈希,以避免存储路径过长。 + +项目存储目录包含以下主要文件和目录: + +| 路径 | 说明 | +| ---- | ---- | +| `sessions-index.json` | 当前项目的会话索引,保存会话列表和每个会话的概要信息。 | +| `.jsonl` | 单个会话的消息记录。每一行是一条 JSON 格式的消息。 | +| `file-history/.git` | 用于代码快照的内部 Git 仓库,供 `/undo` 恢复文件内容。 | + +## 持久化内容 + +### 会话索引 + +`sessions-index.json` 保存最近的会话条目。每个条目包含: + +- 会话 ID、标题、创建时间和更新时间。 +- 会话状态,例如 `pending`、`processing`、`completed`、`failed`、`interrupted`、`ask_permission`、`waiting_for_user`。 +- 最近一次 assistant 回复、思考内容、拒绝原因和失败原因。 +- 最近一次工具调用信息、token 用量和活跃 token 数。 +- 当前会话中仍被跟踪的子进程信息。 + +会话标题默认来自首次用户输入的前 100 个字符。使用会话列表中的重命名功能会更新索引里的标题。 + +### 消息文件 + +每个会话有一个独立的 JSONL 消息文件,文件名是 `.jsonl`。消息按追加顺序写入,常见字段包括: + +| 字段 | 说明 | +| ---- | ---- | +| `id` | 消息 ID。 | +| `sessionId` | 所属会话 ID。 | +| `role` | 消息角色:`system`、`user`、`assistant` 或 `tool`。 | +| `content` | 文本内容。 | +| `contentParams` | 结构化内容,例如图片输入。 | +| `messageParams` | 模型消息参数,例如 tool call ID、tool calls、reasoning content。 | +| `visible` | 是否在界面中显示。 | +| `compacted` | 是否已经被长会话压缩替代。 | +| `checkpointHash` | 与 `/undo` 关联的代码快照哈希。 | +| `meta` | 工具展示、skill、权限、摘要等附加信息。 | + +读取消息文件时,Deep Code 会逐行解析 JSON;无法解析的行会被忽略,以便尽量保留其余可用历史。 + +### 代码快照 + +Deep Code 使用 `file-history/.git` 保存代码快照。这个仓库只作为内部文件历史使用,不是项目仓库本身。 + +- 新会话会初始化一条以会话 ID 命名的内部分支。 +- 每次用户输入前,会记录已跟踪文件的状态。 +- 工具修改文件前后,会按需记录相关文件的状态。 +- 用户消息上的 `checkpointHash` 用来把某次对话位置和对应的代码状态关联起来。 + +快照只覆盖 Deep Code 已跟踪到的文件;无关文件不会因为 `/undo` 被任意改写。 + +## 会话生命周期 + +### 创建会话 + +创建新会话时,Deep Code 会: + +1. 生成新的会话 ID。 +2. 初始化该会话的代码快照分支。 +3. 在 `sessions-index.json` 中添加会话条目。 +4. 写入系统提示、运行时上下文、项目指令和用户消息。 +5. 启动模型请求,并在 assistant 回复和工具执行过程中持续更新索引和消息文件。 + +项目级会话列表最多保留最近 50 条记录。超过上限时,较旧会话会从索引中移除,其消息文件和相关运行时资源也会被清理。 + +### 继续会话 + +`/resume` 会显示当前项目的历史会话列表,并选择一个会话继续。 + +`/continue` 会优先继续当前活动会话;如果没有可继续的活动会话,则进入历史会话选择流程。 + +继续会话时,Deep Code 会读取会话消息文件,过滤已压缩的旧消息,修复未完成的工具调用上下文,并把可用历史转换为模型请求消息。 + +### 长会话压缩 + +当会话上下文过长时,Deep Code 会触发压缩流程: + +- 选取较早的一段非系统消息生成摘要。 +- 将这段旧消息标记为 `compacted: true`。 +- 在消息序列中插入一条不可见的系统摘要消息。 + +后续请求只会使用未压缩消息和摘要消息。原始消息仍保留在 JSONL 文件中,用于审计和界面历史展示。 + +### 中断、失败和权限等待 + +会话状态会随运行过程更新: + +- 用户中断后,状态会变为 `interrupted`,并清理当前会话控制器和被跟踪的子进程。 +- 请求失败时,状态会变为 `failed`,失败原因写入索引。 +- 工具调用需要确认时,状态会变为 `ask_permission`。 +- 工具需要用户输入时,状态会变为 `waiting_for_user`。 + +这些状态都会持久化到 `sessions-index.json`,因此重新打开 CLI 后仍能在会话列表中看到。 + +## `/undo` 如何使用持久化数据 + +`/undo` 的候选项来自可见且未压缩的用户消息。每个候选项会检查是否有关联的 `checkpointHash`,并确认对应快照是否可恢复。 + +根据选择,Deep Code 可以执行以下操作: + +| 操作 | 行为 | +| ---- | ---- | +| 恢复对话 | 截断所选用户消息之前的消息历史,并更新索引中的最新 assistant 信息。 | +| 恢复代码 | 从 `file-history/.git` 中读取所选快照,并还原被跟踪文件。 | +| 同时恢复 | 先恢复代码,再截断对话历史。 | + +恢复对话会重写该会话的 JSONL 文件;恢复代码会修改工作区中被快照跟踪的文件。 + +## 删除和重命名 + +在会话列表中删除会话会: + +- 从 `sessions-index.json` 移除该条目。 +- 删除对应的 `.jsonl` 文件。 +- 清理该会话的内存状态、临时工作目录状态、控制器和仍被跟踪的进程控制信息。 + +重命名会话只更新索引中的 `summary` 字段,不会改动消息文件或代码快照。 + +## 注意事项 + +- 会话数据保存在本机用户目录下,并按项目分隔。 +- 移动项目目录后,新的项目根路径会生成新的 ``;旧路径对应的历史不会自动迁移。 +- `file-history/.git` 是 Deep Code 的内部快照仓库,不应手动修改。 +- 会话删除不会清理内部 Git 仓库中的所有历史对象;它主要删除会话索引、消息文件和运行时资源。 diff --git a/docs/session-persistence_en.md b/docs/session-persistence_en.md new file mode 100644 index 00000000..071a5353 --- /dev/null +++ b/docs/session-persistence_en.md @@ -0,0 +1,139 @@ +# Session Persistence + +Deep Code stores per-project session history in the local user directory. This history powers `/resume`, `/continue`, and `/undo`, and it remains available after the current terminal process exits. + +## Storage Location + +Each project has its own storage directory: + +```text +~/.deepcode/projects// +``` + +`` is generated from the project root path. Normal paths are converted into safe directory names. When the path would be too long, Deep Code keeps part of the project name and appends a stable hash so the storage path stays safe. + +The project storage directory contains these main files and directories: + +| Path | Description | +| ---- | ----------- | +| `sessions-index.json` | Session index for the current project, including the session list and summary metadata. | +| `.jsonl` | Message log for one session. Each line is one JSON message. | +| `file-history/.git` | Internal Git repository used for code checkpoints restored by `/undo`. | + +## Persisted Data + +### Session Index + +`sessions-index.json` stores recent session entries. Each entry includes: + +- Session ID, title, creation time, and update time. +- Session status, such as `pending`, `processing`, `completed`, `failed`, `interrupted`, `ask_permission`, or `waiting_for_user`. +- Latest assistant reply, thinking content, refusal reason, and failure reason. +- Latest tool-call data, token usage, and active token count. +- Metadata for subprocesses still tracked by the session. + +The default session title comes from the first 100 characters of the first user prompt. Renaming a session from the session list updates the title in the index. + +### Message Files + +Each session has a separate JSONL message file named `.jsonl`. Messages are appended in order. Common fields include: + +| Field | Description | +| ----- | ----------- | +| `id` | Message ID. | +| `sessionId` | Owning session ID. | +| `role` | Message role: `system`, `user`, `assistant`, or `tool`. | +| `content` | Text content. | +| `contentParams` | Structured content, such as image input. | +| `messageParams` | Model message parameters, such as tool call IDs, tool calls, and reasoning content. | +| `visible` | Whether the message is shown in the UI. | +| `compacted` | Whether the message has been replaced by long-session compaction. | +| `checkpointHash` | Code checkpoint hash associated with `/undo`. | +| `meta` | Extra metadata for tool display, skills, permissions, summaries, and related features. | + +When loading a message file, Deep Code parses JSON one line at a time. Malformed lines are ignored so the remaining usable history can still be loaded. + +### Code Checkpoints + +Deep Code stores code checkpoints in `file-history/.git`. This repository is only internal file history; it is not the project Git repository. + +- A new session initializes an internal branch named after the session ID. +- Before each user prompt, Deep Code records the state of files it already tracks. +- Before and after tool-based file mutations, Deep Code records the relevant file state as needed. +- `checkpointHash` on user messages links a conversation position to a code state. + +Checkpoints only cover files Deep Code has tracked. Unrelated files are not arbitrarily rewritten by `/undo`. + +## Session Lifecycle + +### Creating A Session + +When creating a new session, Deep Code: + +1. Generates a new session ID. +2. Initializes the code checkpoint branch for that session. +3. Adds an entry to `sessions-index.json`. +4. Writes system prompts, runtime context, project instructions, and the user message. +5. Starts the model request and keeps updating the index and message file as assistant replies and tool executions complete. + +The per-project session list keeps the 50 most recent entries. When the limit is exceeded, older sessions are removed from the index, and their message files and related runtime resources are cleaned up. + +### Continuing A Session + +`/resume` shows the current project's session history and lets you select a session to continue. + +`/continue` first continues the active session. If there is no active session to continue, it opens the session selection flow. + +When continuing a session, Deep Code reads the message file, filters compacted old messages, repairs incomplete tool-call context, and converts the usable history into model request messages. + +### Long-Session Compaction + +When the conversation context grows too large, Deep Code can compact earlier messages: + +- It summarizes an older range of non-system messages. +- It marks those old messages as `compacted: true`. +- It inserts an invisible system summary message into the message sequence. + +Future requests use the remaining active messages and the summary message. The original messages stay in the JSONL file for auditability and UI history. + +### Interruptions, Failures, And Permission Waits + +Session status changes during execution: + +- After a user interruption, status becomes `interrupted`, and Deep Code clears the current session controller and tracked subprocesses. +- After a request failure, status becomes `failed`, and the failure reason is written to the index. +- When a tool call needs confirmation, status becomes `ask_permission`. +- When a tool needs user input, status becomes `waiting_for_user`. + +These states are persisted in `sessions-index.json`, so they remain visible in the session list after reopening the CLI. + +## How `/undo` Uses Persistent Data + +`/undo` candidates come from visible, non-compacted user messages. Each candidate is checked for an associated `checkpointHash`, and Deep Code verifies whether the checkpoint can be restored. + +Depending on the selected mode, Deep Code can perform these operations: + +| Operation | Behavior | +| --------- | -------- | +| Restore conversation | Truncates message history before the selected user message and updates the latest assistant data in the index. | +| Restore code | Reads the selected checkpoint from `file-history/.git` and restores tracked files. | +| Restore both | Restores code first, then truncates the conversation history. | + +Restoring conversation rewrites the session JSONL file. Restoring code modifies workspace files tracked by the selected checkpoint. + +## Delete And Rename + +Deleting a session from the session list: + +- Removes the entry from `sessions-index.json`. +- Deletes the matching `.jsonl` file. +- Clears in-memory state, temporary working-directory state, controllers, and tracked process controls for that session. + +Renaming a session only updates the `summary` field in the index. It does not change message files or code checkpoints. + +## Notes + +- Session data is stored in the local user directory and separated by project. +- If a project directory is moved, the new project root path generates a new ``; history for the old path is not migrated automatically. +- `file-history/.git` is Deep Code's internal checkpoint repository and should not be edited manually. +- Deleting a session does not remove every historical object from the internal Git repository. It mainly removes the session index entry, message file, and runtime resources. From 4cf5cc0bd86670ded58c9a8c4a737060266471cd Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Tue, 9 Jun 2026 11:28:11 +0800 Subject: [PATCH 05/72] fix(ui): improve prompt cursor wrapping and status line display --- src/ui/views/App.tsx | 71 +++++++++++++++++++++++++++++++++--- src/ui/views/PromptInput.tsx | 49 +++++++++++-------------- 2 files changed, 88 insertions(+), 32 deletions(-) diff --git a/src/ui/views/App.tsx b/src/ui/views/App.tsx index 1579848f..bc12962a 100644 --- a/src/ui/views/App.tsx +++ b/src/ui/views/App.tsx @@ -48,12 +48,47 @@ import { SessionManager } from "../../session"; type View = "chat" | "session-list" | "undo" | "mcp-status"; +const STATUS_SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; + type AppProps = { projectRoot: string; initialPrompt?: string; onRestart?: () => void; }; +const StatusLine = React.memo(function StatusLine({ + busy, + text, +}: { + busy: boolean; + text?: string; +}): React.ReactElement { + const [spinnerIndex, setSpinnerIndex] = useState(0); + + useEffect(() => { + if (!busy) { + setSpinnerIndex(0); + return; + } + + const timer = setInterval(() => { + setSpinnerIndex((index) => (index + 1) % STATUS_SPINNER_FRAMES.length); + }, 80); + return () => clearInterval(timer); + }, [busy]); + + return ( + + {busy ? ( + + {STATUS_SPINNER_FRAMES[spinnerIndex]} + + ) : null} + {text ? {text} : null} + + ); +}); + function App({ projectRoot, initialPrompt, onRestart }: AppProps): React.ReactElement { const { exit } = useApp(); const { stdout, write } = useStdout(); @@ -641,6 +676,35 @@ function App({ projectRoot, initialPrompt, onRestart }: AppProps): React.ReactEl } return messages; }, [mode, showWelcome, view, messages, welcomeItem]); + const promptCursorLayoutKey = useMemo(() => { + const lastStaticItem = staticItems.at(-1); + return [ + view, + busy ? "busy" : "idle", + statusLine, + errorLine ?? "", + showProcessStdout ? "stdout" : "main", + activeStatus ?? "", + staticItems.length, + lastStaticItem?.id ?? "", + lastStaticItem?.updateTime ?? "", + shouldShowQuestionPrompt ? (pendingQuestion?.messageId ?? "") : "", + activeAskPermissions?.length ?? 0, + pendingPermissionReply ? "pending-permission-reply" : "no-pending-permission-reply", + ].join("\u001E"); + }, [ + activeAskPermissions, + activeStatus, + busy, + errorLine, + pendingPermissionReply, + pendingQuestion, + shouldShowQuestionPrompt, + showProcessStdout, + staticItems, + statusLine, + view, + ]); const handleQuestionAnswers = useCallback( (answers: AskUserQuestionAnswers) => { @@ -724,11 +788,7 @@ function App({ projectRoot, initialPrompt, onRestart }: AppProps): React.ReactEl ); }} - {statusLine ? ( - - {statusLine} - - ) : null} + {busy || statusLine ? : null} {errorLine ? ( Error: {errorLine} @@ -802,6 +862,7 @@ function App({ projectRoot, initialPrompt, onRestart }: AppProps): React.ReactEl modelConfig={resolvedSettings} promptHistory={promptHistory} busy={busy} + cursorLayoutKey={promptCursorLayoutKey} loadingText={loadingText} runningProcesses={runningProcesses} promptDraft={promptDraft} diff --git a/src/ui/views/PromptInput.tsx b/src/ui/views/PromptInput.tsx index f550afa9..c81d2237 100644 --- a/src/ui/views/PromptInput.tsx +++ b/src/ui/views/PromptInput.tsx @@ -87,6 +87,7 @@ type Props = { screenWidth: number; promptHistory: string[]; busy: boolean; + cursorLayoutKey?: string; loadingText?: string | null; disabled?: boolean; placeholder?: string; @@ -99,27 +100,12 @@ type Props = { onToggleProcessStdout?: () => void; }; -const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; const PROMPT_PREFIX_WIDTH = 2; -const PromptPrefixLine = React.memo(function PromptPrefixLine({ busy }: { busy: boolean }): React.ReactElement { - const [spinnerIndex, setSpinnerIndex] = useState(0); - - useEffect(() => { - if (!busy) { - setSpinnerIndex(0); - return; - } - const timer = setInterval(() => { - setSpinnerIndex((index) => (index + 1) % SPINNER_FRAMES.length); - }, 80); - return () => clearInterval(timer); - }, [busy]); - - const prefix = busy ? `${SPINNER_FRAMES[spinnerIndex]} ` : "> "; +const PromptPrefixLine = React.memo(function PromptPrefixLine(): React.ReactElement { return ( - - {prefix} + + {"> "} ); }); @@ -131,6 +117,7 @@ export const PromptInput = React.memo(function PromptInput({ screenWidth, promptHistory, busy, + cursorLayoutKey, loadingText, disabled, placeholder, @@ -205,12 +192,14 @@ export const PromptInput = React.memo(function PromptInput({ : hasExpandedRegions ? " · ctrl+o collapse" : ""; + const busyStatusText = + loadingText && loadingText.trim() + ? `${loadingText}${processOrPasteHint}` + : `esc to interrupt · ctrl+c to cancel input${processOrPasteHint}`; const footerText = statusMessage ? statusMessage : busy - ? loadingText && loadingText.trim() - ? `${loadingText}${processOrPasteHint}` - : `esc to interrupt · ctrl+c to cancel input${processOrPasteHint}` + ? busyStatusText : `enter send · shift+enter newline · @ files · ctrl+v image · / commands · ctrl+d exit${processOrPasteHint}`; const showFooterText = useMemo( () => showMenu || showSkillsDropdown || openRawModelDropdown || showModelDropdown || showFileMentionMenu, @@ -225,8 +214,14 @@ export const PromptInput = React.memo(function PromptInput({ const useInlineCursor = isPromptCursorAtWrapBoundary(buffer, inputContentWidth); const usePositionedCursor = !disabled && hasTerminalFocus && !showFooterText && stdout.isTTY && !useInlineCursor; const promptCursorLayoutKey = useMemo( - () => [screenWidth, imageUrls.length, selectedSkills.map((skill) => skill.name).join("\u001F")].join("\u001E"), - [imageUrls.length, screenWidth, selectedSkills] + () => + [ + screenWidth, + cursorLayoutKey ?? "default", + imageUrls.length, + selectedSkills.map((skill) => skill.name).join("\u001F"), + ].join("\u001E"), + [cursorLayoutKey, imageUrls.length, screenWidth, selectedSkills] ); useTerminalFocusReporting(stdout, !disabled); useTerminalExtendedKeys(stdout, !disabled); @@ -234,10 +229,10 @@ export const PromptInput = React.memo(function PromptInput({ const terminalCursorActive = usePromptTerminalCursor( inputTextRef, cursorPlacement, - usePositionedCursor, + !busy && usePositionedCursor, promptCursorLayoutKey ); - useHiddenTerminalCursor(stdout, !disabled && !terminalCursorActive); + useHiddenTerminalCursor(stdout, !disabled && (busy || !terminalCursorActive)); const refreshFileMentionItems = React.useCallback(() => { setFileMentionItems(scanFileMentionItems(projectRoot)); @@ -779,7 +774,7 @@ export const PromptInput = React.memo(function PromptInput({ borderRight={false} borderDimColor > - + {renderBufferWithCursor( @@ -787,7 +782,7 @@ export const PromptInput = React.memo(function PromptInput({ !disabled && hasTerminalFocus, placeholder, pastesRef.current, - !terminalCursorActive + !busy && !terminalCursorActive )} {inlineHint ? {inlineHint} : null} From 726034fb1f32653a10d9713cf8c4083b33403ef6 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Tue, 9 Jun 2026 13:34:58 +0800 Subject: [PATCH 06/72] feat: implement bundled built-in skills --- package.json | 3 +- scripts/copy_bundle_assets.js | 27 ++ src/session.ts | 27 +- src/tests/session.test.ts | 81 +++- .../bundled/deepcode-self-refer/SKILL.md | 125 ++++++ .../deepcode-self-refer/references/README.md | 209 ++++++++++ .../references/configuration.md | 217 ++++++++++ .../references/configuration_en.md | 216 ++++++++++ .../deepcode-self-refer/references/mcp.md | 200 +++++++++ .../deepcode-self-refer/references/mcp_en.md | 200 +++++++++ .../deepcode-self-refer/references/notify.md | 211 ++++++++++ .../references/notify_en.md | 211 ++++++++++ .../references/permission.md | 101 +++++ .../references/permission_en.md | 100 +++++ .../references/session-persistence.md | 139 +++++++ .../references/session-persistence_en.md | 139 +++++++ .../skills/bundled/skill-digester/SKILL.md | 115 ++++++ .../skill-digester/scripts/find-skill.js | 215 ++++++++++ .../skills/bundled/skill-writer/SKILL.md | 381 ++++++++++++++++++ 19 files changed, 2911 insertions(+), 6 deletions(-) create mode 100644 scripts/copy_bundle_assets.js create mode 100644 templates/skills/bundled/deepcode-self-refer/SKILL.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/README.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/configuration.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/configuration_en.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/mcp.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/mcp_en.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/notify.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/notify_en.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/permission.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/permission_en.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/session-persistence.md create mode 100644 templates/skills/bundled/deepcode-self-refer/references/session-persistence_en.md create mode 100644 templates/skills/bundled/skill-digester/SKILL.md create mode 100755 templates/skills/bundled/skill-digester/scripts/find-skill.js create mode 100644 templates/skills/bundled/skill-writer/SKILL.md diff --git a/package.json b/package.json index 0d7ef622..911bd74e 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "main": "./dist/cli.js", "files": [ "dist/cli.js", + "dist/bundled/**", "templates/tools/**", "templates/prompts/**", "templates/skills/**", @@ -26,7 +27,7 @@ }, "scripts": { "typecheck": "tsc -p ./ --noEmit", - "bundle": "esbuild ./src/cli.tsx --bundle --platform=node --format=esm --target=node18 --outfile=dist/cli.js --banner:js=\"#!/usr/bin/env node\" --jsx=automatic --jsx-import-source=react --packages=external --log-override:empty-import-meta=silent", + "bundle": "esbuild ./src/cli.tsx --bundle --platform=node --format=esm --target=node18 --outfile=dist/cli.js --banner:js=\"#!/usr/bin/env node\" --jsx=automatic --jsx-import-source=react --packages=external --log-override:empty-import-meta=silent && node scripts/copy_bundle_assets.js", "lint": "eslint src/", "lint:fix": "eslint src/ --fix", "format": "prettier --write 'src/**/*.{ts,tsx}'", diff --git a/scripts/copy_bundle_assets.js b/scripts/copy_bundle_assets.js new file mode 100644 index 00000000..0e1dd948 --- /dev/null +++ b/scripts/copy_bundle_assets.js @@ -0,0 +1,27 @@ +import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +/* global console, process */ + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); +const distDir = join(root, "dist"); +const bundledSkillsSrc = join(root, "templates", "skills", "bundled"); +const bundledSkillsDest = join(distDir, "bundled"); + +if (!existsSync(distDir)) { + mkdirSync(distDir, { recursive: true }); +} + +if (!existsSync(bundledSkillsSrc)) { + console.warn(`Bundled skills directory not found at ${bundledSkillsSrc}`); + process.exit(0); +} + +rmSync(bundledSkillsDest, { recursive: true, force: true }); +cpSync(bundledSkillsSrc, bundledSkillsDest, { + recursive: true, + dereference: true, +}); +console.log("Copied bundled built-in skills to dist/bundled/"); diff --git a/src/session.ts b/src/session.ts index 7c479c8c..5e00b49e 100644 --- a/src/session.ts +++ b/src/session.ts @@ -805,9 +805,22 @@ ${agentInstructions} { root: path.join(this.projectRoot, ".agents", "skills"), displayRoot: "./.agents/skills" }, { root: path.join(homeDir, ".deepcode", "skills"), displayRoot: "~/.deepcode/skills" }, { root: path.join(homeDir, ".agents", "skills"), displayRoot: "~/.agents/skills" }, + { root: this.getBundledSkillsRoot(), displayRoot: "bundled:" }, ]; } + private getBundledSkillsRoot(): string { + const extensionRoot = getExtensionRoot(); + const sourceRoot = path.join(extensionRoot, "templates", "skills", "bundled"); + const distRoot = path.join(extensionRoot, "dist", "bundled"); + + // Source check keeps local development/tests on the checked-in templates. + if (fs.existsSync(path.join(extensionRoot, "src", "session.ts")) && fs.existsSync(sourceRoot)) { + return sourceRoot; + } + return fs.existsSync(distRoot) ? distRoot : sourceRoot; + } + async listSkills(sessionId?: string): Promise { const skillRoots = this.getSkillScanRoots(); const enabledSkills = this.getResolvedSettings().enabledSkills ?? {}; @@ -842,7 +855,9 @@ ${agentInstructions} } catch { continue; } - const skill = this.readSkillInfo(skillPath, `${displayRoot}/${skillName}/SKILL.md`, skillName); + const displayPath = + displayRoot === "bundled:" ? `bundled:${skillName}/SKILL.md` : `${displayRoot}/${skillName}/SKILL.md`; + const skill = this.readSkillInfo(skillPath, displayPath, skillName); if (enabledSkills[skill.name] === false) { continue; } @@ -872,6 +887,16 @@ ${agentInstructions} } private resolveSkillPath(skillPath: string): string { + if (skillPath.startsWith("bundled:")) { + const relativePath = skillPath.slice("bundled:".length); + const root = this.getBundledSkillsRoot(); + const resolvedPath = path.resolve(root, relativePath); + const resolvedRoot = path.resolve(root); + if (resolvedPath === resolvedRoot || !resolvedPath.startsWith(`${resolvedRoot}${path.sep}`)) { + return path.join(root, "__invalid_bundled_skill__"); + } + return resolvedPath; + } if (skillPath.startsWith("~/")) { return path.join(os.homedir(), skillPath.slice(2)); } diff --git a/src/tests/session.test.ts b/src/tests/session.test.ts index e22067fe..abebed3c 100644 --- a/src/tests/session.test.ts +++ b/src/tests/session.test.ts @@ -471,6 +471,57 @@ test("SessionManager lists skills from Deep Code and .agents roots by priority", assert.equal(sharedSkill?.description, "Project .deepcode skill"); }); +test("SessionManager lists bundled skills at lowest priority", async () => { + const workspace = createTempDir("deepcode-bundled-skills-workspace-"); + const home = createTempDir("deepcode-bundled-skills-home-"); + setHomeDir(home); + + const manager = createSessionManager(workspace, "machine-id-bundled-skills"); + const skills = await manager.listSkills(); + const skillWriter = skills.find((skill) => skill.name === "skill-writer"); + const selfRefer = skills.find((skill) => skill.name === "deepcode-self-refer"); + + assert.equal(skillWriter?.path, "bundled:skill-writer/SKILL.md"); + assert.equal(selfRefer?.path, "bundled:deepcode-self-refer/SKILL.md"); + assert.match(skillWriter?.description ?? "", /Guide users through creating/); +}); + +test("SessionManager lets project skills override bundled skills", async () => { + const workspace = createTempDir("deepcode-bundled-override-workspace-"); + const home = createTempDir("deepcode-bundled-override-home-"); + setHomeDir(home); + + const projectSkillDir = path.join(workspace, ".deepcode", "skills", "skill-writer"); + fs.mkdirSync(projectSkillDir, { recursive: true }); + fs.writeFileSync( + path.join(projectSkillDir, "SKILL.md"), + "---\nname: skill-writer\ndescription: Project override skill writer\n---\n# Project Skill Writer\n", + "utf8" + ); + + const manager = createSessionManager(workspace, "machine-id-bundled-override"); + const skillWriter = (await manager.listSkills()).find((skill) => skill.name === "skill-writer"); + + assert.equal(skillWriter?.path, "./.deepcode/skills/skill-writer/SKILL.md"); + assert.equal(skillWriter?.description, "Project override skill writer"); +}); + +test("SessionManager resolves bundled skill prompts", () => { + const workspace = createTempDir("deepcode-bundled-prompt-workspace-"); + const home = createTempDir("deepcode-bundled-prompt-home-"); + setHomeDir(home); + + const manager = createSessionManager(workspace, "machine-id-bundled-prompt"); + const prompt = (manager as any).buildSkillPrompt({ + name: "skill-writer", + path: "bundled:skill-writer/SKILL.md", + description: "Write skills", + }); + + assert.match(prompt, / { const workspace = createTempDir("deepcode-disabled-skills-workspace-"); const home = createTempDir("deepcode-disabled-skills-home-"); @@ -511,6 +562,8 @@ test("SessionManager excludes disabled skills by resolved skill name", async () enabledSkills: { "skill-writer": false, "renamed-disabled": false, + "deepcode-self-refer": false, + "skill-digester": false, "enabled-skill": true, }, }), @@ -2814,7 +2867,10 @@ test("SessionManager stores usage per model across model changes", async () => { const client = { chat: { completions: { - create: async () => { + create: async (request: any) => { + if (isSkillMatchingRequest(request)) { + return createSkillMatchingResponse(); + } const response = responses.shift(); assert.ok(response, "expected a queued chat response"); return response; @@ -3353,7 +3409,10 @@ function createNotifyingSessionManager( const client = { chat: { completions: { - create: async () => { + create: async (request: any) => { + if (isSkillMatchingRequest(request)) { + return createSkillMatchingResponse(); + } const response = responses.shift(); assert.ok(response, "expected a queued chat response"); if (response instanceof Error) { @@ -3391,7 +3450,10 @@ function createMockedClientSessionManager(projectRoot: string, responses: unknow const client = { chat: { completions: { - create: async () => { + create: async (request: any) => { + if (isSkillMatchingRequest(request)) { + return createSkillMatchingResponse(); + } const response = responses.shift(); assert.ok(response, "expected a queued chat response"); return response; @@ -3427,7 +3489,10 @@ function createPermissionSessionManager( const client = { chat: { completions: { - create: async () => { + create: async (request: any) => { + if (isSkillMatchingRequest(request)) { + return createSkillMatchingResponse(); + } const response = responses.shift(); assert.ok(response, "expected a queued chat response"); return response; @@ -3467,6 +3532,14 @@ function createMockedClientSessionManagerWithClient(projectRoot: string, client: class APIUserAbortError extends Error {} +function isSkillMatchingRequest(request: any): boolean { + return request?.response_format?.type === "json_object"; +} + +function createSkillMatchingResponse(): unknown { + return { choices: [{ message: { content: '{"skillNames":[]}' } }] }; +} + function createChatResponse(content: string, usage: Record): unknown { return { choices: [{ message: { content } }], diff --git a/templates/skills/bundled/deepcode-self-refer/SKILL.md b/templates/skills/bundled/deepcode-self-refer/SKILL.md new file mode 100644 index 00000000..96f275f8 --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/SKILL.md @@ -0,0 +1,125 @@ +--- +name: deepcode-self-refer +description: 回答关于 Deep Code CLI 本身的问题——包括功能特性、配置项、斜杠命令、Skills、MCP 集成、权限、通知、会话持久化及故障排查。当用户询问如何配置或使用 Deep Code、如何设置 MCP 服务器、配置通知(如 Slack/飞书)、管理权限、查看可用技能、理解斜杠命令、配置思考模式、使用 Undo 功能,或咨询 Deep Code 与 VSCode 集成等场景时使用。 +--- + +# Deep Code Self-Refer + +This Skill helps you answer user questions about Deep Code CLI itself by consulting the reference documentation bundled with this Skill. All docs live in the `references/` subdirectory — always refer to them for authoritative answers. + +## When to use this Skill + +Use this Skill when the user asks any question about Deep Code itself, such as: + +- "列出可用的 skills" +- "如何配置 MCP?" +- "给当前项目配置 playwright mcp" +- "怎么启用搜索功能?" +- "支持哪些模型?" +- "如何配置思考模式?" +- "怎么设置权限?" +- "任务完成后怎么发通知?" +- "支持哪些斜杠命令?" +- "会话历史保存在哪里?" +- "/undo 是怎么工作的?" +- "Deep Code 和 VSCode 插件怎么配合?" +- Any other question about Deep Code CLI's features, configuration, or usage. + +## Instructions + +### Step 1: Identify the topic + +Map the user's question to the appropriate document(s): + +| Topic | Document | Key contents | +|-------|----------|-------------| +| **Overview, features, quick start** | `references/README.md` | Installation, slash commands, keyboard shortcuts, supported models, FAQ | +| **Configuration & settings** | `references/configuration.md` | `settings.json` fields, config hierarchy, env vars, thinking mode, reasoning effort, webSearchTool, enabledSkills | +| **MCP setup & usage** | `references/mcp.md` | MCP server config format, GitHub/Playwright/Filesystem examples, tool naming (`mcp____`), troubleshooting | +| **Permissions** | `references/permission.md` | Permission scopes (10 types), allow/deny/ask/defaultMode config, priority rules, persistence | +| **Notifications** | `references/notify.md` | Notify script path, injected env vars, Slack/Feishu/iTerm2/macOS/Linux/Windows examples | +| **Session persistence** | `references/session-persistence.md` | Storage paths, JSONL format, session index, compaction, `/undo` mechanics, code snapshots | + +### Step 2: Read the relevant document(s) + +Use the `Read` tool to read the appropriate document(s) from the list above. All paths are relative to this Skill's loaded root directory, where the `references/` subdirectory lives. + +- If the question spans multiple topics, read multiple documents. +- If a document doesn't exist in the user's preferred language (e.g., Chinese), try the other language variant (e.g., `references/configuration_en.md`). +- When answering from references/README.md, focus on the relevant sections. + +### Step 3: Answer with precision + +- **Quote the doc directly** for config examples, JSON snippets, or command syntax. +- **Don't guess** — if the answer isn't in the docs, say so and suggest checking GitHub Issues. +- **Provide copy-paste-ready configurations** when the user asks to set something up (e.g., MCP servers, notify scripts, permissions). +- **Mention related docs** when appropriate (e.g., MCP setup references `references/mcp.md`, the permissions section references `references/permission.md`). + +### Step 4: Handle common request patterns + +**"列出/查看可用的 skills":** +- Explain the skill scanning paths from references/README.md (`./.deepcode/skills/`, `./.agents/skills/`, `~/.deepcode/skills/`, `~/.agents/skills/`, and bundled built-in skills) +- Explain that `/skills` slash command lists available skills +- Mention `enabledSkills` in `settings.json` for enabling/disabling specific skills + +**"配置 MCP":** +- Read `references/mcp.md` for the MCP format and examples +- Ask the user for any required credentials (e.g., GitHub token) +- Provide the exact `mcpServers` JSON block to add to `settings.json` +- Mention using `/mcp` to verify the setup afterwards + +**"如何配置/修改 <设置项>":** +- Read `references/configuration.md` +- Explain which `settings.json` field controls the setting +- Clarify user-level (`~/.deepcode/settings.json`) vs project-level (`.deepcode/settings.json`) +- Provide the exact JSON snippet + +**"<斜杠命令> 是做什么的?":** +- Read the slash command table from references/README.md +- Provide a brief explanation with any additional context from relevant docs + +### Best practices + +1. **Always consult the docs first** — never answer from memory alone; the docs are the source of truth. +2. **Provide copy-paste-ready JSON** — users want to copy config blocks directly into their `settings.json`. +3. **Be specific about file paths** — always specify whether it's `~/.deepcode/settings.json` or `.deepcode/settings.json`. +4. **Mention `/mcp` verification** — after any MCP configuration change, remind users to use `/mcp` to verify. +5. **Acknowledge both Chinese and English docs** — the project has docs in both languages (`references/xxx.md` for Chinese, `references/xxx_en.md` for English). + +## Examples + +### Example 1: "列出可用的skills" + +Read references/README.md, locate the Skills section. Answer: + +- Skills are discovered from: `./.deepcode/skills/`, `./.agents/skills/`, `~/.deepcode/skills/`, `~/.agents/skills/`, and bundled built-in skills such as `bundled:deepcode-self-refer/SKILL.md`. +- Use `/skills` slash command in the Deep Code CLI to list all available skills +- Use `enabledSkills` in `settings.json` to enable/disable skills by name + +### Example 2: "给当前项目配置playwright mcp" + +Read `references/mcp.md`, locate the Playwright example. Answer: + +- Add to `settings.json` (user-level `~/.deepcode/settings.json` or project-level `.deepcode/settings.json`): + +```json +{ + "mcpServers": { + "playwright": { + "command": "npx", + "args": ["@playwright/mcp@latest"] + } + } +} +``` + +- If merging with existing config, add the `"playwright"` entry into the existing `mcpServers` object +- After saving, use `/mcp` in Deep Code to verify the server is running + +### Example 3: "怎么设置通知到Slack?" + +Read `references/notify.md`, locate the Slack section. Answer with the script + config. + +### Example 4: "如何只允许AI读写当前目录?" + +Read `references/permission.md`, locate the strict mode example. Provide the exact JSON. diff --git a/templates/skills/bundled/deepcode-self-refer/references/README.md b/templates/skills/bundled/deepcode-self-refer/references/README.md new file mode 100644 index 00000000..de34da9a --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/README.md @@ -0,0 +1,209 @@ +
+
+
+

+ + deepcode-cli + +

+

Deep Code CLI

+ +[![][npm-release-shield]][npm-release-link] [![][npm-downloads-shield]][npm-downloads-link] [![][github-contributors-shield]][github-contributors-link] [![][github-forks-shield]][github-forks-link] [![][github-stars-shield]][github-stars-link] +[![][github-issues-shield]][github-issues-link] [![][github-issues-pr-shield]][github-issues-pr-link] [![][github-license-shield]][github-license-link] + +[English](README-en.md) · 中文 + +
+
+ +[Deep Code](https://github.com/lessweb/deepcode-cli) 是专为 `deepseek-v4` 模型优化的终端 AI 编码助手,支持深度思考、推理强度控制、Agent Skills 以及 MCP 集成。 + +## 安装 + +```bash +npm install -g @vegamo/deepcode-cli +``` + +在任意项目目录下运行 `deepcode` 即可启动。 + +![intro2](resources/intro2.png) + +## 配置 + +创建 `~/.deepcode/settings.json` 文件,内容如下: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-..." + }, + "thinkingEnabled": true, + "reasoningEffort": "max" +} +``` + +配置文件与 [Deep Code VSCode 插件](https://github.com/lessweb/deepcode) 共享,无需重复配置。 + +完整配置说明(多层级优先级、环境变量等)请参阅 [docs/configuration.md](docs/configuration.md)。 + +## 主要功能 + +### **Skills** +Deep Code CLI 支持 agent skills,允许您扩展助手的能力: + +Skills 会按以下优先级扫描: + +| Scope | Path | Purpose | +| :------ | :-------------------- | :---------------------------- | +| Project | `./.deepcode/skills/` | Deep Code 原生位置,最高优先级 | +| Project | `./.agents/skills/` | 跨客户端互操作 | +| User | `~/.deepcode/skills/` | Deep Code 原生位置 | +| User | `~/.agents/skills/` | 跨客户端互操作 | +| Bundled | `bundled:/SKILL.md` | Deep Code 内置 skills,最低优先级 | + +### **为 DeepSeek 优化** +- 专门为 DeepSeek 模型性能调优。 +- 通过使用[上下文缓存](https://api-docs.deepseek.com/guides/kv_cache)来降低成本。 +- 原生支持[思考模式](https://api-docs.deepseek.com/guides/thinking_mode)和思考强度控制。 + +## 斜杠命令与按键功能 + +| 斜杠命令 | 操作 | +|-------------|----------------------------------| +| `/` | 打开 skills / 命令菜单 | +| `/new` | 开始新对话 | +| `/resume` | 选择历史对话继续 | +| `/continue` | 继续当前对话,或选择历史对话恢复 | +| `/model` | 切换模型、思考模式和推理强度 | +| `/raw` | 切换显示模式(Normal / Lite / Raw 滚动回溯) | +| `/init` | 初始化 AGENTS.md 文件 | +| `/skills` | 列出可用 skills | +| `/mcp` | 查看 MCP 服务器状态和可用工具 | +| `/undo` | 将代码和/或对话恢复到之前的状态 | +| `/exit` | 退出(也可用连续 `Ctrl+D`) | + +| 按键 | 操作 | +|---------------|--------------------| +| `Enter` | 发送消息 | +| `Shift+Enter` | 插入换行(也可用 `Ctrl+J`) | +| `Ctrl+V` | 从剪贴板粘贴图片 | +| `Esc` | 中断当前模型回复 | +| 连续 `Ctrl+D` | 退出 | + +## 支持的模型 + +- `deepseek-v4-pro`(推荐使用) +- `deepseek-v4-flash` +- 任何其他 OpenAI 兼容模型 + + +## 常见问题 + +### Deep Code 是否有 VSCode 插件? + +有的。Deep Code 提供功能完整的 VSCode 插件,可在 [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=vegamo.deepcode-vscode) 安装。插件与 CLI 共享 `~/.deepcode/settings.json` 配置文件,可以在终端和编辑器之间无缝切换。 + +### Deep Code 是否支持理解图片? + +Deep Code 支持多模态,可使用ctrl+v从剪贴板粘贴图片。但目前 deepseek-v4 不支持多模态。有些模型虽然有多模态能力,但对多轮对话请求的限制太严。目前多模态输入推荐使用火山方舟的 Doubao-Seed-2.0-pro 模型,适配效果最好。 + +### 怎样在任务完成后自动给 Slack 发消息? + +编写一个调用 Slack webhook 的 Shell 通知脚本,然后在 `~/.deepcode/settings.json` 中将 `notify` 字段设为该脚本的完整路径即可。详细步骤请参考 [docs/notify.md](docs/notify.md)。 + +### 怎样启用联网搜索功能? + +Deep Code自带免费的、且大部分情况够用的Web Search工具。如果你希望使用自定义脚本进行联网搜索,可以在 `~/.deepcode/settings.json` 中将 `webSearchTool` 设为脚本的完整路径即可。详细步骤可参考:https://github.com/qorzj/web_search_cli + +### 如何配置 MCP? + +Deep Code 支持 MCP(Model Context Protocol),可以连接 GitHub、浏览器、数据库等外部服务。在 `settings.json` 中配置 `mcpServers` 字段即可启用,启动后使用 `/mcp` 命令查看已配置的 MCP 服务器状态和可用工具。 + +详细配置指南:[docs/mcp.md](docs/mcp.md) + +### 如何配置 Deep Code 任务完成后发送通知? + +当 AI 助手完成一轮任务后,Deep Code 可以自动执行一个通知脚本,将任务结果发送到你指定的渠道(如 Slack、系统通知等)。 + +详细配置指南:[docs/notify.md](docs/notify.md) + +### Deep Code 只支持 YOLO 模式吗? + +不是。Deep Code 内置了细粒度的权限控制机制,支持在 AI 助手执行 Shell 命令、读写文件、访问网络等操作前进行确认。你可以通过 `settings.json` 中的 `permissions` 字段按需配置每种权限范围的策略:始终允许、始终询问、或直接拒绝。详见 [docs/permission.md](docs/permission.md)。 + +### 是否支持 Coding Plan? + +支持。只要把 `~/.deepcode/settings.json` 的 `env.BASE_URL` 配置为 OpenAI 兼容的接口地址就行。以火山方舟的 Coding Plan 为例: + +```json +{ + "env": { + "MODEL": "ark-code-latest", + "BASE_URL": "https://ark.cn-beijing.volces.com/api/coding/v3", + "API_KEY": "**************" + }, + "thinkingEnabled": true +} +``` + +## 贡献 + +欢迎贡献代码!以下是参与方式: + +```bash +# 克隆仓库 +git clone https://github.com/lessweb/deepcode-cli.git +cd deepcode-cli + +# 安装依赖 +npm install + +# 本地开发(类型检查 + lint + 格式检查 + 构建) +npm run build + +# 运行测试 +npm test + +# 链接到全局(即本地全局安装) +npm link +``` + +- 提交 PR 前请确保 `npm run check` 通过(类型检查 + lint + 格式检查) +- 建议在执行构建前,先执行 `npm run format` 自动格式化代码,避免构建报错 + +## 获取帮助 + +- 在 GitHub Issues 上报告错误或请求功能 (https://github.com/lessweb/deepcode-cli/issues) + +## 协议 + +- MIT + +## 支持我们 + +如果你觉得这个工具对你有帮助,请考虑通过以下方式支持我们: + +- 在 GitHub 上给我们一个 Star (https://github.com/lessweb/deepcode-cli) +- 向我们提交反馈和建议 +- 分享给你的朋友和同事 + + + +[npm-release-link]: https://www.npmjs.com/package/@vegamo/deepcode-cli +[npm-release-shield]: https://img.shields.io/npm/v/@vegamo/deepcode-cli?color=4d6BFE&labelColor=black&logo=npm&logoColor=white&style=flat-square&cacheSeconds=1800 +[npm-downloads-link]: https://www.npmjs.com/package/@vegamo/deepcode-cli +[npm-downloads-shield]: https://img.shields.io/npm/dt/@vegamo/deepcode-cli?labelColor=black&style=flat-square&color=4d6BFE&cacheSeconds=1800 +[github-contributors-link]: https://github.com/lessweb/deepcode-cli/graphs/contributors +[github-contributors-shield]: https://img.shields.io/github/contributors/lessweb/deepcode-cli?color=4d6BFE&labelColor=black&style=flat-square&cacheSeconds=1800 +[github-forks-link]: https://github.com/lessweb/deepcode-cli/network/members +[github-forks-shield]: https://img.shields.io/github/forks/lessweb/deepcode-cli?color=4d6BFE&labelColor=black&style=flat-square&cacheSeconds=1800 +[github-stars-link]: https://github.com/lessweb/deepcode-cli/network/stargazers +[github-stars-shield]: https://img.shields.io/github/stars/lessweb/deepcode-cli?color=4d6BFE&labelColor=black&style=flat-square&cacheSeconds=1800 +[github-issues-link]: https://github.com/lessweb/deepcode-cli/issues +[github-issues-shield]: https://img.shields.io/github/issues/lessweb/deepcode-cli?color=4d6BFE&labelColor=black&style=flat-square&cacheSeconds=1800 +[github-issues-pr-link]: https://github.com/lessweb/deepcode-cli/pulls +[github-issues-pr-shield]: https://img.shields.io/github/issues-pr/lessweb/deepcode-cli?color=4d6BFE&labelColor=black&style=flat-square&cacheSeconds=1800 +[github-license-link]: https://github.com/lessweb/deepcode-cli/blob/main/LICENSE +[github-license-shield]: https://img.shields.io/github/license/lessweb/deepcode-cli?color=4d6BFE&labelColor=black&style=flat-square&cacheSeconds=1800 diff --git a/templates/skills/bundled/deepcode-self-refer/references/configuration.md b/templates/skills/bundled/deepcode-self-refer/references/configuration.md new file mode 100644 index 00000000..2f198b10 --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/configuration.md @@ -0,0 +1,217 @@ +# Deep Code 配置 + +## 配置层级 + +配置按以下优先级顺序应用(数字较小的会被数字较大的覆盖): + +| 层级 | 配置来源 | 说明 | +| ---- | ------------ | ------------------------------------------- | +| 1 | 默认值 | 应用程序内硬编码的默认值 | +| 2 | 用户设置文件 | 当前用户的全局设置 | +| 3 | 项目设置文件 | 项目特定的设置 | +| 4 | 环境变量 | 系统范围或会话特定的变量 | + +## 设置文件 + +Deep Code 使用 `settings.json` 设置文件进行持久化配置,支持两个层级的存放位置: + +| 文件类型 | 位置 | 作用范围 | +| ------------ | ---------------------------------- | ---------------------------------------------------- | +| 用户设置文件 | `~/.deepcode/settings.json` | 适用于当前用户的所有 Deep Code 会话。 | +| 项目设置文件 | `项目根目录/.deepcode/settings.json` | 仅在该特定项目中运行 Deep Code 时生效。项目设置会覆盖用户设置。 | + +### `settings.json` 中的可用设置 + +以下是 `settings.json` 支持的全部顶层字段,以及 `env` 内部支持的子字段: + +| 字段 | 类型 | 说明 | +| -------------------- | --------- | ------------------------------------------------------------------- | +| `env` | object | 环境变量分组(见下方子字段表) | +| `model` | string | 模型名称。优先级高于 `env.MODEL` | +| `thinkingEnabled` | boolean | 是否启用思考模式(DeepSeek V4 系列默认启用) | +| `reasoningEffort` | string | 推理强度,可选 `"high"` 或 `"max"`(默认 `"max"`) | +| `debugLogEnabled` | boolean | 是否启用调试日志输出(默认 `false`) | +| `telemetryEnabled` | boolean | 是否启用匿名使用数据上报(默认 `true`) | +| `notify` | string | 任务完成通知脚本的完整路径(如 Slack 通知脚本) | +| `webSearchTool` | string | 自定义联网搜索脚本的完整路径 | +| `mcpServers` | object | MCP 服务器配置(键为服务名,值为 McpServerConfig 对象) | +| `temperature` | number | 模型采样温度,范围 `0` 到 `2` | +| `enabledSkills` | object | 按 skill 名称启用或禁用 skill 的配置 | + +#### `env` 子字段 + +| 字段 | 类型 | 说明 | +| ---------- | ------ | ------------------------------------------------------------------ | +| `MODEL` | string | 模型名称。例如 `"deepseek-v4-pro"`、`"deepseek-v4-flash"` | +| `BASE_URL` | string | API 请求的基础 URL。例如 `"https://api.deepseek.com"` | +| `API_KEY` | string | API 密钥 | +| `TEMPERATURE` | string | Chat Completions 采样温度,范围 `"0"` 到 `"2"` | +| `THINKING_ENABLED` | string | 是否启用思考模式 | +| `REASONING_EFFORT` | string | 推理强度 | +| `DEBUG_LOG_ENABLED` | string | 是否启用调试日志输出 | +| `TELEMETRY_ENABLED` | string | 是否启用匿名使用数据上报 | +| `<其他任意KEY>` | string | 自定义环境变量 | + +#### `thinkingEnabled` — 思考模式 + +是否启用 DeepSeek 思考模式。设置为 `true` 启用、`false` 禁用。 + +- 对于 `deepseek-v4-pro` 和 `deepseek-v4-flash`,思考模式**默认启用**。 +- 对于其他模型,思考模式**默认关闭**。 + +#### `reasoningEffort` — 推理强度 + +当思考模式启用时,控制模型思考的深度: + +| 值 | 说明 | +| ------ | --------------------------------- | +| `max` | 最大推理深度(默认值) | +| `high` | 较高推理深度,token消耗相对较小 | + +#### `notify` — 任务完成通知 + +设置一个 Shell 脚本的完整路径。当 AI 助手完成一轮任务后,会自动执行该脚本,可用于发送通知(如 Slack 消息)。 + +通知脚本执行时,会通过环境变量注入以下上下文信息: + +| 环境变量 | 说明 | +|----------|------| +| `DURATION` | 会话耗时,单位秒(整数) | +| `STATUS` | 会话状态:`"completed"` 或 `"failed"` | +| `FAIL_REASON` | 失败原因(仅失败时设置) | +| `BODY` | 最后一条 AI 助手回复的文本内容 | +| `TITLE` | 会话标题(对应 resume 列表中的标题) | + +```json +{ + "notify": "/path/to/notify-script.sh" +} +``` + +> 详细的 Slack、飞书、终端通知、系统通知等配置示例,请参阅 [notify.md](notify.md)。 + +#### `webSearchTool` — 自定义联网搜索 + +Deep Code 内置免费可用的 Web Search 工具。如果需要自定义搜索逻辑,可将 `webSearchTool` 设为一个可执行脚本的完整路径: + +```json +{ + "webSearchTool": "/path/to/my-search-script.sh" +} +``` + +脚本接收一个搜索查询参数,输出 JSON 格式的结果供 AI 使用。 + +#### `enabledSkills` — Skill 启用配置 + +控制 skill 扫描时是否包含指定 skill。键是解析后的 skill 名称,值必须是布尔值: + +```json +{ + "enabledSkills": { + "skill-writer": false, + "code-review": true + } +} +``` + +- 未配置的 skill 默认启用。 +- 将某个 skill 设置为 `false` 后,所有项目级和用户级目录中解析名称相同的 skill 都会被隐藏。 +- 项目设置会按 skill 覆盖用户设置。如果项目设置没有配置某个 skill,则使用用户设置。 + +#### `mcpServers` — MCP 服务器 + +MCP(Model Context Protocol)服务器配置。值是键值对,键为服务名称,值为服务器配置对象。 + +```json +{ + "mcpServers": { + "<服务名>": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx" + } + } + } +} +``` + +| McpServerConfig 字段 | 类型 | 必填 | 说明 | +| -------------------- | -------- | ---- | -------------------------------------------------------------------- | +| `command` | string | 是 | 可执行文件路径或命令(如 `npx`、`node`、`python`) | +| `args` | string[] | 否 | 传递给命令的参数列表 | +| `env` | object | 否 | 传递给 MCP 服务器进程的环境变量 | + +> 当 `command` 为 `npx` 时,Deep Code 会自动在参数前补充 `-y`。 + +详细 MCP 使用说明请参考 [mcp.md](mcp.md)。 + + +#### `debugLogEnabled` — 调试日志 + +设为 `true` 可让程序输出详细的调试日志(默认 `false`),用于排查 API 调用和工具执行的问题。 + +#### `telemetryEnabled` — 匿名使用数据上报 + +设为 `false` 可关闭匿名使用数据上报(默认 `true`)。上报仅包含匿名的机器标识,不包含对话内容、代码或 API 密钥。 + +也可以通过环境变量关闭: + +```bash +DEEPCODE_TELEMETRY_ENABLED=0 deepcode +``` + +## 环境变量优先级 + +环境变量是配置应用程序的常用方式,尤其适用于敏感信息(如 api-key)或可能在不同环境之间更改的设置。 + +### 优先级原则 + +环境变量优先级遵循“越具体、越局部的配置,优先级越高”和“env文件默认保护现有环境,系统变量高于env文件”的覆盖逻辑。(settings.json的env对象可以认为是一种env文件) + +优先级层级 (由低到高) +1. settings.json 外层的 env:这是针对整个工具及其所有子进程的通用配置(全局变量)。可被外层环境变量覆盖,但环境变量KEY会移除`DEEPCODE_`前缀。 +2. settings.json mcpServers 内定义的 env:这是针对特定 MCP 服务的最具体配置(局部变量)。可被外层环境变量覆盖,但环境变量KEY会移除`MCP_`前缀。 +3. Shell 环境系统变量:操作系统层面的环境变量。 + +### 场景 + +#### 一、设置模型的api_key, base_url + +按以下优先级顺序应用(数字较小的会被数字较大的覆盖)(以api_key为例): + +1. 硬编码默认值: `""` +2. 用户级settings.json: `{"env": {"API_KEY": "abc123"}}` +3. 项目级settings.json: `{"env": {"API_KEY": "abc123"}}` +4. 系统环境变量: `DEEPCODE_API_KEY=abc123 deepcode` + +#### 二、设置模型的model, thinkingEnabled, reasoningEffort + +按以下优先级顺序应用(数字较小的会被数字较大的覆盖)(以thinkingEnabled为例): + +1. 硬编码默认值: `true` +2. 用户级settings.json: `{"env": {"THINKING_ENABLED": "true"}}` +3. 用户级settings.json: `{"thinkingEnabled": true}` +4. 项目级settings.json: `{"env": {"THINKING_ENABLED": "true"}}` +5. 项目级settings.json: `{"thinkingEnabled": true}` +6. 系统环境变量: `DEEPCODE_THINKING_ENABLED=true deepcode` + +#### 三、设置启动notify, webSearchTool等外挂脚本的环境变量 + +按以下优先级顺序应用(数字较小的会被数字较大的覆盖)(以notify为例): + +1. 硬编码默认值:`os.environ.get('WEBHOOK', '...') # notify脚本代码` +2. 用户级settings.json: `{"env": {"WEBHOOK": "..."}}` +3. 项目级settings.json: `{"env": {"WEBHOOK": "true"}}` +4. 系统环境变量: `DEEPCODE_WEBHOOK=... deepcode` + +#### 四、设置MCP Service的环境变量 + +按以下优先级顺序应用(数字较小的会被数字较大的覆盖)(以github MCP server为例): + +1. 用户级settings.json: `{"mcpServers":{"github":{"env":{"GITHUB_PERSONAL_ACCESS_TOKEN":"..."}}}}` +2. 用户级settings.json: `{"env": {"MCP_GITHUB_PERSONAL_ACCESS_TOKEN": "..."}}` +3. 项目级settings.json: `{"mcpServers":{"github":{"env":{"GITHUB_PERSONAL_ACCESS_TOKEN":"..."}}}}` +4. 项目级settings.json: `{"env": {"MCP_GITHUB_PERSONAL_ACCESS_TOKEN": "..."}}` +5. 系统环境变量: `DEEPCODE_MCP_GITHUB_PERSONAL_ACCESS_TOKEN=... deepcode` diff --git a/templates/skills/bundled/deepcode-self-refer/references/configuration_en.md b/templates/skills/bundled/deepcode-self-refer/references/configuration_en.md new file mode 100644 index 00000000..fac8c349 --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/configuration_en.md @@ -0,0 +1,216 @@ +# Deep Code Configuration + +## Configuration Hierarchy + +Configuration is applied in the following priority order (lower-numbered sources are overridden by higher-numbered ones): + +| Layer | Configuration Source | Description | +| ----- | -------------------- | ---------------------------------------------- | +| 1 | Defaults | Hardcoded defaults within the application | +| 2 | User settings file | Global settings for the current user | +| 3 | Project settings file| Project-specific settings | +| 4 | Environment variables| System-wide or session-specific variables | + +## Settings File + +Deep Code uses the `settings.json` file for persistent configuration, supporting two storage locations: + +| File Type | Location | Scope | +| ------------------- | ----------------------------------------- | --------------------------------------------------------------------- | +| User settings file | `~/.deepcode/settings.json` | Applies to all Deep Code sessions for the current user. | +| Project settings file | `/.deepcode/settings.json` | Takes effect only when running Deep Code in that specific project. Project settings override user settings. | + +### Available Settings in `settings.json` + +The following are all the top-level fields supported in `settings.json`, along with the sub-fields inside `env`: + +| Field | Type | Description | +| ------------------ | ------- | --------------------------------------------------------------------------- | +| `env` | object | Group of environment variables (see sub-field table below) | +| `model` | string | Model name. Takes precedence over `env.MODEL` | +| `thinkingEnabled` | boolean | Whether to enable thinking mode (enabled by default for DeepSeek V4 series)| +| `reasoningEffort` | string | Reasoning intensity, either `"high"` or `"max"` (default `"max"`) | +| `debugLogEnabled` | boolean | Enable debug log output (default `false`) | +| `telemetryEnabled` | boolean | Enable anonymous usage reporting (default `true`) | +| `notify` | string | Full path to a task-completion notification script (e.g., Slack notification script) | +| `webSearchTool` | string | Full path to a custom web search script | +| `mcpServers` | object | MCP server configurations (keys are service names, values are McpServerConfig objects) | +| `temperature` | number | Sampling temperature for LLM, from `0` to `2` | +| `enabledSkills` | object | Per-skill enable/disable map, keyed by skill name | + +#### `env` Sub-fields + +| Field | Type | Description | +| ----------------- | ------ | ---------------------------------------------------------------- | +| `MODEL` | string | Model name, e.g. `"deepseek-v4-pro"`, `"deepseek-v4-flash"` | +| `BASE_URL` | string | Base URL for API requests, e.g. `"https://api.deepseek.com"` | +| `API_KEY` | string | API key | +| `TEMPERATURE` | string | Sampling temperature for chat completions, from `"0"` to `"2"` | +| `THINKING_ENABLED`| string | Enable thinking mode | +| `REASONING_EFFORT`| string | Reasoning intensity | +| `DEBUG_LOG_ENABLED`| string| Enable debug log output | +| `TELEMETRY_ENABLED`| string| Enable anonymous usage reporting | +| `` | string | Custom environment variable | + +#### `thinkingEnabled` — Thinking Mode + +Whether to enable DeepSeek thinking mode. Set to `true` to enable, `false` to disable. + +- For `deepseek-v4-pro` and `deepseek-v4-flash`, thinking mode is **enabled by default**. +- For other models, thinking mode is **disabled by default**. + +#### `reasoningEffort` — Reasoning Intensity + +When thinking mode is enabled, controls the depth of the model’s reasoning: + +| Value | Description | +| ------ | --------------------------------------------------------- | +| `max` | Maximum reasoning depth (default) | +| `high` | Higher reasoning depth with relatively lower token usage | + +#### `notify` — Task Completion Notification + +Set a full path to a shell script. When the AI assistant finishes a round of tasks, the script is executed automatically, which can be used to send notifications (e.g., a Slack message). + +The following context is injected as environment variables when the notify script runs: + +| Variable | Description | +|----------|-------------| +| `DURATION` | Session duration in seconds (integer) | +| `STATUS` | Session status: `"completed"` or `"failed"` | +| `FAIL_REASON` | Failure reason (only set on failure) | +| `BODY` | The text content of the last AI assistant reply | +| `TITLE` | Session title (matches the resume list title) | + +```json +{ + "notify": "/path/to/notify-script.sh" +} +``` + +> For detailed configuration examples (Slack, Feishu, terminal notifications, system notifications, etc.), see [notify_en.md](notify_en.md). + +#### `webSearchTool` — Custom Web Search + +Deep Code has a built-in, free-to-use Web Search tool. If you need custom search logic, set `webSearchTool` to the full path of an executable script: + +```json +{ + "webSearchTool": "/path/to/my-search-script.sh" +} +``` + +The script receives a search query as an argument and outputs results in JSON format for the AI. + +#### `enabledSkills` — Skill Enablement + +Controls whether skills are included during skill scanning. Keys are resolved skill names, and values must be booleans: + +```json +{ + "enabledSkills": { + "skill-writer": false, + "code-review": true + } +} +``` + +- Missing entries are enabled by default. +- Setting a skill to `false` hides every skill with that resolved `name`, across project and user skill roots. +- Project settings override user settings per skill. If the project setting omits a skill, the user setting is used. + +#### `mcpServers` — MCP Servers + +Configuration for MCP (Model Context Protocol) servers. The value is a key-value pair, where the key is the service name and the value is a server configuration object. + +```json +{ + "mcpServers": { + "": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx" + } + } + } +} +``` + +| McpServerConfig field | Type | Required | Description | +| --------------------- | -------- | -------- | ------------------------------------------------------------------------ | +| `command` | string | Yes | Executable path or command (e.g. `npx`, `node`, `python`) | +| `args` | string[] | No | List of arguments passed to the command | +| `env` | object | No | Environment variables passed to the MCP server process | + +> When `command` is `npx`, Deep Code automatically prepends `-y` to the arguments. + +For detailed MCP usage instructions, refer to [mcp.md](mcp.md). + +#### `debugLogEnabled` — Debug Log + +Set to `true` to enable detailed debug logging (default `false`), useful for troubleshooting API calls and tool execution. + +#### `telemetryEnabled` — Anonymous Usage Reporting + +Set to `false` to disable anonymous usage reporting (default `true`). The report only includes an anonymous machine identifier and does not contain conversation content, code, or API keys. + +You can also disable it via environment variable: + +```bash +DEEPCODE_TELEMETRY_ENABLED=0 deepcode +``` + +## Environment Variable Priority + +Environment variables are a common way to configure applications, especially for sensitive information (such as api-key) or settings that may change between environments. + +### Priority Principle + +Environment variable priority follows the logic of “the more specific and localized the configuration, the higher the priority”, and the override rule of “env files protect existing environment by default, system variables override env files”. (The `env` object in settings.json can be thought of as a type of env file.) + +Priority levels (from lowest to highest): +1. `env` defined at the top level of `settings.json` – this is a general configuration for the entire tool and all its subprocesses (global variables). Can be overridden by outer environment variables, but the environment variable KEY has the `DEEPCODE_` prefix removed. +2. `env` defined inside `mcpServers` in `settings.json` – this is the most specific configuration for a particular MCP service (local variables). Can be overridden by outer environment variables, but the KEY has the `MCP_` prefix removed. +3. Shell/system environment variables – operating system level. + +### Scenarios + +#### 1. Setting the model’s api_key and base_url + +Applied in the following priority order (lower-numbered sources are overridden by higher-numbered ones) – using api_key as an example: + +1. Hardcoded default: `""` +2. User-level settings.json: `{"env": {"API_KEY": "abc123"}}` +3. Project-level settings.json: `{"env": {"API_KEY": "abc123"}}` +4. System environment variable: `DEEPCODE_API_KEY=abc123 deepcode` + +#### 2. Setting model, thinkingEnabled, and reasoningEffort + +Applied in the following priority order (lower-numbered overridden by higher-numbered) – using thinkingEnabled as an example: + +1. Hardcoded default: `true` +2. User-level settings.json: `{"env": {"THINKING_ENABLED": "true"}}` +3. User-level settings.json: `{"thinkingEnabled": true}` +4. Project-level settings.json: `{"env": {"THINKING_ENABLED": "true"}}` +5. Project-level settings.json: `{"thinkingEnabled": true}` +6. System environment variable: `DEEPCODE_THINKING_ENABLED=true deepcode` + +#### 3. Setting environment variables for external scripts like notify and webSearchTool + +Applied in the following priority order (lower-numbered overridden by higher-numbered) – using notify as an example: + +1. Hardcoded default: `os.environ.get('WEBHOOK', '...') # notify script code` +2. User-level settings.json: `{"env": {"WEBHOOK": "..."}}` +3. Project-level settings.json: `{"env": {"WEBHOOK": "true"}}` +4. System environment variable: `DEEPCODE_WEBHOOK=... deepcode` + +#### 4. Setting environment variables for an MCP Service + +Applied in the following priority order (lower-numbered overridden by higher-numbered) – using a GitHub MCP server as an example: + +1. User-level settings.json: `{"mcpServers":{"github":{"env":{"GITHUB_PERSONAL_ACCESS_TOKEN":"..."}}}}` +2. User-level settings.json: `{"env": {"MCP_GITHUB_PERSONAL_ACCESS_TOKEN": "..."}}` +3. Project-level settings.json: `{"mcpServers":{"github":{"env":{"GITHUB_PERSONAL_ACCESS_TOKEN":"..."}}}}` +4. Project-level settings.json: `{"env": {"MCP_GITHUB_PERSONAL_ACCESS_TOKEN": "..."}}` +5. System environment variable: `DEEPCODE_MCP_GITHUB_PERSONAL_ACCESS_TOKEN=... deepcode` diff --git a/templates/skills/bundled/deepcode-self-refer/references/mcp.md b/templates/skills/bundled/deepcode-self-refer/references/mcp.md new file mode 100644 index 00000000..73034a38 --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/mcp.md @@ -0,0 +1,200 @@ +# Deep Code CLI MCP 配置指南 + +Deep Code CLI 支持 MCP(Model Context Protocol),让 AI 助手能够连接外部工具和服务,如 GitHub、浏览器、数据库等。 + +## 概述 + +配置 MCP 后,Deep Code 可以: + +- 操作 GitHub 仓库(查看 Issues、创建 PR、搜索代码等) +- 操控浏览器(截图、点击、填表单等) +- 访问文件系统 +- 连接数据库和 API +- ...以及任何兼容 MCP 协议的外部服务 + +MCP 工具在 Deep Code 中的命名格式为 `mcp__<服务名>__<工具名>`,例如 `mcp__github__search_code`。 + +## 配置 MCP 服务器 + +编辑 `~/.deepcode/settings.json`,添加 `mcpServers` 字段: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-..." + }, + "thinkingEnabled": true, + "reasoningEffort": "max", + "mcpServers": { + "<服务名称>": { + "command": "<可执行文件>", + "args": ["<参数1>", "<参数2>"], + "env": { + "<环境变量>": "<值>" + } + } + } +} +``` + +### 配置项说明 + +| 字段 | 类型 | 必填 | 说明 | +| --------- | -------- | ---- | ---------------------------------------------------------------------------------------------------------------------- | +| `command` | string | 是 | MCP 服务器的可执行文件路径或命令(如 `npx`、`node`、`python`)。当命令是 `npx` 时,Deep Code 会自动在参数前补充 `-y`。 | +| `args` | string[] | 否 | 传递给命令的参数列表 | +| `env` | object | 否 | 传递给 MCP 服务器进程的环境变量(如 API Key) | + +## 常用 MCP 示例 + +### GitHub MCP + +让 Deep Code 直接操作 GitHub 仓库(搜索代码、管理 Issue/PR、读写文件等): + +```json +{ + "mcpServers": { + "github": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx" + } + } + } +} +``` + +> GitHub Personal Access Token 可在 [GitHub Settings > Developer settings > Personal access tokens](https://github.com/settings/tokens) 生成。 + +### 浏览器控制(Playwright) + +让 Deep Code 操控浏览器进行截图、页面操作等: + +```json +{ + "mcpServers": { + "playwright": { + "command": "npx", + "args": ["@playwright/mcp@latest"] + } + } +} +``` + +### 文件系统 + +让 Deep Code 在指定目录中读写文件: + +```json +{ + "mcpServers": { + "filesystem": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"] + } + } +} +``` + +### 自定义 Python MCP + +```json +{ + "mcpServers": { + "my-tool": { + "command": "python", + "args": ["-m", "my_mcp_server"], + "env": { + "API_KEY": "xxx" + } + } + } +} +``` + +## 完整配置示例 + +以下是一个配置了 GitHub 和 Playwright 两个 MCP 服务器的完整 `~/.deepcode/settings.json`: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-xxxxxxxxxxxx" + }, + "thinkingEnabled": true, + "reasoningEffort": "max", + "mcpServers": { + "github": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx" + } + }, + "playwright": { + "command": "npx", + "args": ["@playwright/mcp@latest"] + } + } +} +``` + +## 使用 MCP + +配置完成后,启动 `deepcode`,在聊天中输入 `/mcp` 即可查看所有已配置的 MCP 服务器状态以及每个服务器提供的工具列表。 + +在对话中直接使用 MCP 工具名称即可调用,例如: + +``` +帮我搜索 GitHub 上 deepcode-cli 仓库的 issues +``` + +AI 会自动调用 `mcp__github__search_issues` 工具完成操作。 + +## 工具命名规则 + +MCP 工具名称由三部分组成:`mcp__<服务名>__<工具名>` + +| 服务名 | 工具名 | 完整调用名 | +| ---------- | ----------------------- | ------------------------------------------ | +| github | search_code | `mcp__github__search_code` | +| github | create_pull_request | `mcp__github__create_pull_request` | +| playwright | browser_navigate | `mcp__playwright__browser_navigate` | +| playwright | browser_take_screenshot | `mcp__playwright__browser_take_screenshot` | + +你可以通过 `/mcp` 查看每个服务器提供的具体工具列表。 + +## 故障排查 + +### 启动失败 + +如果 MCP 服务器无法启动,检查: + +1. `command` 是否已安装(如 `npx` 需要 Node.js) +2. `env` 中的环境变量是否正确(如 `GITHUB_PERSONAL_ACCESS_TOKEN`) +3. 运行 `deepcode` 的终端是否有网络访问权限 + +### 工具不显示 + +1. 确认 `settings.json` 中的 `mcpServers` 字段格式正确 +2. 启动 deepcode 后使用 `/mcp` 查看服务器状态 +3. 如果服务器状态显示错误,根据错误信息排查 + +### Windows 用户 + +在 Windows 上,Deep Code CLI 会自动为 `.cmd` 命令添加 shell 支持。如果你的 MCP 命令是批处理脚本,确保文件名以 `.cmd` 结尾。 + +## 编写你自己的 MCP 服务器 + +MCP 服务器遵循 [Model Context Protocol](https://modelcontextprotocol.io/) 规范,使用 JSON-RPC 2.0 通信。你可以用任何语言编写 MCP 服务器,只要实现以下协议即可: + +1. `initialize` — 握手和协议协商 +2. `tools/list` — 返回可用工具列表 +3. `tools/call` — 执行工具调用 + +更多参考:[MCP 官方文档](https://modelcontextprotocol.io/) diff --git a/templates/skills/bundled/deepcode-self-refer/references/mcp_en.md b/templates/skills/bundled/deepcode-self-refer/references/mcp_en.md new file mode 100644 index 00000000..03c4b30c --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/mcp_en.md @@ -0,0 +1,200 @@ +# Deep Code CLI MCP Configuration Guide + +Deep Code CLI supports MCP (Model Context Protocol), enabling AI assistants to connect with external tools and services such as GitHub, browsers, databases, and more. + +## Overview + +Once MCP is configured, Deep Code can: + +- Operate on GitHub repositories (view issues, create PRs, search code, etc.) +- Control browsers (screenshots, clicks, form filling, etc.) +- Access the file system +- Connect to databases and APIs +- ...and any external service compatible with the MCP protocol + +MCP tools are named in Deep Code using the format `mcp____`, for example `mcp__github__search_code`. + +## Configuring MCP Servers + +Edit `~/.deepcode/settings.json` and add the `mcpServers` field: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-..." + }, + "thinkingEnabled": true, + "reasoningEffort": "max", + "mcpServers": { + "": { + "command": "", + "args": ["", ""], + "env": { + "": "" + } + } + } +} +``` + +### Configuration Fields + +| Field | Type | Required | Description | +| --------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `command` | string | Yes | Path or command of the MCP server executable (e.g., `npx`, `node`, `python`). When the command is `npx`, Deep Code automatically prepends `-y` to the arguments. | +| `args` | string[] | No | List of arguments to pass to the command | +| `env` | object | No | Environment variables (e.g., API keys) to pass to the MCP server process | + +## Common MCP Examples + +### GitHub MCP + +Allows Deep Code to directly operate on GitHub repositories (search code, manage issues/PRs, read/write files, etc.): + +```json +{ + "mcpServers": { + "github": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx" + } + } + } +} +``` + +> Generate a GitHub Personal Access Token at [GitHub Settings > Developer settings > Personal access tokens](https://github.com/settings/tokens). + +### Browser Control (Playwright) + +Lets Deep Code control a browser for screenshots, page interactions, etc.: + +```json +{ + "mcpServers": { + "playwright": { + "command": "npx", + "args": ["@playwright/mcp@latest"] + } + } +} +``` + +### File System + +Enables Deep Code to read and write files within a specified directory: + +```json +{ + "mcpServers": { + "filesystem": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"] + } + } +} +``` + +### Custom Python MCP + +```json +{ + "mcpServers": { + "my-tool": { + "command": "python", + "args": ["-m", "my_mcp_server"], + "env": { + "API_KEY": "xxx" + } + } + } +} +``` + +## Full Configuration Example + +Below is a complete `~/.deepcode/settings.json` with both GitHub and Playwright MCP servers configured: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-xxxxxxxxxxxx" + }, + "thinkingEnabled": true, + "reasoningEffort": "max", + "mcpServers": { + "github": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx" + } + }, + "playwright": { + "command": "npx", + "args": ["@playwright/mcp@latest"] + } + } +} +``` + +## Using MCP + +After configuration, start `deepcode` and type `/mcp` in the chat to view the status of all configured MCP servers and the list of tools each server provides. + +Simply use the MCP tool name in your conversation to invoke it, for example: + +``` +Help me search for issues in the deepcode-cli repository on GitHub +``` + +The AI will automatically invoke the `mcp__github__search_issues` tool to complete the action. + +## Tool Naming Convention + +An MCP tool name consists of three parts: `mcp____` + +| Service | Tool Name | Full Invocation Name | +| ---------- | ----------------------- | ------------------------------------------- | +| github | search_code | `mcp__github__search_code` | +| github | create_pull_request | `mcp__github__create_pull_request` | +| playwright | browser_navigate | `mcp__playwright__browser_navigate` | +| playwright | browser_take_screenshot | `mcp__playwright__browser_take_screenshot` | + +You can view the list of tools provided by each server using `/mcp`. + +## Troubleshooting + +### Startup Failure + +If an MCP server fails to start, check: + +1. Whether `command` is installed (e.g., `npx` requires Node.js) +2. Whether environment variables in `env` are correct (e.g., `GITHUB_PERSONAL_ACCESS_TOKEN`) +3. Whether the terminal running `deepcode` has network access + +### Tools Not Showing Up + +1. Verify that the `mcpServers` field in `settings.json` is correctly formatted +2. After starting deepcode, use `/mcp` to check server status +3. If the server status shows an error, debug based on the error message + +### Windows Users + +On Windows, Deep Code CLI automatically adds shell support for `.cmd` commands. If your MCP command is a batch script, ensure the filename ends with `.cmd`. + +## Writing Your Own MCP Server + +MCP servers follow the [Model Context Protocol](https://modelcontextprotocol.io/) specification and communicate using JSON‑RPC 2.0. You can write an MCP server in any language as long as it implements the following methods: + +1. `initialize` — Handshake and protocol negotiation +2. `tools/list` — Return the list of available tools +3. `tools/call` — Execute a tool call + +For more information, see the [official MCP documentation](https://modelcontextprotocol.io/). \ No newline at end of file diff --git a/templates/skills/bundled/deepcode-self-refer/references/notify.md b/templates/skills/bundled/deepcode-self-refer/references/notify.md new file mode 100644 index 00000000..d73eef45 --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/notify.md @@ -0,0 +1,211 @@ +# Deep Code 任务完成通知 + +当 AI 助手完成一轮任务后,Deep Code 可以自动执行一个通知脚本,将任务结果发送到你指定的渠道(如 Slack、系统通知等)。 + +## 工作原理 + +在 `settings.json` 中配置 `notify` 字段,指向一个可执行脚本的完整路径。每次 AI 助手完成任务应答后,Deep Code 会执行该脚本,并通过环境变量注入上下文信息。 + +## 注入的环境变量 + +| 环境变量 | 说明 | +|----------|------| +| `DURATION` | 会话耗时,单位秒(整数) | +| `STATUS` | 会话状态:`"completed"` 或 `"failed"` | +| `FAIL_REASON` | 失败原因(仅失败时设置) | +| `BODY` | 最后一条 AI 助手回复的文本内容 | +| `TITLE` | 会话标题(对应 resume 列表中的标题) | + +## 配置方法 + +编辑 `~/.deepcode/settings.json`,添加 `notify` 字段: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-..." + }, + "thinkingEnabled": true, + "reasoningEffort": "max", + "notify": "/path/to/your-notify-script.sh" +} +``` + +你也可以在 `env` 中配置通知脚本所需的自定义环境变量,例如 Slack Webhook URL: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-...", + "SLACK_WEBHOOK_URL": "https://hooks.slack.com/services/*****/****/**********" + }, + "notify": "/Users/you/.deepcode/notify-slack.sh" +} +``` + +这些 `env` 中的变量会被注入到脚本的执行环境中。 + +## Slack 通知 + +### 1. 获取 Slack Webhook URL + +1. 创建 [Slack App](https://api.slack.com/apps) +2. 在 App 页面点击 **Incoming Webhooks** → **Add New Webhook to Workspace**,生成 Webhook URL + +### 2. 创建通知脚本 + +创建 `~/.deepcode/notify-slack.sh`: + +```bash +#!/usr/bin/env bash +SLACK_WEBHOOK_URL="${SLACK_WEBHOOK_URL:-}" +CURRENT_DIR=$(pwd) +BRANCH=$(git branch --show-current 2>/dev/null) +curl -X POST "$SLACK_WEBHOOK_URL" \ + -H "Content-type: application/json" \ + --data "{ + \"text\": \"✅ Deep Code 任务已完成\n · cwd: $CURRENT_DIR\n · Branch: $BRANCH\n · Duration: $DURATION 秒\" + }" +``` + +给脚本添加可执行权限: + +```bash +chmod +x ~/.deepcode/notify-slack.sh +``` + +### 3. 配置 settings.json + +```json +{ + "env": { + "SLACK_WEBHOOK_URL": "https://hooks.slack.com/services/*****/****/**********" + }, + "notify": "/Users/you/.deepcode/notify-slack.sh" +} +``` + +> Python 版本的脚本同样支持,你可以在 `env` 中传入并引用任意自定义环境变量。 + +## 飞书 / 企业微信等 Webhook 通知 + +以下示例使用 `node` 构建 JSON(自动转义特殊字符),`curl` 发送。通过 `env` 传入 `WEBHOOK_URL`: + +```bash +#!/bin/bash +WEBHOOK_URL="${WEBHOOK_URL:-}" + +STATUS="${STATUS:-completed}" +TITLE="${TITLE:-Untitled}" +DURATION="${DURATION:-0}" +BODY="${BODY:-(no output)}" + +PAYLOAD=$(node -e " +process.stdout.write(JSON.stringify({ + msg_type: 'interactive', + card: { + header: { title: { tag: 'plain_text', content: 'DeepCode: ' + process.env.TITLE + ' ' + process.env.STATUS + ' [' + process.env.DURATION + 's]' } }, + elements: [{ tag: 'markdown', content: (process.env.BODY || '').slice(0, 2000) || '(no output)' }] + } +})) +") + +curl -s -X POST "$WEBHOOK_URL" \ + -H "Content-Type: application/json" \ + -d "$PAYLOAD" +``` + +```json +{ + "env": { + "WEBHOOK_URL": "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxx" + }, + "notify": "/Users/you/.deepcode/notify-feishu.sh" +} +``` + +将 `WEBHOOK_URL` 替换为你的飞书机器人 Webhook 地址。此模式同样适用于 Slack、企业微信等 webhook 类通知,只需修改 JSON payload 格式。 + +## 终端通知(iTerm2 / Windows Terminal) + +如果你的终端是 iTerm2 或 Windows Terminal,可以直接通过 OSC 9 转义序列弹出终端原生通知,无需额外依赖。 + +创建 `~/.deepcode/notify.sh`: + +```bash +#!/bin/bash +# iTerm2 / Windows Terminal OSC 9 通知 +printf '\x1b]9;DeepCode: task %s (%ss)\x07' "${STATUS:-completed}" "${DURATION}" +``` + +```json +{ + "notify": "/Users/you/.deepcode/notify.sh" +} +``` + +Windows 用户如使用 Git Bash,上述脚本同样可用;也可创建 `.bat` 脚本: + +```batch +@echo off +REM Windows Terminal OSC 9 通知 +echo \x1b]9;DeepCode: task %STATUS% (%DURATION%s)\x07 +``` + +## macOS 系统通知 + +```bash +#!/bin/bash +# macOS 系统通知 +osascript -e "display notification \"任务已${STATUS:-完成},耗时 ${DURATION}s\" with title \"DeepCode\"" +``` + +```json +{ + "notify": "/Users/you/.deepcode/notify.sh" +} +``` + +## Linux 系统通知 + +需要安装 `libnotify-bin`: + +```bash +sudo apt install libnotify-bin # Debian/Ubuntu +``` + +创建 `~/.deepcode/notify.sh`: + +```bash +#!/bin/bash +# Linux notify-send 通知 +notify-send "DeepCode" "任务已${STATUS:-完成},耗时 ${DURATION}s" +``` + +```json +{ + "notify": "/home/you/.deepcode/notify.sh" +} +``` + +## Windows msg 弹窗通知 + +```batch +@echo off +REM Windows msg 弹窗通知 +msg %USERNAME% "DeepCode: task %STATUS% (%DURATION%s)" +``` + +```json +{ + "notify": "C:\\Users\\you\\.deepcode\\notify.bat" +} +``` + +## 自定义通知脚本 + +你可以根据通知脚本注入的环境变量自行编写任意逻辑的通知脚本(Python、Node.js、Ruby 等均可),只要脚本可执行即可。脚本中可通过 `env` 字段传入额外需要的配置变量。 diff --git a/templates/skills/bundled/deepcode-self-refer/references/notify_en.md b/templates/skills/bundled/deepcode-self-refer/references/notify_en.md new file mode 100644 index 00000000..b949161c --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/notify_en.md @@ -0,0 +1,211 @@ +# Deep Code Task Completion Notification + +When the AI assistant finishes a round of tasks, Deep Code can automatically execute a notification script to send task results to your chosen channel (Slack, system notifications, etc.). + +## How It Works + +Configure the `notify` field in `settings.json` with the full path to an executable script. Every time the AI assistant completes a task response, Deep Code executes that script and injects context as environment variables. + +## Injected Environment Variables + +| Variable | Description | +|----------|-------------| +| `DURATION` | Session duration in seconds (integer) | +| `STATUS` | Session status: `"completed"` or `"failed"` | +| `FAIL_REASON` | Failure reason (only set on failure) | +| `BODY` | The text content of the last AI assistant reply | +| `TITLE` | Session title (matches the resume list title) | + +## Configuration + +Edit `~/.deepcode/settings.json` and add the `notify` field: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-..." + }, + "thinkingEnabled": true, + "reasoningEffort": "max", + "notify": "/path/to/your-notify-script.sh" +} +``` + +You can also configure custom environment variables for the notify script in `env`, such as a Slack Webhook URL: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-...", + "SLACK_WEBHOOK_URL": "https://hooks.slack.com/services/*****/****/**********" + }, + "notify": "/Users/you/.deepcode/notify-slack.sh" +} +``` + +These `env` variables are injected into the script's execution environment. + +## Slack Notification + +### 1. Get a Slack Webhook URL + +1. Create a [Slack App](https://api.slack.com/apps) +2. In the App page, go to **Incoming Webhooks** → **Add New Webhook to Workspace** to generate a Webhook URL + +### 2. Create the Notification Script + +Create `~/.deepcode/notify-slack.sh`: + +```bash +#!/usr/bin/env bash +SLACK_WEBHOOK_URL="${SLACK_WEBHOOK_URL:-}" +CURRENT_DIR=$(pwd) +BRANCH=$(git branch --show-current 2>/dev/null) +curl -X POST "$SLACK_WEBHOOK_URL" \ + -H "Content-type: application/json" \ + --data "{ + \"text\": \"✅ Deep Code task completed\n · cwd: $CURRENT_DIR\n · Branch: $BRANCH\n · Duration: $DURATION s\" + }" +``` + +Make the script executable: + +```bash +chmod +x ~/.deepcode/notify-slack.sh +``` + +### 3. Configure settings.json + +```json +{ + "env": { + "SLACK_WEBHOOK_URL": "https://hooks.slack.com/services/*****/****/**********" + }, + "notify": "/Users/you/.deepcode/notify-slack.sh" +} +``` + +> A Python version is also supported; you can pass and reference any custom environment variables via `env`. + +## Feishu / WeCom Webhook Notification + +Use `node` to build JSON (auto-escapes special characters) and `curl` to send. Pass `WEBHOOK_URL` via `env`: + +```bash +#!/bin/bash +WEBHOOK_URL="${WEBHOOK_URL:-}" + +STATUS="${STATUS:-completed}" +TITLE="${TITLE:-Untitled}" +DURATION="${DURATION:-0}" +BODY="${BODY:-(no output)}" + +PAYLOAD=$(node -e " +process.stdout.write(JSON.stringify({ + msg_type: 'interactive', + card: { + header: { title: { tag: 'plain_text', content: 'DeepCode: ' + process.env.TITLE + ' ' + process.env.STATUS + ' [' + process.env.DURATION + 's]' } }, + elements: [{ tag: 'markdown', content: (process.env.BODY || '').slice(0, 2000) || '(no output)' }] + } +})) +") + +curl -s -X POST "$WEBHOOK_URL" \ + -H "Content-Type: application/json" \ + -d "$PAYLOAD" +``` + +```json +{ + "env": { + "WEBHOOK_URL": "https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxx" + }, + "notify": "/Users/you/.deepcode/notify-feishu.sh" +} +``` + +Replace `WEBHOOK_URL` with your Feishu bot webhook URL. This pattern also works for other webhook-based notifications (Slack, WeCom, etc.) — just adjust the JSON payload format. + +## Terminal Notification (iTerm2 / Windows Terminal) + +On iTerm2 or Windows Terminal, you can use the OSC 9 escape sequence for native terminal notifications with zero dependencies. + +Create `~/.deepcode/notify.sh`: + +```bash +#!/bin/bash +# iTerm2 / Windows Terminal OSC 9 notification +printf '\x1b]9;DeepCode: task %s (%ss)\x07' "${STATUS:-completed}" "${DURATION}" +``` + +```json +{ + "notify": "/Users/you/.deepcode/notify.sh" +} +``` + +Windows users on Git Bash can use the same script; alternatively, create a `.bat` script: + +```batch +@echo off +REM Windows Terminal OSC 9 notification +echo \x1b]9;DeepCode: task %STATUS% (%DURATION%s)\x07 +``` + +## macOS System Notification + +```bash +#!/bin/bash +# macOS system notification +osascript -e "display notification \"Task ${STATUS:-completed}, took ${DURATION}s\" with title \"DeepCode\"" +``` + +```json +{ + "notify": "/Users/you/.deepcode/notify.sh" +} +``` + +## Linux System Notification + +Requires `libnotify-bin`: + +```bash +sudo apt install libnotify-bin # Debian/Ubuntu +``` + +Create `~/.deepcode/notify.sh`: + +```bash +#!/bin/bash +# Linux notify-send notification +notify-send "DeepCode" "Task ${STATUS:-completed}, took ${DURATION}s" +``` + +```json +{ + "notify": "/home/you/.deepcode/notify.sh" +} +``` + +## Windows msg Popup Notification + +```batch +@echo off +REM Windows msg popup notification +msg %USERNAME% "DeepCode: task %STATUS% (%DURATION%s)" +``` + +```json +{ + "notify": "C:\\Users\\you\\.deepcode\\notify.bat" +} +``` + +## Custom Notification Scripts + +You can write your own notification scripts in any language (Python, Node.js, Ruby, etc.) using the injected environment variables and any additional variables passed via `env`. diff --git a/templates/skills/bundled/deepcode-self-refer/references/permission.md b/templates/skills/bundled/deepcode-self-refer/references/permission.md new file mode 100644 index 00000000..91c19c6f --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/permission.md @@ -0,0 +1,101 @@ +# Deep Code 权限机制 + +Deep Code 内置了一套细粒度的权限控制机制,在 AI 助手执行工具调用(如执行 Shell 命令、读写文件、访问网络等)前,根据用户配置的策略决定是自动放行、直接拒绝、还是弹出交互式确认。 + +## 概述 + +每次 AI 助手调用工具时,系统会自动分析该操作涉及的**权限范围(Permission Scope)**,然后根据 `settings.json` 中的权限配置做出决策。对于需要用户确认的操作,会在终端中弹出交互式选择界面,用户可以选择: + +- **Yes** — 仅本次放行 +- **Yes, and always allow** — 本次放行,并将该权限范围写入项目配置文件,后续同类操作不再询问 +- **No** — 拒绝本次操作 + +## 权限范围 + +Deep Code 定义了以下 10 种权限范围,覆盖了工具调用的各类风险场景: + +| 权限范围 | 说明 | +| -------- | ---- | +| `read-in-cwd` | 读取当前工作区内的文件 | +| `read-out-cwd` | 读取当前工作区外的文件 | +| `write-in-cwd` | 在当前工作区内创建或覆写文件 | +| `write-out-cwd` | 在当前工作区外创建或覆写文件 | +| `delete-in-cwd` | 删除当前工作区内的文件 | +| `delete-out-cwd` | 删除当前工作区外的文件 | +| `query-git-log` | 查询 Git 历史(如 `git log`、`git show`、`git blame`) | +| `mutate-git-log` | 修改 Git 历史(如 `git commit`、`git rebase`、`git tag`) | +| `network` | 访问网络(如 `curl`、`npm install` 等联网操作) | +| `mcp` | 调用 MCP 外部工具 | + +此外还有一个特殊的 `unknown` 范围,当 LLM 无法准确分类命令的副作用时使用,**`unknown` 总是触发询问**。 + +## 权限配置 + +在 `~/.deepcode/settings.json`(用户级)或 `.deepcode/settings.json`(项目级)中通过 `permissions` 字段配置: + +```json +{ + "permissions": { + "allow": [], + "deny": [], + "ask": [], + "defaultMode": "allowAll" + } +} +``` + +### 配置项说明 + +| 字段 | 类型 | 说明 | +| ---- | ---- | ---- | +| `allow` | `string[]` | 始终自动放行的权限范围列表 | +| `deny` | `string[]` | 始终自动拒绝的权限范围列表 | +| `ask` | `string[]` | 始终弹出询问的权限范围列表 | +| `defaultMode` | `"allowAll"` \| `"askAll"` | 未在 `allow`/`deny`/`ask` 中明确列出的权限范围的默认处理方式。默认为 `"allowAll"` | + +### 优先级规则 + +当一个工具调用涉及多个权限范围时,决策按以下优先级进行: + +1. 若任一范围命中 `deny` → **拒绝** +2. 若任一范围命中 `ask` → **询问** +3. 若所有范围均在 `allow` 中 → **自动放行** +4. 否则 → 按 `defaultMode` 处理 + +### 示例:宽松模式(默认) + +```json +{ + "permissions": { + "defaultMode": "allowAll" + } +} +``` + +默认行为:所有操作自动放行,无需确认。 + +### 示例:严格模式 + +```json +{ + "permissions": { + "allow": ["read-in-cwd", "write-in-cwd", "query-git-log"], + "defaultMode": "askAll" + } +} +``` + +此配置的效果: +- 工作区内读写、Git 查询 → 自动放行 +- 其他操作都需要用户确认。 + + +## 持久化机制 + +当用户在权限提示中选择 "Yes, and always allow" 后,对应的权限范围会被写入当前项目的 `.deepcode/settings.json` 文件中: + +- 新增范围会追加到 `permissions.allow` 列表 +- 如果该范围之前存在于 `deny` 或 `ask` 中,会被自动移除 +- 不会重复写入已存在的范围 + +这样后续同类操作就不再询问。 diff --git a/templates/skills/bundled/deepcode-self-refer/references/permission_en.md b/templates/skills/bundled/deepcode-self-refer/references/permission_en.md new file mode 100644 index 00000000..dae739c0 --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/permission_en.md @@ -0,0 +1,100 @@ +# Deep Code Permission Mechanism + +Deep Code includes a fine-grained permission control mechanism. Before the AI assistant executes a tool call (such as running a shell command, reading/writing files, accessing the network, etc.), the system determines whether to auto-allow, auto-deny, or prompt for interactive confirmation based on your configured policy. + +## Overview + +Each time the AI assistant invokes a tool, the system automatically analyzes the **permission scopes** involved and makes a decision based on the permission configuration in `settings.json`. For operations requiring user confirmation, an interactive prompt appears in the terminal with the following choices: + +- **Yes** — Allow this one time only +- **Yes, and always allow** — Allow this time and persistently save the scope to the project configuration so future calls skip the prompt +- **No** — Deny this operation + +## Permission Scopes + +Deep Code defines the following 10 permission scopes, covering various risk scenarios for tool calls: + +| Permission Scope | Description | +| ---------------- | ----------- | +| `read-in-cwd` | Read files inside the current workspace | +| `read-out-cwd` | Read files outside the current workspace | +| `write-in-cwd` | Create or overwrite files inside the current workspace | +| `write-out-cwd` | Create or overwrite files outside the current workspace | +| `delete-in-cwd` | Delete files inside the current workspace | +| `delete-out-cwd` | Delete files outside the current workspace | +| `query-git-log` | Query Git history (e.g., `git log`, `git show`, `git blame`) | +| `mutate-git-log` | Mutate Git history (e.g., `git commit`, `git rebase`, `git tag`) | +| `network` | Access the network (e.g., `curl`, `npm install`) | +| `mcp` | Invoke MCP external tools | + +There is also a special `unknown` scope used when the LLM cannot classify a command's side effects — **`unknown` always triggers a prompt**. + +## Permission Configuration + +Configure permissions in `~/.deepcode/settings.json` (user-level) or `.deepcode/settings.json` (project-level) via the `permissions` field: + +```json +{ + "permissions": { + "allow": [], + "deny": [], + "ask": [], + "defaultMode": "allowAll" + } +} +``` + +### Configuration Fields + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `allow` | `string[]` | Permission scopes that are always auto-allowed | +| `deny` | `string[]` | Permission scopes that are always auto-denied | +| `ask` | `string[]` | Permission scopes that always trigger a confirmation prompt | +| `defaultMode` | `"allowAll"` \| `"askAll"` | Default behavior for scopes not explicitly listed in `allow`/`deny`/`ask`. Defaults to `"allowAll"` | + +### Priority Rules + +When a tool call involves multiple permission scopes, the decision follows this priority: + +1. If any scope matches `deny` → **Deny** +2. If any scope matches `ask` → **Prompt** +3. If all scopes are in `allow` → **Auto-allow** +4. Otherwise → use `defaultMode` + +### Example: Relaxed Mode (default) + +```json +{ + "permissions": { + "defaultMode": "allowAll" + } +} +``` + +Default behavior: all operations are auto-allowed with no confirmation required. + +### Example: Strict Mode + +```json +{ + "permissions": { + "allow": ["read-in-cwd", "write-in-cwd", "query-git-log"], + "defaultMode": "askAll" + } +} +``` + +With this configuration: +- Reading/writing inside the workspace and querying Git history → auto-allowed +- All other operations → require user confirmation + +## Persistence + +When you select "Yes, and always allow" in a permission prompt, the corresponding scope is written to the project's `.deepcode/settings.json`: + +- The scope is appended to the `permissions.allow` list +- If the scope was previously in `deny` or `ask`, it is automatically removed +- Duplicate scopes are not written again + +This means subsequent calls involving the same scope will no longer prompt for confirmation. diff --git a/templates/skills/bundled/deepcode-self-refer/references/session-persistence.md b/templates/skills/bundled/deepcode-self-refer/references/session-persistence.md new file mode 100644 index 00000000..835d2881 --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/session-persistence.md @@ -0,0 +1,139 @@ +# 会话持久化机制 + +Deep Code 会把每个项目的会话记录保存在本机用户目录中。会话历史用于 `/resume`、`/continue` 和 `/undo`,不依赖当前终端进程是否仍在运行。 + +## 存储位置 + +每个项目都有独立的存储目录: + +```text +~/.deepcode/projects// +``` + +`` 由项目根目录路径生成。普通路径会转换为安全的目录名;路径过长时,Deep Code 会保留项目名的一部分,并追加稳定哈希,以避免存储路径过长。 + +项目存储目录包含以下主要文件和目录: + +| 路径 | 说明 | +| ---- | ---- | +| `sessions-index.json` | 当前项目的会话索引,保存会话列表和每个会话的概要信息。 | +| `.jsonl` | 单个会话的消息记录。每一行是一条 JSON 格式的消息。 | +| `file-history/.git` | 用于代码快照的内部 Git 仓库,供 `/undo` 恢复文件内容。 | + +## 持久化内容 + +### 会话索引 + +`sessions-index.json` 保存最近的会话条目。每个条目包含: + +- 会话 ID、标题、创建时间和更新时间。 +- 会话状态,例如 `pending`、`processing`、`completed`、`failed`、`interrupted`、`ask_permission`、`waiting_for_user`。 +- 最近一次 assistant 回复、思考内容、拒绝原因和失败原因。 +- 最近一次工具调用信息、token 用量和活跃 token 数。 +- 当前会话中仍被跟踪的子进程信息。 + +会话标题默认来自首次用户输入的前 100 个字符。使用会话列表中的重命名功能会更新索引里的标题。 + +### 消息文件 + +每个会话有一个独立的 JSONL 消息文件,文件名是 `.jsonl`。消息按追加顺序写入,常见字段包括: + +| 字段 | 说明 | +| ---- | ---- | +| `id` | 消息 ID。 | +| `sessionId` | 所属会话 ID。 | +| `role` | 消息角色:`system`、`user`、`assistant` 或 `tool`。 | +| `content` | 文本内容。 | +| `contentParams` | 结构化内容,例如图片输入。 | +| `messageParams` | 模型消息参数,例如 tool call ID、tool calls、reasoning content。 | +| `visible` | 是否在界面中显示。 | +| `compacted` | 是否已经被长会话压缩替代。 | +| `checkpointHash` | 与 `/undo` 关联的代码快照哈希。 | +| `meta` | 工具展示、skill、权限、摘要等附加信息。 | + +读取消息文件时,Deep Code 会逐行解析 JSON;无法解析的行会被忽略,以便尽量保留其余可用历史。 + +### 代码快照 + +Deep Code 使用 `file-history/.git` 保存代码快照。这个仓库只作为内部文件历史使用,不是项目仓库本身。 + +- 新会话会初始化一条以会话 ID 命名的内部分支。 +- 每次用户输入前,会记录已跟踪文件的状态。 +- 工具修改文件前后,会按需记录相关文件的状态。 +- 用户消息上的 `checkpointHash` 用来把某次对话位置和对应的代码状态关联起来。 + +快照只覆盖 Deep Code 已跟踪到的文件;无关文件不会因为 `/undo` 被任意改写。 + +## 会话生命周期 + +### 创建会话 + +创建新会话时,Deep Code 会: + +1. 生成新的会话 ID。 +2. 初始化该会话的代码快照分支。 +3. 在 `sessions-index.json` 中添加会话条目。 +4. 写入系统提示、运行时上下文、项目指令和用户消息。 +5. 启动模型请求,并在 assistant 回复和工具执行过程中持续更新索引和消息文件。 + +项目级会话列表最多保留最近 50 条记录。超过上限时,较旧会话会从索引中移除,其消息文件和相关运行时资源也会被清理。 + +### 继续会话 + +`/resume` 会显示当前项目的历史会话列表,并选择一个会话继续。 + +`/continue` 会优先继续当前活动会话;如果没有可继续的活动会话,则进入历史会话选择流程。 + +继续会话时,Deep Code 会读取会话消息文件,过滤已压缩的旧消息,修复未完成的工具调用上下文,并把可用历史转换为模型请求消息。 + +### 长会话压缩 + +当会话上下文过长时,Deep Code 会触发压缩流程: + +- 选取较早的一段非系统消息生成摘要。 +- 将这段旧消息标记为 `compacted: true`。 +- 在消息序列中插入一条不可见的系统摘要消息。 + +后续请求只会使用未压缩消息和摘要消息。原始消息仍保留在 JSONL 文件中,用于审计和界面历史展示。 + +### 中断、失败和权限等待 + +会话状态会随运行过程更新: + +- 用户中断后,状态会变为 `interrupted`,并清理当前会话控制器和被跟踪的子进程。 +- 请求失败时,状态会变为 `failed`,失败原因写入索引。 +- 工具调用需要确认时,状态会变为 `ask_permission`。 +- 工具需要用户输入时,状态会变为 `waiting_for_user`。 + +这些状态都会持久化到 `sessions-index.json`,因此重新打开 CLI 后仍能在会话列表中看到。 + +## `/undo` 如何使用持久化数据 + +`/undo` 的候选项来自可见且未压缩的用户消息。每个候选项会检查是否有关联的 `checkpointHash`,并确认对应快照是否可恢复。 + +根据选择,Deep Code 可以执行以下操作: + +| 操作 | 行为 | +| ---- | ---- | +| 恢复对话 | 截断所选用户消息之前的消息历史,并更新索引中的最新 assistant 信息。 | +| 恢复代码 | 从 `file-history/.git` 中读取所选快照,并还原被跟踪文件。 | +| 同时恢复 | 先恢复代码,再截断对话历史。 | + +恢复对话会重写该会话的 JSONL 文件;恢复代码会修改工作区中被快照跟踪的文件。 + +## 删除和重命名 + +在会话列表中删除会话会: + +- 从 `sessions-index.json` 移除该条目。 +- 删除对应的 `.jsonl` 文件。 +- 清理该会话的内存状态、临时工作目录状态、控制器和仍被跟踪的进程控制信息。 + +重命名会话只更新索引中的 `summary` 字段,不会改动消息文件或代码快照。 + +## 注意事项 + +- 会话数据保存在本机用户目录下,并按项目分隔。 +- 移动项目目录后,新的项目根路径会生成新的 ``;旧路径对应的历史不会自动迁移。 +- `file-history/.git` 是 Deep Code 的内部快照仓库,不应手动修改。 +- 会话删除不会清理内部 Git 仓库中的所有历史对象;它主要删除会话索引、消息文件和运行时资源。 diff --git a/templates/skills/bundled/deepcode-self-refer/references/session-persistence_en.md b/templates/skills/bundled/deepcode-self-refer/references/session-persistence_en.md new file mode 100644 index 00000000..071a5353 --- /dev/null +++ b/templates/skills/bundled/deepcode-self-refer/references/session-persistence_en.md @@ -0,0 +1,139 @@ +# Session Persistence + +Deep Code stores per-project session history in the local user directory. This history powers `/resume`, `/continue`, and `/undo`, and it remains available after the current terminal process exits. + +## Storage Location + +Each project has its own storage directory: + +```text +~/.deepcode/projects// +``` + +`` is generated from the project root path. Normal paths are converted into safe directory names. When the path would be too long, Deep Code keeps part of the project name and appends a stable hash so the storage path stays safe. + +The project storage directory contains these main files and directories: + +| Path | Description | +| ---- | ----------- | +| `sessions-index.json` | Session index for the current project, including the session list and summary metadata. | +| `.jsonl` | Message log for one session. Each line is one JSON message. | +| `file-history/.git` | Internal Git repository used for code checkpoints restored by `/undo`. | + +## Persisted Data + +### Session Index + +`sessions-index.json` stores recent session entries. Each entry includes: + +- Session ID, title, creation time, and update time. +- Session status, such as `pending`, `processing`, `completed`, `failed`, `interrupted`, `ask_permission`, or `waiting_for_user`. +- Latest assistant reply, thinking content, refusal reason, and failure reason. +- Latest tool-call data, token usage, and active token count. +- Metadata for subprocesses still tracked by the session. + +The default session title comes from the first 100 characters of the first user prompt. Renaming a session from the session list updates the title in the index. + +### Message Files + +Each session has a separate JSONL message file named `.jsonl`. Messages are appended in order. Common fields include: + +| Field | Description | +| ----- | ----------- | +| `id` | Message ID. | +| `sessionId` | Owning session ID. | +| `role` | Message role: `system`, `user`, `assistant`, or `tool`. | +| `content` | Text content. | +| `contentParams` | Structured content, such as image input. | +| `messageParams` | Model message parameters, such as tool call IDs, tool calls, and reasoning content. | +| `visible` | Whether the message is shown in the UI. | +| `compacted` | Whether the message has been replaced by long-session compaction. | +| `checkpointHash` | Code checkpoint hash associated with `/undo`. | +| `meta` | Extra metadata for tool display, skills, permissions, summaries, and related features. | + +When loading a message file, Deep Code parses JSON one line at a time. Malformed lines are ignored so the remaining usable history can still be loaded. + +### Code Checkpoints + +Deep Code stores code checkpoints in `file-history/.git`. This repository is only internal file history; it is not the project Git repository. + +- A new session initializes an internal branch named after the session ID. +- Before each user prompt, Deep Code records the state of files it already tracks. +- Before and after tool-based file mutations, Deep Code records the relevant file state as needed. +- `checkpointHash` on user messages links a conversation position to a code state. + +Checkpoints only cover files Deep Code has tracked. Unrelated files are not arbitrarily rewritten by `/undo`. + +## Session Lifecycle + +### Creating A Session + +When creating a new session, Deep Code: + +1. Generates a new session ID. +2. Initializes the code checkpoint branch for that session. +3. Adds an entry to `sessions-index.json`. +4. Writes system prompts, runtime context, project instructions, and the user message. +5. Starts the model request and keeps updating the index and message file as assistant replies and tool executions complete. + +The per-project session list keeps the 50 most recent entries. When the limit is exceeded, older sessions are removed from the index, and their message files and related runtime resources are cleaned up. + +### Continuing A Session + +`/resume` shows the current project's session history and lets you select a session to continue. + +`/continue` first continues the active session. If there is no active session to continue, it opens the session selection flow. + +When continuing a session, Deep Code reads the message file, filters compacted old messages, repairs incomplete tool-call context, and converts the usable history into model request messages. + +### Long-Session Compaction + +When the conversation context grows too large, Deep Code can compact earlier messages: + +- It summarizes an older range of non-system messages. +- It marks those old messages as `compacted: true`. +- It inserts an invisible system summary message into the message sequence. + +Future requests use the remaining active messages and the summary message. The original messages stay in the JSONL file for auditability and UI history. + +### Interruptions, Failures, And Permission Waits + +Session status changes during execution: + +- After a user interruption, status becomes `interrupted`, and Deep Code clears the current session controller and tracked subprocesses. +- After a request failure, status becomes `failed`, and the failure reason is written to the index. +- When a tool call needs confirmation, status becomes `ask_permission`. +- When a tool needs user input, status becomes `waiting_for_user`. + +These states are persisted in `sessions-index.json`, so they remain visible in the session list after reopening the CLI. + +## How `/undo` Uses Persistent Data + +`/undo` candidates come from visible, non-compacted user messages. Each candidate is checked for an associated `checkpointHash`, and Deep Code verifies whether the checkpoint can be restored. + +Depending on the selected mode, Deep Code can perform these operations: + +| Operation | Behavior | +| --------- | -------- | +| Restore conversation | Truncates message history before the selected user message and updates the latest assistant data in the index. | +| Restore code | Reads the selected checkpoint from `file-history/.git` and restores tracked files. | +| Restore both | Restores code first, then truncates the conversation history. | + +Restoring conversation rewrites the session JSONL file. Restoring code modifies workspace files tracked by the selected checkpoint. + +## Delete And Rename + +Deleting a session from the session list: + +- Removes the entry from `sessions-index.json`. +- Deletes the matching `.jsonl` file. +- Clears in-memory state, temporary working-directory state, controllers, and tracked process controls for that session. + +Renaming a session only updates the `summary` field in the index. It does not change message files or code checkpoints. + +## Notes + +- Session data is stored in the local user directory and separated by project. +- If a project directory is moved, the new project root path generates a new ``; history for the old path is not migrated automatically. +- `file-history/.git` is Deep Code's internal checkpoint repository and should not be edited manually. +- Deleting a session does not remove every historical object from the internal Git repository. It mainly removes the session index entry, message file, and runtime resources. diff --git a/templates/skills/bundled/skill-digester/SKILL.md b/templates/skills/bundled/skill-digester/SKILL.md new file mode 100644 index 00000000..6e9016d1 --- /dev/null +++ b/templates/skills/bundled/skill-digester/SKILL.md @@ -0,0 +1,115 @@ +--- +name: skill-digester +description: Reviews and improves another DeepCode skill's SKILL.md description field against the Agent Skills description-field rules. Use when the user asks to "digest" a skill, including requests like "digest the pdf skill" or "消化 pdf 技能". +--- + +# Skill Digester + +Use this skill to review and optionally rewrite the `description` field of another DeepCode skill. + +## Interaction Rule + +Whenever user input is needed, call the `AskUserQuestion` tool. Do not ask follow-up questions as plain assistant text. This includes missing skill names, language preference, duplicate matches, malformed frontmatter decisions, and whether to apply a recommended rewrite. + +## Workflow + +1. Identify the target skill from the user's request. + - If the user did not provide a skill name, use `AskUserQuestion` to ask for one. + - Locate the skill by running the bundled Node script from this skill directory: + + ```bash + node ~/.deepcode/skills/skill-digester/scripts/find-skill.js "" "" + ``` + + If this skill is loaded from a project-level or different user-level path, use the `scripts/find-skill.js` file next to this `SKILL.md` instead. + - The script searches the same roots Deep Code CLI scans, in priority order: + 1. Project native skills: `./.deepcode/skills//SKILL.md` + 2. Project interoperable skills: `./.agents/skills//SKILL.md` + 3. User native skills: `~/.deepcode/skills//SKILL.md` + 4. User interoperable skills: `~/.agents/skills//SKILL.md` + - Treat `./` as the current Deep Code project root only; do not scan parent directories unless the running project root is changed. + - The script resolves each candidate's skill name the way Deep Code does: use the trimmed frontmatter `name` when present, otherwise use the folder name with underscores converted to hyphens. + - Match the user's input against the resolved skill name first. If needed, also consider the folder name or an explicit path the user provided. + - Treat the matched skill's `path` as the source `SKILL.md` to review. + - Treat the matched skill's `digestTarget.path` as the only output `SKILL.md` path to create or edit. + - `digestTarget.path` always points to the same scope's native Deep Code root: + - Project sources from `./.deepcode/skills` or `./.agents/skills` digest to `./.deepcode/skills//SKILL.md`. + - User sources from `~/.deepcode/skills` or `~/.agents/skills` digest to `~/.deepcode/skills//SKILL.md`. + - If the script returns one active match, use its `path` for reading and `digestTarget.path` for writing. + - If the script returns active and shadowed matches, present each source path and digest target path, then use `AskUserQuestion` before using a shadowed source. + - If the script returns no match, state that the skill was not found in Deep Code's scanned skill roots and use `AskUserQuestion` to ask whether the user wants to try another name. + +2. Infer the user's preferred language before reviewing. + - Infer a likely language from the user's wording. For example, if the user says `消化pdf技能`, infer Chinese. + - Confirm the language with `AskUserQuestion` in the inferred language. For Chinese, ask: `请选择您偏好的语言。` + - Offer the inferred language first and include `English` as a fallback. The UI provides an `Other` option, so the user can type a different language. + - Use the confirmed preferred language for every later question, recommendation, and rewritten `description` field. + +3. Read the source `SKILL.md`. + - Parse the YAML frontmatter and Markdown body from the matched source path. + - Preserve all frontmatter fields and body content except for the `description` field if the user approves a rewrite. + - If frontmatter is missing or malformed, explain the issue and use `AskUserQuestion` before making structural repairs. + +4. Review the current `description` field against the Agent Skills specification. + - Required constraints: + - It must be non-empty. + - It must be 1-1024 characters. + - It should describe what the skill does. + - It should describe when to use the skill. + - It should include specific keywords that help agents identify relevant tasks. + - Compare the description with the actual `SKILL.md` body. Flag mismatches, missing capabilities, overbroad activation language, vague wording, or important trigger keywords that are absent. + - Do not rewrite for style alone if the existing description is accurate, specific, and useful. + +5. Present the review and recommendation. + - If the description is already good, say so and do not change the file unless the user asks. + - If improvements are useful, show: + - The current description. + - Concise review findings. + - A recommended replacement written in the preferred language. + - The source path being reviewed. + - The digest output path that would be created or edited. + - Use `AskUserQuestion` to ask the user to choose one of three actions in the preferred language: + - Apply the recommended change. + - Abandon the change. + - Continue discussing the wording. + +6. Apply the change only after explicit approval. + - Write only to `digestTarget.path`; never write the digested result to `.agents/skills`. + - If `digestTarget.sameAsSource` is true, update only the `description` field in that existing native `SKILL.md`. + - If `digestTarget.sameAsSource` is false and `digestTarget.exists` is false, create the native target skill directory by copying the source skill directory first, then update only the target `SKILL.md` description. This preserves bundled scripts, references, and assets. + - If `digestTarget.sameAsSource` is false and `digestTarget.exists` is true, update only the `description` field in the existing native target `SKILL.md`; do not overwrite its body or bundled files unless the user explicitly asks. + - Keep the original `name` and any other frontmatter fields unchanged in the file being written. + - Preserve body content exactly unless the user separately asks to edit it. + - After editing, report the source path, updated digest output path, and final description. + +## AskUserQuestion Patterns + +Use one question at a time unless two decisions are tightly coupled. Each question must include `options`; rely on the UI's `Other` option for free-form input. + +Examples: + +```json +{"questions":[{"question":"请选择您偏好的语言。","options":[{"label":"中文","description":"后续询问和推荐描述都使用中文。"},{"label":"English","description":"Use English for follow-up questions and the recommended description."}]}]} +``` + +```json +{"questions":[{"question":"How should I proceed with this description recommendation?","options":[{"label":"Apply change","description":"Update only the description field in the native digest output SKILL.md."},{"label":"Abandon change","description":"Leave the file unchanged."},{"label":"Discuss wording","description":"Continue refining the proposed description before editing."}]}]} +``` + +## Review Heuristics + +A strong description is short, concrete, and activation-oriented. Prefer this pattern: + +```text +. Use when . +``` + +Avoid descriptions that are only generic labels, marketing copy, or internal implementation notes. + +## Safety Notes + +- Never modify a different skill with a similar name without asking. +- Never save the digested output under `.agents/skills`; `.agents/skills` is only a source root for digestion. +- Never move a skill between project and user level during digestion. +- Never change the target skill's language preference after confirmation unless the user asks. + diff --git a/templates/skills/bundled/skill-digester/scripts/find-skill.js b/templates/skills/bundled/skill-digester/scripts/find-skill.js new file mode 100755 index 00000000..2067e023 --- /dev/null +++ b/templates/skills/bundled/skill-digester/scripts/find-skill.js @@ -0,0 +1,215 @@ +#!/usr/bin/env node +/* global __dirname, console, process, require */ + +const fs = require("fs"); +const os = require("os"); +const path = require("path"); + +function usage() { + return "Usage: node scripts/find-skill.js [project-root]"; +} + +function loadMatter() { + for (const base of [process.cwd(), __dirname]) { + try { + const resolved = require.resolve("gray-matter", { paths: [base] }); + return require(resolved); + } catch { + // Try the next lookup base, then fall back to the local parser. + } + } + return null; +} + +function parseFrontmatter(content) { + const matter = loadMatter(); + if (matter) { + try { + return matter(content).data || {}; + } catch { + // Fall back to the minimal frontmatter parser below. + } + } + + if (!content.startsWith("---\n") && !content.startsWith("---\r\n")) { + return {}; + } + const newline = content.startsWith("---\r\n") ? "\r\n" : "\n"; + const end = content.indexOf(`${newline}---${newline}`, 4); + if (end === -1) { + return {}; + } + const raw = content.slice(4, end).split(/\r?\n/); + const data = {}; + for (const line of raw) { + const match = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/); + if (!match) continue; + let value = match[2].trim(); + if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { + value = value.slice(1, -1); + } + data[match[1]] = value; + } + return data; +} + +function readSkillInfo(skillPath, displayPath, folderName) { + const fallbackName = folderName.replace(/_/g, "-"); + try { + const content = fs.readFileSync(skillPath, "utf8"); + const data = parseFrontmatter(content); + const name = typeof data.name === "string" && data.name.trim() ? data.name.trim() : fallbackName; + const description = typeof data.description === "string" ? data.description.trim() : ""; + return { name, folderName, path: skillPath, displayPath, description }; + } catch (error) { + return { name: fallbackName, folderName, path: skillPath, displayPath, description: "", error: error.message }; + } +} + +function isSkillFile(candidatePath) { + try { + return fs.statSync(candidatePath).isFile(); + } catch { + return false; + } +} + +function collect(rootInfo) { + let entries; + try { + entries = fs.readdirSync(rootInfo.root, { withFileTypes: true }); + } catch { + return []; + } + + const skills = []; + for (const entry of entries) { + if (!entry.isDirectory() && !entry.isSymbolicLink()) continue; + const folderName = entry.name; + const skillPath = path.join(rootInfo.root, folderName, "SKILL.md"); + if (!isSkillFile(skillPath)) continue; + const skill = readSkillInfo(skillPath, `${rootInfo.displayRoot}/${folderName}/SKILL.md`, folderName); + const digestTargetPath = path.join(rootInfo.digestRoot, folderName, "SKILL.md"); + skill.digestTarget = { + path: digestTargetPath, + displayPath: `${rootInfo.digestDisplayRoot}/${folderName}/SKILL.md`, + root: rootInfo.digestDisplayRoot, + exists: isSkillFile(digestTargetPath), + sameAsSource: path.resolve(digestTargetPath) === path.resolve(skillPath), + }; + skills.push(skill); + } + return skills; +} + +function expandInputPath(input, projectRoot) { + if (input.startsWith("~/")) return path.join(os.homedir(), input.slice(2)); + if (input.startsWith("~\\")) return path.join(os.homedir(), input.slice(2)); + if (input.startsWith("./")) return path.join(projectRoot, input.slice(2)); + if (input.startsWith(".\\")) return path.join(projectRoot, input.slice(2)); + if (path.isAbsolute(input)) return input; + return null; +} + +function main() { + const query = process.argv[2]; + const projectRoot = process.argv[3] ? path.resolve(process.argv[3]) : process.cwd(); + if (!query) { + console.error(usage()); + process.exit(2); + } + + const projectNativeRoot = path.join(projectRoot, ".deepcode", "skills"); + const userNativeRoot = path.join(os.homedir(), ".deepcode", "skills"); + const roots = [ + { + root: projectNativeRoot, + displayRoot: "./.deepcode/skills", + scope: "project", + kind: "native", + digestRoot: projectNativeRoot, + digestDisplayRoot: "./.deepcode/skills", + }, + { + root: path.join(projectRoot, ".agents", "skills"), + displayRoot: "./.agents/skills", + scope: "project", + kind: "interoperable", + digestRoot: projectNativeRoot, + digestDisplayRoot: "./.deepcode/skills", + }, + { + root: userNativeRoot, + displayRoot: "~/.deepcode/skills", + scope: "user", + kind: "native", + digestRoot: userNativeRoot, + digestDisplayRoot: "~/.deepcode/skills", + }, + { + root: path.join(os.homedir(), ".agents", "skills"), + displayRoot: "~/.agents/skills", + scope: "user", + kind: "interoperable", + digestRoot: userNativeRoot, + digestDisplayRoot: "~/.deepcode/skills", + }, + ]; + + const scanned = []; + for (const rootInfo of roots) { + for (const skill of collect(rootInfo)) { + scanned.push({ ...skill, root: rootInfo.displayRoot, scope: rootInfo.scope, kind: rootInfo.kind }); + } + } + + const activeByName = new Map(); + const shadowed = []; + for (const skill of scanned) { + if (activeByName.has(skill.name)) { + shadowed.push({ ...skill, shadowedBy: activeByName.get(skill.name).displayPath }); + } else { + activeByName.set(skill.name, skill); + } + } + + const inputPath = expandInputPath(query, projectRoot); + const matches = []; + for (const skill of scanned) { + if (skill.name === query || skill.folderName === query) { + matches.push(skill); + continue; + } + if (inputPath) { + const normalized = path.resolve(inputPath); + if (path.resolve(skill.path) === normalized || path.resolve(path.dirname(skill.path)) === normalized) { + matches.push(skill); + } + } + } + + const activeMatches = matches.filter((skill) => activeByName.get(skill.name)?.path === skill.path); + const shadowedMatches = matches.filter((skill) => activeByName.get(skill.name)?.path !== skill.path); + + process.stdout.write( + JSON.stringify( + { + query, + projectRoot, + roots, + found: matches.length > 0, + activeMatches, + shadowedMatches: shadowedMatches.map((skill) => ({ + ...skill, + shadowedBy: activeByName.get(skill.name)?.displayPath, + })), + duplicateNames: shadowed, + }, + null, + 2 + ) + ); + process.stdout.write("\n"); +} + +main(); diff --git a/templates/skills/bundled/skill-writer/SKILL.md b/templates/skills/bundled/skill-writer/SKILL.md new file mode 100644 index 00000000..e30bfdfc --- /dev/null +++ b/templates/skills/bundled/skill-writer/SKILL.md @@ -0,0 +1,381 @@ +--- +name: skill-writer +description: Guide users through creating, updating, debugging, and validating Agent Skills for AI agents. Use when the user wants to create, write, author, design, troubleshoot, validate, or improve a Skill, or needs help with SKILL.md files, frontmatter, or skill structure. +--- + +# Skill Writer + +This Skill helps you create well-structured Agent Skills for AI agents that follow best practices and validation requirements. + +## When to use this Skill + +Use this Skill when: +- Creating a new Agent Skill +- Writing or updating SKILL.md files +- Designing skill structure and frontmatter +- Troubleshooting skill discovery issues +- Converting existing prompts or workflows into Skills + +## Instructions + +### Step 1: Determine Skill scope + +First, understand what the Skill should do: + +1. **Ask clarifying questions**: + - What specific capability should this Skill provide? + - When should AI agents use this Skill? + - What tools or resources does it need? + - Is this for personal use or team sharing? + +2. **Keep it focused**: One Skill = one capability + - Good: "PDF form filling", "Excel data analysis" + - Too broad: "Document processing", "Data tools" + +### Step 2: Choose Skill location + +Determine where to create the Skill: + +**Personal Skills** (`~/.agents/skills/`): +- Individual workflows and preferences +- Experimental Skills +- Personal productivity tools + +**Project Skills** (`.agents/skills/`): +- Team workflows and conventions +- Project-specific expertise +- Shared utilities (committed to git) + +### Step 3: Create Skill structure + +Create the directory and files: + +```bash +# Personal +mkdir -p ~/.agents/skills/skill-name + +# Project +mkdir -p .agents/skills/skill-name +``` + +For multi-file Skills: +``` +skill-name/ +├── SKILL.md (required) +├── reference.md (optional) +├── examples.md (optional) +├── scripts/ +│ └── helper.py (optional) +└── templates/ + └── template.txt (optional) +``` + +### Step 4: Write SKILL.md frontmatter + +Create YAML frontmatter with required fields: + +```yaml +--- +name: skill-name +description: Brief description of what this does and when to use it +--- +``` + +**Field requirements**: + +- **name**: + - Lowercase letters, numbers, hyphens only + - Max 64 characters + - Must match directory name + - Good: `pdf-processor`, `git-commit-helper` + - Bad: `PDF_Processor`, `Git Commits!` + +- **description**: + - Max 1024 characters + - Include BOTH what it does AND when to use it + - Use specific trigger words users would say + - Mention file types, operations, and context + +**Optional frontmatter fields**: + +- **allowed-tools**: Restrict tool access (comma-separated list) + ```yaml + allowed-tools: read + ``` + Use for: + - Read-only Skills + - Security-sensitive workflows + - Limited-scope operations + +### Step 5: Write effective descriptions + +The description is critical for AI agents to discover your Skill. + +**Formula**: `[What it does] + [When to use it] + [Key triggers]` + +**Examples**: + +✅ **Good**: +```yaml +description: Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction. +``` + +✅ **Good**: +```yaml +description: Analyze Excel spreadsheets, create pivot tables, and generate charts. Use when working with Excel files, spreadsheets, or analyzing tabular data in .xlsx format. +``` + +❌ **Too vague**: +```yaml +description: Helps with documents +description: For data analysis +``` + +**Tips**: +- Include specific file extensions (.pdf, .xlsx, .json) +- Mention common user phrases ("analyze", "extract", "generate") +- List concrete operations (not generic verbs) +- Add context clues ("Use when...", "For...") + +### Step 6: Structure the Skill content + +Use clear Markdown sections: + +```markdown +# Skill Name + +Brief overview of what this Skill does. + +## Quick start + +Provide a simple example to get started immediately. + +## Instructions + +Step-by-step guidance for AI agents: +1. First step with clear action +2. Second step with expected outcome +3. Handle edge cases + +## Examples + +Show concrete usage examples with code or commands. + +## Best practices + +- Key conventions to follow +- Common pitfalls to avoid +- When to use vs. not use + +## Requirements + +List any dependencies or prerequisites: +```bash +pip install package-name +``` + +## Advanced usage + +For complex scenarios, see [reference.md](reference.md). +``` + +### Step 7: Add supporting files (optional) + +Create additional files for progressive disclosure: + +**reference.md**: Detailed API docs, advanced options +**examples.md**: Extended examples and use cases +**scripts/**: Helper scripts and utilities +**templates/**: File templates or boilerplate + +Reference them from SKILL.md: +```markdown +For advanced usage, see [reference.md](reference.md). + +Run the helper script: +\`\`\`bash +python scripts/helper.py input.txt +\`\`\` +``` + +### Step 8: Validate the Skill + +Check these requirements: + +✅ **File structure**: +- [ ] SKILL.md exists in correct location +- [ ] Directory name matches frontmatter `name` + +✅ **YAML frontmatter**: +- [ ] Opening `---` on line 1 +- [ ] Closing `---` before content +- [ ] Valid YAML (no tabs, correct indentation) +- [ ] `name` follows naming rules +- [ ] `description` is specific and < 1024 chars + +✅ **Content quality**: +- [ ] Clear instructions for AI agents +- [ ] Concrete examples provided +- [ ] Edge cases handled +- [ ] Dependencies listed (if any) + +✅ **Testing**: +- [ ] Description matches user questions +- [ ] Skill activates on relevant queries +- [ ] Instructions are clear and actionable + +### Step 9: Test the Skill + +1. **Restart AI agents** (if running) to load the Skill + +2. **Ask relevant questions** that match the description: + ``` + Can you help me extract text from this PDF? + ``` + +3. **Verify activation**: AI agents should use the Skill automatically + +4. **Check behavior**: Confirm AI agents follows the instructions correctly + +### Step 10: Debug if needed + +If AI agents doesn't use the Skill: + +1. **Make description more specific**: + - Add trigger words + - Include file types + - Mention common user phrases + +2. **Check file location**: + ```bash + ls ~/.agents/skills/skill-name/SKILL.md + ls .agents/skills/skill-name/SKILL.md + ``` + +3. **Validate YAML**: + ```bash + cat SKILL.md | head -n 10 + ``` + +## Common patterns + +### Read-only Skill + +```yaml +--- +name: code-reader +description: Read and analyze code without making changes. Use for code review, understanding codebases, or documentation. +allowed-tools: read +--- +``` + +### Script-based Skill + +```yaml +--- +name: data-processor +description: Process CSV and JSON data files with Python scripts. Use when analyzing data files or transforming datasets. +--- + +# Data Processor + +## Instructions + +1. Use the processing script: +\`\`\`bash +python scripts/process.py input.csv --output results.json +\`\`\` + +2. Validate output with: +\`\`\`bash +python scripts/validate.py results.json +\`\`\` +``` + +### Multi-file Skill with progressive disclosure + +```yaml +--- +name: api-designer +description: Design REST APIs following best practices. Use when creating API endpoints, designing routes, or planning API architecture. +--- + +# API Designer + +Quick start: See [examples.md](examples.md) + +Detailed reference: See [reference.md](reference.md) + +## Instructions + +1. Gather requirements +2. Design endpoints (see examples.md) +3. Document with OpenAPI spec +4. Review against best practices (see reference.md) +``` + +## Best practices for Skill authors + +1. **One Skill, one purpose**: Don't create mega-Skills +2. **Specific descriptions**: Include trigger words users will say +3. **Clear instructions**: Write for AI agents, not humans +4. **Concrete examples**: Show real code, not pseudocode +5. **List dependencies**: Mention required packages in description +6. **Test with teammates**: Verify activation and clarity +7. **Version your Skills**: Document changes in content +8. **Use progressive disclosure**: Put advanced details in separate files + +## Validation checklist + +Before finalizing a Skill, verify: + +- [ ] Name is lowercase, hyphens only, max 64 chars +- [ ] Description is specific and < 1024 chars +- [ ] Description includes "what" and "when" +- [ ] YAML frontmatter is valid +- [ ] Instructions are step-by-step +- [ ] Examples are concrete and realistic +- [ ] Dependencies are documented +- [ ] File paths use forward slashes +- [ ] Skill activates on relevant queries +- [ ] AI agents follows instructions correctly + +## Troubleshooting + +**Skill doesn't activate**: +- Make description more specific with trigger words +- Include file types and operations in description +- Add "Use when..." clause with user phrases + +**Multiple Skills conflict**: +- Make descriptions more distinct +- Use different trigger words +- Narrow the scope of each Skill + +**Skill has errors**: +- Check YAML syntax (no tabs, proper indentation) +- Verify file paths (use forward slashes) +- Ensure scripts have execute permissions +- List all dependencies + +## Examples + +See the documentation for complete examples: +- Simple single-file Skill (commit-helper) +- Skill with tool permissions (code-reviewer) +- Multi-file Skill (pdf-processing) + +## Output format + +When creating a Skill, I will: + +1. Ask clarifying questions about scope and requirements +2. Suggest a Skill name and location +3. Create the SKILL.md file with proper frontmatter +4. Include clear instructions and examples +5. Add supporting files if needed +6. Provide testing instructions +7. Validate against all requirements + +The result will be a complete, working Skill that follows all best practices and validation rules. + From 84e174de75019be2f2d3061408e63581c69df4ba Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Tue, 9 Jun 2026 15:36:53 +0800 Subject: [PATCH 07/72] feat: add raw mode shortcut `ctrl+r` --- src/tests/prompt-input-keys.test.ts | 8 ++++++++ src/tests/welcome-screen.test.ts | 1 + src/ui/index.ts | 1 + src/ui/views/PromptInput.tsx | 19 +++++++++++++++++-- src/ui/views/WelcomeScreen.tsx | 1 + 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/tests/prompt-input-keys.test.ts b/src/tests/prompt-input-keys.test.ts index a8999b6b..bcad3395 100644 --- a/src/tests/prompt-input-keys.test.ts +++ b/src/tests/prompt-input-keys.test.ts @@ -15,6 +15,7 @@ import { getPromptReturnKeyAction, isPromptCursorAtWrapBoundary, isClearImageAttachmentsShortcut, + isRawModeShortcut, removeCurrentSlashToken, resolvePromptTerminalCursorPosition, toggleSkillSelection, @@ -206,6 +207,13 @@ test("parseTerminalInput recognizes ctrl+x as the image attachment clear shortcu assert.equal(isClearImageAttachmentsShortcut(input, key), true); }); +test("parseTerminalInput recognizes ctrl+r as the raw mode shortcut", () => { + const { input, key } = parseTerminalInput("\u0012"); + assert.equal(input, "r"); + assert.equal(key.ctrl, true); + assert.equal(isRawModeShortcut(input, key), true); +}); + test("parseTerminalInput recognizes ctrl+- modifyOtherKeys sequence (standard)", () => { const { input, key } = parseTerminalInput("\u001B[45;5u"); assert.equal(input, "-"); diff --git a/src/tests/welcome-screen.test.ts b/src/tests/welcome-screen.test.ts index df7e109b..45bb7413 100644 --- a/src/tests/welcome-screen.test.ts +++ b/src/tests/welcome-screen.test.ts @@ -32,5 +32,6 @@ test("buildWelcomeTips includes built-in slash commands and loaded skills", () = const labels = tips.map((tip) => tip.label); assert.ok(labels.includes("/new")); assert.ok(labels.includes("/loaded")); + assert.ok(labels.includes("Ctrl+R")); assert.equal(labels.includes("/fresh"), false); }); diff --git a/src/ui/index.ts b/src/ui/index.ts index 2504bbd8..8f155360 100644 --- a/src/ui/index.ts +++ b/src/ui/index.ts @@ -26,6 +26,7 @@ export { toggleSkillSelection, removeCurrentSlashToken, isClearImageAttachmentsShortcut, + isRawModeShortcut, getPromptReturnKeyAction, renderBufferWithCursor, buildInitPromptSubmission, diff --git a/src/ui/views/PromptInput.tsx b/src/ui/views/PromptInput.tsx index c81d2237..c6b150cb 100644 --- a/src/ui/views/PromptInput.tsx +++ b/src/ui/views/PromptInput.tsx @@ -169,18 +169,19 @@ export const PromptInput = React.memo(function PromptInput({ const showFileMentionMenu = !showSkillsDropdown && !showModelDropdown && + !openRawModelDropdown && fileMentionToken !== null && fileMentionKey !== dismissedFileMentionKey; const slashItems = React.useMemo(() => buildSlashCommands(skills), [skills]); const slashToken = getCurrentSlashToken(buffer); const slashMenu = React.useMemo( () => - showSkillsDropdown || showModelDropdown || showFileMentionMenu + showSkillsDropdown || showModelDropdown || openRawModelDropdown || showFileMentionMenu ? [] : slashToken ? filterSlashCommands(slashItems, slashToken) : [], - [showSkillsDropdown, showModelDropdown, showFileMentionMenu, slashToken, slashItems] + [showSkillsDropdown, showModelDropdown, openRawModelDropdown, showFileMentionMenu, slashToken, slashItems] ); const showMenu = slashMenu.length > 0; const promptHistoryKey = React.useMemo(() => promptHistory.join("\0"), [promptHistory]); @@ -315,6 +316,9 @@ export const PromptInput = React.memo(function PromptInput({ } if (key.escape) { + if (openRawModelDropdown) { + return; + } if (showFileMentionMenu) { return; } @@ -325,6 +329,13 @@ export const PromptInput = React.memo(function PromptInput({ return; } + if (isRawModeShortcut(input, key)) { + setShowSkillsDropdown(false); + setShowModelDropdown(false); + setOpenRawModelDropdown(true); + return; + } + if (key.ctrl && (input === "o" || input === "O")) { if (runningProcesses && runningProcesses.size > 0 && onToggleProcessStdout) { onToggleProcessStdout(); @@ -887,6 +898,10 @@ export function isClearImageAttachmentsShortcut(input: string, key: Pick): boolean { + return key.ctrl && (input === "r" || input === "R"); +} + export type PromptReturnKeyAction = "submit" | "newline" | null; export function getPromptReturnKeyAction(key: Pick): PromptReturnKeyAction { diff --git a/src/ui/views/WelcomeScreen.tsx b/src/ui/views/WelcomeScreen.tsx index 96aef71f..bee7e9ae 100644 --- a/src/ui/views/WelcomeScreen.tsx +++ b/src/ui/views/WelcomeScreen.tsx @@ -23,6 +23,7 @@ const SHORTCUT_TIPS = [ { label: "Enter", description: "Send the prompt" }, { label: "Shift+Enter", description: "Insert a newline" }, { label: "Ctrl+V", description: "Paste an image from the clipboard" }, + { label: "Ctrl+R", description: "Open raw display mode selection" }, { label: "Esc", description: "Interrupt the current model turn" }, { label: "/", description: "Open the skills and commands menu" }, { label: "Ctrl+D twice", description: "Quit Deep Code CLI" }, From 9dca45905eab098c006099248853bdd75d94117a Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Tue, 9 Jun 2026 15:37:28 +0800 Subject: [PATCH 08/72] 0.1.29 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 05d7c4eb..09db34ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@vegamo/deepcode-cli", - "version": "0.1.28", + "version": "0.1.29", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@vegamo/deepcode-cli", - "version": "0.1.28", + "version": "0.1.29", "license": "MIT", "dependencies": { "chalk": "^5.6.2", diff --git a/package.json b/package.json index 911bd74e..aa925b92 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@vegamo/deepcode-cli", - "version": "0.1.28", + "version": "0.1.29", "description": "Deep Code CLI - Vibe coding for the deepseek-v4 model in your terminal", "license": "MIT", "type": "module", From bd6461908e38c6270c77c50960c7ccc45f270590 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Wed, 10 Jun 2026 08:59:12 +0800 Subject: [PATCH 09/72] feat: enhance Windows MCP command quoting and add tests for cmd metacharacters --- src/mcp/mcp-client.ts | 4 +- src/tests/mcp-client.test.ts | 78 +++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/mcp/mcp-client.ts b/src/mcp/mcp-client.ts index d2ef1c88..4420c569 100644 --- a/src/mcp/mcp-client.ts +++ b/src/mcp/mcp-client.ts @@ -427,7 +427,7 @@ export function createMcpSpawnSpec( // On Windows, shell: true lets cmd.exe resolve the command via PATHEXT // (npx -> npx.cmd, etc.). Join command and args into a single string // with empty spawn args to avoid Node 24 DEP0190. - // Only quote arguments that contain spaces or double-quotes to prevent + // Only quote arguments that need protection from cmd.exe to prevent // double-wrapping by Node.js's own shell quoting. command: [command, ...args].map(quoteWindowsArgIfNeeded).join(" "), args: [], @@ -444,7 +444,7 @@ export function createMcpSpawnSpec( } function quoteWindowsArgIfNeeded(arg: string): string { - if (arg.includes(" ") || arg.includes('"')) { + if (/[\s"&|<>^()]/.test(arg)) { return `"${arg.replace(/(\\*)"/g, '$1$1\\"').replace(/\\+$/g, "$&$&")}"`; } return arg; diff --git a/src/tests/mcp-client.test.ts b/src/tests/mcp-client.test.ts index 29151d3a..6a7dc016 100644 --- a/src/tests/mcp-client.test.ts +++ b/src/tests/mcp-client.test.ts @@ -1,6 +1,9 @@ import { test } from "node:test"; import assert from "node:assert/strict"; -import { createMcpSpawnSpec } from "../mcp/mcp-client"; +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import path from "node:path"; +import { McpClient, createMcpSpawnSpec } from "../mcp/mcp-client"; test("createMcpSpawnSpec keeps non-Windows MCP launches shell-free", () => { assert.deepEqual(createMcpSpawnSpec("npx", ["-y", "@playwright/mcp@latest"], "darwin"), { @@ -32,3 +35,76 @@ test("createMcpSpawnSpec quotes Windows command paths and arguments", () => { ); assert.deepEqual(spec.args, []); }); + +test("createMcpSpawnSpec quotes Windows args with cmd metacharacters", () => { + const spec = createMcpSpawnSpec( + "npx", + [ + "-y", + "some-mcp", + "--url=https://example.test?a=1&b=2", + "--pipe=a|b", + "--redirect=out", + "--caret=^value", + "--group=(value)", + ], + "win32" + ); + + assert.equal( + spec.command, + [ + "npx", + "-y", + "some-mcp", + '"--url=https://example.test?a=1&b=2"', + '"--pipe=a|b"', + '"--redirect=out"', + '"--caret=^value"', + '"--group=(value)"', + ].join(" ") + ); + assert.deepEqual(spec.args, []); +}); + +test("McpClient starts a PATH-resolved cmd MCP server on Windows", { skip: process.platform !== "win32" }, async () => { + const serverDir = mkdtempSync(path.join(tmpdir(), "deepcode-mcp-probe-")); + const originalPath = process.env.PATH; + + writeFileSync(path.join(serverDir, "mcp-probe.cmd"), '@echo off\r\nnode "%~dp0mcp-probe-server.cjs"\r\n'); + writeFileSync( + path.join(serverDir, "mcp-probe-server.cjs"), + [ + 'const readline = require("node:readline");', + "const rl = readline.createInterface({ input: process.stdin });", + "function send(message) { process.stdout.write(`${JSON.stringify(message)}\\n`); }", + 'rl.on("line", (line) => {', + " const request = JSON.parse(line);", + ' if (request.method === "initialize") {', + ' send({ jsonrpc: "2.0", id: request.id, result: { protocolVersion: "2025-03-26", capabilities: {}, serverInfo: { name: "probe", version: "1.0.0" } } });', + " return;", + " }", + ' if (request.method === "tools/list") {', + ' send({ jsonrpc: "2.0", id: request.id, result: { tools: [{ name: "probe_tool", inputSchema: { type: "object", properties: {} } }] } });', + " return;", + " }", + "});", + ].join("\n") + ); + + process.env.PATH = `${serverDir}${path.delimiter}${originalPath ?? ""}`; + const client = new McpClient("probe", "mcp-probe", []); + + try { + await client.connect(5_000); + const tools = await client.listTools(5_000); + assert.deepEqual( + tools.map((tool) => tool.name), + ["probe_tool"] + ); + } finally { + client.disconnect(); + process.env.PATH = originalPath; + rmSync(serverDir, { recursive: true, force: true }); + } +}); From 29adf6ab7406e54de97dc52f34b8cbe9681c1119 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Thu, 11 Jun 2026 20:46:20 +0800 Subject: [PATCH 10/72] feat: add plan mode skill and enhance shell init command tests --- src/common/shell-utils.ts | 9 +- src/session.ts | 56 +++----- src/tests/message-view.test.ts | 8 +- src/tests/session.test.ts | 86 ++++++++++- src/tests/shell-utils.test.ts | 13 ++ templates/skills/bundled/plan/SKILL.md | 133 ++++++++++++++++++ .../skills/bundled/skill-writer/SKILL.md | 2 +- 7 files changed, 266 insertions(+), 41 deletions(-) create mode 100644 templates/skills/bundled/plan/SKILL.md diff --git a/src/common/shell-utils.ts b/src/common/shell-utils.ts index 1dcec25a..eb8a2da7 100644 --- a/src/common/shell-utils.ts +++ b/src/common/shell-utils.ts @@ -83,9 +83,14 @@ export function getShellKind(shellPath: string): ShellKind { export function buildShellInitCommand(shellPath: string): string | null { switch (getShellKind(shellPath)) { case "zsh": - return ['ZSHRC="${ZDOTDIR:-$HOME}/.zshrc"', 'if [ -f "$ZSHRC" ]; then . "$ZSHRC"; fi'].join("; "); + return ['ZSHRC="${ZDOTDIR:-$HOME}/.zshrc"', 'if [ -f "$ZSHRC" ]; then { . "$ZSHRC"; } >/dev/null 2>&1; fi'].join( + "; " + ); case "bash": - return ['BASHRC="${BASH_ENV:-$HOME/.bashrc}"', 'if [ -f "$BASHRC" ]; then . "$BASHRC"; fi'].join("; "); + return [ + 'BASHRC="${BASH_ENV:-$HOME/.bashrc}"', + 'if [ -f "$BASHRC" ]; then { . "$BASHRC"; } >/dev/null 2>&1; fi', + ].join("; "); default: return null; } diff --git a/src/session.ts b/src/session.ts index 5e00b49e..ad89b5fe 100644 --- a/src/session.ts +++ b/src/session.ts @@ -66,6 +66,7 @@ const PROJECT_CODE_HASH_LENGTH = 16; const BACKGROUND_FAILURE_LOG_TAIL_CHARS = 4000; const DEFAULT_COMPACT_PROMPT_TOKEN_THRESHOLD = 128 * 1024; const DEEPSEEK_V4_COMPACT_PROMPT_TOKEN_THRESHOLD = 512 * 1024; +const PLAN_MODE_STATUS_MESSAGE = "Set Plan Mode on. Awaiting ."; type ChatCompletionDebugOptions = { enabled?: boolean; @@ -1022,6 +1023,25 @@ ${agentInstructions} }); } + private appendSkillMessages(sessionId: string, skills?: SkillInfo[]): void { + if (!skills || skills.length === 0) { + return; + } + + for (const skill of skills) { + if (skill.name === "plan") { + this.appendSessionMessage(sessionId, this.buildSystemMessage(sessionId, PLAN_MODE_STATUS_MESSAGE)); + } + if (skill.isLoaded) { + continue; + } + const skillPrompt = this.buildSkillPrompt(skill); + const skillMessage = this.buildSkillMessage(sessionId, skillPrompt, skill); + this.appendSessionMessage(sessionId, skillMessage); + this.onAssistantMessage(skillMessage, true); + } + } + getActiveSessionId(): string | null { return this.activeSessionId; } @@ -1145,17 +1165,7 @@ ${agentInstructions} userPrompt.skills = await this.normalizeSkills(userPrompt.skills); this.throwIfAborted(signal); - if (userPrompt.skills && userPrompt.skills.length > 0) { - for (const skill of userPrompt.skills) { - if (skill.isLoaded) { - continue; - } - const skillPrompt = this.buildSkillPrompt(skill); - const skillMessage = this.buildSkillMessage(sessionId, skillPrompt, skill); - this.appendSessionMessage(sessionId, skillMessage); - this.onAssistantMessage(skillMessage, true); - } - } + this.appendSkillMessages(sessionId, userPrompt.skills); this.activeSessionId = sessionId; await this.activateSession(sessionId, controller); @@ -1220,17 +1230,7 @@ ${agentInstructions} userPrompt.skills = await this.normalizeSkills(userPrompt.skills, sessionId); this.throwIfAborted(signal); - if (userPrompt.skills && userPrompt.skills.length > 0) { - for (const skill of userPrompt.skills) { - if (skill.isLoaded) { - continue; - } - const skillPrompt = this.buildSkillPrompt(skill); - const skillMessage = this.buildSkillMessage(sessionId, skillPrompt, skill); - this.appendSessionMessage(sessionId, skillMessage); - this.onAssistantMessage(skillMessage, true); - } - } + this.appendSkillMessages(sessionId, userPrompt.skills); this.activeSessionId = sessionId; await this.activateSession(sessionId, controller); } @@ -2372,17 +2372,7 @@ ${agentInstructions} } userPrompt.skills = await this.normalizeSkills(userPrompt.skills, sessionId); this.throwIfAborted(signal); - if (userPrompt.skills && userPrompt.skills.length > 0) { - for (const skill of userPrompt.skills) { - if (skill.isLoaded) { - continue; - } - const skillPrompt = this.buildSkillPrompt(skill); - const skillMessage = this.buildSkillMessage(sessionId, skillPrompt, skill); - this.appendSessionMessage(sessionId, skillMessage); - this.onAssistantMessage(skillMessage, true); - } - } + this.appendSkillMessages(sessionId, userPrompt.skills); } private buildToolParamsSnippet(toolFunction: unknown | null): string { diff --git a/src/tests/message-view.test.ts b/src/tests/message-view.test.ts index 7d6b781c..ff497707 100644 --- a/src/tests/message-view.test.ts +++ b/src/tests/message-view.test.ts @@ -105,6 +105,10 @@ function makeSessionMessage(overrides: Partial & Pick { const msg = makeSessionMessage({ role: "user", content: "hello", visible: false }); assert.equal(renderMessageToStdout(msg, RawMode.Raw), ""); @@ -128,7 +132,7 @@ test("MessageView echoes submitted user prompts with live prompt wrapping width" const msg = makeSessionMessage({ role: "user", content: "abcdefg" }); const output = renderToString(React.createElement(MessageView, { message: msg, width: 8 }), { columns: 8 }); - assert.equal(output, "> abcdef\n g\n"); + assert.equal(stripAnsi(output), "> abcdef\n g\n"); }); test("MessageView echoes model changes with submitted prompt wrapping", () => { @@ -139,7 +143,7 @@ test("MessageView echoes model changes with submitted prompt wrapping", () => { }); const output = renderToString(React.createElement(MessageView, { message: msg, width: 8 }), { columns: 8 }); - assert.equal(output, "> abcdef\n gh\n"); + assert.equal(stripAnsi(output), "> abcdef\n gh\n"); }); test("renderMessageToStdout renders assistant non-thinking messages with ✦", () => { diff --git a/src/tests/session.test.ts b/src/tests/session.test.ts index abebed3c..40877579 100644 --- a/src/tests/session.test.ts +++ b/src/tests/session.test.ts @@ -6,13 +6,14 @@ import * as os from "os"; import * as path from "path"; import { GitFileHistory } from "../common/file-history"; import { clearSessionState } from "../common/state"; -import { getProjectCode, SessionManager, type SessionMessage } from "../session"; +import { getProjectCode, SessionManager, type SessionMessage, type SkillInfo } from "../session"; const originalFetch = globalThis.fetch; const originalConsoleWarn = console.warn; const originalHome = process.env.HOME; const originalUserProfile = process.env.USERPROFILE; const tempDirs: string[] = []; +const PLAN_MODE_STATUS_MESSAGE = "Set Plan Mode on. Awaiting ."; /** Set homedir in a cross-platform way (HOME on Unix, USERPROFILE on Windows). */ function setHomeDir(dir: string): void { @@ -522,6 +523,70 @@ test("SessionManager resolves bundled skill prompts", () => { assert.match(prompt, /# Skill Writer/); }); +test("SessionManager appends plan mode status whenever the plan skill is selected", async () => { + const workspace = createTempDir("deepcode-plan-skill-workspace-"); + const home = createTempDir("deepcode-plan-skill-home-"); + setHomeDir(home); + + const manager = createSessionManager(workspace, "machine-id-plan-skill"); + const planSkill = await getPlanSkill(manager); + + const sessionId = await manager.createSession({ text: "", skills: [planSkill] }); + let messages = manager.listSessionMessages(sessionId); + assert.equal(countPlanModeStatusMessages(messages), 1); + assert.equal(countLoadedSkillMessages(messages, "plan"), 1); + + await manager.replySession(sessionId, { text: "", skills: [planSkill] }); + messages = manager.listSessionMessages(sessionId); + assert.equal(countPlanModeStatusMessages(messages), 2); + assert.equal(countLoadedSkillMessages(messages, "plan"), 1); +}); + +test("SessionManager appends plan mode status when the plan skill is auto-matched", async () => { + const workspace = createTempDir("deepcode-plan-matched-workspace-"); + const home = createTempDir("deepcode-plan-matched-home-"); + setHomeDir(home); + + const client = { + chat: { + completions: { + create: async (request: any) => { + if (isSkillMatchingRequest(request)) { + return createSkillMatchingResponse(["plan"]); + } + return createChatResponse("planned", { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }); + }, + }, + }, + }; + const manager = createMockedClientSessionManagerWithClient(workspace, client); + + const sessionId = await manager.createSession({ text: "Plan Mode for this change" }); + const messages = manager.listSessionMessages(sessionId); + assert.equal(countPlanModeStatusMessages(messages), 1); + assert.equal(countLoadedSkillMessages(messages, "plan"), 1); +}); + +test("SessionManager appends plan mode status for deferred permission prompts", async () => { + const workspace = createTempDir("deepcode-plan-deferred-workspace-"); + const home = createTempDir("deepcode-plan-deferred-home-"); + setHomeDir(home); + + const manager = createSessionManager(workspace, "machine-id-plan-deferred"); + const sessionId = await manager.createSession({ text: "" }); + const planSkill = await getPlanSkill(manager); + + await (manager as any).appendDeferredPermissionPrompt( + sessionId, + { text: "", skills: [planSkill] }, + new AbortController() + ); + + const messages = manager.listSessionMessages(sessionId); + assert.equal(countPlanModeStatusMessages(messages), 1); + assert.equal(countLoadedSkillMessages(messages, "plan"), 1); +}); + test("SessionManager excludes disabled skills by resolved skill name", async () => { const workspace = createTempDir("deepcode-disabled-skills-workspace-"); const home = createTempDir("deepcode-disabled-skills-home-"); @@ -564,6 +629,7 @@ test("SessionManager excludes disabled skills by resolved skill name", async () "renamed-disabled": false, "deepcode-self-refer": false, "skill-digester": false, + plan: false, "enabled-skill": true, }, }), @@ -3400,6 +3466,20 @@ function createSessionManager(projectRoot: string, machineId: string): SessionMa }); } +async function getPlanSkill(manager: SessionManager): Promise { + const planSkill = (await manager.listSkills()).find((skill) => skill.name === "plan"); + assert.ok(planSkill); + return planSkill; +} + +function countPlanModeStatusMessages(messages: SessionMessage[]): number { + return messages.filter((message) => message.role === "system" && message.content === PLAN_MODE_STATUS_MESSAGE).length; +} + +function countLoadedSkillMessages(messages: SessionMessage[], skillName: string): number { + return messages.filter((message) => message.role === "system" && message.meta?.skill?.name === skillName).length; +} + function createNotifyingSessionManager( projectRoot: string, responses: unknown[], @@ -3536,8 +3616,8 @@ function isSkillMatchingRequest(request: any): boolean { return request?.response_format?.type === "json_object"; } -function createSkillMatchingResponse(): unknown { - return { choices: [{ message: { content: '{"skillNames":[]}' } }] }; +function createSkillMatchingResponse(skillNames: string[] = []): unknown { + return { choices: [{ message: { content: JSON.stringify({ skillNames }) } }] }; } function createChatResponse(content: string, usage: Record): unknown { diff --git a/src/tests/shell-utils.test.ts b/src/tests/shell-utils.test.ts index 50a71f41..8ec56bb1 100644 --- a/src/tests/shell-utils.test.ts +++ b/src/tests/shell-utils.test.ts @@ -2,6 +2,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { buildDisableExtglobCommand, + buildShellInitCommand, getShellKind, posixPathToWindowsPath, resolveWindowsGitBashPath, @@ -39,6 +40,18 @@ test("Shell kind detection supports Windows bash.exe paths", () => { assert.equal(buildDisableExtglobCommand("/bin/zsh"), "setopt NO_EXTENDED_GLOB 2>/dev/null || true"); }); +test("Shell init commands suppress startup file output", () => { + assert.equal( + buildShellInitCommand("/bin/zsh"), + 'ZSHRC="${ZDOTDIR:-$HOME}/.zshrc"; if [ -f "$ZSHRC" ]; then { . "$ZSHRC"; } >/dev/null 2>&1; fi' + ); + assert.equal( + buildShellInitCommand("/bin/bash"), + 'BASHRC="${BASH_ENV:-$HOME/.bashrc}"; if [ -f "$BASHRC" ]; then { . "$BASHRC"; } >/dev/null 2>&1; fi' + ); + assert.equal(buildShellInitCommand("/bin/fish"), null); +}); + test("Windows Git Bash detection prefers bash.exe from PATH", () => { const bashPath = "D:\\Tools\\Git\\bin\\bash.exe"; const resolved = resolveWindowsGitBashPath({ diff --git a/templates/skills/bundled/plan/SKILL.md b/templates/skills/bundled/plan/SKILL.md new file mode 100644 index 00000000..b73c1abc --- /dev/null +++ b/templates/skills/bundled/plan/SKILL.md @@ -0,0 +1,133 @@ +--- +name: plan +description: Plan tasks through a strict non-mutating collaboration workflow before implementation. Use ONLY when the user asks for Plan Mode, planning only or non-mutating exploration. +--- + +# Plan Mode (Conversational) + +You work in 3 phases, and you should *chat your way* to a great plan before finalizing it. A great plan is very detailed—intent- and implementation-wise—so that it can be handed to another engineer or agent to be implemented right away. It must be **decision complete**, where the implementer does not need to make any decisions. + +## Mode rules (strict) + +You are in **Plan Mode** until a developer message explicitly ends it. + +Plan Mode is not changed by user intent, tone, or imperative language. If a user asks for execution while still in Plan Mode, treat it as a request to **plan the execution**, not perform it. + +## Plan Mode vs UpdatePlan tool + +Plan Mode is a collaboration mode that can involve requesting user input and eventually issuing a `` block. + +Separately, `UpdatePlan` is Deep Code's checklist/progress tool. It updates the current task plan with a complete markdown task list, but it does not enter or exit Plan Mode and it is not the final planning artifact. Do not use `UpdatePlan` as a substitute for the `` block. + +## Execution vs. mutation in Plan Mode + +You may explore and execute **non-mutating** actions that improve the plan. You must not perform **mutating** actions. + +### Allowed (non-mutating, plan-improving) + +Actions that gather truth, reduce ambiguity, or validate feasibility without changing repo-tracked state. Examples: + +* Reading or searching files, configs, schemas, types, manifests, and docs +* Static analysis, inspection, and repo exploration +* Dry-run style commands when they do not edit repo-tracked files +* Tests, builds, or checks that may write to caches or build artifacts (for example, `target/`, `.cache/`, or snapshots) so long as they do not edit repo-tracked files + +### Not allowed (mutating, plan-executing) + +Actions that implement the plan or change repo-tracked state. Examples: + +* Editing or writing files +* Running formatters or linters that rewrite files +* Applying patches, migrations, or codegen that updates repo-tracked files +* Side-effectful commands whose purpose is to carry out the plan rather than refine it + +When in doubt: if the action would reasonably be described as "doing the work" rather than "planning the work," do not do it. + +## PHASE 1 — Ground in the environment (explore first, ask second) + +Begin by grounding yourself in the actual environment. Eliminate unknowns in the prompt by discovering facts, not by asking the user. Resolve all questions that can be answered through exploration or inspection. Identify missing or ambiguous details only if they cannot be derived from the environment. Silent exploration between turns is allowed and encouraged. + +Before asking the user any question, perform at least one targeted non-mutating exploration pass (for example: search relevant files, inspect likely entrypoints/configs, confirm current implementation shape), unless no local environment/repo is available. + +Exception: you may ask clarifying questions about the user's prompt before exploring, ONLY if there are obvious ambiguities or contradictions in the prompt itself. However, if ambiguity might be resolved by exploring, always prefer exploring first. + +Do not ask questions that can be answered from the repo or system (for example, "where is this struct?" or "which UI component should we use?" when exploration can make it clear). Only ask once you have exhausted reasonable non-mutating exploration. + +## PHASE 2 — Intent chat (what they actually want) + +* Keep asking until you can clearly state: goal + success criteria, audience, in/out of scope, constraints, current state, and the key preferences/tradeoffs. +* Bias toward questions over guessing: if any high-impact ambiguity remains, do NOT plan yet—ask. + +## PHASE 3 — Implementation chat (what/how we’ll build) + +* Once intent is stable, keep asking until the spec is decision complete: approach, interfaces (APIs/schemas/I/O), data flow, edge cases/failure modes, testing + acceptance criteria, rollout/monitoring, and any migrations/compat constraints. + +## Asking questions + +Critical rules: + +* Strongly prefer using the `AskUserQuestion` tool to ask any questions. +* Offer only meaningful multiple‑choice options; don’t include filler choices that are obviously wrong or irrelevant. +* In rare cases where an unavoidable, important question can’t be expressed with reasonable multiple‑choice options (due to extreme ambiguity), you may ask it directly without the tool. + +You SHOULD ask many questions, but each question must: + +* materially change the spec/plan, OR +* confirm/lock an assumption, OR +* choose between meaningful tradeoffs. +* not be answerable by non-mutating commands. + +Use the `AskUserQuestion` tool only for decisions that materially change the plan, for confirming important assumptions, or for information that cannot be discovered via non-mutating exploration. Ask one question at a time when possible, provide concrete options with `label` and optional `description`, and use `multiSelect` only when multiple choices can be combined. + +## Two kinds of unknowns (treat differently) + +1. **Discoverable facts** (repo/system truth): explore first. + + * Before asking, run targeted searches and check likely sources of truth (configs/manifests/entrypoints/schemas/types/constants). + * Ask only if: multiple plausible candidates; nothing found but you need a missing identifier/context; or ambiguity is actually product intent. + * If asking, present concrete candidates (paths/service names) + recommend one. + * Never ask questions you can answer from your environment (e.g., “where is this struct”). + +2. **Preferences/tradeoffs** (not discoverable): ask early. + + * These are intent or implementation preferences that cannot be derived from exploration. + * Provide 2–4 mutually exclusive options + a recommended default. + * If unanswered, proceed with the recommended option and record it as an assumption in the final plan. + +## Finalization rule + +Only output the final plan when it is decision complete and leaves no decisions to the implementer. + +When you present the official plan, wrap it in a `` block so the client can render it specially: + +1) The opening tag must be on its own line. +2) Start the plan content on the next line (no text on the same line as the tag). +3) The closing tag must be on its own line. +4) Use Markdown inside the block. +5) Keep the tags exactly as `` and `` (do not translate or rename them), even if the plan content is in another language. + +Example: + + +plan content + + +plan content should be human and agent digestible. The final plan must be plan-only, concise by default, and include: + +* A clear title +* A brief summary section +* Important changes or additions to public APIs/interfaces/types +* Test cases and scenarios +* Explicit assumptions and defaults chosen where needed + +When possible, prefer a compact structure with 3-5 short sections, usually: Summary, Key Changes or Implementation Changes, Test Plan, and Assumptions. Do not include a separate Scope section unless scope boundaries are genuinely important to avoid mistakes. + +Prefer grouped implementation bullets by subsystem or behavior over file-by-file inventories. Mention files only when needed to disambiguate a non-obvious change, and avoid naming more than 3 paths unless extra specificity is necessary to prevent mistakes. Prefer behavior-level descriptions over symbol-by-symbol removal lists. For v1 feature-addition plans, do not invent detailed schema, validation, precedence, fallback, or wire-shape policy unless the request establishes it or it is needed to prevent a concrete implementation mistake; prefer the intended capability and minimum interface/behavior changes. + +Keep bullets short and avoid explanatory sub-bullets unless they are needed to prevent ambiguity. Prefer the minimum detail needed for implementation safety, not exhaustive coverage. Within each section, compress related changes into a few high-signal bullets and omit branch-by-branch logic, repeated invariants, and long lists of unaffected behavior unless they are necessary to prevent a likely implementation mistake. Avoid repeated repo facts and irrelevant edge-case or rollout detail. For straightforward refactors, keep the plan to a compact summary, key edits, tests, and assumptions. If the user asks for more detail, then expand. + +Do not ask "should I proceed?" in the final output. The user can easily switch out of Plan mode and request implementation if you have included a `` block in your response. Alternatively, they can decide to stay in Plan mode and continue refining the plan. + +Only produce at most one `` block per turn, and only when you are presenting a complete spec. + +If the user stays in Plan mode and asks for revisions after a prior ``, any new `` must be a complete replacement. diff --git a/templates/skills/bundled/skill-writer/SKILL.md b/templates/skills/bundled/skill-writer/SKILL.md index e30bfdfc..1a7801c3 100644 --- a/templates/skills/bundled/skill-writer/SKILL.md +++ b/templates/skills/bundled/skill-writer/SKILL.md @@ -1,6 +1,6 @@ --- name: skill-writer -description: Guide users through creating, updating, debugging, and validating Agent Skills for AI agents. Use when the user wants to create, write, author, design, troubleshoot, validate, or improve a Skill, or needs help with SKILL.md files, frontmatter, or skill structure. +description: Guide users through creating, updating, debugging, and validating Agent Skills for AI agents. Use when the user wants to create, write, author, design, troubleshoot, validate, or improve a Skill, or needs help with SKILL.md, frontmatter, or skill structure. --- # Skill Writer From 7dba5131ef7296059550fc8f38fef2c9b6569cd3 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Thu, 11 Jun 2026 21:34:14 +0800 Subject: [PATCH 11/72] feat: update PLAN_MODE_STATUS_MESSAGE --- src/session.ts | 2 +- src/tests/session.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/session.ts b/src/session.ts index ad89b5fe..383f3490 100644 --- a/src/session.ts +++ b/src/session.ts @@ -66,7 +66,7 @@ const PROJECT_CODE_HASH_LENGTH = 16; const BACKGROUND_FAILURE_LOG_TAIL_CHARS = 4000; const DEFAULT_COMPACT_PROMPT_TOKEN_THRESHOLD = 128 * 1024; const DEEPSEEK_V4_COMPACT_PROMPT_TOKEN_THRESHOLD = 512 * 1024; -const PLAN_MODE_STATUS_MESSAGE = "Set Plan Mode on. Awaiting ."; +const PLAN_MODE_STATUS_MESSAGE = "/plan\n └ Set Plan Mode on. Awaiting ."; type ChatCompletionDebugOptions = { enabled?: boolean; diff --git a/src/tests/session.test.ts b/src/tests/session.test.ts index 40877579..8df048b4 100644 --- a/src/tests/session.test.ts +++ b/src/tests/session.test.ts @@ -13,7 +13,7 @@ const originalConsoleWarn = console.warn; const originalHome = process.env.HOME; const originalUserProfile = process.env.USERPROFILE; const tempDirs: string[] = []; -const PLAN_MODE_STATUS_MESSAGE = "Set Plan Mode on. Awaiting ."; +const PLAN_MODE_STATUS_MESSAGE = "/plan\n └ Set Plan Mode on. Awaiting ."; /** Set homedir in a cross-platform way (HOME on Unix, USERPROFILE on Windows). */ function setHomeDir(dir: string): void { From 07cfe21464520d1dd71d23dffac3d317e10a9fd6 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Fri, 12 Jun 2026 10:00:57 +0800 Subject: [PATCH 12/72] feat: add support for implicit invocation control in skills --- src/prompt.ts | 19 ++++++++++- src/session.ts | 18 ++++++++-- src/tests/prompt.test.ts | 21 ++++++++++++ src/tests/session.test.ts | 72 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 3 deletions(-) diff --git a/src/prompt.ts b/src/prompt.ts index c5c888c6..3b18ba6f 100644 --- a/src/prompt.ts +++ b/src/prompt.ts @@ -3,6 +3,7 @@ import * as fs from "fs"; import * as os from "os"; import * as path from "path"; import ejs from "ejs"; +import matter from "gray-matter"; import { fileURLToPath } from "url"; import type { SessionMessage } from "./session"; import { findGitBashPath, resolveShellPath } from "./common/shell-utils"; @@ -184,11 +185,27 @@ export function buildSkillDocumentsPrompt(skills: SkillPromptDocument[]): string function renderSkillDocumentBlock(skill: SkillPromptDocument): string { const pathAttribute = skill.path ? ` path="${escapeXml(skill.path)}"` : ""; const resources = renderSkillResources(skill.skillFilePath); + const content = stripSkillPromptMetadata(skill.content); return `<${skill.name}-skill${pathAttribute}> -${skill.content}${resources} +${content}${resources} `; } +function stripSkillPromptMetadata(content: string): string { + try { + const parsed = matter(content); + if (!Object.prototype.hasOwnProperty.call(parsed.data, "metadata")) { + return content; + } + + const frontmatter = { ...parsed.data }; + delete frontmatter.metadata; + return matter.stringify(parsed.content, frontmatter); + } catch { + return content; + } +} + function renderSkillResources(skillFilePath?: string): string { if (!skillFilePath) { return ""; diff --git a/src/session.ts b/src/session.ts index 383f3490..6a594b2f 100644 --- a/src/session.ts +++ b/src/session.ts @@ -289,6 +289,7 @@ export type SkillInfo = { path: string; description: string; isLoaded?: boolean; + allowImplicitInvocation?: boolean; }; type SessionManagerOptions = { @@ -732,13 +733,14 @@ Response in JSON format: If none of the available skills match, respond with an empty array, i.e. \`{"skillNames": []}\`.\n `; const simpleSkills = skills - .filter((x) => !x.isLoaded) + .filter((x) => !x.isLoaded && x.allowImplicitInvocation !== false) .map((x) => { return { name: x.name, description: x.description }; }); if (simpleSkills.length === 0) { return []; } + const candidateSkillNames = new Set(simpleSkills.map((skill) => skill.name)); const { client, model, baseURL, debugLogEnabled } = this.createOpenAIClient(); if (!client) { @@ -787,7 +789,10 @@ ${agentInstructions} const parsed = JSON.parse(content); if (parsed && Array.isArray(parsed.skillNames)) { - return parsed.skillNames; + return parsed.skillNames.filter( + (skillName: unknown): skillName is string => + typeof skillName === "string" && candidateSkillNames.has(skillName) + ); } return []; @@ -938,6 +943,14 @@ ${agentInstructions} try { const skillMd = fs.readFileSync(skillPath, "utf8"); const parsed = matter(skillMd); + const metadata = parsed.data.metadata; + const allowImplicitInvocation = + metadata && + typeof metadata === "object" && + !Array.isArray(metadata) && + (metadata as Record)["allow-implicit-invocation"] === false + ? false + : undefined; return { name: typeof parsed.data.name === "string" && parsed.data.name.trim() @@ -945,6 +958,7 @@ ${agentInstructions} : fallbackSkill.name, path: displayPath, description: typeof parsed.data.description === "string" ? parsed.data.description.trim() : "", + allowImplicitInvocation, }; } catch { return fallbackSkill; diff --git a/src/tests/prompt.test.ts b/src/tests/prompt.test.ts index cef6c620..899a2b26 100644 --- a/src/tests/prompt.test.ts +++ b/src/tests/prompt.test.ts @@ -88,6 +88,27 @@ test("getDefaultSkillPrompt loads the default skill template", () => { assert.equal(prompt.includes('path="templates/skills/'), false); }); +test("buildSkillDocumentsPrompt excludes SKILL.md frontmatter metadata", () => { + const prompt = buildSkillDocumentsPrompt([ + { + name: "example", + content: + "---\nname: example\ndescription: Example skill\nlicense: MIT\ncompatibility: Node.js\nallowed-tools: Read Bash\nmetadata:\n author: test\n allow-implicit-invocation: false\n---\n# Example Skill\n\nUse these instructions.\n", + }, + ]); + + assert.equal(prompt.includes("name: example"), true); + assert.equal(prompt.includes("description: Example skill"), true); + assert.equal(prompt.includes("license: MIT"), true); + assert.equal(prompt.includes("compatibility: Node.js"), true); + assert.equal(prompt.includes("allowed-tools: Read Bash"), true); + assert.equal(prompt.includes("# Example Skill"), true); + assert.equal(prompt.includes("Use these instructions."), true); + assert.equal(prompt.includes("metadata:"), false); + assert.equal(prompt.includes("author: test"), false); + assert.equal(prompt.includes("allow-implicit-invocation"), false); +}); + test("buildSkillDocumentsPrompt lists skill resources", () => { const skillDir = createTempDir("deepcode-skill-resources-"); fs.mkdirSync(path.join(skillDir, "scripts"), { recursive: true }); diff --git a/src/tests/session.test.ts b/src/tests/session.test.ts index 8df048b4..38767e43 100644 --- a/src/tests/session.test.ts +++ b/src/tests/session.test.ts @@ -644,6 +644,78 @@ test("SessionManager excludes disabled skills by resolved skill name", async () assert.equal(skills[0]?.path, "./.deepcode/skills/enabled-skill/SKILL.md"); }); +test("SessionManager keeps implicit opt-out skills available for manual invocation", async () => { + const workspace = createTempDir("deepcode-manual-only-skill-workspace-"); + const home = createTempDir("deepcode-manual-only-skill-home-"); + setHomeDir(home); + + const skillDir = path.join(workspace, ".agents", "skills", "manual-only"); + fs.mkdirSync(skillDir, { recursive: true }); + fs.writeFileSync( + path.join(skillDir, "SKILL.md"), + "---\nname: manual-only\ndescription: Manual-only skill\nmetadata:\n allow-implicit-invocation: false\n---\n# Manual Only\n", + "utf8" + ); + + const manager = createSessionManager(workspace, "machine-id-manual-only-skill"); + const skill = (await manager.listSkills()).find((candidate) => candidate.name === "manual-only"); + assert.ok(skill); + assert.equal(skill.allowImplicitInvocation, false); + + const sessionId = await manager.createSession({ text: "", skills: [skill] }); + const skillMessages = manager + .listSessionMessages(sessionId) + .filter((message) => message.role === "system" && message.meta?.skill?.name === "manual-only"); + + assert.equal(skillMessages.length, 1); + assert.match(skillMessages[0]?.content ?? "", / { + const workspace = createTempDir("deepcode-implicit-opt-out-workspace-"); + const home = createTempDir("deepcode-implicit-opt-out-home-"); + setHomeDir(home); + globalThis.fetch = (async () => ({ ok: true, text: async () => "" }) as Response) as typeof fetch; + + const writeSkill = (name: string, metadata = ""): void => { + const skillDir = path.join(workspace, ".deepcode", "skills", name); + fs.mkdirSync(skillDir, { recursive: true }); + fs.writeFileSync( + path.join(skillDir, "SKILL.md"), + `---\nname: ${name}\ndescription: ${name} description${metadata}\n---\n# ${name}\n`, + "utf8" + ); + }; + writeSkill("auto-skill"); + writeSkill("manual-only", "\nmetadata:\n allow-implicit-invocation: false"); + + const requests: any[] = []; + const client = { + chat: { + completions: { + create: async (request: any) => { + requests.push(request); + if (isSkillMatchingRequest(request)) { + return createSkillMatchingResponse(["manual-only", "auto-skill"]); + } + return createChatResponse("done", { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }); + }, + }, + }, + }; + const manager = createMockedClientSessionManagerWithClient(workspace, client); + (manager as any).activateSession = async () => {}; + + const sessionId = await manager.createSession({ text: "choose an automatic skill" }); + const matchingPrompt = String(requests[0]?.messages?.[0]?.content ?? ""); + + assert.match(matchingPrompt, /"name": "auto-skill"/); + assert.doesNotMatch(matchingPrompt, /"name": "manual-only"/); + assert.equal(countLoadedSkillMessages(manager.listSessionMessages(sessionId), "auto-skill"), 1); + assert.equal(countLoadedSkillMessages(manager.listSessionMessages(sessionId), "manual-only"), 0); +}); + test("SessionManager dispose disconnects MCP servers", async () => { const workspace = createTempDir("deepcode-mcp-dispose-workspace-"); const serverPath = path.join(workspace, "mcp-server.cjs"); From 849bab4589ee16eb4f781a45beff832d65ec7adc Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Fri, 12 Jun 2026 14:13:38 +0800 Subject: [PATCH 13/72] feat: add agent-skills.md --- docs/agent-skills.md | 322 ++++++++++++++++++++++++++++++++++++++++ docs/agent-skills_en.md | 322 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 644 insertions(+) create mode 100644 docs/agent-skills.md create mode 100644 docs/agent-skills_en.md diff --git a/docs/agent-skills.md b/docs/agent-skills.md new file mode 100644 index 00000000..b1bd4e45 --- /dev/null +++ b/docs/agent-skills.md @@ -0,0 +1,322 @@ +# Deep Code CLI Agent Skills 指南 + +## 概述 + +适合写成 skill 的内容通常具备以下特点: + +- 会重复使用,例如固定的代码审查流程、发布流程或文档生成流程 +- 需要较长的说明,不适合每次都粘贴到对话中 +- 需要配套资源,例如模板、脚本、schema、示例或参考文档 +- 需要明确触发条件,例如“处理 PDF 表单”或“为本项目生成数据库迁移” + +不适合写成 skill 的内容: + +- 一次性的任务要求 +- 当前仓库的短规则,此类内容更适合写入 `AGENTS.md` +- 需要实时连接外部系统的能力,此类能力更适合通过 MCP 提供工具 + +## 扫描位置 + +Deep Code CLI 会按以下顺序扫描 skills。相同 `name` 的 skill 只保留优先级最高的一个。 + +| 优先级 | Scope | Path | 用途 | +| ------ | ------- | --------------------- | ---- | +| 1 | Project | `./.deepcode/skills/` | Deep Code 项目级原生位置 | +| 2 | Project | `./.agents/skills/` | 项目级跨客户端互操作位置 | +| 3 | User | `~/.deepcode/skills/` | Deep Code 用户级原生位置 | +| 4 | User | `~/.agents/skills/` | 用户级跨客户端互操作位置 | +| 5 | Global | `built-in` | Deep Code 内置 skills | + +目录结构示例: + +```text +.deepcode/ +└── skills/ + └── code-review/ + ├── SKILL.md + ├── checklist.md + └── scripts/ + └── collect-diff.sh +``` + +## 最小 Skill + +每个 skill 必须放在独立目录中,并包含 `SKILL.md`。 + +```markdown +--- +name: code-review +description: Review code changes for correctness, regressions, security risks, and missing tests. Use when the user asks for a review, PR review, diff review, or pre-merge check. +--- + +# Code Review + +Use a code review mindset. Prioritize bugs, behavioral regressions, security issues, +and missing tests over style comments. + +## Workflow + +1. Inspect the diff and relevant surrounding code. +2. List findings first, ordered by severity. +3. Include file and line references for every finding. +4. If there are no findings, say so and mention residual risks or test gaps. +``` + +## `SKILL.md` Frontmatter + +Deep Code CLI reads the YAML frontmatter at the top of `SKILL.md`. + +| 字段 | 必填 | Deep Code 行为 | 建议 | +| ---- | ---- | -------------- | ---- | +| `name` | 建议必填 | 作为 skill 的唯一名称。缺失时使用目录名,并把 `_` 转成 `-`。 | 使用小写字母、数字和连字符。保持与目录名一致。 | +| `description` | 建议必填 | 用于自动匹配任务,也显示在 `/skills` 和斜杠菜单中。 | 写清楚 skill 做什么、何时使用、常见触发词。 | +| `metadata.allow-implicit-invocation` | 可选 | 设置为 `false` 时,不参与自动匹配;仍可手动选择。 | 用于只想手动调用的 skill。 | + +示例: + +```yaml +--- +name: db-migration +description: Create and review database migrations for this project. Use when the user asks to add columns, change schema, write migrations, or validate rollback behavior. +metadata: + allow-implicit-invocation: false +--- +``` + +> Deep Code CLI 当前只解释上表中的字段。其他 frontmatter 字段可用于跨客户端互操作或文档说明,但不会自动限制 Deep Code 的工具权限。 + +## 写好 `description` + +`description` 是最重要的发现信号。Deep Code 会在自动匹配阶段只把 skill 的 `name` 和 `description` 交给模型判断,因此描述越具体,匹配越可靠。 + +推荐结构: + +```text +<这个 skill 做什么>. Use when <任务类型、文件类型、领域、用户常见说法或触发词>. +``` + +好的示例: + +```yaml +description: Extract tables from PDF files, fill PDF forms, and merge documents. Use when working with PDFs, forms, invoices, statements, or document extraction. +``` + +```yaml +description: Generate Lessweb routes, services, and Pydantic request models. Use when editing Lessweb projects, adding @Get/@Post endpoints, configuring IOC modules, or updating OpenAPI output. +``` + +避免: + +```yaml +description: Helps with documents +description: Useful project skill +description: Tooling instructions +``` + +检查清单: + +- 是否说明了具体能力,而不是只写主题名 +- 是否说明了何时使用,而不是只写结果 +- 是否包含用户可能输入的关键词 +- 是否包含相关文件类型、框架名、命令名或领域名 +- 是否避免覆盖过宽,导致无关任务也触发 + +## Skill 正文结构 + +`SKILL.md` 的正文应面向 agent,而不是面向普通读者。写法要直接、可执行、可验证。 + +推荐结构: + +```markdown +# Skill Name + +Briefly state what this skill is for. + +## When to use + +- Use when ... +- Do not use when ... + +## Workflow + +1. Read ... +2. Run ... +3. Edit ... +4. Verify ... + +## Rules + +- Preserve ... +- Never ... +- Ask the user when ... + +## Examples + +... +``` + +写作原则: + +- 使用命令式步骤,例如“Read the schema first”或“Run tests after editing” +- 把必须遵守的约束写成明确规则 +- 对高风险操作写清楚边界,例如删除文件、迁移数据、发送请求 +- 对常见分支写出决策规则,例如“如果没有配置文件,先搜索默认路径” +- 避免把大量参考资料全部塞进 `SKILL.md` + +## 附加资源 + +一个 skill 可以包含 `SKILL.md` 之外的文件: + +```text +my-skill/ +├── SKILL.md +├── references/ +│ └── api.md +├── examples/ +│ └── request.json +├── scripts/ +│ └── validate.py +└── templates/ + └── report.md +``` + +如果某些内容会让 `SKILL.md` 过长或难以阅读,可以放到附加文件中: + +- `references/` 放长文档、规范、API 说明 +- `examples/` 放输入输出样例 +- `scripts/` 放可复用脚本 +- `templates/` 放文档或代码模板 +- 在 `SKILL.md` 中说明什么时候需要使用这些附加文件 + +示例: + +```markdown +## Workflow + +1. Read `references/schema.md` before changing generated types. +2. Use `templates/migration.sql` when creating a new migration. +3. Run `python scripts/check_migration.py ` before reporting completion. +``` + +## 调用方式 + +Deep Code CLI 支持自动和手动两种调用方式。 + +### 自动调用 + +每次用户输入后,Deep Code 会根据可用 skills 的 `name` 和 `description` 判断哪些 skill 与任务匹配。匹配到的 skill 会被加载到当前会话中。 + +自动调用规则: + +- 已加载的 skill 不会在同一会话中重复加载 +- `metadata.allow-implicit-invocation: false` 的 skill 不会自动加载 +- 自动匹配会结合当前 `AGENTS.md` 指令 +- 如果没有匹配项,则不加载 skill + +### 手动调用 + +你可以在输入框中使用 `/` 打开 skills / 命令菜单,选择某个 skill;也可以使用 `/skills` 查看可用 skills。 + +常用命令: + +| 命令 | 作用 | +| ---- | ---- | +| `/` | 打开 skills / 命令菜单 | +| `/skills` | 列出可用 skills | +| `/` | 从菜单中选择对应 skill | + +## 启用和禁用 + +使用 `settings.json` 的 `enabledSkills` 可以按 skill 名称启用或禁用 skill。 + +```json +{ + "enabledSkills": { + "code-review": true, + "db-migration": false + } +} +``` + +规则: + +- 未配置的 skill 默认启用 +- 设置为 `false` 会隐藏所有扫描位置中同名的 skill +- 项目设置会按 skill 覆盖用户设置 + +更多配置说明请参考 [configuration.md](configuration.md)。 + +## 与 `AGENTS.md`、MCP 的区别 + +| 机制 | 适合放什么 | 不适合放什么 | +| ---- | ---------- | ------------ | +| `AGENTS.md` | 当前仓库的长期规则、代码风格、测试命令、协作约定 | 可复用的复杂工作流或跨项目工具说明 | +| Agent Skill | 可复用工作流、领域知识、模板、脚本、参考资料 | 只对当前一次任务生效的临时要求 | +| MCP | 外部系统能力、实时数据、浏览器、数据库、GitHub 等工具调用 | 纯文本流程说明 | + +常见组合: + +- 把项目规则写进 `AGENTS.md` +- 把可复用流程写成 skill +- 把需要执行外部动作的能力接入 MCP + +## 编写示例:项目发布 Skill + +```markdown +--- +name: release-check +description: Prepare and verify a project release. Use when the user asks to release, publish, bump version, update changelog, or run pre-release checks. +--- + +# Release Check + +Use this skill to prepare a safe release for this repository. + +## Workflow + +1. Read `package.json` and the existing changelog. +2. Inspect commits or diffs since the previous release tag. +3. Update version and changelog only when the user explicitly asks. +4. Run the project test and build commands. +5. Report the version, changed files, verification results, and remaining risks. + +## Rules + +- Do not publish packages unless the user explicitly asks. +- Do not create or push git tags without explicit approval. +- Preserve existing changelog style. +``` + +## 故障排查 + +### `/skills` 中看不到 skill + +检查: + +1. 目录是否位于 Deep Code 扫描位置之一 +2. 文件名是否为 `SKILL.md` +3. `SKILL.md` 是否在独立 skill 目录中,例如 `.deepcode/skills/my-skill/SKILL.md` +4. `enabledSkills` 是否把该 skill 设置为 `false` +5. 是否存在同名 skill 被更高优先级位置覆盖 + +### 自动调用不稳定 + +检查: + +1. `description` 是否包含清晰的使用场景和触发词 +2. skill 是否过宽,导致模型难以判断边界 +3. 是否设置了 `metadata.allow-implicit-invocation: false` +4. 用户请求是否需要更明确地提到该 skill 的领域或文件类型 + +### Skill 内容过长 + +建议: + +1. 保留 `SKILL.md` 中的核心流程和规则 +2. 把长文档移到 `references/` +3. 把重复命令移到 `scripts/` +4. 在 `SKILL.md` 中说明何时读取相关文件 + +## 参考 + +- [Agent Skills Specification](https://agentskills.io/specification) diff --git a/docs/agent-skills_en.md b/docs/agent-skills_en.md new file mode 100644 index 00000000..50f3a2a5 --- /dev/null +++ b/docs/agent-skills_en.md @@ -0,0 +1,322 @@ +# Deep Code CLI Agent Skills Guide + +## Overview + +A good skill is useful when the instruction set is: + +- Reused across tasks, such as code review, release preparation, or report generation +- Too long or detailed to paste into every prompt +- Backed by resources, such as templates, scripts, schemas, examples, or reference docs +- Triggered by a clear situation, such as "process a PDF form" or "create a database migration for this project" + +Do not use a skill for: + +- One-off task requirements +- Short repository rules, which usually belong in `AGENTS.md` +- Live external actions, which usually belong in MCP tools + +## Scan Locations + +Deep Code CLI scans skills in the following order. If multiple skills resolve to the same `name`, only the highest-priority one is kept. + +| Priority | Scope | Path | Purpose | +| -------- | ------- | --------------------- | ------- | +| 1 | Project | `./.deepcode/skills/` | Native Deep Code project skills | +| 2 | Project | `./.agents/skills/` | Project skills shared with other agent clients | +| 3 | User | `~/.deepcode/skills/` | Native Deep Code user skills | +| 4 | User | `~/.agents/skills/` | User skills shared with other agent clients | +| 5 | Global | `built-in` | Skills bundled with Deep Code | + +Example structure: + +```text +.deepcode/ +└── skills/ + └── code-review/ + ├── SKILL.md + ├── checklist.md + └── scripts/ + └── collect-diff.sh +``` + +## Minimal Skill + +Each skill must live in its own directory and contain `SKILL.md`. + +```markdown +--- +name: code-review +description: Review code changes for correctness, regressions, security risks, and missing tests. Use when the user asks for a review, PR review, diff review, or pre-merge check. +--- + +# Code Review + +Use a code review mindset. Prioritize bugs, behavioral regressions, security issues, +and missing tests over style comments. + +## Workflow + +1. Inspect the diff and relevant surrounding code. +2. List findings first, ordered by severity. +3. Include file and line references for every finding. +4. If there are no findings, say so and mention residual risks or test gaps. +``` + +## `SKILL.md` Frontmatter + +Deep Code CLI reads YAML frontmatter at the top of `SKILL.md`. + +| Field | Required | Deep Code behavior | Recommendation | +| ----- | -------- | ------------------ | -------------- | +| `name` | Recommended | Used as the unique skill name. If missing, Deep Code uses the directory name and converts `_` to `-`. | Use lowercase letters, numbers, and hyphens. Keep it aligned with the directory name. | +| `description` | Recommended | Used for automatic matching and shown in `/skills` and the slash menu. | Describe what the skill does, when to use it, and common trigger terms. | +| `metadata.allow-implicit-invocation` | Optional | When set to `false`, the skill is excluded from automatic matching but can still be selected manually. | Use for manual-only skills. | + +Example: + +```yaml +--- +name: db-migration +description: Create and review database migrations for this project. Use when the user asks to add columns, change schema, write migrations, or validate rollback behavior. +metadata: + allow-implicit-invocation: false +--- +``` + +> Deep Code CLI currently interprets only the fields listed above. Other frontmatter fields may be useful for cross-client compatibility or documentation, but they do not automatically restrict Deep Code tool permissions. + +## Write a Strong `description` + +The `description` is the most important discovery signal. During automatic matching, Deep Code gives the model only each skill's `name` and `description`, so specific descriptions match more reliably. + +Recommended pattern: + +```text +. Use when . +``` + +Good examples: + +```yaml +description: Extract tables from PDF files, fill PDF forms, and merge documents. Use when working with PDFs, forms, invoices, statements, or document extraction. +``` + +```yaml +description: Generate Lessweb routes, services, and Pydantic request models. Use when editing Lessweb projects, adding @Get/@Post endpoints, configuring IOC modules, or updating OpenAPI output. +``` + +Avoid: + +```yaml +description: Helps with documents +description: Useful project skill +description: Tooling instructions +``` + +Checklist: + +- State the concrete capability, not only the topic +- State when to use it, not only the expected result +- Include terms users are likely to type +- Include relevant file types, framework names, command names, or domain names +- Avoid overbroad wording that triggers on unrelated tasks + +## Skill Body Structure + +The body of `SKILL.md` should be written for an agent, not for a general reader. Keep it direct, actionable, and verifiable. + +Recommended structure: + +```markdown +# Skill Name + +Briefly state what this skill is for. + +## When to use + +- Use when ... +- Do not use when ... + +## Workflow + +1. Read ... +2. Run ... +3. Edit ... +4. Verify ... + +## Rules + +- Preserve ... +- Never ... +- Ask the user when ... + +## Examples + +... +``` + +Writing principles: + +- Use imperative steps, such as "Read the schema first" or "Run tests after editing" +- Write mandatory constraints as explicit rules +- Define boundaries for high-risk operations, such as deleting files, migrating data, or sending requests +- Document common branches, such as "if no config file exists, search the default paths first" +- Move long reference material out of `SKILL.md` + +## Supporting Resources + +A skill can include files next to `SKILL.md`: + +```text +my-skill/ +├── SKILL.md +├── references/ +│ └── api.md +├── examples/ +│ └── request.json +├── scripts/ +│ └── validate.py +└── templates/ + └── report.md +``` + +Use supporting files for material that would make `SKILL.md` too long or too hard to scan: + +- Put long docs, specs, and API notes in `references/` +- Put input and output samples in `examples/` +- Put reusable commands in `scripts/` +- Put document or code skeletons in `templates/` +- Explain in `SKILL.md` when each supporting file is relevant + +Example: + +```markdown +## Workflow + +1. Read `references/schema.md` before changing generated types. +2. Use `templates/migration.sql` when creating a new migration. +3. Run `python scripts/check_migration.py ` before reporting completion. +``` + +## Invocation + +Deep Code CLI supports automatic and manual skill invocation. + +### Automatic Invocation + +After each user message, Deep Code checks the available skills' `name` and `description` fields and selects the skills that match the task. Matching skills are loaded into the current session. + +Automatic invocation rules: + +- A loaded skill is not loaded again in the same session +- A skill with `metadata.allow-implicit-invocation: false` is not loaded automatically +- Matching considers the current `AGENTS.md` instructions +- If no skill matches, no skill is loaded + +### Manual Invocation + +Type `/` in the input box to open the skills and commands menu, then select a skill. Use `/skills` to list available skills. + +Common commands: + +| Command | Behavior | +| ------- | -------- | +| `/` | Open the skills and commands menu | +| `/skills` | List available skills | +| `/` | Select the matching skill from the menu | + +## Enable and Disable Skills + +Use `enabledSkills` in `settings.json` to enable or disable skills by name. + +```json +{ + "enabledSkills": { + "code-review": true, + "db-migration": false + } +} +``` + +Rules: + +- Skills not listed are enabled by default +- Setting a skill to `false` hides every scanned skill with that resolved name +- Project settings override user settings per skill + +For more details, see [configuration_en.md](configuration_en.md). + +## Skills vs. `AGENTS.md` vs. MCP + +| Mechanism | Best for | Not best for | +| --------- | -------- | ------------ | +| `AGENTS.md` | Long-lived repository rules, coding style, test commands, collaboration conventions | Reusable complex workflows or cross-project tool instructions | +| Agent Skill | Reusable workflows, domain knowledge, templates, scripts, reference docs | Temporary requirements for a single task | +| MCP | External systems, live data, browser control, databases, GitHub, and other tool calls | Pure text workflow instructions | + +Common pattern: + +- Put repository rules in `AGENTS.md` +- Put reusable workflows in skills +- Put external actions behind MCP tools + +## Example: Project Release Skill + +```markdown +--- +name: release-check +description: Prepare and verify a project release. Use when the user asks to release, publish, bump version, update changelog, or run pre-release checks. +--- + +# Release Check + +Use this skill to prepare a safe release for this repository. + +## Workflow + +1. Read `package.json` and the existing changelog. +2. Inspect commits or diffs since the previous release tag. +3. Update version and changelog only when the user explicitly asks. +4. Run the project test and build commands. +5. Report the version, changed files, verification results, and remaining risks. + +## Rules + +- Do not publish packages unless the user explicitly asks. +- Do not create or push git tags without explicit approval. +- Preserve existing changelog style. +``` + +## Troubleshooting + +### The skill does not appear in `/skills` + +Check: + +1. The directory is under one of the Deep Code scan locations +2. The file is named `SKILL.md` +3. `SKILL.md` is inside its own skill directory, such as `.deepcode/skills/my-skill/SKILL.md` +4. `enabledSkills` has not set the skill to `false` +5. A higher-priority skill with the same name is not shadowing it + +### Automatic invocation is unreliable + +Check: + +1. The `description` contains clear use cases and trigger terms +2. The skill is not so broad that the model cannot infer its boundary +3. `metadata.allow-implicit-invocation` is not set to `false` +4. The user request mentions the relevant domain or file type clearly enough + +### The skill is too long + +Recommendations: + +1. Keep the core workflow and rules in `SKILL.md` +2. Move long documentation into `references/` +3. Move repeatable commands into `scripts/` +4. Explain when the agent should read each supporting file + +## References + +- [Agent Skills Specification](https://agentskills.io/specification) From fb4aaa88fcb5c2f0df5b3a6db190119686c3702b Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Fri, 12 Jun 2026 16:07:42 +0800 Subject: [PATCH 14/72] feat: add agents-md.md and quickstart.md --- docs/agent-skills.md | 2 +- docs/agent-skills_en.md | 2 +- docs/agents-md.md | 220 ++++++++++++++++++++++++++++++++++++++++ docs/agents-md_en.md | 220 ++++++++++++++++++++++++++++++++++++++++ docs/quickstart.md | 197 +++++++++++++++++++++++++++++++++++ docs/quickstart_en.md | 197 +++++++++++++++++++++++++++++++++++ 6 files changed, 836 insertions(+), 2 deletions(-) create mode 100644 docs/agents-md.md create mode 100644 docs/agents-md_en.md create mode 100644 docs/quickstart.md create mode 100644 docs/quickstart_en.md diff --git a/docs/agent-skills.md b/docs/agent-skills.md index b1bd4e45..9ba77ab5 100644 --- a/docs/agent-skills.md +++ b/docs/agent-skills.md @@ -1,4 +1,4 @@ -# Deep Code CLI Agent Skills 指南 +# Agent Skills ## 概述 diff --git a/docs/agent-skills_en.md b/docs/agent-skills_en.md index 50f3a2a5..13d2ad7b 100644 --- a/docs/agent-skills_en.md +++ b/docs/agent-skills_en.md @@ -1,4 +1,4 @@ -# Deep Code CLI Agent Skills Guide +# Agent Skills ## Overview diff --git a/docs/agents-md.md b/docs/agents-md.md new file mode 100644 index 00000000..9888e7c9 --- /dev/null +++ b/docs/agents-md.md @@ -0,0 +1,220 @@ +# AGENTS.md + +`AGENTS.md` 是写给 AI 编码助手的项目说明文件。它用于记录长期有效的项目规则,让 Deep Code 在这个仓库中工作时知道如何安装依赖、运行测试、修改代码、提交变更,以及遵守哪些团队约定。 + +如果你经常在提示词里重复说明“先运行哪个测试”“不要修改哪个目录”“PR 描述要包含什么”,就适合把这些内容写进 `AGENTS.md`。 + +## 适合写什么 + +`AGENTS.md` 适合保存当前项目的稳定规则: + +- 项目结构和重要目录 +- 安装、开发、构建、测试命令 +- 代码风格、命名约定、格式化要求 +- 测试要求和验证步骤 +- 提交、PR、发布流程 +- 安全、配置、凭据处理注意事项 +- 只对本仓库有效的 AI 协作规则 + +不适合写入 `AGENTS.md` 的内容: + +- 一次性任务要求,例如“这次只改登录页” +- 复杂可复用工作流,此类内容更适合写成 Agent Skill +- 外部系统连接信息,此类能力更适合通过 MCP 配置 +- API Key、密码、Token 等敏感信息 + +## 创建文件 + +在项目中运行: + +```text +/init +``` + +Deep Code 会帮助你创建或更新 `AGENTS.md`。你也可以手动创建: + +```bash +touch AGENTS.md +``` + +如果你希望把说明放在 Deep Code 专用目录中,也可以使用: + +```bash +mkdir -p .deepcode +touch .deepcode/AGENTS.md +``` + +常见选择: + +| 文件 | 适合场景 | +| ---- | -------- | +| `AGENTS.md` | 希望项目中的不同 AI 编码工具都能读取 | +| `.deepcode/AGENTS.md` | 希望规则只面向 Deep Code | +| `~/.deepcode/AGENTS.md` | 个人默认偏好,适用于没有项目说明的仓库 | + +## 推荐结构 + +保持简短、清晰、可执行。推荐从下面这些章节开始: + +```markdown +# 仓库指南 + +## 项目结构 + +说明主要目录,以及新增代码应该放在哪里。 + +## 开发命令 + +- `npm install` — 安装依赖。 +- `npm test` — 运行测试套件。 +- `npm run build` — 构建项目。 + +## 代码风格 + +说明格式化、命名和框架约定。 + +## 测试 + +说明什么时候需要添加测试,以及需要运行哪些命令。 + +## Pull Request + +说明提交风格、PR 检查项、截图或发布说明要求。 + +## AI 助手注意事项 + +列出 AI 助手需要遵守的规则,例如不要修改哪些文件,或完成前要执行哪些检查。 +``` + +你不需要保留所有章节。只写对当前项目有帮助的内容。 + +## 写作原则 + +### 写具体命令 + +推荐: + +```markdown +## 开发命令 + +- `npm install` — 安装依赖。 +- `npm test` — 运行全部测试。 +- `npm run build` — 执行类型检查并构建 CLI。 +``` + +避免: + +```markdown +完成前运行常用命令。 +``` + +### 写明确规则 + +推荐: + +```markdown +## 测试 + +修改行为时需要新增或更新测试。完成前,测试相关修改运行 +`npm test`,代码修改运行 `npm run build`。 +``` + +避免: + +```markdown +确保一切正常。 +``` + +### 写项目事实 + +推荐: + +```markdown +## 项目结构 + +- `src/` 存放应用代码。 +- `tests/` 存放自动化测试。 +- `docs/` 存放面向用户的文档。 +``` + +避免: + +```markdown +这是一个普通的 TypeScript 项目。 +``` + +### 写安全边界 + +推荐: + +```markdown +## 安全 + +不要提交 API Key 或 Token。本地凭据放在 `~/.deepcode/settings.json`, +项目示例中的敏感信息需要脱敏。 +``` + +避免: + +```markdown +注意保护密钥。 +``` + +## 示例 + +下面是一个较完整的 `AGENTS.md` 示例: + +```markdown +# 仓库指南 + +## 项目结构 + +- `src/` 存放应用代码。 +- `src/tests/` 存放自动化测试。 +- `docs/` 存放面向用户的文档。 +- `config/` 存放项目配置示例。 + +## 开发命令 + +- `npm install` — 安装依赖。 +- `npm test` — 运行自动化测试。 +- `npm run build` — 运行检查并构建 CLI。 + +## 代码风格 + +使用 TypeScript。保持代码清晰,优先使用明确命名,并遵循现有 +格式风格。不要引入无关重构。 + +## 测试 + +修改行为时需要添加测试。优先运行范围最小的相关测试;条件允许时, +完成前运行 `npm test` 或 `npm run build`。 + +## AI 助手注意事项 + +- 不要提交密钥或本地生成文件。 +- 保留用户已有修改。 +- 说明无法执行的验证步骤。 +``` + +## 与 Skills、MCP 的区别 + +| 工具 | 适合放什么 | +| ---- | ---------- | +| `AGENTS.md` | 当前仓库的长期规则、命令、风格、验证步骤 | +| Agent Skill | 可复用工作流、领域知识、模板、脚本、参考资料 | +| MCP | GitHub、浏览器、数据库等外部工具和实时数据 | + +常见组合: + +- 在 `AGENTS.md` 中写“这个项目怎么做” +- 在 Agent Skill 中写“这类任务怎么做” +- 用 MCP 提供“需要连接外部服务才能做”的能力 + +## 维护建议 + +- 项目命令变化后及时更新 +- 删除已经过期的规则 +- 避免写太长,优先保留高频、重要、容易出错的约定 +- 不要写敏感信息 +- 如果规则只适用于某次任务,直接写在当前对话中即可 diff --git a/docs/agents-md_en.md b/docs/agents-md_en.md new file mode 100644 index 00000000..e63047b1 --- /dev/null +++ b/docs/agents-md_en.md @@ -0,0 +1,220 @@ +# AGENTS.md + +`AGENTS.md` is a project instruction file for AI coding assistants. Use it to record long-lived repository rules so Deep Code knows how to install dependencies, run tests, edit code, prepare changes, and follow team conventions. + +If you often repeat instructions such as "run this test first", "do not edit that directory", or "include these details in the PR summary", put them in `AGENTS.md`. + +## What to Include + +Use `AGENTS.md` for stable project rules: + +- Project structure and important directories +- Install, development, build, and test commands +- Coding style, naming conventions, and formatting rules +- Testing expectations and verification steps +- Commit, pull request, and release conventions +- Security, configuration, and credential handling notes +- AI collaboration rules that apply only to this repository + +Do not use `AGENTS.md` for: + +- One-off task requirements, such as "only edit the login page this time" +- Complex reusable workflows, which are better as Agent Skills +- External service connections, which are better configured with MCP +- API keys, passwords, tokens, or other secrets + +## Create the File + +Run this inside a project: + +```text +/init +``` + +Deep Code helps create or update `AGENTS.md`. You can also create it manually: + +```bash +touch AGENTS.md +``` + +If you want Deep Code-specific project instructions, you can use: + +```bash +mkdir -p .deepcode +touch .deepcode/AGENTS.md +``` + +Common choices: + +| File | Best for | +| ---- | -------- | +| `AGENTS.md` | Rules that should be visible to multiple AI coding tools | +| `.deepcode/AGENTS.md` | Rules intended only for Deep Code | +| `~/.deepcode/AGENTS.md` | Personal defaults for repositories without project instructions | + +## Recommended Structure + +Keep it short, clear, and actionable. Start with sections like these: + +```markdown +# Repository Guidelines + +## Project Structure + +Describe the main directories and where new code should go. + +## Development Commands + +- `npm install` — Install dependencies. +- `npm test` — Run the test suite. +- `npm run build` — Build the project. + +## Coding Style + +Describe formatting, naming, and framework conventions. + +## Testing + +Explain when to add tests and which commands to run. + +## Pull Requests + +Describe commit style, PR checklist, screenshots, or release notes. + +## Agent Notes + +List rules for AI assistants, such as files to avoid or checks to run before finishing. +``` + +You do not need every section. Keep only what helps in this repository. + +## Writing Principles + +### Write Concrete Commands + +Good: + +```markdown +## Development Commands + +- `npm install` — Install dependencies. +- `npm test` — Run all tests. +- `npm run build` — Type-check and build the CLI. +``` + +Avoid: + +```markdown +Run the usual commands before finishing. +``` + +### Write Explicit Rules + +Good: + +```markdown +## Testing + +Add or update tests when changing behavior. Before reporting completion, run +`npm test` for test-only changes and `npm run build` for code changes. +``` + +Avoid: + +```markdown +Make sure everything works. +``` + +### Write Repository Facts + +Good: + +```markdown +## Project Structure + +- `src/` contains application code. +- `tests/` contains automated tests. +- `docs/` contains user-facing documentation. +``` + +Avoid: + +```markdown +This is a normal TypeScript project. +``` + +### Write Safety Boundaries + +Good: + +```markdown +## Security + +Do not commit API keys or tokens. Use `~/.deepcode/settings.json` for local +credentials and keep project examples redacted. +``` + +Avoid: + +```markdown +Be careful with secrets. +``` + +## Example + +Here is a complete `AGENTS.md` example: + +```markdown +# Repository Guidelines + +## Project Structure + +- `src/` contains application code. +- `src/tests/` contains automated tests. +- `docs/` contains user-facing documentation. +- `config/` contains project configuration examples. + +## Development Commands + +- `npm install` — Install dependencies. +- `npm test` — Run automated tests. +- `npm run build` — Run checks and build the CLI. + +## Coding Style + +Use TypeScript. Keep code readable, prefer clear names, and follow the existing +formatting style. Do not introduce unrelated refactors. + +## Testing + +Add tests when changing behavior. Run the narrowest relevant test first, then +run `npm test` or `npm run build` before reporting completion when practical. + +## Agent Notes + +- Do not commit secrets or generated local files. +- Preserve existing user changes. +- Explain any verification step that could not be run. +``` + +## AGENTS.md vs. Skills vs. MCP + +| Mechanism | Best for | +| --------- | -------- | +| `AGENTS.md` | Long-lived repository rules, commands, style, and verification steps | +| Agent Skill | Reusable workflows, domain knowledge, templates, scripts, and reference docs | +| MCP | External tools and live data, such as GitHub, browsers, or databases | + +Common pattern: + +- Put "how this project works" in `AGENTS.md` +- Put "how this type of task works" in an Agent Skill +- Use MCP for work that requires external services + +## Maintenance Tips + +- Update commands when the project changes +- Remove outdated rules +- Keep it concise; prioritize frequent, important, and easy-to-miss conventions +- Do not include secrets +- If a rule applies only to the current task, write it in the current conversation instead diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 00000000..8de1f3ce --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,197 @@ +# 快速开始 + +Deep Code 是一款开源的终端 AI 编程助手,专为 DeepSeek-V4 系列模型适配,支持深度思考、推理强度控制,并通过 Skills 和 MCP 扩展更多能力。 + +## 前置要求 + +使用前请确认本机已安装: + +- Node.js `22` 或更高版本 +- 一个可用的 DeepSeek API Key + +## 安装 + +使用 npm 全局安装: + +```bash +npm install -g @vegamo/deepcode-cli +``` + +安装后检查版本: + +```bash +deepcode --version +``` + +## 配置 DeepSeek-V4 + +Deep Code 推荐使用 `deepseek-v4-pro`,也支持 `deepseek-v4-flash`。创建 `~/.deepcode/settings.json`,写入你的 DeepSeek 模型配置: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-..." + }, + "thinkingEnabled": true, + "reasoningEffort": "max" +} +``` + +把 `API_KEY` 替换成你的 DeepSeek API Key。 + +常用字段: + +| 字段 | 说明 | +| ---- | ---- | +| `env.MODEL` | DeepSeek 模型名称,推荐 `deepseek-v4-pro` | +| `env.BASE_URL` | DeepSeek API 地址,默认 `https://api.deepseek.com` | +| `env.API_KEY` | DeepSeek API Key | +| `thinkingEnabled` | 是否启用思考模式 | +| `reasoningEffort` | 推理强度,常用 `"high"` 或 `"max"` | + +也可以在项目目录中创建 `.deepcode/settings.json`,为当前项目单独设置模型、权限或 MCP。 + +更多 DeepSeek 官方配置说明可参考 [Deep Code 集成指南](https://api-docs.deepseek.com/zh-cn/quick_start/agent_integrations/deepcode)。 + +更多配置项请参考 [configuration.md](configuration.md)。 + +## 启动 + +进入你的项目目录: + +```bash +cd path/to/your/project +deepcode +``` + +Deep Code 会在当前目录中启动交互式界面。你可以直接输入任务,然后按 `Enter` 发送。 + +如果想带着初始问题启动: + +```bash +deepcode -p "总结这个项目" +``` + +## 第一次可以这样问 + +可以先从只读任务开始: + +```text +总结这个仓库,并说明如何运行它。 +``` + +```text +找出主要入口文件,并解释请求流程。 +``` + +然后尝试让 Deep Code 修改代码: + +```text +为登录校验逻辑添加一个单元测试。 +``` + +```text +运行测试用例,并修复失败的测试。 +``` + +也可以让它先给出计划: + +```text +在修改文件前,先给出一个为用户列表添加分页的计划。 +``` + +## 常用操作 + +| 操作 | 用法 | +| ---- | ---- | +| 发送消息 | `Enter` | +| 输入多行 | `Shift+Enter` 或 `Ctrl+J` | +| 中断当前回复 | `Esc` | +| 粘贴图片 | `Ctrl+V` | +| 退出 | 连续按两次 `Ctrl+D`,或使用 `/exit` | + +## 斜杠命令 + +在输入框中输入 `/` 可以打开命令菜单。 + +| 命令 | 作用 | +| ---- | ---- | +| `/new` | 开始新对话 | +| `/resume` | 选择历史对话继续 | +| `/continue` | 继续当前对话,或恢复最近的对话 | +| `/model` | 切换模型、思考模式和推理强度 | +| `/init` | 为当前项目生成 `AGENTS.md` 指令文件 | +| `/skills` | 查看可用 Agent Skills | +| `/mcp` | 查看 MCP 服务状态和可用工具 | +| `/undo` | 将代码和/或对话恢复到之前的状态 | +| `/raw` | 切换显示模式 | +| `/exit` | 退出 Deep Code | + +## 为项目添加说明 + +在项目中运行: + +```text +/init +``` + +Deep Code 会帮助你创建 `AGENTS.md`。这个文件适合记录项目约定,例如: + +- 项目如何安装依赖和运行测试 +- 代码风格和提交要求 +- 重要目录说明 +- 修改代码前后需要执行的检查 + +之后 Deep Code 在该项目中工作时会自动参考这些说明。 + +## 使用 Skills + +Agent Skills 适合保存可复用工作流,例如代码审查、发布检查、文档生成或某个框架的固定开发流程。 + +查看可用 skills: + +```text +/skills +``` + +也可以输入 `/`,在菜单中选择某个 skill。 + +更多说明请参考 [agent-skills.md](agent-skills.md)。 + +## 连接外部工具 + +如果你想让 Deep Code 连接 GitHub、浏览器、数据库或其他服务,可以配置 MCP。 + +配置后,在 Deep Code 中运行: + +```text +/mcp +``` + +即可查看已连接的 MCP 服务和可用工具。 + +更多说明请参考 [mcp.md](mcp.md)。 + +## 权限与安全 + +Deep Code 可能会读取文件、修改代码或运行命令。你可以通过权限配置控制哪些操作自动允许、哪些操作需要确认、哪些操作直接拒绝。 + +Deep Code 默认支持 YOLO 模式,可以更流畅地执行读写文件、运行命令等操作。如果你希望更谨慎,可以使用严格模式,让 Deep Code 在执行较高风险操作前询问你。 + +更多说明请参考 [permission.md](permission.md)。 + +## 任务完成通知 + +如果希望 Deep Code 完成任务后通知你,可以配置通知脚本,例如发送 Slack、飞书、系统通知或终端提示。 + +更多说明请参考 [notify.md](notify.md)。 + +## 下一步 + +- 阅读完整配置说明:[configuration.md](configuration.md) +- 配置权限策略:[permission.md](permission.md) +- 编写 Agent Skills:[agent-skills.md](agent-skills.md) +- 配置 MCP 外部工具:[mcp.md](mcp.md) +- 配置任务完成通知:[notify.md](notify.md) diff --git a/docs/quickstart_en.md b/docs/quickstart_en.md new file mode 100644 index 00000000..44f62692 --- /dev/null +++ b/docs/quickstart_en.md @@ -0,0 +1,197 @@ +# Quickstart + +Deep Code is an open-source terminal AI coding assistant for the DeepSeek-V4 model, supporting deep thinking, reasoning effort control, and extend its capabilities with Skills and MCP. + +## Prerequisites + +Before you start, make sure you have: + +- Node.js `22` or later +- A DeepSeek API key + +## Install + +Install Deep Code globally with npm: + +```bash +npm install -g @vegamo/deepcode-cli +``` + +Check the installed version: + +```bash +deepcode --version +``` + +## Configure DeepSeek-V4 + +Deep Code recommends `deepseek-v4-pro` and also supports `deepseek-v4-flash`. Create `~/.deepcode/settings.json` and add your DeepSeek model configuration: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-..." + }, + "thinkingEnabled": true, + "reasoningEffort": "max" +} +``` + +Replace `API_KEY` with your DeepSeek API key. + +Common fields: + +| Field | Description | +| ----- | ----------- | +| `env.MODEL` | DeepSeek model name, recommended `deepseek-v4-pro` | +| `env.BASE_URL` | DeepSeek API endpoint, default `https://api.deepseek.com` | +| `env.API_KEY` | DeepSeek API key | +| `thinkingEnabled` | Whether to enable thinking mode | +| `reasoningEffort` | Reasoning effort, commonly `"high"` or `"max"` | + +You can also create `.deepcode/settings.json` inside a project to customize the model, permissions, or MCP settings for that project only. + +For DeepSeek's official setup notes, see the [Deep Code integration guide](https://api-docs.deepseek.com/zh-cn/quick_start/agent_integrations/deepcode). + +For all configuration options, see [configuration_en.md](configuration_en.md). + +## Start + +Open your project directory: + +```bash +cd path/to/your/project +deepcode +``` + +Deep Code starts an interactive terminal UI in the current directory. Type a task and press `Enter`. + +To start with an initial prompt: + +```bash +deepcode -p "Summarize this project" +``` + +## Try These First + +Start with a read-only task: + +```text +Summarize this repository and explain how to run it. +``` + +```text +Find the main entry points and explain the request flow. +``` + +Then try a coding task: + +```text +Add a unit test for the login validation logic. +``` + +```text +Run the test suite and fix the failing tests. +``` + +You can also ask for a plan first: + +```text +Before editing files, propose a plan for adding pagination to the user list. +``` + +## Basic Controls + +| Action | Key | +| ------ | --- | +| Send message | `Enter` | +| Insert a newline | `Shift+Enter` or `Ctrl+J` | +| Interrupt the current response | `Esc` | +| Paste an image | `Ctrl+V` | +| Quit | Press `Ctrl+D` twice, or use `/exit` | + +## Slash Commands + +Type `/` in the input box to open the command menu. + +| Command | Action | +| ------- | ------ | +| `/new` | Start a new conversation | +| `/resume` | Choose a previous conversation to continue | +| `/continue` | Continue the current conversation or resume the latest one | +| `/model` | Switch model, thinking mode, and reasoning effort | +| `/init` | Create an `AGENTS.md` instruction file for the current project | +| `/skills` | Show available Agent Skills | +| `/mcp` | Show MCP server status and available tools | +| `/undo` | Restore code and/or conversation to an earlier point | +| `/raw` | Change the display mode | +| `/exit` | Quit Deep Code | + +## Add Project Instructions + +Run this inside a project: + +```text +/init +``` + +Deep Code helps create `AGENTS.md`. Use it to record project conventions, such as: + +- How to install dependencies and run tests +- Code style and contribution expectations +- Important directory notes +- Checks to run before or after editing code + +Deep Code automatically uses these instructions when working in the project. + +## Use Skills + +Agent Skills are reusable workflows, such as code review, release checks, documentation generation, or framework-specific development steps. + +List available skills: + +```text +/skills +``` + +You can also type `/` and choose a skill from the menu. + +For more details, see [agent-skills_en.md](agent-skills_en.md). + +## Connect External Tools + +Use MCP to connect Deep Code to GitHub, browsers, databases, or other services. + +After configuring MCP, run: + +```text +/mcp +``` + +This shows connected MCP servers and available tools. + +For setup instructions, see [mcp_en.md](mcp_en.md). + +## Permissions and Safety + +Deep Code may read files, edit code, or run commands. You can configure which actions are allowed automatically, which require confirmation, and which are denied. + +Deep Code supports YOLO mode by default, so it can smoothly read and write files, run commands, and continue common coding tasks. If you prefer a more cautious setup, use strict permissions so Deep Code asks before higher-risk actions. + +For details, see [permission_en.md](permission_en.md). + +## Task Completion Notifications + +Deep Code can run a notification script when a task finishes, such as sending a Slack message, Feishu message, system notification, or terminal alert. + +For examples, see [notify_en.md](notify_en.md). + +## Next Steps + +- Read the full configuration guide: [configuration_en.md](configuration_en.md) +- Configure permissions: [permission_en.md](permission_en.md) +- Write Agent Skills: [agent-skills_en.md](agent-skills_en.md) +- Configure MCP tools: [mcp_en.md](mcp_en.md) +- Configure task completion notifications: [notify_en.md](notify_en.md) From cb35887e7ee1fcc55dd5267cdfab2d1ac4d617a2 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Sat, 13 Jun 2026 00:02:30 +0800 Subject: [PATCH 15/72] feat: update karpathy-guidelines.md to enhance clarity on success criteria and implementation checks --- templates/skills/karpathy-guidelines.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/templates/skills/karpathy-guidelines.md b/templates/skills/karpathy-guidelines.md index ae47e9da..36137d81 100644 --- a/templates/skills/karpathy-guidelines.md +++ b/templates/skills/karpathy-guidelines.md @@ -10,8 +10,6 @@ Behavioral guidelines to reduce common LLM coding mistakes. **Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment. -**Internal use:** Apply these guidelines silently. Do not cite this document, its title, or guideline names in user-facing responses. - ## 1. Think Before Coding **Don't assume. Don't hide confusion. Surface tradeoffs.** @@ -54,6 +52,15 @@ The test: Every changed line should trace directly to the user's request. **Define success criteria. Loop until verified.** +Before implementing, define the exact observable acceptance check: +- Command output +- Test assertion +- UI state +- File diff +- API response + +Do not start implementation if "works" cannot be checked objectively. If the check is unclear and would change the solution, ask before coding using AskUserQuestion tool. + Transform tasks into verifiable goals: - "Add validation" → "Write tests for invalid inputs, then make them pass" - "Fix the bug" → "Write a test that reproduces it, then make it pass" @@ -67,3 +74,16 @@ For multi-step tasks, state a brief plan: ``` Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. + +## 5. No Proxy Success + +**Passing means the acceptance check passes.** + +Don't substitute weaker signals: +- "No crash" unless that was the goal. +- "Non-empty output" unless any output is valid. +- "Looks plausible" unless the task is subjective. +- "Some tests pass" while the target check fails. +- "Implementation complete" without verification. + +Report exact pass, partial progress, or failure. From b9117ec1c141bfb0f14efb48e6fb1b234bbc4197 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Sat, 13 Jun 2026 00:19:30 +0800 Subject: [PATCH 16/72] feat: update templates/skills/bundled/deepcode-self-refer/SKILL.md --- .../bundled/deepcode-self-refer/SKILL.md | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/templates/skills/bundled/deepcode-self-refer/SKILL.md b/templates/skills/bundled/deepcode-self-refer/SKILL.md index 96f275f8..56b902ef 100644 --- a/templates/skills/bundled/deepcode-self-refer/SKILL.md +++ b/templates/skills/bundled/deepcode-self-refer/SKILL.md @@ -58,9 +58,23 @@ Use the `Read` tool to read the appropriate document(s) from the list above. All ### Step 4: Handle common request patterns **"列出/查看可用的 skills":** -- Explain the skill scanning paths from references/README.md (`./.deepcode/skills/`, `./.agents/skills/`, `~/.deepcode/skills/`, `~/.agents/skills/`, and bundled built-in skills) -- Explain that `/skills` slash command lists available skills -- Mention `enabledSkills` in `settings.json` for enabling/disabling specific skills +- Treat `/skills` as the canonical UI for listing currently available skills. +- If answering directly, do not infer the list only from loaded skill prompts or from project/user directories. Enumerate all discovery roots: + 1. `./.deepcode/skills//SKILL.md` + 2. `./.agents/skills//SKILL.md` + 3. `~/.deepcode/skills//SKILL.md` + 4. `~/.agents/skills//SKILL.md` + 5. bundled built-in skills as `bundled:/SKILL.md` +- For a source checkout, bundled skills live under `templates/skills/bundled//SKILL.md`. For a packaged install, bundled skills may live under `dist/bundled//SKILL.md`. +- Read each candidate `SKILL.md` frontmatter to get the resolved `name` and `description`; the folder name is only a fallback. +- De-duplicate by resolved `name`, keeping the highest-priority root from the order above. +- Apply `enabledSkills` from `settings.json`: if `enabledSkills[""] === false`, do not list that skill as available. +- Clearly separate discoverable skills from other concepts: + - Discoverable skills are selectable through `/skills` and come from the roots above. + - Bundled skills are discoverable skills shipped with Deep Code, such as `bundled:deepcode-self-refer/SKILL.md`. + - Default prompt templates or always-injected guidance are not necessarily discoverable skills unless they also exist as `*/SKILL.md` in one of the scan roots. + - Slash commands such as `/skills`, `/mcp`, and `/undo` are commands, not skills. +- Mention that `/skills` can be used to verify the result and `enabledSkills` can enable/disable specific skills by name. **"配置 MCP":** - Read `references/mcp.md` for the MCP format and examples @@ -90,9 +104,11 @@ Use the `Read` tool to read the appropriate document(s) from the list above. All ### Example 1: "列出可用的skills" -Read references/README.md, locate the Skills section. Answer: +Read references/README.md, locate the Skills section, then enumerate all scan roots including bundled skills. Answer: - Skills are discovered from: `./.deepcode/skills/`, `./.agents/skills/`, `~/.deepcode/skills/`, `~/.agents/skills/`, and bundled built-in skills such as `bundled:deepcode-self-refer/SKILL.md`. +- In a source checkout, check `templates/skills/bundled/*/SKILL.md`; in a packaged install, check `dist/bundled/*/SKILL.md`. +- Built-in bundled skills may include `deepcode-self-refer`, `plan`, `skill-digester`, and `skill-writer`; verify the actual list by scanning the bundled root because it can change between versions. - Use `/skills` slash command in the Deep Code CLI to list all available skills - Use `enabledSkills` in `settings.json` to enable/disable skills by name From 1d5f6f36c8d775ab1fcb1247c49198aa542a9c11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 13 Jun 2026 00:03:47 +0000 Subject: [PATCH 17/72] chore(deps-dev): bump esbuild and tsx Bumps [esbuild](https://github.com/evanw/esbuild) and [tsx](https://github.com/privatenumber/tsx). These dependencies needed to be updated together. Updates `esbuild` from 0.28.0 to 0.28.1 - [Release notes](https://github.com/evanw/esbuild/releases) - [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md) - [Commits](https://github.com/evanw/esbuild/compare/v0.28.0...v0.28.1) Updates `tsx` from 4.21.0 to 4.22.4 - [Release notes](https://github.com/privatenumber/tsx/releases) - [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs) - [Commits](https://github.com/privatenumber/tsx/compare/v4.21.0...v4.22.4) --- updated-dependencies: - dependency-name: esbuild dependency-version: 0.28.1 dependency-type: direct:development - dependency-name: tsx dependency-version: 4.22.4 dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- package-lock.json | 730 +++++++--------------------------------------- 1 file changed, 111 insertions(+), 619 deletions(-) diff --git a/package-lock.json b/package-lock.json index 09db34ab..6de20e9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -299,9 +299,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", - "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" ], @@ -316,9 +316,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.0.tgz", - "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" ], @@ -333,9 +333,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", - "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" ], @@ -350,9 +350,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.0.tgz", - "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" ], @@ -367,9 +367,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", - "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" ], @@ -384,9 +384,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", - "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" ], @@ -401,9 +401,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", - "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" ], @@ -418,9 +418,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", - "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" ], @@ -435,9 +435,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", - "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" ], @@ -452,9 +452,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", - "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" ], @@ -469,9 +469,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", - "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" ], @@ -486,9 +486,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", - "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" ], @@ -503,9 +503,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", - "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" ], @@ -520,9 +520,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", - "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" ], @@ -537,9 +537,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", - "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" ], @@ -554,9 +554,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", - "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" ], @@ -571,9 +571,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", - "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" ], @@ -588,9 +588,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", - "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" ], @@ -605,9 +605,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", - "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" ], @@ -622,9 +622,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", - "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" ], @@ -639,9 +639,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", - "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" ], @@ -656,9 +656,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", - "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "cpu": [ "arm64" ], @@ -673,9 +673,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", - "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" ], @@ -690,9 +690,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", - "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" ], @@ -707,9 +707,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", - "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" ], @@ -724,9 +724,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", - "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" ], @@ -1773,9 +1773,9 @@ ] }, "node_modules/esbuild": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.0.tgz", - "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1786,32 +1786,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.0", - "@esbuild/android-arm": "0.28.0", - "@esbuild/android-arm64": "0.28.0", - "@esbuild/android-x64": "0.28.0", - "@esbuild/darwin-arm64": "0.28.0", - "@esbuild/darwin-x64": "0.28.0", - "@esbuild/freebsd-arm64": "0.28.0", - "@esbuild/freebsd-x64": "0.28.0", - "@esbuild/linux-arm": "0.28.0", - "@esbuild/linux-arm64": "0.28.0", - "@esbuild/linux-ia32": "0.28.0", - "@esbuild/linux-loong64": "0.28.0", - "@esbuild/linux-mips64el": "0.28.0", - "@esbuild/linux-ppc64": "0.28.0", - "@esbuild/linux-riscv64": "0.28.0", - "@esbuild/linux-s390x": "0.28.0", - "@esbuild/linux-x64": "0.28.0", - "@esbuild/netbsd-arm64": "0.28.0", - "@esbuild/netbsd-x64": "0.28.0", - "@esbuild/openbsd-arm64": "0.28.0", - "@esbuild/openbsd-x64": "0.28.0", - "@esbuild/openharmony-arm64": "0.28.0", - "@esbuild/sunos-x64": "0.28.0", - "@esbuild/win32-arm64": "0.28.0", - "@esbuild/win32-ia32": "0.28.0", - "@esbuild/win32-x64": "0.28.0" + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" } }, "node_modules/escalade": { @@ -2238,19 +2238,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-tsconfig": { - "version": "4.14.0", - "resolved": "https://registry.npmmirror.com/get-tsconfig/-/get-tsconfig-4.14.0.tgz", - "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, "node_modules/glob": { "version": "13.0.6", "resolved": "https://registry.npmmirror.com/glob/-/glob-13.0.6.tgz", @@ -3247,16 +3234,6 @@ "node": ">=4" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/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/restore-cursor": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", @@ -3529,14 +3506,13 @@ } }, "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmmirror.com/tsx/-/tsx-4.21.0.tgz", - "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz", + "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.27.0", - "get-tsconfig": "^4.7.5" + "esbuild": "~0.28.0" }, "bin": { "tsx": "dist/cli.mjs" @@ -3548,490 +3524,6 @@ "fsevents": "~2.3.3" } }, - "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" - } - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", From 66cc09826fa3a5f616c1f1841caebc1aab38bcc0 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Mon, 15 Jun 2026 10:21:31 +0800 Subject: [PATCH 18/72] feat: update karpathy-guidelines.md --- templates/skills/karpathy-guidelines.md | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/templates/skills/karpathy-guidelines.md b/templates/skills/karpathy-guidelines.md index 36137d81..41e23d73 100644 --- a/templates/skills/karpathy-guidelines.md +++ b/templates/skills/karpathy-guidelines.md @@ -1,7 +1,6 @@ --- name: karpathy-guidelines description: Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid overcomplication, make surgical changes, surface assumptions, and define verifiable success criteria. -license: MIT --- # Karpathy Guidelines @@ -52,15 +51,6 @@ The test: Every changed line should trace directly to the user's request. **Define success criteria. Loop until verified.** -Before implementing, define the exact observable acceptance check: -- Command output -- Test assertion -- UI state -- File diff -- API response - -Do not start implementation if "works" cannot be checked objectively. If the check is unclear and would change the solution, ask before coding using AskUserQuestion tool. - Transform tasks into verifiable goals: - "Add validation" → "Write tests for invalid inputs, then make them pass" - "Fix the bug" → "Write a test that reproduces it, then make it pass" @@ -73,17 +63,4 @@ For multi-step tasks, state a brief plan: 3. [Step] → verify: [check] ``` -Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. - -## 5. No Proxy Success - -**Passing means the acceptance check passes.** - -Don't substitute weaker signals: -- "No crash" unless that was the goal. -- "Non-empty output" unless any output is valid. -- "Looks plausible" unless the task is subjective. -- "Some tests pass" while the target check fails. -- "Implementation complete" without verification. - -Report exact pass, partial progress, or failure. +Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. \ No newline at end of file From 72d710ec9621c5258ef72a60459c16b9d68513e4 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Mon, 15 Jun 2026 10:44:21 +0800 Subject: [PATCH 19/72] feat: update default skill loading so enabledSkills can skip the built-in skills --- src/prompt.ts | 19 +- src/session.ts | 2 +- src/tests/prompt.test.ts | 9 +- src/tests/session.test.ts | 34 ++++ templates/skills/agent-drift-guard.md | 152 ---------------- templates/skills/plan-and-execute.md | 246 -------------------------- 6 files changed, 57 insertions(+), 405 deletions(-) delete mode 100644 templates/skills/agent-drift-guard.md delete mode 100644 templates/skills/plan-and-execute.md diff --git a/src/prompt.ts b/src/prompt.ts index 3b18ba6f..dce34940 100644 --- a/src/prompt.ts +++ b/src/prompt.ts @@ -100,6 +100,10 @@ type PromptToolOptions = { webSearchEnabled?: boolean; }; +type DefaultSkillPromptOptions = { + enabledSkills?: Record; +}; + const DEFAULT_SKILL_TEMPLATES = ["karpathy-guidelines.md"]; const DEFAULT_SKILL_RESOURCE_FILE_LIMIT = 50; const SKILL_RESOURCE_EXCLUDED_DIRS = new Set([ @@ -153,13 +157,20 @@ function readToolDocs(extensionRoot: string, options: PromptToolOptions = {}): s return docs.join("\n\n"); } -function readDefaultSkillDocs(extensionRoot: string): Array<{ name: string; content: string }> { +function readDefaultSkillDocs( + extensionRoot: string, + enabledSkills: Record = {} +): Array<{ name: string; content: string }> { const skillsDir = path.join(extensionRoot, "templates", "skills"); return DEFAULT_SKILL_TEMPLATES.map((entry) => { const fullPath = path.join(skillsDir, entry); + const name = path.basename(entry, ".md"); + if (enabledSkills[name] === false) { + return null; + } try { return { - name: path.basename(entry, ".md"), + name, content: fs.readFileSync(fullPath, "utf8").trim(), }; } catch { @@ -168,8 +179,8 @@ function readDefaultSkillDocs(extensionRoot: string): Array<{ name: string; cont }).filter((skill): skill is { name: string; content: string } => Boolean(skill?.content)); } -export function getDefaultSkillPrompt(): string { - const skillDocs = readDefaultSkillDocs(getExtensionRoot()); +export function getDefaultSkillPrompt(options: DefaultSkillPromptOptions = {}): string { + const skillDocs = readDefaultSkillDocs(getExtensionRoot(), options.enabledSkills); if (skillDocs.length === 0) { return ""; } diff --git a/src/session.ts b/src/session.ts index 6a594b2f..3460cea5 100644 --- a/src/session.ts +++ b/src/session.ts @@ -1142,7 +1142,7 @@ ${agentInstructions} const systemMessage = this.buildSystemMessage(sessionId, systemPrompt); this.appendSessionMessage(sessionId, systemMessage); - const defaultSkillPrompt = getDefaultSkillPrompt(); + const defaultSkillPrompt = getDefaultSkillPrompt({ enabledSkills: this.getResolvedSettings().enabledSkills }); if (defaultSkillPrompt) { const defaultSkillMessage = this.buildSystemMessage(sessionId, defaultSkillPrompt); this.appendSessionMessage(sessionId, defaultSkillMessage); diff --git a/src/tests/prompt.test.ts b/src/tests/prompt.test.ts index 899a2b26..6b474c1e 100644 --- a/src/tests/prompt.test.ts +++ b/src/tests/prompt.test.ts @@ -88,6 +88,12 @@ test("getDefaultSkillPrompt loads the default skill template", () => { assert.equal(prompt.includes('path="templates/skills/'), false); }); +test("getDefaultSkillPrompt skips disabled default skills", () => { + const prompt = getDefaultSkillPrompt({ enabledSkills: { "karpathy-guidelines": false } }); + + assert.equal(prompt, ""); +}); + test("buildSkillDocumentsPrompt excludes SKILL.md frontmatter metadata", () => { const prompt = buildSkillDocumentsPrompt([ { @@ -200,8 +206,7 @@ test("runtime prompt assets live under templates", () => { assert.equal(fs.existsSync(path.join(repoRoot, "templates", "tools", "web-search.md")), true); assert.equal(fs.existsSync(path.join(repoRoot, "templates", "tools", "read.md.ejs")), true); assert.equal(fs.existsSync(path.join(repoRoot, "templates", "prompts", "init_command.md.ejs")), true); - assert.equal(fs.existsSync(path.join(repoRoot, "templates", "skills", "agent-drift-guard.md")), true); - assert.equal(fs.existsSync(path.join(repoRoot, "templates", "skills", "plan-and-execute.md")), true); + assert.equal(fs.existsSync(path.join(repoRoot, "templates", "skills", "karpathy-guidelines.md")), true); assert.equal(fs.existsSync(path.join(repoRoot, "templates", "tools", "read.md")), false); assert.equal(fs.existsSync(path.join(repoRoot, "docs", "tools")), false); assert.equal(fs.existsSync(path.join(repoRoot, "docs", "prompts")), false); diff --git a/src/tests/session.test.ts b/src/tests/session.test.ts index 38767e43..57b981bb 100644 --- a/src/tests/session.test.ts +++ b/src/tests/session.test.ts @@ -1138,6 +1138,40 @@ test("createSession appends default system prompts in prefix-cache-friendly orde assert.equal(systemContents[3], "root project instructions"); }); +test("createSession skips disabled default skills", async () => { + const workspace = createTempDir("deepcode-disabled-default-skill-workspace-"); + const home = createTempDir("deepcode-disabled-default-skill-home-"); + setHomeDir(home); + + const manager = new SessionManager({ + projectRoot: workspace, + createOpenAIClient: () => ({ + client: null, + model: "test-model", + baseURL: "https://api.deepseek.com", + thinkingEnabled: false, + machineId: "machine-id-disabled-default-skill", + }), + getResolvedSettings: () => ({ + model: "test-model", + enabledSkills: { "karpathy-guidelines": false }, + }), + renderMarkdown: (text) => text, + onAssistantMessage: () => {}, + }); + + const sessionId = await manager.createSession({ text: "hello" }); + const systemContents = manager + .listSessionMessages(sessionId) + .filter((message) => message.role === "system") + .map((message) => message.content ?? ""); + + assert.equal(systemContents.length, 2); + assert.match(systemContents[0] ?? "", /# Available Tools/); + assert.doesNotMatch(systemContents.join("\n"), //); + assert.match(systemContents[1] ?? "", /# Local Workspace Environment/); +}); + test("createSession includes agent instructions in the skill matching system prompt", async () => { const workspace = createTempDir("deepcode-skill-match-create-workspace-"); const home = createTempDir("deepcode-skill-match-create-home-"); diff --git a/templates/skills/agent-drift-guard.md b/templates/skills/agent-drift-guard.md deleted file mode 100644 index c6711b12..00000000 --- a/templates/skills/agent-drift-guard.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -name: agent-drift-guard -description: Detect and correct execution drift while working on user requests. Use when you are actively implementing, debugging, reviewing, or investigating and there is a risk of wandering beyond the user's goal, adding unrequested work, touching live systems, over-exploring, or ignoring repeated user boundary corrections. Especially useful during multi-step coding tasks, production-adjacent requests, ambiguous scopes, and anytime you should self-check whether it is still solving the requested problem. ---- - -# Agent Drift Guard - -Keep execution tightly aligned with the user's actual request. - -## Quick Start - -Run this mental check before substantial work and again whenever the plan expands: - -1. State the user's requested outcome in one sentence. -2. List explicit non-goals or boundaries the user has set. -3. Ask whether the next action directly advances the requested outcome. -4. If not, either cut it or pause to confirm. - -## Drift Signals - -Treat these as warning signs that execution may be drifting: - -- Exploring broadly before opening the most relevant file, command, or artifact. -- Solving adjacent operational issues when the user asked only for code changes. -- Adding extra safeguards, scripts, docs, refactors, or cleanup that the user did not ask for. -- Reframing the task around what seems "better" instead of what was requested. -- Continuing with a broader plan after the user narrows the scope. -- Repeating searches or tool calls without increasing certainty. -- Mixing diagnosis, remediation, and feature work when the user asked for only one of them. -- Touching production-like state, external systems, or live data without explicit permission. - -## Severity Levels - -### Level 1: Mild Drift - -Examples: -- One or two extra exploratory commands. -- Considering a broader solution but not acting on it yet. -- Briefly over-explaining instead of moving the task forward. - -Response: -- Auto-correct silently. -- Narrow to the smallest next action. -- Do not interrupt the user. - -### Level 2: Material Drift - -Examples: -- Planning additional deliverables not requested. -- Writing helper scripts, migrations, docs, or tests outside the asked scope. -- Expanding from code changes into operational fixes. -- Continuing after the user has already corrected the scope once. - -Response: -- Stop and realign internally first. -- If the broader action is avoidable, drop it and continue on scope. -- If the broader action has non-obvious tradeoffs, ask a brief confirmation question. - -### Level 3: Boundary or Risk Violation - -Examples: -- Modifying live systems, production data, external services, or user-owned state without being asked. -- Taking destructive or hard-to-reverse actions outside the requested scope. -- Ignoring repeated user instructions about what not to do. - -Response: -- Pause before acting. -- Surface the exact boundary and ask for confirmation. -- Offer the smallest on-scope option first. - -## Self-Check Loop - -Use this loop during execution: - -### Before the first meaningful action - -Write down mentally: -- Requested outcome -- Allowed scope -- Forbidden scope -- Smallest useful next step - -### After each non-trivial step - -Ask: -- Did this step directly help deliver the requested outcome? -- Did I learn something that changes scope, or only implementation? -- Am I about to do more than the user asked? - -### After a user correction - -Treat the correction as a hard boundary update. - -Then: -- Remove the old broader plan. -- Do not defend the discarded work. -- Continue from the narrowed scope. -- If needed, acknowledge briefly and move on. - -## Decision Rules - -Use these rules in order: - -1. Prefer the most direct artifact first. - - Open the relevant file before scanning the whole repo. - - Inspect the specific failing path before designing a general framework. - -2. Prefer the smallest complete fix. - - Solve the asked problem before improving related systems. - - Avoid bonus work unless it is required for correctness. - -3. Prefer internal correction over user interruption. - - If you can shrink back to scope confidently, do it. - - Ask only when the next step changes deliverables, risk, or ownership. - -4. Treat repeated user constraints as priority signals. - - A repeated instruction means your execution style is currently misaligned. - - Tighten scope immediately. - -5. Separate categories of work. - - Code change, investigation, production remediation, cleanup, and documentation are distinct tasks unless the user explicitly combines them. - -## Good Intervention Style - -When you must pause, keep it short and specific: - -- State the potential drift in one sentence. -- Name the tradeoff or boundary. -- Offer the smallest on-scope option first. - -Example: - -"Quick alignment check: I can keep this to the code fix only, or also add an ops cleanup step. I'll stick to the code fix unless you want both." - -## Anti-Patterns - -Do not: - -- Create cleanup scripts, docs, or side tools just because they seem useful. -- Broaden the task after discovering a neighboring problem. -- Continue with a plan the user has already rejected. -- Justify drift with "best practice" when the user asked for a narrower deliverable. -- Hide extra work inside a larger patch. - -## Final Check Before Responding - -Before sending the final answer, verify: - -- The delivered work matches the requested outcome. -- No extra deliverables were added without confirmation. -- Any assumptions are stated briefly. -- Suggested next steps are optional, not bundled into the completed work. diff --git a/templates/skills/plan-and-execute.md b/templates/skills/plan-and-execute.md deleted file mode 100644 index 9fc8bd2d..00000000 --- a/templates/skills/plan-and-execute.md +++ /dev/null @@ -1,246 +0,0 @@ ---- -name: plan-and-execute -description: Automatically plan and execute requirements. Creates a markdown task list with the UpdatePlan tool, and systematically executes each task while updating progress. Use when working with task planning or when you need to break down and execute complex multi-step requirements. ---- - -# Plan and Execute - -This Skill helps you automatically plan and execute requirements. It creates a structured markdown task list with the UpdatePlan tool and systematically works through each task while keeping progress visible. - -## Quick Start - -When you need to work through a multi-step request: - -1. Analyze the requirements and explore enough project context -2. Clarify unclear or ambiguous requirements with AskUserQuestion -3. Create a markdown task list by calling the UpdatePlan tool -4. Execute tasks one by one, updating the tool plan in real time -5. Revise the remaining plan as new context appears - -## Instructions - -### Step 1: Analyze the requirements - -Identify the requirements from the available context. Explore the project enough to make the plan concrete and accurate. - -If the original requirements are unclear, incomplete, or ambiguous, call the AskUserQuestion tool before creating the task list. Ask only the questions needed to avoid implementing the wrong behavior, and keep each question specific to the decision that affects the plan or acceptance criteria. - -If a required referenced file path is missing, ask for it with AskUserQuestion: - -``` -What is the path to the referenced file? -``` - -Referenced files can be in any text format (.md, .txt, etc.) that contains task requirements or feature descriptions. If no additional file is needed, continue from the available requirements. - -- What are the main requirements? -- What tasks need to be completed? -- Are there dependencies between tasks? -- What is the complexity level? -- Which files, modules, commands, or tests are relevant? -- What ambiguity would change the implementation or acceptance criteria? - -### Step 2: Create the task list - -Create a structured markdown task list and pass it to the UpdatePlan tool as the `plan` string. The tool input must use this shape: - -```json -{ - "plan": "## Task List\n\n- [ ] Task 1 description\n- [ ] Task 2 description\n- [ ] Task 3 description" -} -``` - -Use this markdown format for the `plan` content: - -```markdown -## Task List - -- [ ] Task 1 description -- [ ] Task 2 description -- [ ] Task 3 description -``` - -Break down complex requirements into specific, actionable tasks and call UpdatePlan with the full markdown task list. - -### Step 3: Execute tasks systematically - -For each task in the list: - -1. **Refresh the plan**: Before starting the first task and after completing each task, re-evaluate the latest conversation and project context. Update the remaining tasks when scope, order, blockers, or follow-up work changes. -2. **Mark as in progress**: Call UpdatePlan with the task changed from `[ ]` to `[>]` -3. **Execute the task**: Use appropriate tools to complete the work -4. **Mark as completed**: Call UpdatePlan with the task changed from `[>]` to `[x]` when finished -5. **Move to next task**: Only ONE task should be in progress at a time - -Important rules: -- Always keep the plan aligned with the latest context before executing the next task -- Always call UpdatePlan BEFORE starting work on a task -- Always call UpdatePlan IMMEDIATELY after completing a task -- Always pass the complete current markdown task list, not a partial diff -- Never work on multiple tasks simultaneously -- Remove tasks that are no longer relevant, and add newly discovered tasks before working on them -- If you encounter errors, keep the task as `[>]` and create new tasks to resolve blockers - -### Step 4: Handle task breakdown - -If during execution you discover a task is more complex than expected: - -1. Keep the current task as `[>]` -2. Call UpdatePlan with new sub-tasks below it with indentation: - ```markdown - - [>] Main task - - [ ] Sub-task 1 - - [ ] Sub-task 2 - ``` -3. Complete sub-tasks first, then mark the main task as complete with UpdatePlan - -### Step 5: Final verification - -After all tasks are completed (`[x]`): - -1. Review the original requirements to ensure everything is addressed -2. Run any final checks (tests, builds, linting) -3. Call UpdatePlan with every task marked `[x]` -4. Provide a concise completion summary in the final response - -## Task State Symbols - -- `[ ]` - Pending -- `[>]` - In progress -- `[x]` - Completed -- `[!]` - Blocked - -## Examples - -### Example 1: Simple feature request - -**Example requirements:** -```markdown -# 新功能:添加深色模式切换 - -用户应该能够在浅色和深色主题之间切换。 -切换开关应放在设置页面中。 -``` - -**分析后的 UpdatePlan 调用:** -```markdown -## Task List - -- [ ] 在设置页面创建深色模式切换组件 -- [ ] 添加深色模式状态管理(context/store) -- [ ] 实现深色主题的 CSS-in-JS 样式 -- [ ] 更新现有组件以支持主题切换 -- [ ] 运行测试并验证功能 -``` - -**UpdatePlan call during execution:** -```markdown -## Task List - -- [x] 在设置页面创建深色模式切换组件 -- [>] 添加深色模式状态管理(context/store) -- [ ] 实现深色主题的 CSS-in-JS 样式 -- [ ] 更新现有组件以支持主题切换 -- [ ] 运行测试并验证功能 -``` - -### Example 2: Bug fix with investigation - -**Example requirements:** -```markdown -# Fix bug:登录表单提交时崩溃 - -当用户点击提交时,应用崩溃。 -错误信息:"Cannot read property 'email' of undefined" -``` - -**UpdatePlan call after analysis:** -```markdown -## Task List - -- [ ] 在本地复现缺陷 -- [ ] 调查登录表单组件中的错误 -- [ ] 定位 undefined email 属性的根本原因 -- [ ] 实施修复 -- [ ] 添加验证以防止类似问题 -- [ ] 使用各种输入测试修复 -- [ ] 更新错误处理 -``` - -## When to Use This Skill - -Use this Skill when: - -1. **Complex multi-step tasks** - Request requires 3+ distinct steps -2. **Feature implementation** - Building new functionality from requirements -3. **Bug fixing** - Need to investigate, fix, and verify -4. **Refactoring** - Multiple files or components need changes -5. **Detailed requirements** - Specifications need to be translated into concrete tasks -6. **Need progress tracking** - Want visible progress without editing source files - -## When NOT to Use This Skill - -Skip this Skill when: - -1. **Single simple task** - Just one straightforward action needed -2. **Trivial changes** - Quick fixes that don't need planning -3. **Informational requests** - User just wants explanation, not execution -4. **No execution requested** - User only wants brainstorming or a high-level explanation - -## Best Practices - -1. **Be specific with tasks**: "Add login button to navbar" not "Update UI" -2. **Keep tasks atomic**: Each task should be independently completable -3. **Update immediately**: Don't batch status updates, do them in real-time -4. **One task at a time**: Never mark multiple tasks as `[>]` -5. **Handle blockers**: If stuck, create new tasks to resolve the blocker -6. **Verify completion**: Only mark `[x]` when task is fully done - -## Advanced Usage - -### Handling dependencies - -When tasks have dependencies, order them properly: - -```markdown -- [ ] Create database schema -- [ ] Implement API endpoints (depends on schema) -- [ ] Build frontend forms (depends on API) -``` - -### Using sub-tasks - -For complex tasks, break them down: - -```markdown -- [>] Implement authentication system - - [x] Set up JWT library - - [>] Create login endpoint - - [ ] Create logout endpoint - - [ ] Add token refresh logic -``` - -### Adding notes - -Add implementation notes or findings: - -```markdown -- [x] Investigate performance issue - - Note: Found N+1 query in user loader - - Solution: Added dataloader batching -``` - -## Workflow Summary - -1. Analyze the requirements and relevant project context -2. Call AskUserQuestion if the original requirements are unclear or ambiguous -3. Call UpdatePlan with the structured markdown task list -4. Refresh the remaining plan before the first task -5. For each task: - - Update to `[>]` with UpdatePlan - - Execute the task - - Update to `[x]` with UpdatePlan - - Re-evaluate and revise remaining tasks before moving on -6. Call UpdatePlan with all tasks completed and summarize the result - -This approach keeps planning and progress tracking in the UpdatePlan display, leaving source materials unchanged unless the actual task requires editing them. From b1a1d4a08626022b7678fb3dbec94abe2d7c9b7a Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Mon, 15 Jun 2026 10:50:45 +0800 Subject: [PATCH 20/72] 0.1.30 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 09db34ab..fc94a3f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@vegamo/deepcode-cli", - "version": "0.1.29", + "version": "0.1.30", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@vegamo/deepcode-cli", - "version": "0.1.29", + "version": "0.1.30", "license": "MIT", "dependencies": { "chalk": "^5.6.2", diff --git a/package.json b/package.json index aa925b92..add0e271 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@vegamo/deepcode-cli", - "version": "0.1.29", + "version": "0.1.30", "description": "Deep Code CLI - Vibe coding for the deepseek-v4 model in your terminal", "license": "MIT", "type": "module", From cc7b0c31d6f156d7fb784e24a42f88785269e663 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Mon, 15 Jun 2026 10:58:18 +0800 Subject: [PATCH 21/72] feat: update templates/skills/bundled/deepcode-self-refer/SKILL.md --- templates/skills/bundled/deepcode-self-refer/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/skills/bundled/deepcode-self-refer/SKILL.md b/templates/skills/bundled/deepcode-self-refer/SKILL.md index 56b902ef..357868cd 100644 --- a/templates/skills/bundled/deepcode-self-refer/SKILL.md +++ b/templates/skills/bundled/deepcode-self-refer/SKILL.md @@ -1,6 +1,6 @@ --- name: deepcode-self-refer -description: 回答关于 Deep Code CLI 本身的问题——包括功能特性、配置项、斜杠命令、Skills、MCP 集成、权限、通知、会话持久化及故障排查。当用户询问如何配置或使用 Deep Code、如何设置 MCP 服务器、配置通知(如 Slack/飞书)、管理权限、查看可用技能、理解斜杠命令、配置思考模式、使用 Undo 功能,或咨询 Deep Code 与 VSCode 集成等场景时使用。 +description: Answers questions about Deep Code CLI itself — including features, configuration options, slash commands, Skills, MCP integration, permissions, notifications, session persistence, and troubleshooting. Use this when users ask how to configure or use Deep Code, how to set up an MCP server, configure notifications (such as Slack/Feishu), manage permissions, view available skills, understand slash commands, configure thinking mode, etc. --- # Deep Code Self-Refer From f725737e0bc5f6029f7f6badcf6186607113d023 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Tue, 16 Jun 2026 13:11:50 +0800 Subject: [PATCH 22/72] feat: update bundled/skill-digester/SKILL.md --- .../skills/bundled/skill-digester/SKILL.md | 63 +++++++++++++++++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/templates/skills/bundled/skill-digester/SKILL.md b/templates/skills/bundled/skill-digester/SKILL.md index 6e9016d1..acc969e8 100644 --- a/templates/skills/bundled/skill-digester/SKILL.md +++ b/templates/skills/bundled/skill-digester/SKILL.md @@ -1,18 +1,28 @@ --- name: skill-digester -description: Reviews and improves another DeepCode skill's SKILL.md description field against the Agent Skills description-field rules. Use when the user asks to "digest" a skill, including requests like "digest the pdf skill" or "消化 pdf 技能". +description: Reviews and improves another DeepCode skill's SKILL.md description field, and guides Agent Skill installation into user or project .agents/skills roots. Use when the user asks to digest a skill, install an Agent Skill, install a skill to user/project scope, or says "消化技能" or "安装 agent skill". --- # Skill Digester -Use this skill to review and optionally rewrite the `description` field of another DeepCode skill. +Use this skill for two related tasks: + +- Review and optionally rewrite the `description` field of another DeepCode skill. +- Guide installation of an Agent Skill into an interoperable `.agents/skills` root. ## Interaction Rule -Whenever user input is needed, call the `AskUserQuestion` tool. Do not ask follow-up questions as plain assistant text. This includes missing skill names, language preference, duplicate matches, malformed frontmatter decisions, and whether to apply a recommended rewrite. +Whenever user input is needed, call the `AskUserQuestion` tool. Do not ask follow-up questions as plain assistant text. This includes missing skill names or paths, install scope, language preference, duplicate matches, malformed frontmatter decisions, and whether to apply a recommended rewrite. ## Workflow +First classify the request: + +- If the user asks to install, add, copy, or place an Agent Skill, use the [Install Agent Skill Workflow](#install-agent-skill-workflow). +- Otherwise, use the [Digest Description Workflow](#digest-description-workflow). + +## Digest Description Workflow + 1. Identify the target skill from the user's request. - If the user did not provide a skill name, use `AskUserQuestion` to ask for one. - Locate the skill by running the bundled Node script from this skill directory: @@ -82,6 +92,46 @@ Whenever user input is needed, call the `AskUserQuestion` tool. Do not ask follo - Preserve body content exactly unless the user separately asks to edit it. - After editing, report the source path, updated digest output path, and final description. +## Install Agent Skill Workflow + +Use this workflow when the user asks to install an Agent Skill. Installation always writes to `.agents/skills`, not `.deepcode/skills`. + +1. Identify the source skill directory. + - If the user provided an explicit file or directory path, resolve it: + - `~/...` relative to the user's home directory. + - `./...` relative to the current project root. + - Absolute paths as written. + - A `SKILL.md` path means its parent directory is the source skill directory. + - If the user provided a skill name instead of a path, locate it with `scripts/find-skill.js` using the same command and match rules as the digest workflow. + - If the user did not provide a skill name or path, use `AskUserQuestion` to ask for the source skill name or path. + - The source directory must contain `SKILL.md`. If it does not, report that the path is not an Agent Skill and ask for another source only if the user still wants to install. + +2. Determine the installed skill folder name. + - Parse the source `SKILL.md` frontmatter. + - Use the trimmed frontmatter `name` when present. + - Otherwise use the source folder name with underscores converted to hyphens. + - Use that resolved name as the target folder name. + +3. Ask exactly one installation scope question. + - Use `AskUserQuestion` to ask whether to install the skill at user level or project level. + - Offer only these scope choices: + - User-level install: `~/.agents/skills//` + - Project-level install: `./.agents/skills//` + - Do not ask any other installation preference before copying. + +4. Copy the complete skill directory. + - User-level destination: `~/.agents/skills//`. + - Project-level destination: `./.agents/skills//`. + - Copy the whole source skill directory, including `SKILL.md`, `references/`, `scripts/`, `templates/`, examples, assets, and other support files. + - Preserve file contents and relative paths exactly. + - Create the `.agents/skills` parent directory if needed. + - If the destination directory already exists, stop and report the conflict. Do not overwrite or merge files unless the user explicitly asks in a later message. + +5. Report the result. + - Report the source directory and installation destination. + - Mention that the agent client may need to reload or restart before the installed skill appears. + - Do not digest, rewrite, or normalize the installed skill unless the user separately asks for that. + ## AskUserQuestion Patterns Use one question at a time unless two decisions are tightly coupled. Each question must include `options`; rely on the UI's `Other` option for free-form input. @@ -96,6 +146,10 @@ Examples: {"questions":[{"question":"How should I proceed with this description recommendation?","options":[{"label":"Apply change","description":"Update only the description field in the native digest output SKILL.md."},{"label":"Abandon change","description":"Leave the file unchanged."},{"label":"Discuss wording","description":"Continue refining the proposed description before editing."}]}]} ``` +```json +{"questions":[{"question":"Where should I install this Agent Skill?","options":[{"label":"User-level","description":"Install to ~/.agents/skills so it is available across projects."},{"label":"Project-level","description":"Install to ./.agents/skills so it is available in this project."}]}]} +``` + ## Review Heuristics A strong description is short, concrete, and activation-oriented. Prefer this pattern: @@ -110,6 +164,7 @@ Avoid descriptions that are only generic labels, marketing copy, or internal imp - Never modify a different skill with a similar name without asking. - Never save the digested output under `.agents/skills`; `.agents/skills` is only a source root for digestion. +- Never save installed Agent Skills under `.deepcode/skills`; installation writes only to `.agents/skills`. - Never move a skill between project and user level during digestion. +- Never overwrite or merge an existing installed skill directory unless the user explicitly asks after seeing the conflict. - Never change the target skill's language preference after confirmation unless the user asks. - From f11ab92a9dc29ec81b4222a4e6d194f8f0546dfc Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Tue, 16 Jun 2026 13:18:55 +0800 Subject: [PATCH 23/72] 0.1.31 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c64d6e43..8db59638 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@vegamo/deepcode-cli", - "version": "0.1.30", + "version": "0.1.31", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@vegamo/deepcode-cli", - "version": "0.1.30", + "version": "0.1.31", "license": "MIT", "dependencies": { "chalk": "^5.6.2", diff --git a/package.json b/package.json index add0e271..d1165f4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@vegamo/deepcode-cli", - "version": "0.1.30", + "version": "0.1.31", "description": "Deep Code CLI - Vibe coding for the deepseek-v4 model in your terminal", "license": "MIT", "type": "module", From 2b8dc93a0864adf07b8e9f7caf1071a1f2ac8c3b Mon Sep 17 00:00:00 2001 From: hcyang Date: Tue, 16 Jun 2026 14:23:07 +0800 Subject: [PATCH 24/72] fix: update ESLint config for browser globals and fix vscode extension build --- .github/workflows/ci.yml | 9 +- .gitignore | 3 + eslint.config.mjs | 35 +- package-lock.json | 7739 ++++++++++++----- package.json | 64 +- packages/cli/package.json | 42 + {src => packages/cli/src}/cli.tsx | 2 +- .../cli/src}/common/update-check.ts | 2 +- packages/cli/src/generated/git-commit.ts | 8 + .../cli/src}/tests/ask-user-question.test.ts | 2 +- .../cli/src}/tests/clipboard.test.ts | 0 .../cli/src}/tests/dropdown-menu.test.ts | 0 .../cli/src}/tests/exit-summary.test.ts | 2 +- .../cli/src}/tests/file-mentions.test.ts | 0 .../cli/src}/tests/loading-text.test.ts | 0 .../cli/src}/tests/markdown.test.ts | 0 .../cli/src}/tests/message-view.test.ts | 2 +- .../cli/src}/tests/permission-prompt.test.ts | 0 .../cli/src}/tests/prompt-buffer.test.ts | 0 .../cli/src}/tests/prompt-input-keys.test.ts | 2 +- .../cli/src}/tests/prompt-undo-redo.test.ts | 0 packages/cli/src/tests/run-tests.mjs | 15 + .../cli/src}/tests/session-list.test.ts | 2 +- .../cli/src}/tests/slash-commands.test.ts | 2 +- .../cli/src}/tests/thinking-state.test.ts | 2 +- .../cli/src}/tests/update-check.test.ts | 0 .../cli/src}/tests/welcome-screen.test.ts | 0 {src => packages/cli/src}/ui/ascii-art.ts | 0 .../src}/ui/components/DropdownMenu/index.tsx | 0 .../ui/components/FileMentionMenu/index.tsx | 0 .../src}/ui/components/MessageView/index.tsx | 0 .../ui/components/MessageView/markdown.ts | 0 .../src}/ui/components/MessageView/types.ts | 2 +- .../src}/ui/components/MessageView/utils.ts | 2 +- .../ui/components/ModelsDropdown/index.tsx | 2 +- .../ui/components/RawModeExitPrompt/index.tsx | 0 .../ui/components/RawModelDropdown/index.tsx | 0 .../ui/components/SkillsDropdown/index.tsx | 2 +- .../cli/src}/ui/components/index.ts | 0 {src => packages/cli/src}/ui/constants.ts | 0 .../cli/src}/ui/contexts/AppContext.tsx | 0 .../cli/src}/ui/contexts/RawModeContext.tsx | 0 .../cli/src}/ui/contexts/index.ts | 0 .../cli/src}/ui/core/ask-user-question.ts | 2 +- .../cli/src}/ui/core/clipboard.ts | 0 .../cli/src}/ui/core/file-mentions.ts | 0 .../cli/src}/ui/core/loading-text.ts | 2 +- .../cli/src}/ui/core/prompt-buffer.ts | 0 .../cli/src}/ui/core/prompt-undo-redo.ts | 0 .../cli/src}/ui/core/slash-commands.ts | 2 +- .../cli/src}/ui/core/thinking-state.ts | 2 +- {src => packages/cli/src}/ui/exit-summary.ts | 2 +- {src => packages/cli/src}/ui/hooks/cursor.ts | 0 {src => packages/cli/src}/ui/hooks/index.ts | 0 .../cli/src}/ui/hooks/useHistoryNavigation.ts | 0 .../cli/src}/ui/hooks/usePasteHandling.ts | 0 .../cli/src}/ui/hooks/useTerminalInput.ts | 0 {src => packages/cli/src}/ui/index.ts | 0 {src => packages/cli/src}/ui/utils/index.ts | 6 +- {src => packages/cli/src}/ui/views/App.tsx | 12 +- .../cli/src}/ui/views/AppContainer.tsx | 0 .../src}/ui/views/AskUserQuestionPrompt.tsx | 0 .../cli/src}/ui/views/McpStatusList.tsx | 2 +- .../cli/src}/ui/views/PermissionPrompt.tsx | 4 +- .../cli/src}/ui/views/ProcessStdoutView.tsx | 4 +- .../cli/src}/ui/views/PromptInput.tsx | 6 +- .../cli/src}/ui/views/SessionList.tsx | 2 +- .../cli/src}/ui/views/SlashCommandMenu.tsx | 2 +- .../cli/src}/ui/views/ThemedGradient.tsx | 0 .../cli/src}/ui/views/UndoSelector.tsx | 2 +- .../cli/src}/ui/views/UpdatePrompt.tsx | 0 .../cli/src}/ui/views/WelcomeScreen.tsx | 4 +- packages/cli/tsconfig.json | 26 + packages/core/package.json | 39 + .../core/src}/common/bash-timeout.ts | 0 .../core/src}/common/debug-logger.ts | 0 .../core/src}/common/error-logger.ts | 0 .../core/src}/common/file-history.ts | 0 .../core/src}/common/file-utils.ts | 0 .../core/src}/common/model-capabilities.ts | 0 {src => packages/core/src}/common/notify.ts | 0 .../core/src}/common/openai-client.ts | 0 .../src}/common/openai-message-converter.ts | 0 .../core/src}/common/openai-thinking.ts | 0 .../core/src}/common/permissions.ts | 0 .../core/src}/common/process-tree.ts | 0 .../core/src}/common/shell-utils.ts | 0 {src => packages/core/src}/common/state.ts | 0 .../core/src}/common/telemetry.ts | 0 packages/core/src/common/tool-types.ts | 107 + {src => packages/core/src}/common/validate.ts | 2 +- packages/core/src/generated/git-commit.ts | 8 + packages/core/src/index.ts | 132 + {src => packages/core/src}/mcp/mcp-client.ts | 0 {src => packages/core/src}/mcp/mcp-manager.ts | 0 {src => packages/core/src}/prompt.ts | 0 {src => packages/core/src}/session.ts | 0 {src => packages/core/src}/settings.ts | 0 .../core/src}/tests/debug-logger.test.ts | 0 .../core/src}/tests/mcp-client.test.ts | 0 .../core/src}/tests/memory-leak.test.ts | 0 .../tests/openai-message-converter.test.ts | 0 .../core/src}/tests/openai-thinking.test.ts | 0 .../core/src}/tests/permissions.test.ts | 0 .../core/src}/tests/process-tree.test.ts | 0 .../core/src}/tests/prompt.test.ts | 0 packages/core/src/tests/run-tests.mjs | 15 + .../core/src}/tests/session.test.ts | 0 .../src}/tests/settings-and-notify.test.ts | 0 .../core/src}/tests/shell-utils.test.ts | 0 .../core/src}/tests/telemetry.test.ts | 0 .../core/src}/tests/tool-executor.test.ts | 0 .../core/src}/tests/tool-handlers.test.ts | 0 .../src}/tests/web-search-handler.test.ts | 0 .../src}/tools/ask-user-question-handler.ts | 0 .../core/src}/tools/bash-handler.ts | 0 .../core/src}/tools/edit-handler.ts | 0 {src => packages/core/src}/tools/executor.ts | 130 +- .../core/src}/tools/read-handler.ts | 0 .../core/src}/tools/update-plan-handler.ts | 0 .../core/src}/tools/web-search-handler.ts | 0 .../core/src}/tools/write-handler.ts | 0 .../templates}/prompts/init_command.md.ejs | 0 .../bundled/deepcode-self-refer/SKILL.md | 20 +- .../deepcode-self-refer/references/README.md | 49 +- .../references/configuration.md | 100 +- .../references/configuration_en.md | 97 +- .../deepcode-self-refer/references/mcp.md | 0 .../deepcode-self-refer/references/mcp_en.md | 22 +- .../deepcode-self-refer/references/notify.md | 14 +- .../references/notify_en.md | 14 +- .../references/permission.md | 34 +- .../references/permission_en.md | 33 +- .../references/session-persistence.md | 40 +- .../references/session-persistence_en.md | 40 +- .../templates}/skills/bundled/plan/SKILL.md | 72 +- .../skills/bundled/skill-digester/SKILL.md | 30 +- .../skill-digester/scripts/find-skill.js | 0 .../skills/bundled/skill-writer/SKILL.md | 29 +- .../templates}/skills/karpathy-guidelines.md | 7 +- .../templates}/tools/ask-user-question.md | 2 + .../core/templates}/tools/bash.md | 65 +- .../core/templates}/tools/edit.md | 7 +- .../core/templates}/tools/read.md.ejs | 0 .../core/templates}/tools/update-plan.md | 5 +- .../core/templates}/tools/web-search.md | 2 + .../core/templates}/tools/write.md | 8 +- packages/core/tsconfig.json | 21 + packages/core/tsconfig.tsbuildinfo | 1 + packages/vscode-ide-companion/.vscodeignore | 8 + packages/vscode-ide-companion/LICENSE | 21 + packages/vscode-ide-companion/README.md | 94 + packages/vscode-ide-companion/README_cn.md | 94 + packages/vscode-ide-companion/README_en.md | 87 + packages/vscode-ide-companion/package.json | 85 + .../resources/deepcode_screenshot.png | Bin 0 -> 357519 bytes .../resources/deepcoding_icon.png | Bin 0 -> 77727 bytes .../resources/deepcoding_icon.svg | 1 + .../vscode-ide-companion/resources/faq1.gif | Bin 0 -> 186246 bytes .../resources/prompt-attachments.js | 273 + .../resources/webview.css | 1604 ++++ .../resources/webview.html | 2354 +++++ .../vscode-ide-companion/src/extension.ts | 562 ++ packages/vscode-ide-companion/src/provider.ts | 319 + .../src/tests/extension-utils.test.ts | 132 + .../src/tests/extension.test.ts | 445 + .../src/tests/run-tests.mjs | 15 + packages/vscode-ide-companion/src/utils.ts | 61 + .../vscode-ide-companion/tsconfig.build.json | 21 + packages/vscode-ide-companion/tsconfig.json | 23 + scripts/build-vscode-companion.js | 23 + scripts/build.js | 23 + scripts/clean.js | 39 + ...bundle_assets.js => copy-bundle-assets.js} | 14 +- scripts/esbuild-vscode.config.js | 29 + scripts/esbuild.config.js | 28 + scripts/generate-git-commit-info.js | 46 + scripts/start.js | 22 + src/tests/run-tests.mjs | 13 - tsconfig.json | 39 +- 180 files changed, 12838 insertions(+), 2803 deletions(-) create mode 100644 packages/cli/package.json rename {src => packages/cli/src}/cli.tsx (98%) rename {src => packages/cli/src}/common/update-check.ts (99%) create mode 100644 packages/cli/src/generated/git-commit.ts rename {src => packages/cli/src}/tests/ask-user-question.test.ts (98%) rename {src => packages/cli/src}/tests/clipboard.test.ts (100%) rename {src => packages/cli/src}/tests/dropdown-menu.test.ts (100%) rename {src => packages/cli/src}/tests/exit-summary.test.ts (97%) rename {src => packages/cli/src}/tests/file-mentions.test.ts (100%) rename {src => packages/cli/src}/tests/loading-text.test.ts (100%) rename {src => packages/cli/src}/tests/markdown.test.ts (100%) rename {src => packages/cli/src}/tests/message-view.test.ts (99%) rename {src => packages/cli/src}/tests/permission-prompt.test.ts (100%) rename {src => packages/cli/src}/tests/prompt-buffer.test.ts (100%) rename {src => packages/cli/src}/tests/prompt-input-keys.test.ts (99%) rename {src => packages/cli/src}/tests/prompt-undo-redo.test.ts (100%) create mode 100644 packages/cli/src/tests/run-tests.mjs rename {src => packages/cli/src}/tests/session-list.test.ts (98%) rename {src => packages/cli/src}/tests/slash-commands.test.ts (98%) rename {src => packages/cli/src}/tests/thinking-state.test.ts (96%) rename {src => packages/cli/src}/tests/update-check.test.ts (100%) rename {src => packages/cli/src}/tests/welcome-screen.test.ts (100%) rename {src => packages/cli/src}/ui/ascii-art.ts (100%) rename {src => packages/cli/src}/ui/components/DropdownMenu/index.tsx (100%) rename {src => packages/cli/src}/ui/components/FileMentionMenu/index.tsx (100%) rename {src => packages/cli/src}/ui/components/MessageView/index.tsx (100%) rename {src => packages/cli/src}/ui/components/MessageView/markdown.ts (100%) rename {src => packages/cli/src}/ui/components/MessageView/types.ts (84%) rename {src => packages/cli/src}/ui/components/MessageView/utils.ts (99%) rename {src => packages/cli/src}/ui/components/ModelsDropdown/index.tsx (98%) rename {src => packages/cli/src}/ui/components/RawModeExitPrompt/index.tsx (100%) rename {src => packages/cli/src}/ui/components/RawModelDropdown/index.tsx (100%) rename {src => packages/cli/src}/ui/components/SkillsDropdown/index.tsx (97%) rename {src => packages/cli/src}/ui/components/index.ts (100%) rename {src => packages/cli/src}/ui/constants.ts (100%) rename {src => packages/cli/src}/ui/contexts/AppContext.tsx (100%) rename {src => packages/cli/src}/ui/contexts/RawModeContext.tsx (100%) rename {src => packages/cli/src}/ui/contexts/index.ts (100%) rename {src => packages/cli/src}/ui/core/ask-user-question.ts (98%) rename {src => packages/cli/src}/ui/core/clipboard.ts (100%) rename {src => packages/cli/src}/ui/core/file-mentions.ts (100%) rename {src => packages/cli/src}/ui/core/loading-text.ts (96%) rename {src => packages/cli/src}/ui/core/prompt-buffer.ts (100%) rename {src => packages/cli/src}/ui/core/prompt-undo-redo.ts (100%) rename {src => packages/cli/src}/ui/core/slash-commands.ts (98%) rename {src => packages/cli/src}/ui/core/thinking-state.ts (94%) rename {src => packages/cli/src}/ui/exit-summary.ts (98%) rename {src => packages/cli/src}/ui/hooks/cursor.ts (100%) rename {src => packages/cli/src}/ui/hooks/index.ts (100%) rename {src => packages/cli/src}/ui/hooks/useHistoryNavigation.ts (100%) rename {src => packages/cli/src}/ui/hooks/usePasteHandling.ts (100%) rename {src => packages/cli/src}/ui/hooks/useTerminalInput.ts (100%) rename {src => packages/cli/src}/ui/index.ts (100%) rename {src => packages/cli/src}/ui/utils/index.ts (94%) rename {src => packages/cli/src}/ui/views/App.tsx (98%) rename {src => packages/cli/src}/ui/views/AppContainer.tsx (100%) rename {src => packages/cli/src}/ui/views/AskUserQuestionPrompt.tsx (100%) rename {src => packages/cli/src}/ui/views/McpStatusList.tsx (99%) rename {src => packages/cli/src}/ui/views/PermissionPrompt.tsx (98%) rename {src => packages/cli/src}/ui/views/ProcessStdoutView.tsx (98%) rename {src => packages/cli/src}/ui/views/PromptInput.tsx (99%) rename {src => packages/cli/src}/ui/views/SessionList.tsx (99%) rename {src => packages/cli/src}/ui/views/SlashCommandMenu.tsx (98%) rename {src => packages/cli/src}/ui/views/ThemedGradient.tsx (100%) rename {src => packages/cli/src}/ui/views/UndoSelector.tsx (99%) rename {src => packages/cli/src}/ui/views/UpdatePrompt.tsx (100%) rename {src => packages/cli/src}/ui/views/WelcomeScreen.tsx (97%) create mode 100644 packages/cli/tsconfig.json create mode 100644 packages/core/package.json rename {src => packages/core/src}/common/bash-timeout.ts (100%) rename {src => packages/core/src}/common/debug-logger.ts (100%) rename {src => packages/core/src}/common/error-logger.ts (100%) rename {src => packages/core/src}/common/file-history.ts (100%) rename {src => packages/core/src}/common/file-utils.ts (100%) rename {src => packages/core/src}/common/model-capabilities.ts (100%) rename {src => packages/core/src}/common/notify.ts (100%) rename {src => packages/core/src}/common/openai-client.ts (100%) rename {src => packages/core/src}/common/openai-message-converter.ts (100%) rename {src => packages/core/src}/common/openai-thinking.ts (100%) rename {src => packages/core/src}/common/permissions.ts (100%) rename {src => packages/core/src}/common/process-tree.ts (100%) rename {src => packages/core/src}/common/shell-utils.ts (100%) rename {src => packages/core/src}/common/state.ts (100%) rename {src => packages/core/src}/common/telemetry.ts (100%) create mode 100644 packages/core/src/common/tool-types.ts rename {src => packages/core/src}/common/validate.ts (99%) create mode 100644 packages/core/src/generated/git-commit.ts create mode 100644 packages/core/src/index.ts rename {src => packages/core/src}/mcp/mcp-client.ts (100%) rename {src => packages/core/src}/mcp/mcp-manager.ts (100%) rename {src => packages/core/src}/prompt.ts (100%) rename {src => packages/core/src}/session.ts (100%) rename {src => packages/core/src}/settings.ts (100%) rename {src => packages/core/src}/tests/debug-logger.test.ts (100%) rename {src => packages/core/src}/tests/mcp-client.test.ts (100%) rename {src => packages/core/src}/tests/memory-leak.test.ts (100%) rename {src => packages/core/src}/tests/openai-message-converter.test.ts (100%) rename {src => packages/core/src}/tests/openai-thinking.test.ts (100%) rename {src => packages/core/src}/tests/permissions.test.ts (100%) rename {src => packages/core/src}/tests/process-tree.test.ts (100%) rename {src => packages/core/src}/tests/prompt.test.ts (100%) create mode 100644 packages/core/src/tests/run-tests.mjs rename {src => packages/core/src}/tests/session.test.ts (100%) rename {src => packages/core/src}/tests/settings-and-notify.test.ts (100%) rename {src => packages/core/src}/tests/shell-utils.test.ts (100%) rename {src => packages/core/src}/tests/telemetry.test.ts (100%) rename {src => packages/core/src}/tests/tool-executor.test.ts (100%) rename {src => packages/core/src}/tests/tool-handlers.test.ts (100%) rename {src => packages/core/src}/tests/web-search-handler.test.ts (100%) rename {src => packages/core/src}/tools/ask-user-question-handler.ts (100%) rename {src => packages/core/src}/tools/bash-handler.ts (100%) rename {src => packages/core/src}/tools/edit-handler.ts (100%) rename {src => packages/core/src}/tools/executor.ts (67%) rename {src => packages/core/src}/tools/read-handler.ts (100%) rename {src => packages/core/src}/tools/update-plan-handler.ts (100%) rename {src => packages/core/src}/tools/web-search-handler.ts (100%) rename {src => packages/core/src}/tools/write-handler.ts (100%) rename {templates => packages/core/templates}/prompts/init_command.md.ejs (100%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/SKILL.md (81%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/README.md (87%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/configuration.md (64%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/configuration_en.md (71%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/mcp.md (100%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/mcp_en.md (96%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/notify.md (91%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/notify_en.md (91%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/permission.md (61%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/permission_en.md (64%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/session-persistence.md (75%) rename {templates => packages/core/templates}/skills/bundled/deepcode-self-refer/references/session-persistence_en.md (72%) rename {templates => packages/core/templates}/skills/bundled/plan/SKILL.md (78%) rename {templates => packages/core/templates}/skills/bundled/skill-digester/SKILL.md (89%) rename {templates => packages/core/templates}/skills/bundled/skill-digester/scripts/find-skill.js (100%) rename {templates => packages/core/templates}/skills/bundled/skill-writer/SKILL.md (99%) rename {templates => packages/core/templates}/skills/karpathy-guidelines.md (97%) rename {templates => packages/core/templates}/tools/ask-user-question.md (99%) rename {templates => packages/core/templates}/tools/bash.md (54%) rename {templates => packages/core/templates}/tools/edit.md (97%) rename {templates => packages/core/templates}/tools/read.md.ejs (100%) rename {templates => packages/core/templates}/tools/update-plan.md (97%) rename {templates => packages/core/templates}/tools/web-search.md (99%) rename {templates => packages/core/templates}/tools/write.md (86%) create mode 100644 packages/core/tsconfig.json create mode 100644 packages/core/tsconfig.tsbuildinfo create mode 100644 packages/vscode-ide-companion/.vscodeignore create mode 100644 packages/vscode-ide-companion/LICENSE create mode 100644 packages/vscode-ide-companion/README.md create mode 100644 packages/vscode-ide-companion/README_cn.md create mode 100644 packages/vscode-ide-companion/README_en.md create mode 100644 packages/vscode-ide-companion/package.json create mode 100644 packages/vscode-ide-companion/resources/deepcode_screenshot.png create mode 100644 packages/vscode-ide-companion/resources/deepcoding_icon.png create mode 100644 packages/vscode-ide-companion/resources/deepcoding_icon.svg create mode 100644 packages/vscode-ide-companion/resources/faq1.gif create mode 100644 packages/vscode-ide-companion/resources/prompt-attachments.js create mode 100644 packages/vscode-ide-companion/resources/webview.css create mode 100644 packages/vscode-ide-companion/resources/webview.html create mode 100644 packages/vscode-ide-companion/src/extension.ts create mode 100644 packages/vscode-ide-companion/src/provider.ts create mode 100644 packages/vscode-ide-companion/src/tests/extension-utils.test.ts create mode 100644 packages/vscode-ide-companion/src/tests/extension.test.ts create mode 100644 packages/vscode-ide-companion/src/tests/run-tests.mjs create mode 100644 packages/vscode-ide-companion/src/utils.ts create mode 100644 packages/vscode-ide-companion/tsconfig.build.json create mode 100644 packages/vscode-ide-companion/tsconfig.json create mode 100644 scripts/build-vscode-companion.js create mode 100644 scripts/build.js create mode 100644 scripts/clean.js rename scripts/{copy_bundle_assets.js => copy-bundle-assets.js} (62%) create mode 100644 scripts/esbuild-vscode.config.js create mode 100644 scripts/esbuild.config.js create mode 100644 scripts/generate-git-commit-info.js create mode 100644 scripts/start.js delete mode 100644 src/tests/run-tests.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4dc891f0..db286bd8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,6 @@ jobs: - windows-latest - macos-latest node-version: - - "20" - "22" - "24" @@ -38,8 +37,14 @@ jobs: - name: TypeCheck + Lint + Format Check run: npm run check - - name: Bundle + - name: Build Core + run: npm run build --workspace=@vegamo/deepcode-core + + - name: Bundle CLI run: npm run bundle + - name: Build VSCode Extension + run: npm run build:vscode + - name: Test run: npm test diff --git a/.gitignore b/.gitignore index 8f054d4b..cd80bbf9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ node_modules/ dist/ +out/ +src/generated/ .DS_Store .idea/ .vscode/ *.tgz *.log +*.vsix .deepcode/settings.json diff --git a/eslint.config.mjs b/eslint.config.mjs index 50e41491..b9ec5dc1 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -43,12 +43,43 @@ export default tseslint.config( }, // Test files: relaxed rules { - files: ["src/tests/**/*.ts"], + files: ["packages/*/src/tests/**/*.ts", "packages/*/src/tests/**/*.mjs"], + languageOptions: { + globals: { + process: "readonly", + console: "readonly", + }, + }, rules: { "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-unused-vars": "off", }, }, + // Script files: Node.js environment + { + files: ["./scripts/**/*.js", "./scripts/**/*.mjs", "packages/*/scripts/**/*.js"], + languageOptions: { + globals: { + process: "readonly", + console: "readonly", + }, + }, + }, + // Browser resources: VSCode webview scripts + { + files: ["packages/*/resources/**/*.js"], + languageOptions: { + globals: { + window: "readonly", + document: "readonly", + console: "readonly", + FileReader: "readonly", + Blob: "readonly", + URL: "readonly", + fetch: "readonly", + }, + }, + }, // Prettier config: disable conflicting ESLint rules, MUST be last - prettierConfig, + prettierConfig ); diff --git a/package-lock.json b/package-lock.json index fc94a3f8..3e6afcbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,29 +1,14 @@ { - "name": "@vegamo/deepcode-cli", - "version": "0.1.30", + "name": "deepcode", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@vegamo/deepcode-cli", - "version": "0.1.30", + "name": "deepcode", "license": "MIT", - "dependencies": { - "chalk": "^5.6.2", - "ejs": "^5.0.2", - "gradient-string": "^3.0.0", - "gray-matter": "^4.0.3", - "ignore": "^7.0.5", - "ink": "^7.0.4", - "ink-gradient": "^4.0.1", - "openai": "^6.35.0", - "react": "^19.2.5", - "undici": "^7.25.0", - "zod": "^4.4.3" - }, - "bin": { - "deepcode": "dist/cli.js" - }, + "workspaces": [ + "packages/*" + ], "devDependencies": { "@eslint/js": "^9.39.4", "@types/ejs": "^3.1.5", @@ -40,9 +25,6 @@ "tsx": "^4.21.0", "typescript": "^6.0.3", "typescript-eslint": "^8.59.2" - }, - "engines": { - "node": ">=22" } }, "node_modules/@alcalzone/ansi-tokenize": { @@ -58,14 +40,211 @@ "node": ">=18" } }, + "node_modules/@alcalzone/ansi-tokenize/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@azu/format-text": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@azu/format-text/-/format-text-1.0.2.tgz", + "integrity": "sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@azu/style-format": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@azu/style-format/-/style-format-1.0.1.tgz", + "integrity": "sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "@azu/format-text": "^1.0.1" + } + }, + "node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.10.1", + "resolved": "https://registry.npmmirror.com/@azure/core-auth/-/core-auth-1.10.1.tgz", + "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.10.2", + "resolved": "https://registry.npmmirror.com/@azure/core-client/-/core-client-1.10.2.tgz", + "integrity": "sha512-1D2LpsU7y9xrqKjdIbsB7PlrRePw0xsVV8p+AKTlzITrWmscajryfJCdDJB/oGwvDI5HmRo04eMMADB67uwAwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.24.0", + "resolved": "https://registry.npmmirror.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.24.0.tgz", + "integrity": "sha512-PpLsoDQ3AMmKZ0VU+0GrmqMxgp/sExjlVm4R+nLWngeoEGAzOIPVifaxKGU5gMv+nWELUoHfvrolWD+ZS/nFJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/@azure/core-tracing/-/core-tracing-1.3.1.tgz", + "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.13.1", + "resolved": "https://registry.npmmirror.com/@azure/core-util/-/core-util-1.13.1.tgz", + "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "4.13.1", + "resolved": "https://registry.npmmirror.com/@azure/identity/-/identity-4.13.1.tgz", + "integrity": "sha512-5C/2WD5Vb1lHnZS16dNQRPMjN6oV/Upba+C9nBIs15PmOi6A3ZGs4Lr2u60zw4S04gi+u3cEXiqTVP7M4Pz3kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^5.5.0", + "@azure/msal-node": "^5.1.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/@azure/logger/-/logger-1.3.0.tgz", + "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "5.13.0", + "resolved": "https://registry.npmmirror.com/@azure/msal-browser/-/msal-browser-5.13.0.tgz", + "integrity": "sha512-Ea23x0U8XNFY+qJ9T44zO2BbY+AHdb+WdjmYnx36OhJ/KO+PGU5pmsNHf1DCElYX+6wyVRJz1HFeCPC/cHbRug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.8.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "16.8.0", + "resolved": "https://registry.npmmirror.com/@azure/msal-common/-/msal-common-16.8.0.tgz", + "integrity": "sha512-5S4RHOcInL2Nu2U217tDZbWGI6StMfcWCrA7TWvWdJmXQ+cYrrIqr84AsN62fGh2MDBysiBJPt6CfWceJfloEA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "5.2.4", + "resolved": "https://registry.npmmirror.com/@azure/msal-node/-/msal-node-5.2.4.tgz", + "integrity": "sha512-rpBUg9dA8UpC2WiFt3KeDKVQmmmVrfxdRnW+F1ebgou/jX/0tAvYuonaq5RUo8OaqzOrj4x/HaI8DmY56RXZ2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.8.0", + "jsonwebtoken": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -74,9 +253,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.3", - "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.3.tgz", - "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { @@ -84,21 +263,21 @@ } }, "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -115,14 +294,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -132,14 +311,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -149,9 +328,9 @@ } }, "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, "license": "MIT", "engines": { @@ -159,29 +338,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -191,9 +370,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "engines": { @@ -201,9 +380,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { @@ -211,9 +390,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "engines": { @@ -221,27 +400,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.3", - "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.3.tgz", - "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.29.0" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -251,33 +430,33 @@ } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", "debug": "^4.3.1" }, "engines": { @@ -285,23 +464,23 @@ } }, "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", - "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" ], @@ -316,9 +495,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.0.tgz", - "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" ], @@ -333,9 +512,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", - "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" ], @@ -350,9 +529,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.0.tgz", - "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" ], @@ -367,9 +546,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", - "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" ], @@ -384,9 +563,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", - "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" ], @@ -401,9 +580,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", - "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" ], @@ -418,9 +597,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", - "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" ], @@ -435,9 +614,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", - "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" ], @@ -452,9 +631,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", - "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" ], @@ -469,9 +648,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", - "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" ], @@ -486,9 +665,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", - "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" ], @@ -503,9 +682,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", - "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" ], @@ -520,9 +699,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", - "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" ], @@ -537,9 +716,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", - "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" ], @@ -554,9 +733,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", - "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" ], @@ -571,9 +750,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", - "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" ], @@ -588,9 +767,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", - "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" ], @@ -605,9 +784,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", - "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" ], @@ -622,9 +801,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", - "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" ], @@ -639,9 +818,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", - "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" ], @@ -656,9 +835,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", - "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "cpu": [ "arm64" ], @@ -673,9 +852,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", - "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" ], @@ -690,9 +869,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", - "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" ], @@ -707,9 +886,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", - "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" ], @@ -724,9 +903,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", - "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" ], @@ -847,36 +1026,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/@eslint/js": { "version": "9.39.4", "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.39.4.tgz", @@ -1030,1149 +1179,4054 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@types/ejs": { - "version": "3.1.5", - "resolved": "https://registry.npmmirror.com/@types/ejs/-/ejs-3.1.5.tgz", - "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/gradient-string": { - "version": "1.1.6", - "resolved": "https://registry.npmmirror.com/@types/gradient-string/-/gradient-string-1.1.6.tgz", - "integrity": "sha512-LkaYxluY4G5wR1M4AKQUal2q61Di1yVVCw42ImFTuaIoQVgmV0WP1xUaLB8zwb47mp82vWTpePI9JmrjEnJ7nQ==", "license": "MIT", "dependencies": { - "@types/tinycolor2": "*" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 8" + } }, - "node_modules/@types/node": { - "version": "25.6.0", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-25.6.0.tgz", - "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.19.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmmirror.com/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", - "devOptional": true, + "node_modules/@secretlint/config-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/config-creator/-/config-creator-10.2.2.tgz", + "integrity": "sha512-BynOBe7Hn3LJjb3CqCHZjeNB09s/vgf0baBaHVw67w7gHF0d25c3ZsZ5+vv8TgwSchRdUCRrbbcq5i2B1fJ2QQ==", + "dev": true, "license": "MIT", "dependencies": { - "csstype": "^3.2.2" + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@types/tinycolor2": { - "version": "1.4.6", - "resolved": "https://registry.npmmirror.com/@types/tinycolor2/-/tinycolor2-1.4.6.tgz", - "integrity": "sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==", - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.2.tgz", - "integrity": "sha512-j/bwmkBvHUtPNxzuWe5z6BEk3q54YRyGlBXkSsmfoih7zNrBvl5A9A98anlp/7JbyZcWIJ8KXo/3Tq/DjFLtuQ==", + "node_modules/@secretlint/config-loader": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/config-loader/-/config-loader-10.2.2.tgz", + "integrity": "sha512-ndjjQNgLg4DIcMJp4iaRD6xb9ijWQZVbd9694Ol2IszBIbGPPkwZHzJYKICbTBmh6AH/pLr0CiCaWdGJU7RbpQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.59.2", - "@typescript-eslint/type-utils": "8.59.2", - "@typescript-eslint/utils": "8.59.2", - "@typescript-eslint/visitor-keys": "8.59.2", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.0" + "@secretlint/profiler": "^10.2.2", + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "ajv": "^8.17.1", + "debug": "^4.4.1", + "rc-config-loader": "^4.1.3" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.59.2", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "node": ">=20.0.0" } }, - "node_modules/@typescript-eslint/parser": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.59.2.tgz", - "integrity": "sha512-plR3pp6D+SSUn1HM7xvSkx12/DhoHInI2YF35KAcVFNZvlC0gtrWqx7Qq1oH2Ssgi0vlFRCTbP+DZc7B9+TtsQ==", + "node_modules/@secretlint/config-loader/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.59.2", - "@typescript-eslint/types": "8.59.2", - "@typescript-eslint/typescript-estree": "8.59.2", - "@typescript-eslint/visitor-keys": "8.59.2", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.59.2.tgz", - "integrity": "sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw==", + "node_modules/@secretlint/config-loader/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/core": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/core/-/core-10.2.2.tgz", + "integrity": "sha512-6rdwBwLP9+TO3rRjMVW1tX+lQeo5gBbxl1I5F8nh8bgGtKwdlCMhMKsBWzWg1ostxx/tIG7OjZI0/BxsP8bUgw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.59.2", - "@typescript-eslint/types": "^8.59.2", - "debug": "^4.4.3" + "@secretlint/profiler": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "structured-source": "^4.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "node": ">=20.0.0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.59.2.tgz", - "integrity": "sha512-JzfyEpEtOU89CcFSwyNS3mu4MLvLSXqnmX05+aKBDM+TdR5jzcGOEBwxwGNxrEQ7p/z6kK2WyioCGBf2zZBnvg==", + "node_modules/@secretlint/formatter": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/formatter/-/formatter-10.2.2.tgz", + "integrity": "sha512-10f/eKV+8YdGKNQmoDUD1QnYL7TzhI2kzyx95vsJKbEa8akzLAR5ZrWIZ3LbcMmBLzxlSQMMccRmi05yDQ5YDA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.2", - "@typescript-eslint/visitor-keys": "8.59.2" + "@secretlint/resolver": "^10.2.2", + "@secretlint/types": "^10.2.2", + "@textlint/linter-formatter": "^15.2.0", + "@textlint/module-interop": "^15.2.0", + "@textlint/types": "^15.2.0", + "chalk": "^5.4.1", + "debug": "^4.4.1", + "pluralize": "^8.0.0", + "strip-ansi": "^7.1.0", + "table": "^6.9.0", + "terminal-link": "^4.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=20.0.0" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.2.tgz", - "integrity": "sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw==", + "node_modules/@secretlint/formatter/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.59.2.tgz", - "integrity": "sha512-nhqaj1nmTdVVl/BP5omXNRGO38jn5iosis2vbdmupF2txCf8ylWT8lx+JlvMYYVqzGVKtjojUFoQ3JRWK+mfzQ==", + "node_modules/@secretlint/node": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/node/-/node-10.2.2.tgz", + "integrity": "sha512-eZGJQgcg/3WRBwX1bRnss7RmHHK/YlP/l7zOQsrjexYt6l+JJa5YhUmHbuGXS94yW0++3YkEJp0kQGYhiw1DMQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.2", - "@typescript-eslint/typescript-estree": "8.59.2", - "@typescript-eslint/utils": "8.59.2", - "debug": "^4.4.3", - "ts-api-utils": "^2.5.0" + "@secretlint/config-loader": "^10.2.2", + "@secretlint/core": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "@secretlint/source-creator": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "p-map": "^7.0.3" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "node": ">=20.0.0" } }, - "node_modules/@typescript-eslint/types": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.59.2.tgz", - "integrity": "sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==", + "node_modules/@secretlint/profiler": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/profiler/-/profiler-10.2.2.tgz", + "integrity": "sha512-qm9rWfkh/o8OvzMIfY8a5bCmgIniSpltbVlUVl983zDG1bUuQNd1/5lUEeWx5o/WJ99bXxS7yNI4/KIXfHexig==", "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } + "license": "MIT" }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.2.tgz", - "integrity": "sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg==", + "node_modules/@secretlint/resolver": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/resolver/-/resolver-10.2.2.tgz", + "integrity": "sha512-3md0cp12e+Ae5V+crPQYGd6aaO7ahw95s28OlULGyclyyUtf861UoRGS2prnUrKh7MZb23kdDOyGCYb9br5e4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/secretlint-formatter-sarif": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/secretlint-formatter-sarif/-/secretlint-formatter-sarif-10.2.2.tgz", + "integrity": "sha512-ojiF9TGRKJJw308DnYBucHxkpNovDNu1XvPh7IfUp0A12gzTtxuWDqdpuVezL7/IP8Ua7mp5/VkDMN9OLp1doQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.59.2", - "@typescript-eslint/tsconfig-utils": "8.59.2", - "@typescript-eslint/types": "8.59.2", - "@typescript-eslint/visitor-keys": "8.59.2", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" + "node-sarif-builder": "^3.2.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "node_modules/@secretlint/secretlint-rule-no-dotenv": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/secretlint-rule-no-dotenv/-/secretlint-rule-no-dotenv-10.2.2.tgz", + "integrity": "sha512-KJRbIShA9DVc5Va3yArtJ6QDzGjg3PRa1uYp9As4RsyKtKSSZjI64jVca57FZ8gbuk4em0/0Jq+uy6485wxIdg==", "dev": true, "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=20.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "node_modules/@secretlint/secretlint-rule-preset-recommend": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/secretlint-rule-preset-recommend/-/secretlint-rule-preset-recommend-10.2.2.tgz", + "integrity": "sha512-K3jPqjva8bQndDKJqctnGfwuAxU2n9XNCPtbXVI5JvC7FnQiNg/yWlQPbMUlBXtBoBGFYp08A94m6fvtc9v+zA==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=20.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "node_modules/@secretlint/source-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/source-creator/-/source-creator-10.2.2.tgz", + "integrity": "sha512-h6I87xJfwfUTgQ7irWq7UTdq/Bm1RuQ/fYhA3dtTIAop5BwSFmZyrchph4WcoEvbN460BWKmk4RYSvPElIIvxw==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "brace-expansion": "^5.0.5" + "@secretlint/types": "^10.2.2", + "istextorbinary": "^9.5.0" }, "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=20.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.8.0", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.0.tgz", - "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "node_modules/@secretlint/types": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/@secretlint/types/-/types-10.2.2.tgz", + "integrity": "sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=20.0.0" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.59.2.tgz", - "integrity": "sha512-Juw3EinkXqjaffxz6roowvV7GZT/kET5vSKKZT6upl5TXdWkLkYmNPXwDDL2Vkt2DPn0nODIS4egC/0AGxKo/Q==", + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.59.2", - "@typescript-eslint/types": "8.59.2", - "@typescript-eslint/typescript-estree": "8.59.2" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.2.tgz", - "integrity": "sha512-NwjLUnGy8/Zfx23fl50tRC8rYaYnM52xNRYFAXvmiil9yh1+K6aRVQMnzW6gQB/1DLgWt977lYQn7C+wtgXZiA==", + "node_modules/@textlint/ast-node-types": { + "version": "15.7.1", + "resolved": "https://registry.npmmirror.com/@textlint/ast-node-types/-/ast-node-types-15.7.1.tgz", + "integrity": "sha512-Wii5UgUKFEh9Uv6wbq1zr4/Kf+dtjiUuzPrrXzKp8H+ifkvKNzi23V4Nz+6wVyHQn5T28AFuc8VH8OtzvGYecA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter": { + "version": "15.7.1", + "resolved": "https://registry.npmmirror.com/@textlint/linter-formatter/-/linter-formatter-15.7.1.tgz", + "integrity": "sha512-TdwZ/debWYFD05K3CcoHtwvnCrza29wZxD+BjDTk/V5N7iRqkK1dTTHSD4A8AIgROLiDkHJmIKQbasbmsg8AvA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.59.2", - "eslint-visitor-keys": "^5.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@azu/format-text": "^1.0.2", + "@azu/style-format": "^1.0.1", + "@textlint/module-interop": "15.7.1", + "@textlint/resolver": "15.7.1", + "@textlint/types": "15.7.1", + "chalk": "^4.1.2", + "debug": "^4.4.3", + "js-yaml": "^4.1.1", + "lodash": "^4.18.1", + "pluralize": "^2.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "table": "^6.9.0", + "text-table": "^0.2.0" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "node_modules/@textlint/linter-formatter/node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8" } }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "node_modules/@textlint/linter-formatter/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/linter-formatter/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" + "node": ">=8" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@textlint/linter-formatter/node_modules/pluralize": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/pluralize/-/pluralize-2.0.0.tgz", + "integrity": "sha512-TqNZzQCD4S42De9IfnnBvILN7HAW7riLqsCyp8lgjXeysyPlX5HhqKAcJHHHb9XskE4/a+7VGC9zzx8Ls0jOAw==", "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } + "license": "MIT" }, - "node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "node_modules/@textlint/linter-formatter/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">=8" } }, - "node_modules/ansi-escapes": { - "version": "7.3.0", - "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-7.3.0.tgz", - "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "node_modules/@textlint/linter-formatter/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { - "environment": "^1.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } + "node_modules/@textlint/module-interop": { + "version": "15.7.1", + "resolved": "https://registry.npmmirror.com/@textlint/module-interop/-/module-interop-15.7.1.tgz", + "integrity": "sha512-Jg+sQW2L/cRJypk59wtcMUVVpt8vmit5ZMT3gUnFwevP3A6Qp1HfOtUy9ObT4hBX3lOSGT/ekcCDxR1pL7uH1g==", + "dev": true, + "license": "MIT" }, - "node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "node_modules/@textlint/resolver": { + "version": "15.7.1", + "resolved": "https://registry.npmmirror.com/@textlint/resolver/-/resolver-15.7.1.tgz", + "integrity": "sha512-8XnO0pgF6mXnm41VvWmBbEIdGPhiCUt31uLZkOis1ECeg/1SoUcIT6Mx/F0e1rukq8l0UlOSeY9a31CsvRMK0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@textlint/types": { + "version": "15.7.1", + "resolved": "https://registry.npmmirror.com/@textlint/types/-/types-15.7.1.tgz", + "integrity": "sha512-Vye/GmFNBTgVzZFtIFJTmLB+s2A7oIADxNG6r9UhfPuY+Czv0z5G3xeyFZZudPlfxURsKUyPIU5XsjOFqVp33A==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "dependencies": { + "@textlint/ast-node-types": "15.7.1" } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@types/ejs": { + "version": "3.1.5", + "resolved": "https://registry.npmmirror.com/@types/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/gradient-string": { + "version": "1.1.6", + "resolved": "https://registry.npmmirror.com/@types/gradient-string/-/gradient-string-1.1.6.tgz", + "integrity": "sha512-LkaYxluY4G5wR1M4AKQUal2q61Di1yVVCw42ImFTuaIoQVgmV0WP1xUaLB8zwb47mp82vWTpePI9JmrjEnJ7nQ==", "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@types/tinycolor2": "*" } }, - "node_modules/auto-bind": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/auto-bind/-/auto-bind-5.0.1.tgz", - "integrity": "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "dev": true, "license": "MIT" }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.29", - "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz", - "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==", + "node_modules/@types/node": { + "version": "25.9.3", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-25.9.3.tgz", + "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==", "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" } }, - "node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.17", + "resolved": "https://registry.npmmirror.com/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", + "devOptional": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "csstype": "^3.2.2" } }, - "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "node_modules/@types/sarif": { + "version": "2.1.7", + "resolved": "https://registry.npmmirror.com/@types/sarif/-/sarif-2.1.7.tgz", + "integrity": "sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/tinycolor2": { + "version": "1.4.6", + "resolved": "https://registry.npmmirror.com/@types/tinycolor2/-/tinycolor2-1.4.6.tgz", + "integrity": "sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==", + "license": "MIT" + }, + "node_modules/@types/vscode": { + "version": "1.120.0", + "resolved": "https://registry.npmmirror.com/@types/vscode/-/vscode-1.120.0.tgz", + "integrity": "sha512-feaT4Rst+FkTch5zz/ZbNCxoIvo55YU80Be2kiL7OJcod4+CUYf2lUBPdIJzozNnSEMq1VRTGrWEcCGFB3fBmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", + "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", - "update-browserslist-db": "^1.2.3" - }, - "bin": { - "browserslist": "cli.js" + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/type-utils": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.61.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 4" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001792", - "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", - "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", + "node_modules/@typescript-eslint/parser": { + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.61.0.tgz", + "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", + "debug": "^4.4.3" + }, "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/cli-boxes": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/cli-boxes/-/cli-boxes-4.0.1.tgz", - "integrity": "sha512-5IOn+jcCEHEraYolBPs/sT4BxYCe2nHg374OPiItB1O96KZFseS2gthU4twyYzeDcFew4DaUM/xwc5BQf08JJw==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", + "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", + "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.61.0", + "@typescript-eslint/types": "^8.61.0", + "debug": "^4.4.3" + }, "engines": { - "node": ">=18.20 <19 || >=20.10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", + "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", + "dev": true, "license": "MIT", "dependencies": { - "restore-cursor": "^4.0.0" + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/cli-truncate": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-6.0.0.tgz", - "integrity": "sha512-3+YKIUFsohD9MIoOFPFBldjAlnfCmCDcqe6aYGFqlDTRKg80p4wg35L+j83QQ63iOlKRccEkbn8IuM++HsgEjA==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", + "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", + "dev": true, "license": "MIT", - "dependencies": { - "slice-ansi": "^9.0.0", - "string-width": "^8.2.0" - }, "engines": { - "node": ">=22" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/code-excerpt": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/code-excerpt/-/code-excerpt-4.0.0.tgz", - "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", + "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", + "dev": true, "license": "MIT", "dependencies": { - "convert-to-spaces": "^2.0.1" + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@typescript-eslint/types": { + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.61.0.tgz", + "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", "dev": true, "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", + "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.61.0", + "@typescript-eslint/tsconfig-utils": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "license": "MIT" - }, - "node_modules/convert-to-spaces": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", - "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "18 || 20 || >=22" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">= 8" + "node": "18 || 20 || >=22" } }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "ms": "^2.1.3" + "brace-expansion": "^5.0.5" }, "engines": { - "node": ">=6.0" + "node": "18 || 20 || >=22" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.61.0.tgz", + "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", + "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.61.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.6", + "resolved": "https://registry.npmmirror.com/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.6.tgz", + "integrity": "sha512-jIXhD0eWQ1JA6ln/5Dltyx22UxWNrw0hZmhy2rlv6m6KgF7kplHx3g0fzi09lNmTJQRR91OlemYp3xFnvDK9og==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@vegamo/deepcode-cli": { + "resolved": "packages/cli", + "link": true + }, + "node_modules/@vegamo/deepcode-core": { + "resolved": "packages/core", + "link": true + }, + "node_modules/@vegamo/deepcode-vscode": { + "resolved": "packages/vscode-ide-companion", + "link": true + }, + "node_modules/@vscode/vsce": { + "version": "3.9.2", + "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-3.9.2.tgz", + "integrity": "sha512-XSxMosEEDO6vLxELAHVkwmhC0qe0ijZni2jB9Rcs8kQsW4lhTDQ/wMzmwFs/buotAWSnpmUp/dRWD2ufG3UYKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/identity": "^4.1.0", + "@secretlint/node": "^10.1.2", + "@secretlint/secretlint-formatter-sarif": "^10.1.2", + "@secretlint/secretlint-rule-no-dotenv": "^10.1.2", + "@secretlint/secretlint-rule-preset-recommend": "^10.1.2", + "@vscode/vsce-sign": "^2.0.0", + "azure-devops-node-api": "^12.5.0", + "chalk": "^4.1.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^12.1.0", + "form-data": "^4.0.0", + "glob": "^13.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^14.1.0", + "mime": "^1.3.4", + "minimatch": "^10.2.2", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "secretlint": "^10.1.2", + "semver": "^7.5.2", + "tmp": "^0.2.3", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^3.2.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "node_modules/@vscode/vsce-sign": { + "version": "2.0.9", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign/-/vsce-sign-2.0.9.tgz", + "integrity": "sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g==", + "dev": true, + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optionalDependencies": { + "@vscode/vsce-sign-alpine-arm64": "2.0.6", + "@vscode/vsce-sign-alpine-x64": "2.0.6", + "@vscode/vsce-sign-darwin-arm64": "2.0.6", + "@vscode/vsce-sign-darwin-x64": "2.0.6", + "@vscode/vsce-sign-linux-arm": "2.0.6", + "@vscode/vsce-sign-linux-arm64": "2.0.6", + "@vscode/vsce-sign-linux-x64": "2.0.6", + "@vscode/vsce-sign-win32-arm64": "2.0.6", + "@vscode/vsce-sign-win32-x64": "2.0.6" + } + }, + "node_modules/@vscode/vsce-sign-alpine-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz", + "integrity": "sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-alpine-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz", + "integrity": "sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz", + "integrity": "sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz", + "integrity": "sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz", + "integrity": "sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz", + "integrity": "sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz", + "integrity": "sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-win32-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz", + "integrity": "sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce-sign-win32-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz", + "integrity": "sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@vscode/vsce/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@vscode/vsce/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@vscode/vsce/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/auto-bind": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/auto-bind/-/auto-bind-5.0.1.tgz", + "integrity": "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/azure-devops-node-api": { + "version": "12.5.0", + "resolved": "https://registry.npmmirror.com/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", + "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.37", + "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.37.tgz", + "integrity": "sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binaryextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmmirror.com/binaryextensions/-/binaryextensions-6.11.0.tgz", + "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/boundary": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/boundary/-/boundary-2.0.0.tgz", + "integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001799", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cheerio": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/cheerio/-/cheerio-1.2.0.tgz", + "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.1.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.19.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/cli-boxes": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/cli-boxes/-/cli-boxes-4.0.1.tgz", + "integrity": "sha512-5IOn+jcCEHEraYolBPs/sT4BxYCe2nHg374OPiItB1O96KZFseS2gthU4twyYzeDcFew4DaUM/xwc5BQf08JJw==", + "license": "MIT", + "engines": { + "node": ">=18.20 <19 || >=20.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cockatiel": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/cockatiel/-/cockatiel-3.2.1.tgz", + "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/code-excerpt": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", + "license": "MIT", + "dependencies": { + "convert-to-spaces": "^2.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-to-spaces": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmmirror.com/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" } }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editions": { + "version": "6.22.0", + "resolved": "https://registry.npmmirror.com/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "version-range": "^4.15.0" + }, + "engines": { + "ecmascript": ">= es5", + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/ejs": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/ejs/-/ejs-5.0.2.tgz", + "integrity": "sha512-IpbUaI/CAW86l3f+T8zN0iggSc0LmMZLcIW5eRVStLVNCoTXkE0YlncbbH50fp8Cl6zHIky0sW2uUbhBqGw0Jw==", + "license": "Apache-2.0", + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.12.18" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.372", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.372.tgz", + "integrity": "sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-toolkit": { + "version": "1.47.1", + "resolved": "https://registry.npmmirror.com/es-toolkit/-/es-toolkit-1.47.1.tgz", + "integrity": "sha512-5RAqEwf4P4E17p+W75KLOWw/nOvKZzSQpxM32IpI2KZLaVonjTrZ0Ai5ghMaVI9eKC2p8eoQgcBdkEDgzFk6+Q==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmmirror.com/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs-extra": { + "version": "11.3.5", + "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.5.tgz", + "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/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/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmmirror.com/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmmirror.com/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmmirror.com/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/gradient-string": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/gradient-string/-/gradient-string-3.0.0.tgz", + "integrity": "sha512-frdKI4Qi8Ihp4C6wZNB565de/THpIaw3DjP5ku87M+N9rNSGmPTjfkq61SdRXB7eCaL8O1hkKDvf6CDMtOzIAg==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "tinygradient": "^1.1.5" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gradient-string/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmmirror.com/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmmirror.com/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmmirror.com/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/ink": { + "version": "7.0.6", + "resolved": "https://registry.npmmirror.com/ink/-/ink-7.0.6.tgz", + "integrity": "sha512-/KG651f+LHln9gumb5ltieFqzNGJdhX1b/WwsCUd2Py7Htuk9KUzyFrk25ugmzjXyDneXSoXD3cm4ql4dWFGsQ==", + "license": "MIT", + "dependencies": { + "@alcalzone/ansi-tokenize": "^0.3.0", + "ansi-escapes": "^7.3.0", + "ansi-styles": "^6.2.3", + "auto-bind": "^5.0.1", + "chalk": "^5.6.2", + "cli-boxes": "^4.0.1", + "cli-cursor": "^4.0.0", + "cli-truncate": "^6.0.0", + "code-excerpt": "^4.0.0", + "es-toolkit": "^1.45.1", + "indent-string": "^5.0.0", + "is-in-ci": "^2.0.0", + "patch-console": "^2.0.0", + "react-reconciler": "^0.33.0", + "scheduler": "^0.27.0", + "signal-exit": "^3.0.7", + "slice-ansi": "^9.0.0", + "stack-utils": "^2.0.6", + "string-width": "^8.2.0", + "terminal-size": "^4.0.1", + "type-fest": "^5.5.0", + "widest-line": "^6.0.0", + "wrap-ansi": "^10.0.0", + "ws": "^8.20.0", + "yoga-layout": "~3.2.1" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "@types/react": ">=19.2.0", + "react": ">=19.2.0", + "react-devtools-core": ">=6.1.2" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react-devtools-core": { + "optional": true + } + } + }, + "node_modules/ink-gradient": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/ink-gradient/-/ink-gradient-4.0.1.tgz", + "integrity": "sha512-0ckdiM84zkfCdnTtcnq4BS3egIhUPPDoCqSx/7NUFsAVooBbdRuGnnWpk0fuaOTqU6rlZRh9F4LN1UI8fxd81Q==", + "license": "MIT", + "dependencies": { + "@types/gradient-string": "^1.1.6", + "gradient-string": "^3.0.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + }, + "peerDependencies": { + "ink": ">=6", + "react": ">=19.2.0" + } + }, + "node_modules/ink/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ink/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ink/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/cli-truncate": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-6.0.0.tgz", + "integrity": "sha512-3+YKIUFsohD9MIoOFPFBldjAlnfCmCDcqe6aYGFqlDTRKg80p4wg35L+j83QQ63iOlKRccEkbn8IuM++HsgEjA==", + "license": "MIT", + "dependencies": { + "slice-ansi": "^9.0.0", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ink/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/ink/node_modules/slice-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-9.0.0.tgz", + "integrity": "sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" + }, + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/ejs": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-5.0.2.tgz", - "integrity": "sha512-IpbUaI/CAW86l3f+T8zN0iggSc0LmMZLcIW5eRVStLVNCoTXkE0YlncbbH50fp8Cl6zHIky0sW2uUbhBqGw0Jw==", - "license": "Apache-2.0", + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-in-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/is-in-ci/-/is-in-ci-2.0.0.tgz", + "integrity": "sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w==", + "license": "MIT", "bin": { - "ejs": "bin/cli.js" + "is-in-ci": "cli.js" }, "engines": { - "node": ">=0.12.18" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.353", - "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.353.tgz", - "integrity": "sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==", + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, "engines": { - "node": ">=18" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-toolkit": { - "version": "1.46.1", - "resolved": "https://registry.npmmirror.com/es-toolkit/-/es-toolkit-1.46.1.tgz", - "integrity": "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istextorbinary": { + "version": "9.5.0", + "resolved": "https://registry.npmmirror.com/istextorbinary/-/istextorbinary-9.5.0.tgz", + "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", - "workspaces": [ - "docs", - "benchmarks" - ] + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } }, - "node_modules/esbuild": { - "version": "0.28.0", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.0.tgz", - "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmmirror.com/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmmirror.com/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", "dev": true, "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.0", - "@esbuild/android-arm": "0.28.0", - "@esbuild/android-arm64": "0.28.0", - "@esbuild/android-x64": "0.28.0", - "@esbuild/darwin-arm64": "0.28.0", - "@esbuild/darwin-x64": "0.28.0", - "@esbuild/freebsd-arm64": "0.28.0", - "@esbuild/freebsd-x64": "0.28.0", - "@esbuild/linux-arm": "0.28.0", - "@esbuild/linux-arm64": "0.28.0", - "@esbuild/linux-ia32": "0.28.0", - "@esbuild/linux-loong64": "0.28.0", - "@esbuild/linux-mips64el": "0.28.0", - "@esbuild/linux-ppc64": "0.28.0", - "@esbuild/linux-riscv64": "0.28.0", - "@esbuild/linux-s390x": "0.28.0", - "@esbuild/linux-x64": "0.28.0", - "@esbuild/netbsd-arm64": "0.28.0", - "@esbuild/netbsd-x64": "0.28.0", - "@esbuild/openbsd-arm64": "0.28.0", - "@esbuild/openbsd-x64": "0.28.0", - "@esbuild/openharmony-arm64": "0.28.0", - "@esbuild/sunos-x64": "0.28.0", - "@esbuild/win32-arm64": "0.28.0", - "@esbuild/win32-ia32": "0.28.0", - "@esbuild/win32-x64": "0.28.0" + "node": ">=0.10.0" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/eslint": { - "version": "9.39.4", - "resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.39.4.tgz", - "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "node_modules/linkify-it": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-5.0.1.tgz", + "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lint-staged": { + "version": "17.0.7", + "resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-17.0.7.tgz", + "integrity": "sha512-JrSobt+tW3rH8IOMi8tDZd3foorM5yPEkLD/V2NxobgHrFfHWGee4MOLVuZeScgxftEwbHrPHIFA/ZL+nUJeuA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.2", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.5", - "@eslint/js": "9.39.4", - "@eslint/plugin-kit": "^0.4.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.14.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.5", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" + "listr2": "^10.2.1", + "picomatch": "^4.0.4", + "string-argv": "^0.3.2", + "tinyexec": "^1.2.4" }, "bin": { - "eslint": "bin/eslint.js" + "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=22.22.1" }, "funding": { - "url": "https://eslint.org/donate" + "url": "https://opencollective.com/lint-staged" }, - "peerDependencies": { - "jiti": "*" + "optionalDependencies": { + "yaml": "^2.9.0" + } + }, + "node_modules/listr2": { + "version": "10.2.1", + "resolved": "https://registry.npmmirror.com/listr2/-/listr2-10.2.1.tgz", + "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.2.0", + "eventemitter3": "^5.0.4", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^10.0.0" }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } + "engines": { + "node": ">=22.13.0" } }, - "node_modules/eslint-config-prettier": { - "version": "10.1.8", - "resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", - "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" + "dependencies": { + "p-locate": "^5.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint-config-prettier" + "engines": { + "node": ">=10" }, - "peerDependencies": { - "eslint": ">=7.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "7.1.1", - "resolved": "https://registry.npmmirror.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", - "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmmirror.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.24.4", - "@babel/parser": "^7.24.4", - "hermes-parser": "^0.25.1", - "zod": "^3.25.0 || ^4.0.0", - "zod-validation-error": "^3.5.0 || ^4.0.0" + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { "node": ">=18" }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/markdown-it": { + "version": "14.2.0", + "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.1", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/eslint/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4" + "node": ">= 0.4" } }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmmirror.com/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 8" } }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=0.10" + "node": ">=8.6" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, "engines": { - "node": ">=4.0" + "node": ">=4" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, - "license": "MIT" - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "license": "MIT", "dependencies": { - "is-extendable": "^0.1.0" + "mime-db": "1.52.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { + "node_modules/mimic-fn": { "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "license": "MIT", "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "node": ">=6" } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, "engines": { - "node": ">=16.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "optional": true, "engines": { "node": ">=10" }, @@ -2180,662 +5234,517 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=16" + "node": "*" } }, - "node_modules/flatted": { - "version": "3.4.2", - "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "hasInstallScript": true, "license": "MIT", "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=6.9.0" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/get-east-asian-width": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", - "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmmirror.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "optional": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, - "node_modules/get-tsconfig": { - "version": "4.14.0", - "resolved": "https://registry.npmmirror.com/get-tsconfig/-/get-tsconfig-4.14.0.tgz", - "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmmirror.com/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "dev": true, "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } + "optional": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" }, - "node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmmirror.com/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "node_modules/node-abi": { + "version": "3.92.0", + "resolved": "https://registry.npmmirror.com/node-abi/-/node-abi-3.92.0.tgz", + "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", + "optional": true, "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" + "semver": "^7.3.5" }, "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=10" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/node-abi/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" + "optional": true, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=10.13.0" + "node": ">=10" } }, - "node_modules/glob/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", "dev": true, "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } + "optional": true }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "node_modules/node-releases": { + "version": "2.0.47", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.47.tgz", + "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=18" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "node_modules/node-sarif-builder": { + "version": "3.4.0", + "resolved": "https://registry.npmmirror.com/node-sarif-builder/-/node-sarif-builder-3.4.0.tgz", + "integrity": "sha512-tGnJW6OKRii9u/b2WiUViTJS+h7Apxx17qsMUjsUeNDiMMX5ZFf8F8Fcz7PAQ6omvOxHZtvDTmOYKJQwmfpjeg==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "brace-expansion": "^5.0.5" + "@types/sarif": "^2.1.7", + "fs-extra": "^11.1.1" }, "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=20" } }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmmirror.com/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gradient-string": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/gradient-string/-/gradient-string-3.0.0.tgz", - "integrity": "sha512-frdKI4Qi8Ihp4C6wZNB565de/THpIaw3DjP5ku87M+N9rNSGmPTjfkq61SdRXB7eCaL8O1hkKDvf6CDMtOzIAg==", - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "chalk": "^5.3.0", - "tinygradient": "^1.1.5" + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": ">=14" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/gray-matter": { - "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/gray-matter/-/gray-matter-4.0.3.tgz", - "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", - "license": "MIT", + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", "dependencies": { - "js-yaml": "^3.13.1", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" + "lru-cache": "^10.0.1" }, "engines": { - "node": ">=6.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "ISC" }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmmirror.com/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "node_modules/normalize-package-data/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, - "license": "MIT" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmmirror.com/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "hermes-estree": "0.25.1" + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/husky": { - "version": "9.1.7", - "resolved": "https://registry.npmmirror.com/husky/-/husky-9.1.7.tgz", - "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", - "bin": { - "husky": "bin.js" - }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/typicode" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "license": "MIT", - "engines": { - "node": ">= 4" + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "wrappy": "1" } }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmmirror.com/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", "dev": true, "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "license": "MIT", - "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ink": { - "version": "7.0.4", - "resolved": "https://registry.npmmirror.com/ink/-/ink-7.0.4.tgz", - "integrity": "sha512-4wsM/gMKOT2ZANNTJibI6I9IcwBfobqv/CgaDcwvOaCREZIQxo3iGQS7qPHa2hmA67NYltZWCMtBDELB/mcbJQ==", - "license": "MIT", - "dependencies": { - "@alcalzone/ansi-tokenize": "^0.3.0", - "ansi-escapes": "^7.3.0", - "ansi-styles": "^6.2.3", - "auto-bind": "^5.0.1", - "chalk": "^5.6.2", - "cli-boxes": "^4.0.1", - "cli-cursor": "^4.0.0", - "cli-truncate": "^6.0.0", - "code-excerpt": "^4.0.0", - "es-toolkit": "^1.45.1", - "indent-string": "^5.0.0", - "is-in-ci": "^2.0.0", - "patch-console": "^2.0.0", - "react-reconciler": "^0.33.0", - "scheduler": "^0.27.0", - "signal-exit": "^3.0.7", - "slice-ansi": "^9.0.0", - "stack-utils": "^2.0.6", - "string-width": "^8.2.0", - "terminal-size": "^4.0.1", - "type-fest": "^5.5.0", - "widest-line": "^6.0.0", - "wrap-ansi": "^10.0.0", - "ws": "^8.20.0", - "yoga-layout": "~3.2.1" - }, - "engines": { - "node": ">=22" - }, + "node_modules/openai": { + "version": "6.42.0", + "resolved": "https://registry.npmmirror.com/openai/-/openai-6.42.0.tgz", + "integrity": "sha512-1WFEt/uXMXOLhYRNkgJWo08Y2YNvNwpVU72K7ibrWgWpNOXd4VojXLbe6SQ4bLiUQ3Y8jz4IiyVkylJCL1DtZg==", + "license": "Apache-2.0", "peerDependencies": { - "@types/react": ">=19.2.0", - "react": ">=19.2.0", - "react-devtools-core": ">=6.1.2" + "ws": "^8.18.0", + "zod": "^3.25 || ^4.0" }, "peerDependenciesMeta": { - "@types/react": { + "ws": { "optional": true }, - "react-devtools-core": { + "zod": { "optional": true } } }, - "node_modules/ink-gradient": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/ink-gradient/-/ink-gradient-4.0.1.tgz", - "integrity": "sha512-0ckdiM84zkfCdnTtcnq4BS3egIhUPPDoCqSx/7NUFsAVooBbdRuGnnWpk0fuaOTqU6rlZRh9F4LN1UI8fxd81Q==", - "license": "MIT", - "dependencies": { - "@types/gradient-string": "^1.1.6", - "gradient-string": "^3.0.0", - "strip-ansi": "^7.1.2" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - }, - "peerDependencies": { - "ink": ">=6", - "react": ">=19.2.0" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmmirror.com/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "license": "MIT", "dependencies": { - "get-east-asian-width": "^1.3.1" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-in-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/is-in-ci/-/is-in-ci-2.0.0.tgz", - "integrity": "sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w==", + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "dev": true, "license": "MIT", - "bin": { - "is-in-ci": "cli.js" - }, "engines": { - "node": ">=20" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "callsites": "^3.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=6" } }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", "dev": true, "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/parse-json/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=6" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", "dev": true, "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "semver": "^5.1.0" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "entities": "^6.0.0" }, - "engines": { - "node": ">= 0.8.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/lint-staged": { - "version": "17.0.4", - "resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-17.0.4.tgz", - "integrity": "sha512-+rU9lSUyVOZ/hDUmRLVGzyS2v73cDdQjX+XQz1AaOdIE4RysLq0HoPW2HrrgeNCLklkhi904VBU1bmgWLHVnkA==", + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", "dev": true, "license": "MIT", "dependencies": { - "listr2": "^10.2.1", - "picomatch": "^4.0.4", - "string-argv": "^0.3.2", - "tinyexec": "^1.1.2" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": ">=22.22.1" + "domhandler": "^5.0.3", + "parse5": "^7.0.0" }, "funding": { - "url": "https://opencollective.com/lint-staged" - }, - "optionalDependencies": { - "yaml": "^2.8.4" + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/listr2": { - "version": "10.2.1", - "resolved": "https://registry.npmmirror.com/listr2/-/listr2-10.2.1.tgz", - "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmmirror.com/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", "dev": true, "license": "MIT", "dependencies": { - "cli-truncate": "^5.2.0", - "eventemitter3": "^5.0.4", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^10.0.0" + "parse5": "^7.0.0" }, - "engines": { - "node": ">=22.13.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/listr2/node_modules/cli-truncate": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-5.2.0.tgz", - "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^8.0.0", - "string-width": "^8.2.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=20" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/listr2/node_modules/slice-ansi": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-8.0.0.tgz", - "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", - "dev": true, + "node_modules/patch-console": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/patch-console/-/patch-console-2.0.0.tgz", + "integrity": "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==", "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.3", - "is-fullwidth-code-point": "^5.1.0" - }, "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "restore-cursor": "^5.0.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=18" + "node": "18 || 20 || >=22" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/log-update/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", "dev": true, "license": "MIT", - "dependencies": { - "mimic-function": "^5.0.0" - }, "engines": { "node": ">=18" }, @@ -2843,517 +5752,726 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, "engines": { - "node": ">=18" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/log-update/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "node_modules/log-update/node_modules/slice-ansi": { + "node_modules/prebuild-install": { "version": "7.1.2", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "resolved": "https://registry.npmmirror.com/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" }, - "engines": { - "node": ">=18" + "bin": { + "prebuild-install": "bin.js" }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "engines": { + "node": ">=10" } }, - "node_modules/log-update/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8.0" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "node_modules/prettier": { + "version": "3.8.4", + "resolved": "https://registry.npmmirror.com/prettier/-/prettier-3.8.4.tgz", + "integrity": "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=18" + "node": ">=14" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, "dependencies": { - "yallist": "^3.0.2" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/qs": { + "version": "6.15.2", + "resolved": "https://registry.npmmirror.com/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", "dependencies": { - "brace-expansion": "^1.1.7" + "side-channel": "^1.1.0" }, "engines": { - "node": "*" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, - "license": "MIT" + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "node_modules/rc-config-loader": { + "version": "4.1.4", + "resolved": "https://registry.npmmirror.com/rc-config-loader/-/rc-config-loader-4.1.4.tgz", + "integrity": "sha512-3GiwEzklkbXTDp52UR5nT8iXgYAx1V9ZG/kDZT7p60u2GCv2XTwQq4NzinMoMpNtXhmt3WkhYXcj6HH8HdwCEQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "js-yaml": "^4.1.1", + "json5": "^2.2.3", + "require-from-string": "^2.0.2" + } }, - "node_modules/node-releases": { - "version": "2.0.38", - "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.38.tgz", - "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/react": { + "version": "19.2.7", + "resolved": "https://registry.npmmirror.com/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/openai": { - "version": "6.35.0", - "resolved": "https://registry.npmmirror.com/openai/-/openai-6.35.0.tgz", - "integrity": "sha512-L/skwIGnt5xQZHb0UfTu9uAUKbis3ehKypOuJKi20QvG7UStV6C8IC3myGYHcdiF4kms/bAvOJ9UqqNWqi8x/Q==", - "license": "Apache-2.0", - "bin": { - "openai": "bin/cli" + "node_modules/react-reconciler": { + "version": "0.33.0", + "resolved": "https://registry.npmmirror.com/react-reconciler/-/react-reconciler-0.33.0.tgz", + "integrity": "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.25 || ^4.0" + "engines": { + "node": ">=0.10.0" }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } + "peerDependencies": { + "react": "^19.2.0" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" + "mute-stream": "~0.0.4" }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.8" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", "dev": true, "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", "dev": true, "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "callsites": "^3.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">= 6" } }, - "node_modules/patch-console": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/patch-console/-/patch-console-2.0.0.tgz", - "integrity": "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=0.10.0" } }, - "node_modules/path-exists": { + "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", - "dev": true, - "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.3.6", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.3.6.tgz", - "integrity": "sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==", + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "engines": { - "node": "20 || >=22" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 0.8.0" + "node": ">=11.0.0" } }, - "node_modules/prettier": { - "version": "3.8.3", - "resolved": "https://registry.npmmirror.com/prettier/-/prettier-3.8.3.tgz", - "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/secretlint": { + "version": "10.2.2", + "resolved": "https://registry.npmmirror.com/secretlint/-/secretlint-10.2.2.tgz", + "integrity": "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==", "dev": true, "license": "MIT", + "dependencies": { + "@secretlint/config-creator": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/node": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "debug": "^4.4.1", + "globby": "^14.1.0", + "read-pkg": "^9.0.1" + }, "bin": { - "prettier": "bin/prettier.cjs" + "secretlint": "bin/secretlint.js" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">=20.0.0" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/react": { - "version": "19.2.5", - "resolved": "https://registry.npmmirror.com/react/-/react-19.2.5.tgz", - "integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/react-reconciler": { - "version": "0.33.0", - "resolved": "https://registry.npmmirror.com/react-reconciler/-/react-reconciler-0.33.0.tgz", - "integrity": "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "license": "MIT", "dependencies": { - "scheduler": "^0.27.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=0.10.0" - }, - "peerDependencies": { - "react": "^19.2.0" + "node": ">=8" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, - "license": "MIT" - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/section-matter": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/section-matter/-/section-matter-1.0.0.tgz", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, "license": "MIT", "dependencies": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", + "optional": true, "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, "node_modules/slice-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-9.0.0.tgz", - "integrity": "sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==", + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" }, "engines": { - "node": ">=22" + "node": ">=20" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -3372,6 +6490,26 @@ "node": ">=10" } }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz", @@ -3435,601 +6573,383 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tagged-tag": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/tagged-tag/-/tagged-tag-1.0.0.tgz", - "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", - "license": "MIT", - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terminal-size": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/terminal-size/-/terminal-size-4.0.1.tgz", - "integrity": "sha512-avMLDQpUI9I5XFrklECw1ZEUPJhqzcwSWsyyI8blhRLT+8N1jLJWLWWYQpB2q2xthq8xDvjZPISVh53T/+CLYQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tinycolor2": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz", - "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.1.2.tgz", - "integrity": "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinygradient": { - "version": "1.1.5", - "resolved": "https://registry.npmmirror.com/tinygradient/-/tinygradient-1.1.5.tgz", - "integrity": "sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==", - "license": "MIT", - "dependencies": { - "@types/tinycolor2": "^1.4.0", - "tinycolor2": "^1.0.0" - } - }, - "node_modules/ts-api-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz", - "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/tsx": { - "version": "4.21.0", - "resolved": "https://registry.npmmirror.com/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/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", - "cpu": [ - "arm64" - ], + "node_modules/structured-source": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/structured-source/-/structured-source-4.0.0.tgz", + "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "license": "BSD-2-Clause", + "dependencies": { + "boundary": "^2.0.0" } }, - "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", - "cpu": [ - "x64" - ], + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", - "cpu": [ - "arm64" - ], + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, "engines": { - "node": ">=18" + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" } }, - "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", - "cpu": [ - "x64" - ], + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmmirror.com/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=18" + "node": ">=10.0.0" } }, - "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", - "cpu": [ - "arm" - ], + "node_modules/table/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", - "cpu": [ - "arm64" - ], + "node_modules/table/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", - "cpu": [ - "ia32" - ], + "node_modules/table/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", - "cpu": [ - "loong64" - ], + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/table/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", - "cpu": [ - "mips64el" - ], + "node_modules/table/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", - "cpu": [ - "ppc64" - ], + "node_modules/table/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", - "cpu": [ - "riscv64" - ], - "dev": true, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", - "cpu": [ - "s390x" - ], + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmmirror.com/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" } }, - "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", - "cpu": [ - "x64" - ], + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, "engines": { - "node": ">=18" + "node": ">=6" } }, - "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", - "cpu": [ - "arm64" - ], + "node_modules/terminal-link": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/terminal-link/-/terminal-link-4.0.0.tgz", + "integrity": "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "ansi-escapes": "^7.0.0", + "supports-hyperlinks": "^3.2.0" + }, "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/terminal-size": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/terminal-size/-/terminal-size-4.0.1.tgz", + "integrity": "sha512-avMLDQpUI9I5XFrklECw1ZEUPJhqzcwSWsyyI8blhRLT+8N1jLJWLWWYQpB2q2xthq8xDvjZPISVh53T/+CLYQ==", "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", - "cpu": [ - "arm64" - ], + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "license": "MIT" + }, + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmmirror.com/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, "engines": { - "node": ">=18" + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" } }, - "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", - "cpu": [ - "x64" - ], + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], "engines": { "node": ">=18" } }, - "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", - "cpu": [ - "arm64" - ], + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, "engines": { - "node": ">=18" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/tinygradient": { + "version": "1.1.5", + "resolved": "https://registry.npmmirror.com/tinygradient/-/tinygradient-1.1.5.tgz", + "integrity": "sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==", "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@types/tinycolor2": "^1.4.0", + "tinycolor2": "^1.0.0" } }, - "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", - "cpu": [ - "arm64" - ], + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=18" + "node": ">=14.14" } }, - "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", - "cpu": [ - "ia32" - ], + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "is-number": "^7.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8.0" } }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", - "cpu": [ - "x64" - ], + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=18" + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.22.4", + "resolved": "https://registry.npmmirror.com/tsx/-/tsx-4.22.4.tgz", + "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==", "dev": true, - "hasInstallScript": true, "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, "bin": { - "esbuild": "bin/esbuild" + "tsx": "dist/cli.mjs" }, "engines": { - "node": ">=18" + "node": ">=18.0.0" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" + "fsevents": "~2.3.3" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmmirror.com/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" } }, "node_modules/type-check": { @@ -4046,9 +6966,9 @@ } }, "node_modules/type-fest": { - "version": "5.6.0", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-5.6.0.tgz", - "integrity": "sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==", + "version": "5.7.0", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-5.7.0.tgz", + "integrity": "sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==", "license": "(MIT OR CC0-1.0)", "dependencies": { "tagged-tag": "^1.0.0" @@ -4060,6 +6980,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-rest-client": { + "version": "1.8.11", + "resolved": "https://registry.npmmirror.com/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, "node_modules/typescript": { "version": "6.0.3", "resolved": "https://registry.npmmirror.com/typescript/-/typescript-6.0.3.tgz", @@ -4075,16 +7007,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.59.2", - "resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.59.2.tgz", - "integrity": "sha512-pJw051uomb3ZeCzGTpRb8RbEqB5Y4WWet8gl/GcTlU35BSx0PVdZ86/bqkQCyKKuraVQEK7r6kBHQXF+fBhkoQ==", + "version": "8.61.0", + "resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.61.0.tgz", + "integrity": "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.59.2", - "@typescript-eslint/parser": "8.59.2", - "@typescript-eslint/typescript-estree": "8.59.2", - "@typescript-eslint/utils": "8.59.2" + "@typescript-eslint/eslint-plugin": "8.61.0", + "@typescript-eslint/parser": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4098,22 +7030,58 @@ "typescript": ">=4.8.4 <6.1.0" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmmirror.com/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "dev": true, + "license": "MIT" + }, "node_modules/undici": { - "version": "7.25.0", - "resolved": "https://registry.npmmirror.com/undici/-/undici-7.25.0.tgz", - "integrity": "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==", + "version": "7.27.2", + "resolved": "https://registry.npmmirror.com/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", "license": "MIT", "engines": { "node": ">=20.18.1" } }, "node_modules/undici-types": { - "version": "7.19.2", - "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.19.2.tgz", - "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", "dev": true, "license": "MIT" }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -4155,6 +7123,69 @@ "punycode": "^2.1.0" } }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmmirror.com/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", + "dev": true, + "license": "Artistic-2.0", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", @@ -4213,9 +7244,29 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC", + "optional": true + }, "node_modules/ws": { "version": "8.21.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "resolved": "https://registry.npmmirror.com/ws/-/ws-8.21.0.tgz", "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "license": "MIT", "engines": { @@ -4234,6 +7285,46 @@ } } }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", @@ -4242,9 +7333,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.4", - "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.8.4.tgz", - "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==", + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "dev": true, "license": "ISC", "optional": true, @@ -4258,6 +7349,29 @@ "url": "https://github.com/sponsors/eemeli" } }, + "node_modules/yauzl": { + "version": "3.4.0", + "resolved": "https://registry.npmmirror.com/yauzl/-/yauzl-3.4.0.tgz", + "integrity": "sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmmirror.com/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -4298,6 +7412,117 @@ "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } + }, + "packages/cli": { + "name": "@vegamo/deepcode-cli", + "version": "0.1.30", + "license": "MIT", + "dependencies": { + "@vegamo/deepcode-core": "file:../core", + "chalk": "^5.6.2", + "gradient-string": "^3.0.0", + "ignore": "^7.0.5", + "ink": "^7.0.4", + "ink-gradient": "^4.0.1", + "react": "^19.2.5" + }, + "bin": { + "deepcode": "dist/cli.js" + }, + "engines": { + "node": ">=22" + } + }, + "packages/cli/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "packages/cli/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "packages/core": { + "name": "@vegamo/deepcode-core", + "version": "0.1.30", + "license": "MIT", + "dependencies": { + "chalk": "^5.6.2", + "ejs": "^5.0.2", + "gray-matter": "^4.0.3", + "ignore": "^7.0.5", + "openai": "^6.35.0", + "undici": "^7.25.0", + "zod": "^4.4.3" + } + }, + "packages/core/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "packages/core/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "packages/vscode": { + "name": "@vegamo/deepcode-vscode", + "version": "0.1.22", + "extraneous": true, + "license": "MIT", + "dependencies": { + "@vegamo/deepcode-core": "*", + "markdown-it": "^14.1.1", + "openai": "^6.35.0" + }, + "devDependencies": { + "@types/markdown-it": "^14.1.1", + "@types/vscode": "^1.85.0" + }, + "engines": { + "vscode": "^1.85.0" + } + }, + "packages/vscode-ide-companion": { + "name": "@vegamo/deepcode-vscode", + "version": "0.1.22", + "license": "MIT", + "dependencies": { + "@vegamo/deepcode-core": "file:../core", + "markdown-it": "^14.2.0" + }, + "devDependencies": { + "@types/markdown-it": "^14.1.1", + "@types/vscode": "^1.85.0", + "@vscode/vsce": "^3.6.0" + }, + "engines": { + "vscode": "^1.85.0" + } } } } diff --git a/package.json b/package.json index add0e271..a0e4e793 100644 --- a/package.json +++ b/package.json @@ -1,57 +1,33 @@ { - "name": "@vegamo/deepcode-cli", - "version": "0.1.30", - "description": "Deep Code CLI - Vibe coding for the deepseek-v4 model in your terminal", + "name": "deepcode", + "description": "Deep Code — CLI, core library, and VSCode companion", "license": "MIT", + "packageManager": "npm@10.9.4", "type": "module", + "workspaces": [ + "packages/*" + ], "repository": { "type": "git", - "url": "https://github.com/lessweb/deepcode-cli.git" - }, - "homepage": "https://deepcode.vegamo.cn", - "bin": { - "deepcode": "./dist/cli.js" - }, - "main": "./dist/cli.js", - "files": [ - "dist/cli.js", - "dist/bundled/**", - "templates/tools/**", - "templates/prompts/**", - "templates/skills/**", - "README.md", - "LICENSE" - ], - "engines": { - "node": ">=22" + "url": "git+https://github.com/lessweb/deepcode-cli.git" }, "scripts": { - "typecheck": "tsc -p ./ --noEmit", - "bundle": "esbuild ./src/cli.tsx --bundle --platform=node --format=esm --target=node18 --outfile=dist/cli.js --banner:js=\"#!/usr/bin/env node\" --jsx=automatic --jsx-import-source=react --packages=external --log-override:empty-import-meta=silent && node scripts/copy_bundle_assets.js", - "lint": "eslint src/", - "lint:fix": "eslint src/ --fix", - "format": "prettier --write 'src/**/*.{ts,tsx}'", - "format:check": "prettier --check 'src/**/*.{ts,tsx}'", + "typecheck": "npm run typecheck --workspaces --if-present", + "generate": "node scripts/generate-git-commit-info.js", + "bundle": "npm run generate && node scripts/esbuild.config.js && node scripts/copy-bundle-assets.js", + "lint": "eslint 'packages/*/src/**/*.{ts,tsx}' 'scripts/*.js'", + "lint:fix": "eslint 'packages/*/src/**/*.{ts,tsx}' 'scripts/*.js' --fix", + "format": "prettier --write 'packages/*/src/**/*.{ts,tsx}' 'scripts/*.js'", + "format:check": "prettier --check 'packages/*/src/**/*.{ts,tsx}' 'scripts/*.js'", "check": "npm run typecheck && npm run lint && npm run format:check", - "build": "npm run check && npm run bundle && node -e \"require('fs').chmodSync('dist/cli.js', 0o755)\"", - "test": "node src/tests/run-tests.mjs", - "test:single": "tsx --test", - "prepack": "npm run build", + "clean": "node scripts/clean.js", + "build": "node scripts/build.js", + "build:vscode": "node scripts/build-vscode-companion.js", + "start": "node scripts/start.js", + "build-and-start": "npm run build && npm run start", + "test": "npm run test --workspaces --if-present", "prepare": "husky" }, - "dependencies": { - "chalk": "^5.6.2", - "ejs": "^5.0.2", - "gradient-string": "^3.0.0", - "gray-matter": "^4.0.3", - "ignore": "^7.0.5", - "ink": "^7.0.4", - "ink-gradient": "^4.0.1", - "openai": "^6.35.0", - "react": "^19.2.5", - "undici": "^7.25.0", - "zod": "^4.4.3" - }, "devDependencies": { "@eslint/js": "^9.39.4", "@types/ejs": "^3.1.5", diff --git a/packages/cli/package.json b/packages/cli/package.json new file mode 100644 index 00000000..21e7ae8e --- /dev/null +++ b/packages/cli/package.json @@ -0,0 +1,42 @@ +{ + "name": "@vegamo/deepcode-cli", + "version": "0.1.30", + "description": "Deep Code CLI - Vibe coding for the deepseek-v4 model in your terminal", + "license": "MIT", + "type": "module", + "repository": { + "type": "git", + "url": "git+https://github.com/lessweb/deepcode-cli.git" + }, + "homepage": "https://deepcode.vegamo.cn", + "bin": { + "deepcode": "./dist/cli.js" + }, + "main": "./dist/cli.js", + "files": [ + "dist/cli.js", + "dist/bundled/**", + "README.md", + "LICENSE" + ], + "engines": { + "node": ">=22" + }, + "scripts": { + "typecheck": "tsc -p ./ --noEmit", + "bundle": "node ../../scripts/esbuild.config.js", + "build": "npm run typecheck && npm run bundle && node ../../scripts/copy-bundle-assets.js && node -e \"require('fs').chmodSync('dist/cli.js', 0o755)\"", + "prepublishOnly": "npm run build", + "format": "prettier --write .", + "test": "node src/tests/run-tests.mjs" + }, + "dependencies": { + "@vegamo/deepcode-core": "file:../core", + "chalk": "^5.6.2", + "gradient-string": "^3.0.0", + "ignore": "^7.0.5", + "ink": "^7.0.4", + "ink-gradient": "^4.0.1", + "react": "^19.2.5" + } +} diff --git a/src/cli.tsx b/packages/cli/src/cli.tsx similarity index 98% rename from src/cli.tsx rename to packages/cli/src/cli.tsx index 6da6505d..c595916b 100644 --- a/src/cli.tsx +++ b/packages/cli/src/cli.tsx @@ -1,6 +1,6 @@ import React from "react"; import { render } from "ink"; -import { setShellIfWindows } from "./common/shell-utils"; +import { setShellIfWindows } from "@vegamo/deepcode-core"; import { checkForNpmUpdate, promptForPendingUpdate, type PackageInfo } from "./common/update-check"; import { AppContainer } from "./ui"; diff --git a/src/common/update-check.ts b/packages/cli/src/common/update-check.ts similarity index 99% rename from src/common/update-check.ts rename to packages/cli/src/common/update-check.ts index 2d27c7a6..7a4710be 100644 --- a/src/common/update-check.ts +++ b/packages/cli/src/common/update-check.ts @@ -5,7 +5,7 @@ import * as os from "os"; import * as path from "path"; import { render, type Instance } from "ink"; import { UpdatePrompt, type UpdatePromptChoice } from "../ui"; -import { killProcessTree } from "./process-tree"; +import { killProcessTree } from "@vegamo/deepcode-core"; export type PackageInfo = { name: string; diff --git a/packages/cli/src/generated/git-commit.ts b/packages/cli/src/generated/git-commit.ts new file mode 100644 index 00000000..e32594c8 --- /dev/null +++ b/packages/cli/src/generated/git-commit.ts @@ -0,0 +1,8 @@ +/** + * @license + * Copyright 2026 @vegamo deepcode + */ + +// Auto-generated by scripts/generate-git-commit-info.js. Do not edit. +export const GIT_COMMIT_INFO = "cc7b0c3"; +export const CLI_VERSION = "0.1.30"; diff --git a/src/tests/ask-user-question.test.ts b/packages/cli/src/tests/ask-user-question.test.ts similarity index 98% rename from src/tests/ask-user-question.test.ts rename to packages/cli/src/tests/ask-user-question.test.ts index f7543512..7b4f387e 100644 --- a/src/tests/ask-user-question.test.ts +++ b/packages/cli/src/tests/ask-user-question.test.ts @@ -1,7 +1,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { findPendingAskUserQuestion, formatAskUserQuestionAnswers, formatAskUserQuestionDecline } from "../ui"; -import type { SessionMessage } from "../session"; +import type { SessionMessage } from "@vegamo/deepcode-core"; function message(content: unknown): SessionMessage { const now = "2026-04-29T00:00:00.000Z"; diff --git a/src/tests/clipboard.test.ts b/packages/cli/src/tests/clipboard.test.ts similarity index 100% rename from src/tests/clipboard.test.ts rename to packages/cli/src/tests/clipboard.test.ts diff --git a/src/tests/dropdown-menu.test.ts b/packages/cli/src/tests/dropdown-menu.test.ts similarity index 100% rename from src/tests/dropdown-menu.test.ts rename to packages/cli/src/tests/dropdown-menu.test.ts diff --git a/src/tests/exit-summary.test.ts b/packages/cli/src/tests/exit-summary.test.ts similarity index 97% rename from src/tests/exit-summary.test.ts rename to packages/cli/src/tests/exit-summary.test.ts index 5ea4b579..e0d481db 100644 --- a/src/tests/exit-summary.test.ts +++ b/packages/cli/src/tests/exit-summary.test.ts @@ -1,7 +1,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { buildExitSummaryText } from "../ui"; -import type { ModelUsage, SessionEntry } from "../session"; +import type { ModelUsage, SessionEntry } from "@vegamo/deepcode-core"; const stripAnsi = (text: string): string => text.replace(/\u001b\[[0-9;]*m/g, ""); diff --git a/src/tests/file-mentions.test.ts b/packages/cli/src/tests/file-mentions.test.ts similarity index 100% rename from src/tests/file-mentions.test.ts rename to packages/cli/src/tests/file-mentions.test.ts diff --git a/src/tests/loading-text.test.ts b/packages/cli/src/tests/loading-text.test.ts similarity index 100% rename from src/tests/loading-text.test.ts rename to packages/cli/src/tests/loading-text.test.ts diff --git a/src/tests/markdown.test.ts b/packages/cli/src/tests/markdown.test.ts similarity index 100% rename from src/tests/markdown.test.ts rename to packages/cli/src/tests/markdown.test.ts diff --git a/src/tests/message-view.test.ts b/packages/cli/src/tests/message-view.test.ts similarity index 99% rename from src/tests/message-view.test.ts rename to packages/cli/src/tests/message-view.test.ts index ff497707..fbd2b097 100644 --- a/src/tests/message-view.test.ts +++ b/packages/cli/src/tests/message-view.test.ts @@ -13,7 +13,7 @@ import { parseToolPayload, } from "../ui/components/MessageView/utils"; import { RawMode } from "../ui/contexts"; -import type { SessionMessage } from "../session"; +import type { SessionMessage } from "@vegamo/deepcode-core"; import type { ToolSummary } from "../ui/components/MessageView/types"; test("parseDiffPreview removes headers and classifies lines", () => { diff --git a/src/tests/permission-prompt.test.ts b/packages/cli/src/tests/permission-prompt.test.ts similarity index 100% rename from src/tests/permission-prompt.test.ts rename to packages/cli/src/tests/permission-prompt.test.ts diff --git a/src/tests/prompt-buffer.test.ts b/packages/cli/src/tests/prompt-buffer.test.ts similarity index 100% rename from src/tests/prompt-buffer.test.ts rename to packages/cli/src/tests/prompt-buffer.test.ts diff --git a/src/tests/prompt-input-keys.test.ts b/packages/cli/src/tests/prompt-input-keys.test.ts similarity index 99% rename from src/tests/prompt-input-keys.test.ts rename to packages/cli/src/tests/prompt-input-keys.test.ts index bcad3395..0c5773cf 100644 --- a/src/tests/prompt-input-keys.test.ts +++ b/packages/cli/src/tests/prompt-input-keys.test.ts @@ -28,7 +28,7 @@ import { insertText, backspace, } from "../ui"; -import type { SessionMessage, SkillInfo } from "../session"; +import type { SessionMessage, SkillInfo } from "@vegamo/deepcode-core"; import { dispatchTerminalInput, parseTerminalInput } from "../ui/hooks"; function collectDispatchedInput(data: string) { diff --git a/src/tests/prompt-undo-redo.test.ts b/packages/cli/src/tests/prompt-undo-redo.test.ts similarity index 100% rename from src/tests/prompt-undo-redo.test.ts rename to packages/cli/src/tests/prompt-undo-redo.test.ts diff --git a/packages/cli/src/tests/run-tests.mjs b/packages/cli/src/tests/run-tests.mjs new file mode 100644 index 00000000..87748b2d --- /dev/null +++ b/packages/cli/src/tests/run-tests.mjs @@ -0,0 +1,15 @@ +// Test runner for @vegamo/deepcode-cli +import { globSync } from "glob"; +import { spawnSync } from "child_process"; +import { fileURLToPath } from "url"; +import * as path from "path"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const testFiles = globSync("*.test.ts", { cwd: __dirname }); + +const result = spawnSync(process.execPath, ["--import", "tsx", "--test", ...testFiles], { + stdio: "inherit", + cwd: __dirname, +}); + +process.exit(result.status ?? 1); diff --git a/src/tests/session-list.test.ts b/packages/cli/src/tests/session-list.test.ts similarity index 98% rename from src/tests/session-list.test.ts rename to packages/cli/src/tests/session-list.test.ts index 6fe41c70..654b4152 100644 --- a/src/tests/session-list.test.ts +++ b/packages/cli/src/tests/session-list.test.ts @@ -1,7 +1,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { formatSessionTitle, filterSessions, formatSessionStatus } from "../ui"; -import type { SessionEntry } from "../session"; +import type { SessionEntry } from "@vegamo/deepcode-core"; test("formatSessionTitle replaces newlines with spaces", () => { assert.equal(formatSessionTitle("first line\nsecond line\r\nthird"), "first line second line third"); diff --git a/src/tests/slash-commands.test.ts b/packages/cli/src/tests/slash-commands.test.ts similarity index 98% rename from src/tests/slash-commands.test.ts rename to packages/cli/src/tests/slash-commands.test.ts index 30d77eeb..420e5a48 100644 --- a/src/tests/slash-commands.test.ts +++ b/packages/cli/src/tests/slash-commands.test.ts @@ -7,7 +7,7 @@ import { formatSlashCommandDescription, formatSlashCommandLabel, } from "../ui"; -import type { SkillInfo } from "../session"; +import type { SkillInfo } from "@vegamo/deepcode-core"; const skills: SkillInfo[] = [ { name: "skill-writer", path: "~/.agents/skills/skill-writer/SKILL.md", description: "Write a SKILL.md" }, diff --git a/src/tests/thinking-state.test.ts b/packages/cli/src/tests/thinking-state.test.ts similarity index 96% rename from src/tests/thinking-state.test.ts rename to packages/cli/src/tests/thinking-state.test.ts index 8f2a0e30..efbee883 100644 --- a/src/tests/thinking-state.test.ts +++ b/packages/cli/src/tests/thinking-state.test.ts @@ -1,7 +1,7 @@ import { test } from "node:test"; import assert from "node:assert/strict"; import { findExpandedThinkingId } from "../ui"; -import type { SessionMessage } from "../session"; +import type { SessionMessage } from "@vegamo/deepcode-core"; function buildMessage( id: string, diff --git a/src/tests/update-check.test.ts b/packages/cli/src/tests/update-check.test.ts similarity index 100% rename from src/tests/update-check.test.ts rename to packages/cli/src/tests/update-check.test.ts diff --git a/src/tests/welcome-screen.test.ts b/packages/cli/src/tests/welcome-screen.test.ts similarity index 100% rename from src/tests/welcome-screen.test.ts rename to packages/cli/src/tests/welcome-screen.test.ts diff --git a/src/ui/ascii-art.ts b/packages/cli/src/ui/ascii-art.ts similarity index 100% rename from src/ui/ascii-art.ts rename to packages/cli/src/ui/ascii-art.ts diff --git a/src/ui/components/DropdownMenu/index.tsx b/packages/cli/src/ui/components/DropdownMenu/index.tsx similarity index 100% rename from src/ui/components/DropdownMenu/index.tsx rename to packages/cli/src/ui/components/DropdownMenu/index.tsx diff --git a/src/ui/components/FileMentionMenu/index.tsx b/packages/cli/src/ui/components/FileMentionMenu/index.tsx similarity index 100% rename from src/ui/components/FileMentionMenu/index.tsx rename to packages/cli/src/ui/components/FileMentionMenu/index.tsx diff --git a/src/ui/components/MessageView/index.tsx b/packages/cli/src/ui/components/MessageView/index.tsx similarity index 100% rename from src/ui/components/MessageView/index.tsx rename to packages/cli/src/ui/components/MessageView/index.tsx diff --git a/src/ui/components/MessageView/markdown.ts b/packages/cli/src/ui/components/MessageView/markdown.ts similarity index 100% rename from src/ui/components/MessageView/markdown.ts rename to packages/cli/src/ui/components/MessageView/markdown.ts diff --git a/src/ui/components/MessageView/types.ts b/packages/cli/src/ui/components/MessageView/types.ts similarity index 84% rename from src/ui/components/MessageView/types.ts rename to packages/cli/src/ui/components/MessageView/types.ts index 743eb2dc..dc727469 100644 --- a/src/ui/components/MessageView/types.ts +++ b/packages/cli/src/ui/components/MessageView/types.ts @@ -1,4 +1,4 @@ -import type { SessionMessage } from "../../../session"; +import type { SessionMessage } from "@vegamo/deepcode-core"; export type MessageViewProps = { message: SessionMessage; diff --git a/src/ui/components/MessageView/utils.ts b/packages/cli/src/ui/components/MessageView/utils.ts similarity index 99% rename from src/ui/components/MessageView/utils.ts rename to packages/cli/src/ui/components/MessageView/utils.ts index 91ae64be..4b6158d1 100644 --- a/src/ui/components/MessageView/utils.ts +++ b/packages/cli/src/ui/components/MessageView/utils.ts @@ -1,5 +1,5 @@ import type { DiffPreviewLine, ToolSummary } from "./types"; -import type { SessionMessage } from "../../../session"; +import type { SessionMessage } from "@vegamo/deepcode-core"; import { RawMode } from "../../contexts"; import chalk from "chalk"; diff --git a/src/ui/components/ModelsDropdown/index.tsx b/packages/cli/src/ui/components/ModelsDropdown/index.tsx similarity index 98% rename from src/ui/components/ModelsDropdown/index.tsx rename to packages/cli/src/ui/components/ModelsDropdown/index.tsx index 6e807569..9fe968b4 100644 --- a/src/ui/components/ModelsDropdown/index.tsx +++ b/packages/cli/src/ui/components/ModelsDropdown/index.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from "react"; import { useInput } from "ink"; import DropdownMenu from "../DropdownMenu"; -import type { ModelConfigSelection, ReasoningEffort } from "../../../settings"; +import type { ModelConfigSelection, ReasoningEffort } from "@vegamo/deepcode-core"; type ModelStep = "model" | "thinking"; diff --git a/src/ui/components/RawModeExitPrompt/index.tsx b/packages/cli/src/ui/components/RawModeExitPrompt/index.tsx similarity index 100% rename from src/ui/components/RawModeExitPrompt/index.tsx rename to packages/cli/src/ui/components/RawModeExitPrompt/index.tsx diff --git a/src/ui/components/RawModelDropdown/index.tsx b/packages/cli/src/ui/components/RawModelDropdown/index.tsx similarity index 100% rename from src/ui/components/RawModelDropdown/index.tsx rename to packages/cli/src/ui/components/RawModelDropdown/index.tsx diff --git a/src/ui/components/SkillsDropdown/index.tsx b/packages/cli/src/ui/components/SkillsDropdown/index.tsx similarity index 97% rename from src/ui/components/SkillsDropdown/index.tsx rename to packages/cli/src/ui/components/SkillsDropdown/index.tsx index 4ec53397..1fe65ebb 100644 --- a/src/ui/components/SkillsDropdown/index.tsx +++ b/packages/cli/src/ui/components/SkillsDropdown/index.tsx @@ -1,6 +1,6 @@ import DropdownMenu from "../DropdownMenu"; import React, { useEffect, useState } from "react"; -import type { SkillInfo } from "../../../session"; +import type { SkillInfo } from "@vegamo/deepcode-core"; import { useInput } from "ink"; import { isSkillSelected } from "../../views/SlashCommandMenu"; diff --git a/src/ui/components/index.ts b/packages/cli/src/ui/components/index.ts similarity index 100% rename from src/ui/components/index.ts rename to packages/cli/src/ui/components/index.ts diff --git a/src/ui/constants.ts b/packages/cli/src/ui/constants.ts similarity index 100% rename from src/ui/constants.ts rename to packages/cli/src/ui/constants.ts diff --git a/src/ui/contexts/AppContext.tsx b/packages/cli/src/ui/contexts/AppContext.tsx similarity index 100% rename from src/ui/contexts/AppContext.tsx rename to packages/cli/src/ui/contexts/AppContext.tsx diff --git a/src/ui/contexts/RawModeContext.tsx b/packages/cli/src/ui/contexts/RawModeContext.tsx similarity index 100% rename from src/ui/contexts/RawModeContext.tsx rename to packages/cli/src/ui/contexts/RawModeContext.tsx diff --git a/src/ui/contexts/index.ts b/packages/cli/src/ui/contexts/index.ts similarity index 100% rename from src/ui/contexts/index.ts rename to packages/cli/src/ui/contexts/index.ts diff --git a/src/ui/core/ask-user-question.ts b/packages/cli/src/ui/core/ask-user-question.ts similarity index 98% rename from src/ui/core/ask-user-question.ts rename to packages/cli/src/ui/core/ask-user-question.ts index 8a07e400..f49b191e 100644 --- a/src/ui/core/ask-user-question.ts +++ b/packages/cli/src/ui/core/ask-user-question.ts @@ -1,4 +1,4 @@ -import type { SessionMessage, SessionStatus } from "../../session"; +import type { SessionMessage, SessionStatus } from "@vegamo/deepcode-core"; export type AskUserQuestionOption = { label: string; diff --git a/src/ui/core/clipboard.ts b/packages/cli/src/ui/core/clipboard.ts similarity index 100% rename from src/ui/core/clipboard.ts rename to packages/cli/src/ui/core/clipboard.ts diff --git a/src/ui/core/file-mentions.ts b/packages/cli/src/ui/core/file-mentions.ts similarity index 100% rename from src/ui/core/file-mentions.ts rename to packages/cli/src/ui/core/file-mentions.ts diff --git a/src/ui/core/loading-text.ts b/packages/cli/src/ui/core/loading-text.ts similarity index 96% rename from src/ui/core/loading-text.ts rename to packages/cli/src/ui/core/loading-text.ts index 2c965ea3..c757ce55 100644 --- a/src/ui/core/loading-text.ts +++ b/packages/cli/src/ui/core/loading-text.ts @@ -1,4 +1,4 @@ -import type { LlmStreamProgress, SessionEntry } from "../../session"; +import type { LlmStreamProgress, SessionEntry } from "@vegamo/deepcode-core"; type RunningProcesses = SessionEntry["processes"]; diff --git a/src/ui/core/prompt-buffer.ts b/packages/cli/src/ui/core/prompt-buffer.ts similarity index 100% rename from src/ui/core/prompt-buffer.ts rename to packages/cli/src/ui/core/prompt-buffer.ts diff --git a/src/ui/core/prompt-undo-redo.ts b/packages/cli/src/ui/core/prompt-undo-redo.ts similarity index 100% rename from src/ui/core/prompt-undo-redo.ts rename to packages/cli/src/ui/core/prompt-undo-redo.ts diff --git a/src/ui/core/slash-commands.ts b/packages/cli/src/ui/core/slash-commands.ts similarity index 98% rename from src/ui/core/slash-commands.ts rename to packages/cli/src/ui/core/slash-commands.ts index 04840baa..ba5ae6ec 100644 --- a/src/ui/core/slash-commands.ts +++ b/packages/cli/src/ui/core/slash-commands.ts @@ -1,4 +1,4 @@ -import type { SkillInfo } from "../../session"; +import type { SkillInfo } from "@vegamo/deepcode-core"; export type SlashCommandKind = | "skill" diff --git a/src/ui/core/thinking-state.ts b/packages/cli/src/ui/core/thinking-state.ts similarity index 94% rename from src/ui/core/thinking-state.ts rename to packages/cli/src/ui/core/thinking-state.ts index 02245091..0c9c5c7f 100644 --- a/src/ui/core/thinking-state.ts +++ b/packages/cli/src/ui/core/thinking-state.ts @@ -1,4 +1,4 @@ -import type { SessionMessage } from "../../session"; +import type { SessionMessage } from "@vegamo/deepcode-core"; /** * Returns the message id of the assistant "thinking" message that should stay diff --git a/src/ui/exit-summary.ts b/packages/cli/src/ui/exit-summary.ts similarity index 98% rename from src/ui/exit-summary.ts rename to packages/cli/src/ui/exit-summary.ts index c55d9ce8..25e09b48 100644 --- a/src/ui/exit-summary.ts +++ b/packages/cli/src/ui/exit-summary.ts @@ -1,6 +1,6 @@ import chalk from "chalk"; import gradientString from "gradient-string"; -import type { ModelUsage, SessionEntry } from "../session"; +import type { ModelUsage, SessionEntry } from "@vegamo/deepcode-core"; type ExitSummaryInput = { session: SessionEntry | null; diff --git a/src/ui/hooks/cursor.ts b/packages/cli/src/ui/hooks/cursor.ts similarity index 100% rename from src/ui/hooks/cursor.ts rename to packages/cli/src/ui/hooks/cursor.ts diff --git a/src/ui/hooks/index.ts b/packages/cli/src/ui/hooks/index.ts similarity index 100% rename from src/ui/hooks/index.ts rename to packages/cli/src/ui/hooks/index.ts diff --git a/src/ui/hooks/useHistoryNavigation.ts b/packages/cli/src/ui/hooks/useHistoryNavigation.ts similarity index 100% rename from src/ui/hooks/useHistoryNavigation.ts rename to packages/cli/src/ui/hooks/useHistoryNavigation.ts diff --git a/src/ui/hooks/usePasteHandling.ts b/packages/cli/src/ui/hooks/usePasteHandling.ts similarity index 100% rename from src/ui/hooks/usePasteHandling.ts rename to packages/cli/src/ui/hooks/usePasteHandling.ts diff --git a/src/ui/hooks/useTerminalInput.ts b/packages/cli/src/ui/hooks/useTerminalInput.ts similarity index 100% rename from src/ui/hooks/useTerminalInput.ts rename to packages/cli/src/ui/hooks/useTerminalInput.ts diff --git a/src/ui/index.ts b/packages/cli/src/ui/index.ts similarity index 100% rename from src/ui/index.ts rename to packages/cli/src/ui/index.ts diff --git a/src/ui/utils/index.ts b/packages/cli/src/ui/utils/index.ts similarity index 94% rename from src/ui/utils/index.ts rename to packages/cli/src/ui/utils/index.ts index b9b61ec4..6feb0306 100644 --- a/src/ui/utils/index.ts +++ b/packages/cli/src/ui/utils/index.ts @@ -2,9 +2,9 @@ import chalk from "chalk"; import { renderMessageToStdout } from "../components/MessageView/utils"; import type { RawMode } from "../contexts"; import type { PromptDraft } from "../views/PromptInput"; -import type { ModelConfigSelection } from "../../settings"; -import type { SessionEntry, SessionMessage } from "../../session"; -import type { SessionManager } from "../../session"; +import type { ModelConfigSelection } from "@vegamo/deepcode-core"; +import type { SessionEntry, SessionMessage } from "@vegamo/deepcode-core"; +import type { SessionManager } from "@vegamo/deepcode-core"; /** * Render all messages directly to stdout for Raw mode display. diff --git a/src/ui/views/App.tsx b/packages/cli/src/ui/views/App.tsx similarity index 98% rename from src/ui/views/App.tsx rename to packages/cli/src/ui/views/App.tsx index bc12962a..fe1f81cf 100644 --- a/src/ui/views/App.tsx +++ b/packages/cli/src/ui/views/App.tsx @@ -1,9 +1,9 @@ import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"; import { Box, Static, Text, useApp, useStdout, useWindowSize } from "ink"; import chalk from "chalk"; -import { createOpenAIClient } from "../../common/openai-client"; -import type { PermissionScope } from "../../settings"; -import { type ModelConfigSelection } from "../../settings"; +import { createOpenAIClient } from "@vegamo/deepcode-core"; +import type { PermissionScope } from "@vegamo/deepcode-core"; +import { type ModelConfigSelection } from "@vegamo/deepcode-core"; import { type PromptDraft, PromptInput, type PromptSubmission } from "./PromptInput"; import { MessageView, RawModeExitPrompt } from "../components"; import { SessionList } from "./SessionList"; @@ -31,7 +31,7 @@ import { isCurrentSessionEmpty, renderRawModeMessages, } from "../utils"; -import { resolveCurrentSettings, writeModelConfigSelection } from "../../settings"; +import { resolveCurrentSettings, writeModelConfigSelection } from "@vegamo/deepcode-core"; import { isCollapsedThinking } from "../core/thinking-state"; import { ANSI_CLEAR_SCREEN } from "../constants"; import type { @@ -43,8 +43,8 @@ import type { SkillInfo, UndoTarget, UserPromptContent, -} from "../../session"; -import { SessionManager } from "../../session"; +} from "@vegamo/deepcode-core"; +import { SessionManager } from "@vegamo/deepcode-core"; type View = "chat" | "session-list" | "undo" | "mcp-status"; diff --git a/src/ui/views/AppContainer.tsx b/packages/cli/src/ui/views/AppContainer.tsx similarity index 100% rename from src/ui/views/AppContainer.tsx rename to packages/cli/src/ui/views/AppContainer.tsx diff --git a/src/ui/views/AskUserQuestionPrompt.tsx b/packages/cli/src/ui/views/AskUserQuestionPrompt.tsx similarity index 100% rename from src/ui/views/AskUserQuestionPrompt.tsx rename to packages/cli/src/ui/views/AskUserQuestionPrompt.tsx diff --git a/src/ui/views/McpStatusList.tsx b/packages/cli/src/ui/views/McpStatusList.tsx similarity index 99% rename from src/ui/views/McpStatusList.tsx rename to packages/cli/src/ui/views/McpStatusList.tsx index 40d2f3f4..5a68832b 100644 --- a/src/ui/views/McpStatusList.tsx +++ b/packages/cli/src/ui/views/McpStatusList.tsx @@ -1,6 +1,6 @@ import React, { useState, useMemo, useCallback } from "react"; import { Box, Text, useInput, useWindowSize } from "ink"; -import type { McpServerStatus } from "../../mcp/mcp-manager"; +import type { McpServerStatus } from "@vegamo/deepcode-core"; type Props = { statuses: McpServerStatus[]; diff --git a/src/ui/views/PermissionPrompt.tsx b/packages/cli/src/ui/views/PermissionPrompt.tsx similarity index 98% rename from src/ui/views/PermissionPrompt.tsx rename to packages/cli/src/ui/views/PermissionPrompt.tsx index 320dd7ab..c90f5e68 100644 --- a/src/ui/views/PermissionPrompt.tsx +++ b/packages/cli/src/ui/views/PermissionPrompt.tsx @@ -1,8 +1,8 @@ import React, { useEffect, useMemo, useState } from "react"; import { Box, Text } from "ink"; import { useTerminalInput } from "../hooks"; -import type { AskPermissionRequest, AskPermissionScope, UserToolPermission } from "../../common/permissions"; -import type { PermissionScope } from "../../settings"; +import type { AskPermissionRequest, AskPermissionScope, UserToolPermission } from "@vegamo/deepcode-core"; +import type { PermissionScope } from "@vegamo/deepcode-core"; export type PermissionPromptResult = { permissions: UserToolPermission[]; diff --git a/src/ui/views/ProcessStdoutView.tsx b/packages/cli/src/ui/views/ProcessStdoutView.tsx similarity index 98% rename from src/ui/views/ProcessStdoutView.tsx rename to packages/cli/src/ui/views/ProcessStdoutView.tsx index bd5e6363..f341eb82 100644 --- a/src/ui/views/ProcessStdoutView.tsx +++ b/packages/cli/src/ui/views/ProcessStdoutView.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useMemo, useRef, useState } from "react"; import { Box, Text } from "ink"; -import { BASH_TIMEOUT_DECREMENT_MS, BASH_TIMEOUT_INCREMENT_MS } from "../../common/bash-timeout"; -import type { BashTimeoutAdjustment, SessionEntry, SessionProcessEntry } from "../../session"; +import { BASH_TIMEOUT_DECREMENT_MS, BASH_TIMEOUT_INCREMENT_MS } from "@vegamo/deepcode-core"; +import type { BashTimeoutAdjustment, SessionEntry, SessionProcessEntry } from "@vegamo/deepcode-core"; import { useTerminalInput } from "../hooks"; type RunningProcesses = SessionEntry["processes"]; diff --git a/src/ui/views/PromptInput.tsx b/packages/cli/src/ui/views/PromptInput.tsx similarity index 99% rename from src/ui/views/PromptInput.tsx rename to packages/cli/src/ui/views/PromptInput.tsx index c6b150cb..8124d7aa 100644 --- a/src/ui/views/PromptInput.tsx +++ b/packages/cli/src/ui/views/PromptInput.tsx @@ -60,10 +60,10 @@ import { useTerminalFocusReporting, } from "../hooks"; import SlashCommandMenu, { isSkillSelected } from "./SlashCommandMenu"; -import type { ModelConfigSelection, PermissionScope } from "../../settings"; +import type { ModelConfigSelection, PermissionScope } from "@vegamo/deepcode-core"; import { FileMentionMenu, ModelsDropdown, RawModelDropdown, SkillsDropdown } from "../components"; -import type { SessionEntry, SkillInfo } from "../../session"; -import type { UserToolPermission } from "../../common/permissions"; +import type { SessionEntry, SkillInfo } from "@vegamo/deepcode-core"; +import type { UserToolPermission } from "@vegamo/deepcode-core"; export type PromptSubmission = { text: string; diff --git a/src/ui/views/SessionList.tsx b/packages/cli/src/ui/views/SessionList.tsx similarity index 99% rename from src/ui/views/SessionList.tsx rename to packages/cli/src/ui/views/SessionList.tsx index 49d94e7f..a41cae3a 100644 --- a/src/ui/views/SessionList.tsx +++ b/packages/cli/src/ui/views/SessionList.tsx @@ -1,6 +1,6 @@ import React, { useState, useMemo, useCallback } from "react"; import { Box, Text, useInput, useWindowSize } from "ink"; -import type { SessionEntry, SessionStatus } from "../../session"; +import type { SessionEntry, SessionStatus } from "@vegamo/deepcode-core"; import { truncate } from "../components/MessageView/utils"; type Props = { diff --git a/src/ui/views/SlashCommandMenu.tsx b/packages/cli/src/ui/views/SlashCommandMenu.tsx similarity index 98% rename from src/ui/views/SlashCommandMenu.tsx rename to packages/cli/src/ui/views/SlashCommandMenu.tsx index d93446de..c138bec8 100644 --- a/src/ui/views/SlashCommandMenu.tsx +++ b/packages/cli/src/ui/views/SlashCommandMenu.tsx @@ -3,7 +3,7 @@ import type { SlashCommandItem } from "../core/slash-commands"; import { ARGS_SEPARATOR } from "../constants"; import React from "react"; import { Box, Text } from "ink"; -import type { SkillInfo } from "../../session"; +import type { SkillInfo } from "@vegamo/deepcode-core"; type SlashCommandMenuProps = { items: SlashCommandItem[]; diff --git a/src/ui/views/ThemedGradient.tsx b/packages/cli/src/ui/views/ThemedGradient.tsx similarity index 100% rename from src/ui/views/ThemedGradient.tsx rename to packages/cli/src/ui/views/ThemedGradient.tsx diff --git a/src/ui/views/UndoSelector.tsx b/packages/cli/src/ui/views/UndoSelector.tsx similarity index 99% rename from src/ui/views/UndoSelector.tsx rename to packages/cli/src/ui/views/UndoSelector.tsx index 977bca26..50a99977 100644 --- a/src/ui/views/UndoSelector.tsx +++ b/packages/cli/src/ui/views/UndoSelector.tsx @@ -1,6 +1,6 @@ import React, { useMemo, useState } from "react"; import { Box, Text, useInput, useWindowSize } from "ink"; -import type { UndoTarget } from "../../session"; +import type { UndoTarget } from "@vegamo/deepcode-core"; export type UndoRestoreMode = "code-and-conversation" | "conversation"; diff --git a/src/ui/views/UpdatePrompt.tsx b/packages/cli/src/ui/views/UpdatePrompt.tsx similarity index 100% rename from src/ui/views/UpdatePrompt.tsx rename to packages/cli/src/ui/views/UpdatePrompt.tsx diff --git a/src/ui/views/WelcomeScreen.tsx b/packages/cli/src/ui/views/WelcomeScreen.tsx similarity index 97% rename from src/ui/views/WelcomeScreen.tsx rename to packages/cli/src/ui/views/WelcomeScreen.tsx index bee7e9ae..fdcf9211 100644 --- a/src/ui/views/WelcomeScreen.tsx +++ b/packages/cli/src/ui/views/WelcomeScreen.tsx @@ -2,8 +2,8 @@ import React, { useMemo, useState } from "react"; import { Box, Text } from "ink"; import * as os from "node:os"; import path from "node:path"; -import type { SkillInfo } from "../../session"; -import type { ResolvedDeepcodingSettings } from "../../settings"; +import type { SkillInfo } from "@vegamo/deepcode-core"; +import type { ResolvedDeepcodingSettings } from "@vegamo/deepcode-core"; import { buildSlashCommands, BUILTIN_SLASH_COMMANDS, formatSlashCommandDescription } from "../core/slash-commands"; import { ThemedGradient } from "./ThemedGradient"; import { AsciiLogo } from "../ascii-art"; diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json new file mode 100644 index 00000000..44d2799d --- /dev/null +++ b/packages/cli/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "ignoreDeprecations": "6.0", + "lib": ["ES2022"], + "jsx": "react-jsx", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "noEmit": true, + "isolatedModules": true, + "allowSyntheticDefaultImports": true, + "types": ["node"], + "baseUrl": ".", + "paths": { + "@vegamo/deepcode-core": ["../core/src/index.ts"], + "@vegamo/deepcode-core/*": ["../core/src/*"] + } + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "../core/src/**/*.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 00000000..eb73e22a --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,39 @@ +{ + "name": "@vegamo/deepcode-core", + "version": "0.1.30", + "description": "Deep Code core library — LLM session management, tool execution, and shared utilities", + "license": "MIT", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "repository": { + "type": "git", + "url": "git+https://github.com/lessweb/deepcode-cli.git" + }, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "files": [ + "dist/**", + "templates/**" + ], + "scripts": { + "typecheck": "tsc -p ./ --noEmit", + "build": "tsc -p ./", + "prepublishOnly": "npm run build", + "format": "prettier --write .", + "test": "node src/tests/run-tests.mjs" + }, + "dependencies": { + "chalk": "^5.6.2", + "ejs": "^5.0.2", + "gray-matter": "^4.0.3", + "ignore": "^7.0.5", + "openai": "^6.35.0", + "undici": "^7.25.0", + "zod": "^4.4.3" + } +} diff --git a/src/common/bash-timeout.ts b/packages/core/src/common/bash-timeout.ts similarity index 100% rename from src/common/bash-timeout.ts rename to packages/core/src/common/bash-timeout.ts diff --git a/src/common/debug-logger.ts b/packages/core/src/common/debug-logger.ts similarity index 100% rename from src/common/debug-logger.ts rename to packages/core/src/common/debug-logger.ts diff --git a/src/common/error-logger.ts b/packages/core/src/common/error-logger.ts similarity index 100% rename from src/common/error-logger.ts rename to packages/core/src/common/error-logger.ts diff --git a/src/common/file-history.ts b/packages/core/src/common/file-history.ts similarity index 100% rename from src/common/file-history.ts rename to packages/core/src/common/file-history.ts diff --git a/src/common/file-utils.ts b/packages/core/src/common/file-utils.ts similarity index 100% rename from src/common/file-utils.ts rename to packages/core/src/common/file-utils.ts diff --git a/src/common/model-capabilities.ts b/packages/core/src/common/model-capabilities.ts similarity index 100% rename from src/common/model-capabilities.ts rename to packages/core/src/common/model-capabilities.ts diff --git a/src/common/notify.ts b/packages/core/src/common/notify.ts similarity index 100% rename from src/common/notify.ts rename to packages/core/src/common/notify.ts diff --git a/src/common/openai-client.ts b/packages/core/src/common/openai-client.ts similarity index 100% rename from src/common/openai-client.ts rename to packages/core/src/common/openai-client.ts diff --git a/src/common/openai-message-converter.ts b/packages/core/src/common/openai-message-converter.ts similarity index 100% rename from src/common/openai-message-converter.ts rename to packages/core/src/common/openai-message-converter.ts diff --git a/src/common/openai-thinking.ts b/packages/core/src/common/openai-thinking.ts similarity index 100% rename from src/common/openai-thinking.ts rename to packages/core/src/common/openai-thinking.ts diff --git a/src/common/permissions.ts b/packages/core/src/common/permissions.ts similarity index 100% rename from src/common/permissions.ts rename to packages/core/src/common/permissions.ts diff --git a/src/common/process-tree.ts b/packages/core/src/common/process-tree.ts similarity index 100% rename from src/common/process-tree.ts rename to packages/core/src/common/process-tree.ts diff --git a/src/common/shell-utils.ts b/packages/core/src/common/shell-utils.ts similarity index 100% rename from src/common/shell-utils.ts rename to packages/core/src/common/shell-utils.ts diff --git a/src/common/state.ts b/packages/core/src/common/state.ts similarity index 100% rename from src/common/state.ts rename to packages/core/src/common/state.ts diff --git a/src/common/telemetry.ts b/packages/core/src/common/telemetry.ts similarity index 100% rename from src/common/telemetry.ts rename to packages/core/src/common/telemetry.ts diff --git a/packages/core/src/common/tool-types.ts b/packages/core/src/common/tool-types.ts new file mode 100644 index 00000000..1d664a76 --- /dev/null +++ b/packages/core/src/common/tool-types.ts @@ -0,0 +1,107 @@ +import type OpenAI from "openai"; +import type { ReasoningEffort } from "../settings"; + +export type CreateOpenAIClient = () => { + client: OpenAI | null; + model: string; + baseURL?: string; + temperature?: number; + thinkingEnabled: boolean; + reasoningEffort?: ReasoningEffort; + debugLogEnabled?: boolean; + telemetryEnabled?: boolean; + notify?: string; + webSearchTool?: string; + env?: Record; + machineId?: string; +}; + +export type ToolCall = { + id: string; + type: "function"; + function: { + name: string; + arguments: string; + }; +}; + +export type ToolExecutionContext = { + sessionId: string; + projectRoot: string; + toolCall: ToolCall; + createOpenAIClient?: CreateOpenAIClient; + onProcessStart?: (processId: string | number, command: string) => void; + onProcessExit?: (processId: string | number) => void; + onProcessStdout?: (processId: string | number, chunk: string) => void; + onProcessTimeoutControl?: (processId: string | number, control: ProcessTimeoutControl | null) => void; + onBackgroundProcessComplete?: (completion: BackgroundProcessCompletion) => void; + onBeforeFileMutation?: (filePath: string) => void; + onAfterFileMutation?: (filePath: string) => void; + bashTimeoutMs?: number; + bashMinTimeoutMs?: number; +}; + +export type ToolExecutionHooks = { + onProcessStart?: (processId: string | number, command: string) => void; + onProcessExit?: (processId: string | number) => void; + onProcessStdout?: (processId: string | number, chunk: string) => void; + onProcessTimeoutControl?: (processId: string | number, control: ProcessTimeoutControl | null) => void; + onBackgroundProcessComplete?: (completion: BackgroundProcessCompletion) => void; + onBeforeFileMutation?: (filePath: string) => void; + onAfterFileMutation?: (filePath: string) => void; + shouldStop?: () => boolean; +}; + +export type BackgroundProcessCompletion = { + taskId: string; + processId: number; + command: string; + outputPath: string; + ok: boolean; + exitCode: number | null; + signal: string | null; + error?: string; + cwd: string | null; + shellPath: string; + startedAtMs: number; + completedAtMs: number; +}; + +export type ProcessTimeoutInfo = { + timeoutMs: number; + startedAtMs: number; + deadlineAtMs: number; + timedOut: boolean; +}; + +export type ProcessTimeoutControl = { + getInfo: () => ProcessTimeoutInfo; + setTimeoutMs: (timeoutMs: number) => ProcessTimeoutInfo; +}; + +export type ToolExecutionResult = { + ok: boolean; + name: string; + output?: string; + error?: string; + metadata?: Record; + awaitUserResponse?: boolean; + followUpMessages?: ToolExecutionFollowUpMessage[]; +}; + +export type ToolExecutionFollowUpMessage = { + role: "system"; + content: string; + contentParams?: unknown | null; +}; + +export type ToolHandler = ( + args: Record, + context: ToolExecutionContext +) => Promise; + +export type ToolCallExecution = { + toolCallId: string; + content: string; + result: ToolExecutionResult; +}; diff --git a/src/common/validate.ts b/packages/core/src/common/validate.ts similarity index 99% rename from src/common/validate.ts rename to packages/core/src/common/validate.ts index b1195d8d..7e274253 100644 --- a/src/common/validate.ts +++ b/packages/core/src/common/validate.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import type { ToolExecutionContext, ToolExecutionResult } from "../tools/executor"; +import type { ToolExecutionContext, ToolExecutionResult } from "./tool-types"; export type ValidationResult = { ok: true; input: Record } | { ok: false; error: string }; diff --git a/packages/core/src/generated/git-commit.ts b/packages/core/src/generated/git-commit.ts new file mode 100644 index 00000000..e32594c8 --- /dev/null +++ b/packages/core/src/generated/git-commit.ts @@ -0,0 +1,8 @@ +/** + * @license + * Copyright 2026 @vegamo deepcode + */ + +// Auto-generated by scripts/generate-git-commit-info.js. Do not edit. +export const GIT_COMMIT_INFO = "cc7b0c3"; +export const CLI_VERSION = "0.1.30"; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts new file mode 100644 index 00000000..8ad813a7 --- /dev/null +++ b/packages/core/src/index.ts @@ -0,0 +1,132 @@ +// Core library public API — used by both CLI and VSCode companion. + +// Settings +export { + resolveCurrentSettings, + resolveSettings, + resolveSettingsSources, + readSettings, + readProjectSettings, + writeSettings, + writeProjectSettings, + writeModelConfigSelection, + applyModelConfigSelection, + modelConfigKey, + getUserSettingsPath, + getProjectSettingsPath, + DEFAULT_MODEL, + DEFAULT_BASE_URL, +} from "./settings"; +export type { + DeepcodingSettings, + ResolvedDeepcodingSettings, + ModelConfigSelection, + PermissionScope, + PermissionSettings, + PermissionDefaultMode, + McpServerConfig, + ReasoningEffort, +} from "./settings"; + +// Session +export { SessionManager, getProjectCode, getCompactPromptTokenThreshold } from "./session"; +export type { + SessionMessage, + SessionEntry, + SessionStatus, + SessionsIndex, + SessionMessageRole, + MessageMeta, + UndoTarget, + UserPromptContent, + SkillInfo, + ModelUsage, + SessionProcessEntry, + BashTimeoutAdjustment, + LlmStreamProgress, +} from "./session"; + +// Prompt utilities +export { + getSystemPrompt, + getCompactPrompt, + getRuntimeContext, + getDefaultSkillPrompt, + getExtensionRoot, + getTools, + buildSkillDocumentsPrompt, +} from "./prompt"; +export type { ToolDefinition, SkillPromptDocument } from "./prompt"; + +// Tools +export { ToolExecutor } from "./tools/executor"; +export type { + CreateOpenAIClient, + ToolCall, + ToolExecutionContext, + ToolExecutionHooks, + ToolExecutionResult, + ToolHandler, + ToolCallExecution, + ProcessTimeoutInfo, + ProcessTimeoutControl, + BackgroundProcessCompletion, + ToolExecutionFollowUpMessage, +} from "./common/tool-types"; + +// Tool handlers +export { handleBashTool, clearSessionWorkingDir } from "./tools/bash-handler"; +export { handleReadTool } from "./tools/read-handler"; +export { handleWriteTool } from "./tools/write-handler"; +export { handleEditTool } from "./tools/edit-handler"; +export { handleUpdatePlanTool } from "./tools/update-plan-handler"; +export { handleWebSearchTool } from "./tools/web-search-handler"; +export { handleAskUserQuestionTool } from "./tools/ask-user-question-handler"; + +// MCP +export { McpManager } from "./mcp/mcp-manager"; +export { McpClient } from "./mcp/mcp-client"; +export type { McpServerStatus } from "./mcp/mcp-manager"; + +// Common utilities +export { createOpenAIClient } from "./common/openai-client"; +export { buildThinkingRequestOptions } from "./common/openai-thinking"; +export { readTextFileWithMetadata, writeTextFile, buildDiffPreview, ensureParentDirectory } from "./common/file-utils"; +export { normalizeFilePath, getSnippet, clearSessionState, recordFileState, getFileState } from "./common/state"; +export { GitFileHistory } from "./common/file-history"; +export { killProcessTree } from "./common/process-tree"; +export { launchNotifyScript } from "./common/notify"; +export { reportNewPrompt } from "./common/telemetry"; +export { DEEPSEEK_V4_MODELS, supportsMultimodal, defaultsToThinkingMode } from "./common/model-capabilities"; +export { findGitBashPath, resolveShellPath, setShellIfWindows } from "./common/shell-utils"; +export { logApiError } from "./common/error-logger"; +export { logOpenAIChatCompletionDebug } from "./common/debug-logger"; +export { + clampBashTimeoutMs, + DEFAULT_BASH_TIMEOUT_MS, + BASH_TIMEOUT_INCREMENT_MS, + BASH_TIMEOUT_DECREMENT_MS, +} from "./common/bash-timeout"; +export { executeValidatedTool, semanticBoolean } from "./common/validate"; +export { OpenAIMessageConverter } from "./common/openai-message-converter"; +export { + computeToolCallPermissions, + buildPermissionToolExecution, + hasUserPermissionReplies, + appendProjectPermissionAllows, + normalizeAskPermissions, + parseToolCallForPermissions, +} from "./common/permissions"; +export type { + AskPermissionRequest, + AskPermissionScope, + BashPermissionScope, + MessageToolPermission, + PermissionDecision, + PermissionToolCall, + UserToolPermission, +} from "./common/permissions"; + +// State types +export type { FileState, FileSnippet, FileLineEnding } from "./common/state"; +export type { FileReadMetadata } from "./common/file-utils"; diff --git a/src/mcp/mcp-client.ts b/packages/core/src/mcp/mcp-client.ts similarity index 100% rename from src/mcp/mcp-client.ts rename to packages/core/src/mcp/mcp-client.ts diff --git a/src/mcp/mcp-manager.ts b/packages/core/src/mcp/mcp-manager.ts similarity index 100% rename from src/mcp/mcp-manager.ts rename to packages/core/src/mcp/mcp-manager.ts diff --git a/src/prompt.ts b/packages/core/src/prompt.ts similarity index 100% rename from src/prompt.ts rename to packages/core/src/prompt.ts diff --git a/src/session.ts b/packages/core/src/session.ts similarity index 100% rename from src/session.ts rename to packages/core/src/session.ts diff --git a/src/settings.ts b/packages/core/src/settings.ts similarity index 100% rename from src/settings.ts rename to packages/core/src/settings.ts diff --git a/src/tests/debug-logger.test.ts b/packages/core/src/tests/debug-logger.test.ts similarity index 100% rename from src/tests/debug-logger.test.ts rename to packages/core/src/tests/debug-logger.test.ts diff --git a/src/tests/mcp-client.test.ts b/packages/core/src/tests/mcp-client.test.ts similarity index 100% rename from src/tests/mcp-client.test.ts rename to packages/core/src/tests/mcp-client.test.ts diff --git a/src/tests/memory-leak.test.ts b/packages/core/src/tests/memory-leak.test.ts similarity index 100% rename from src/tests/memory-leak.test.ts rename to packages/core/src/tests/memory-leak.test.ts diff --git a/src/tests/openai-message-converter.test.ts b/packages/core/src/tests/openai-message-converter.test.ts similarity index 100% rename from src/tests/openai-message-converter.test.ts rename to packages/core/src/tests/openai-message-converter.test.ts diff --git a/src/tests/openai-thinking.test.ts b/packages/core/src/tests/openai-thinking.test.ts similarity index 100% rename from src/tests/openai-thinking.test.ts rename to packages/core/src/tests/openai-thinking.test.ts diff --git a/src/tests/permissions.test.ts b/packages/core/src/tests/permissions.test.ts similarity index 100% rename from src/tests/permissions.test.ts rename to packages/core/src/tests/permissions.test.ts diff --git a/src/tests/process-tree.test.ts b/packages/core/src/tests/process-tree.test.ts similarity index 100% rename from src/tests/process-tree.test.ts rename to packages/core/src/tests/process-tree.test.ts diff --git a/src/tests/prompt.test.ts b/packages/core/src/tests/prompt.test.ts similarity index 100% rename from src/tests/prompt.test.ts rename to packages/core/src/tests/prompt.test.ts diff --git a/packages/core/src/tests/run-tests.mjs b/packages/core/src/tests/run-tests.mjs new file mode 100644 index 00000000..ce87cbd2 --- /dev/null +++ b/packages/core/src/tests/run-tests.mjs @@ -0,0 +1,15 @@ +// Test runner for @vegamo/deepcode-core +import { globSync } from "glob"; +import { spawnSync } from "child_process"; +import { fileURLToPath } from "url"; +import * as path from "path"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const testFiles = globSync("*.test.ts", { cwd: __dirname }); + +const result = spawnSync(process.execPath, ["--import", "tsx", "--test", ...testFiles], { + stdio: "inherit", + cwd: __dirname, +}); + +process.exit(result.status ?? 1); diff --git a/src/tests/session.test.ts b/packages/core/src/tests/session.test.ts similarity index 100% rename from src/tests/session.test.ts rename to packages/core/src/tests/session.test.ts diff --git a/src/tests/settings-and-notify.test.ts b/packages/core/src/tests/settings-and-notify.test.ts similarity index 100% rename from src/tests/settings-and-notify.test.ts rename to packages/core/src/tests/settings-and-notify.test.ts diff --git a/src/tests/shell-utils.test.ts b/packages/core/src/tests/shell-utils.test.ts similarity index 100% rename from src/tests/shell-utils.test.ts rename to packages/core/src/tests/shell-utils.test.ts diff --git a/src/tests/telemetry.test.ts b/packages/core/src/tests/telemetry.test.ts similarity index 100% rename from src/tests/telemetry.test.ts rename to packages/core/src/tests/telemetry.test.ts diff --git a/src/tests/tool-executor.test.ts b/packages/core/src/tests/tool-executor.test.ts similarity index 100% rename from src/tests/tool-executor.test.ts rename to packages/core/src/tests/tool-executor.test.ts diff --git a/src/tests/tool-handlers.test.ts b/packages/core/src/tests/tool-handlers.test.ts similarity index 100% rename from src/tests/tool-handlers.test.ts rename to packages/core/src/tests/tool-handlers.test.ts diff --git a/src/tests/web-search-handler.test.ts b/packages/core/src/tests/web-search-handler.test.ts similarity index 100% rename from src/tests/web-search-handler.test.ts rename to packages/core/src/tests/web-search-handler.test.ts diff --git a/src/tools/ask-user-question-handler.ts b/packages/core/src/tools/ask-user-question-handler.ts similarity index 100% rename from src/tools/ask-user-question-handler.ts rename to packages/core/src/tools/ask-user-question-handler.ts diff --git a/src/tools/bash-handler.ts b/packages/core/src/tools/bash-handler.ts similarity index 100% rename from src/tools/bash-handler.ts rename to packages/core/src/tools/bash-handler.ts diff --git a/src/tools/edit-handler.ts b/packages/core/src/tools/edit-handler.ts similarity index 100% rename from src/tools/edit-handler.ts rename to packages/core/src/tools/edit-handler.ts diff --git a/src/tools/executor.ts b/packages/core/src/tools/executor.ts similarity index 67% rename from src/tools/executor.ts rename to packages/core/src/tools/executor.ts index 53846f48..6af57c4c 100644 --- a/src/tools/executor.ts +++ b/packages/core/src/tools/executor.ts @@ -1,5 +1,3 @@ -import type OpenAI from "openai"; -import type { ReasoningEffort } from "../settings"; import { handleAskUserQuestionTool } from "./ask-user-question-handler"; import { handleBashTool } from "./bash-handler"; import { handleEditTool } from "./edit-handler"; @@ -8,105 +6,28 @@ import { handleUpdatePlanTool } from "./update-plan-handler"; import { handleWebSearchTool } from "./web-search-handler"; import { handleWriteTool } from "./write-handler"; import type { McpManager } from "../mcp/mcp-manager"; - -export type CreateOpenAIClient = () => { - client: OpenAI | null; - model: string; - baseURL?: string; - temperature?: number; - thinkingEnabled: boolean; - reasoningEffort?: ReasoningEffort; - debugLogEnabled?: boolean; - telemetryEnabled?: boolean; - notify?: string; - webSearchTool?: string; - env?: Record; - machineId?: string; -}; - -export type ToolCall = { - id: string; - type: "function"; - function: { - name: string; - arguments: string; - }; -}; - -export type ToolExecutionContext = { - sessionId: string; - projectRoot: string; - toolCall: ToolCall; - createOpenAIClient?: CreateOpenAIClient; - onProcessStart?: (processId: string | number, command: string) => void; - onProcessExit?: (processId: string | number) => void; - onProcessStdout?: (processId: string | number, chunk: string) => void; - onProcessTimeoutControl?: (processId: string | number, control: ProcessTimeoutControl | null) => void; - onBackgroundProcessComplete?: (completion: BackgroundProcessCompletion) => void; - onBeforeFileMutation?: (filePath: string) => void; - onAfterFileMutation?: (filePath: string) => void; - bashTimeoutMs?: number; - bashMinTimeoutMs?: number; -}; - -export type ToolExecutionHooks = { - onProcessStart?: (processId: string | number, command: string) => void; - onProcessExit?: (processId: string | number) => void; - onProcessStdout?: (processId: string | number, chunk: string) => void; - onProcessTimeoutControl?: (processId: string | number, control: ProcessTimeoutControl | null) => void; - onBackgroundProcessComplete?: (completion: BackgroundProcessCompletion) => void; - onBeforeFileMutation?: (filePath: string) => void; - onAfterFileMutation?: (filePath: string) => void; - shouldStop?: () => boolean; -}; - -export type BackgroundProcessCompletion = { - taskId: string; - processId: number; - command: string; - outputPath: string; - ok: boolean; - exitCode: number | null; - signal: string | null; - error?: string; - cwd: string | null; - shellPath: string; - startedAtMs: number; - completedAtMs: number; -}; - -export type ProcessTimeoutInfo = { - timeoutMs: number; - startedAtMs: number; - deadlineAtMs: number; - timedOut: boolean; -}; - -export type ProcessTimeoutControl = { - getInfo: () => ProcessTimeoutInfo; - setTimeoutMs: (timeoutMs: number) => ProcessTimeoutInfo; -}; - -export type ToolExecutionResult = { - ok: boolean; - name: string; - output?: string; - error?: string; - metadata?: Record; - awaitUserResponse?: boolean; - followUpMessages?: ToolExecutionFollowUpMessage[]; -}; - -export type ToolExecutionFollowUpMessage = { - role: "system"; - content: string; - contentParams?: unknown | null; -}; - -export type ToolHandler = ( - args: Record, - context: ToolExecutionContext -) => Promise; +import type { + CreateOpenAIClient, + ToolCall, + ToolExecutionHooks, + ToolExecutionResult, + ToolHandler, + ToolCallExecution, +} from "../common/tool-types"; + +export type { + CreateOpenAIClient, + ToolCall, + ToolExecutionContext, + ToolExecutionHooks, + ToolExecutionResult, + ToolHandler, + ToolCallExecution, + ProcessTimeoutInfo, + ProcessTimeoutControl, + BackgroundProcessCompletion, + ToolExecutionFollowUpMessage, +} from "../common/tool-types"; const BUILT_IN_TOOL_NAME_ALIASES = new Map([ ["Bash", "bash"], @@ -115,12 +36,6 @@ const BUILT_IN_TOOL_NAME_ALIASES = new Map([ ["Edit", "edit"], ]); -export type ToolCallExecution = { - toolCallId: string; - content: string; - result: ToolExecutionResult; -}; - export class ToolExecutor { private readonly projectRoot: string; private readonly createOpenAIClient?: CreateOpenAIClient; @@ -216,7 +131,6 @@ export class ToolExecutor { const handlerName = BUILT_IN_TOOL_NAME_ALIASES.get(toolName) ?? toolName; const handler = this.toolHandlers.get(handlerName); if (!handler) { - // Try MCP tools if (this.mcpManager?.isMcpTool(toolName)) { const parsedArgs = this.parseToolArguments(toolCall.function.arguments); const args = parsedArgs.ok ? parsedArgs.args : {}; diff --git a/src/tools/read-handler.ts b/packages/core/src/tools/read-handler.ts similarity index 100% rename from src/tools/read-handler.ts rename to packages/core/src/tools/read-handler.ts diff --git a/src/tools/update-plan-handler.ts b/packages/core/src/tools/update-plan-handler.ts similarity index 100% rename from src/tools/update-plan-handler.ts rename to packages/core/src/tools/update-plan-handler.ts diff --git a/src/tools/web-search-handler.ts b/packages/core/src/tools/web-search-handler.ts similarity index 100% rename from src/tools/web-search-handler.ts rename to packages/core/src/tools/web-search-handler.ts diff --git a/src/tools/write-handler.ts b/packages/core/src/tools/write-handler.ts similarity index 100% rename from src/tools/write-handler.ts rename to packages/core/src/tools/write-handler.ts diff --git a/templates/prompts/init_command.md.ejs b/packages/core/templates/prompts/init_command.md.ejs similarity index 100% rename from templates/prompts/init_command.md.ejs rename to packages/core/templates/prompts/init_command.md.ejs diff --git a/templates/skills/bundled/deepcode-self-refer/SKILL.md b/packages/core/templates/skills/bundled/deepcode-self-refer/SKILL.md similarity index 81% rename from templates/skills/bundled/deepcode-self-refer/SKILL.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/SKILL.md index 357868cd..5a8b377c 100644 --- a/templates/skills/bundled/deepcode-self-refer/SKILL.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/SKILL.md @@ -31,14 +31,14 @@ Use this Skill when the user asks any question about Deep Code itself, such as: Map the user's question to the appropriate document(s): -| Topic | Document | Key contents | -|-------|----------|-------------| -| **Overview, features, quick start** | `references/README.md` | Installation, slash commands, keyboard shortcuts, supported models, FAQ | -| **Configuration & settings** | `references/configuration.md` | `settings.json` fields, config hierarchy, env vars, thinking mode, reasoning effort, webSearchTool, enabledSkills | -| **MCP setup & usage** | `references/mcp.md` | MCP server config format, GitHub/Playwright/Filesystem examples, tool naming (`mcp____`), troubleshooting | -| **Permissions** | `references/permission.md` | Permission scopes (10 types), allow/deny/ask/defaultMode config, priority rules, persistence | -| **Notifications** | `references/notify.md` | Notify script path, injected env vars, Slack/Feishu/iTerm2/macOS/Linux/Windows examples | -| **Session persistence** | `references/session-persistence.md` | Storage paths, JSONL format, session index, compaction, `/undo` mechanics, code snapshots | +| Topic | Document | Key contents | +| ----------------------------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| **Overview, features, quick start** | `references/README.md` | Installation, slash commands, keyboard shortcuts, supported models, FAQ | +| **Configuration & settings** | `references/configuration.md` | `settings.json` fields, config hierarchy, env vars, thinking mode, reasoning effort, webSearchTool, enabledSkills | +| **MCP setup & usage** | `references/mcp.md` | MCP server config format, GitHub/Playwright/Filesystem examples, tool naming (`mcp____`), troubleshooting | +| **Permissions** | `references/permission.md` | Permission scopes (10 types), allow/deny/ask/defaultMode config, priority rules, persistence | +| **Notifications** | `references/notify.md` | Notify script path, injected env vars, Slack/Feishu/iTerm2/macOS/Linux/Windows examples | +| **Session persistence** | `references/session-persistence.md` | Storage paths, JSONL format, session index, compaction, `/undo` mechanics, code snapshots | ### Step 2: Read the relevant document(s) @@ -58,6 +58,7 @@ Use the `Read` tool to read the appropriate document(s) from the list above. All ### Step 4: Handle common request patterns **"列出/查看可用的 skills":** + - Treat `/skills` as the canonical UI for listing currently available skills. - If answering directly, do not infer the list only from loaded skill prompts or from project/user directories. Enumerate all discovery roots: 1. `./.deepcode/skills//SKILL.md` @@ -77,18 +78,21 @@ Use the `Read` tool to read the appropriate document(s) from the list above. All - Mention that `/skills` can be used to verify the result and `enabledSkills` can enable/disable specific skills by name. **"配置 MCP":** + - Read `references/mcp.md` for the MCP format and examples - Ask the user for any required credentials (e.g., GitHub token) - Provide the exact `mcpServers` JSON block to add to `settings.json` - Mention using `/mcp` to verify the setup afterwards **"如何配置/修改 <设置项>":** + - Read `references/configuration.md` - Explain which `settings.json` field controls the setting - Clarify user-level (`~/.deepcode/settings.json`) vs project-level (`.deepcode/settings.json`) - Provide the exact JSON snippet **"<斜杠命令> 是做什么的?":** + - Read the slash command table from references/README.md - Provide a brief explanation with any additional context from relevant docs diff --git a/templates/skills/bundled/deepcode-self-refer/references/README.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/README.md similarity index 87% rename from templates/skills/bundled/deepcode-self-refer/references/README.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/README.md index de34da9a..9a4e27e0 100644 --- a/templates/skills/bundled/deepcode-self-refer/references/README.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/references/README.md @@ -51,46 +51,48 @@ npm install -g @vegamo/deepcode-cli ## 主要功能 ### **Skills** + Deep Code CLI 支持 agent skills,允许您扩展助手的能力: Skills 会按以下优先级扫描: -| Scope | Path | Purpose | -| :------ | :-------------------- | :---------------------------- | -| Project | `./.deepcode/skills/` | Deep Code 原生位置,最高优先级 | -| Project | `./.agents/skills/` | 跨客户端互操作 | -| User | `~/.deepcode/skills/` | Deep Code 原生位置 | -| User | `~/.agents/skills/` | 跨客户端互操作 | +| Scope | Path | Purpose | +| :------ | :------------------------- | :-------------------------------- | +| Project | `./.deepcode/skills/` | Deep Code 原生位置,最高优先级 | +| Project | `./.agents/skills/` | 跨客户端互操作 | +| User | `~/.deepcode/skills/` | Deep Code 原生位置 | +| User | `~/.agents/skills/` | 跨客户端互操作 | | Bundled | `bundled:/SKILL.md` | Deep Code 内置 skills,最低优先级 | ### **为 DeepSeek 优化** + - 专门为 DeepSeek 模型性能调优。 - 通过使用[上下文缓存](https://api-docs.deepseek.com/guides/kv_cache)来降低成本。 - 原生支持[思考模式](https://api-docs.deepseek.com/guides/thinking_mode)和思考强度控制。 ## 斜杠命令与按键功能 -| 斜杠命令 | 操作 | -|-------------|----------------------------------| -| `/` | 打开 skills / 命令菜单 | -| `/new` | 开始新对话 | -| `/resume` | 选择历史对话继续 | -| `/continue` | 继续当前对话,或选择历史对话恢复 | -| `/model` | 切换模型、思考模式和推理强度 | +| 斜杠命令 | 操作 | +| ----------- | -------------------------------------------- | +| `/` | 打开 skills / 命令菜单 | +| `/new` | 开始新对话 | +| `/resume` | 选择历史对话继续 | +| `/continue` | 继续当前对话,或选择历史对话恢复 | +| `/model` | 切换模型、思考模式和推理强度 | | `/raw` | 切换显示模式(Normal / Lite / Raw 滚动回溯) | -| `/init` | 初始化 AGENTS.md 文件 | -| `/skills` | 列出可用 skills | +| `/init` | 初始化 AGENTS.md 文件 | +| `/skills` | 列出可用 skills | | `/mcp` | 查看 MCP 服务器状态和可用工具 | -| `/undo` | 将代码和/或对话恢复到之前的状态 | -| `/exit` | 退出(也可用连续 `Ctrl+D`) | +| `/undo` | 将代码和/或对话恢复到之前的状态 | +| `/exit` | 退出(也可用连续 `Ctrl+D`) | -| 按键 | 操作 | -|---------------|--------------------| -| `Enter` | 发送消息 | +| 按键 | 操作 | +| ------------- | --------------------------- | +| `Enter` | 发送消息 | | `Shift+Enter` | 插入换行(也可用 `Ctrl+J`) | -| `Ctrl+V` | 从剪贴板粘贴图片 | -| `Esc` | 中断当前模型回复 | -| 连续 `Ctrl+D` | 退出 | +| `Ctrl+V` | 从剪贴板粘贴图片 | +| `Esc` | 中断当前模型回复 | +| 连续 `Ctrl+D` | 退出 | ## 支持的模型 @@ -98,7 +100,6 @@ Skills 会按以下优先级扫描: - `deepseek-v4-flash` - 任何其他 OpenAI 兼容模型 - ## 常见问题 ### Deep Code 是否有 VSCode 插件? diff --git a/templates/skills/bundled/deepcode-self-refer/references/configuration.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/configuration.md similarity index 64% rename from templates/skills/bundled/deepcode-self-refer/references/configuration.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/configuration.md index 2f198b10..ad437ab8 100644 --- a/templates/skills/bundled/deepcode-self-refer/references/configuration.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/references/configuration.md @@ -4,53 +4,53 @@ 配置按以下优先级顺序应用(数字较小的会被数字较大的覆盖): -| 层级 | 配置来源 | 说明 | -| ---- | ------------ | ------------------------------------------- | -| 1 | 默认值 | 应用程序内硬编码的默认值 | -| 2 | 用户设置文件 | 当前用户的全局设置 | -| 3 | 项目设置文件 | 项目特定的设置 | -| 4 | 环境变量 | 系统范围或会话特定的变量 | +| 层级 | 配置来源 | 说明 | +| ---- | ------------ | ------------------------ | +| 1 | 默认值 | 应用程序内硬编码的默认值 | +| 2 | 用户设置文件 | 当前用户的全局设置 | +| 3 | 项目设置文件 | 项目特定的设置 | +| 4 | 环境变量 | 系统范围或会话特定的变量 | ## 设置文件 Deep Code 使用 `settings.json` 设置文件进行持久化配置,支持两个层级的存放位置: -| 文件类型 | 位置 | 作用范围 | -| ------------ | ---------------------------------- | ---------------------------------------------------- | -| 用户设置文件 | `~/.deepcode/settings.json` | 适用于当前用户的所有 Deep Code 会话。 | +| 文件类型 | 位置 | 作用范围 | +| ------------ | ------------------------------------ | --------------------------------------------------------------- | +| 用户设置文件 | `~/.deepcode/settings.json` | 适用于当前用户的所有 Deep Code 会话。 | | 项目设置文件 | `项目根目录/.deepcode/settings.json` | 仅在该特定项目中运行 Deep Code 时生效。项目设置会覆盖用户设置。 | ### `settings.json` 中的可用设置 以下是 `settings.json` 支持的全部顶层字段,以及 `env` 内部支持的子字段: -| 字段 | 类型 | 说明 | -| -------------------- | --------- | ------------------------------------------------------------------- | -| `env` | object | 环境变量分组(见下方子字段表) | -| `model` | string | 模型名称。优先级高于 `env.MODEL` | -| `thinkingEnabled` | boolean | 是否启用思考模式(DeepSeek V4 系列默认启用) | -| `reasoningEffort` | string | 推理强度,可选 `"high"` 或 `"max"`(默认 `"max"`) | -| `debugLogEnabled` | boolean | 是否启用调试日志输出(默认 `false`) | -| `telemetryEnabled` | boolean | 是否启用匿名使用数据上报(默认 `true`) | -| `notify` | string | 任务完成通知脚本的完整路径(如 Slack 通知脚本) | -| `webSearchTool` | string | 自定义联网搜索脚本的完整路径 | -| `mcpServers` | object | MCP 服务器配置(键为服务名,值为 McpServerConfig 对象) | -| `temperature` | number | 模型采样温度,范围 `0` 到 `2` | -| `enabledSkills` | object | 按 skill 名称启用或禁用 skill 的配置 | +| 字段 | 类型 | 说明 | +| ------------------ | ------- | ------------------------------------------------------- | +| `env` | object | 环境变量分组(见下方子字段表) | +| `model` | string | 模型名称。优先级高于 `env.MODEL` | +| `thinkingEnabled` | boolean | 是否启用思考模式(DeepSeek V4 系列默认启用) | +| `reasoningEffort` | string | 推理强度,可选 `"high"` 或 `"max"`(默认 `"max"`) | +| `debugLogEnabled` | boolean | 是否启用调试日志输出(默认 `false`) | +| `telemetryEnabled` | boolean | 是否启用匿名使用数据上报(默认 `true`) | +| `notify` | string | 任务完成通知脚本的完整路径(如 Slack 通知脚本) | +| `webSearchTool` | string | 自定义联网搜索脚本的完整路径 | +| `mcpServers` | object | MCP 服务器配置(键为服务名,值为 McpServerConfig 对象) | +| `temperature` | number | 模型采样温度,范围 `0` 到 `2` | +| `enabledSkills` | object | 按 skill 名称启用或禁用 skill 的配置 | #### `env` 子字段 -| 字段 | 类型 | 说明 | -| ---------- | ------ | ------------------------------------------------------------------ | -| `MODEL` | string | 模型名称。例如 `"deepseek-v4-pro"`、`"deepseek-v4-flash"` | -| `BASE_URL` | string | API 请求的基础 URL。例如 `"https://api.deepseek.com"` | -| `API_KEY` | string | API 密钥 | -| `TEMPERATURE` | string | Chat Completions 采样温度,范围 `"0"` 到 `"2"` | -| `THINKING_ENABLED` | string | 是否启用思考模式 | -| `REASONING_EFFORT` | string | 推理强度 | -| `DEBUG_LOG_ENABLED` | string | 是否启用调试日志输出 | -| `TELEMETRY_ENABLED` | string | 是否启用匿名使用数据上报 | -| `<其他任意KEY>` | string | 自定义环境变量 | +| 字段 | 类型 | 说明 | +| ------------------- | ------ | --------------------------------------------------------- | +| `MODEL` | string | 模型名称。例如 `"deepseek-v4-pro"`、`"deepseek-v4-flash"` | +| `BASE_URL` | string | API 请求的基础 URL。例如 `"https://api.deepseek.com"` | +| `API_KEY` | string | API 密钥 | +| `TEMPERATURE` | string | Chat Completions 采样温度,范围 `"0"` 到 `"2"` | +| `THINKING_ENABLED` | string | 是否启用思考模式 | +| `REASONING_EFFORT` | string | 推理强度 | +| `DEBUG_LOG_ENABLED` | string | 是否启用调试日志输出 | +| `TELEMETRY_ENABLED` | string | 是否启用匿名使用数据上报 | +| `<其他任意KEY>` | string | 自定义环境变量 | #### `thinkingEnabled` — 思考模式 @@ -63,10 +63,10 @@ Deep Code 使用 `settings.json` 设置文件进行持久化配置,支持两 当思考模式启用时,控制模型思考的深度: -| 值 | 说明 | -| ------ | --------------------------------- | -| `max` | 最大推理深度(默认值) | -| `high` | 较高推理深度,token消耗相对较小 | +| 值 | 说明 | +| ------ | ------------------------------- | +| `max` | 最大推理深度(默认值) | +| `high` | 较高推理深度,token消耗相对较小 | #### `notify` — 任务完成通知 @@ -74,13 +74,13 @@ Deep Code 使用 `settings.json` 设置文件进行持久化配置,支持两 通知脚本执行时,会通过环境变量注入以下上下文信息: -| 环境变量 | 说明 | -|----------|------| -| `DURATION` | 会话耗时,单位秒(整数) | -| `STATUS` | 会话状态:`"completed"` 或 `"failed"` | -| `FAIL_REASON` | 失败原因(仅失败时设置) | -| `BODY` | 最后一条 AI 助手回复的文本内容 | -| `TITLE` | 会话标题(对应 resume 列表中的标题) | +| 环境变量 | 说明 | +| ------------- | ------------------------------------- | +| `DURATION` | 会话耗时,单位秒(整数) | +| `STATUS` | 会话状态:`"completed"` 或 `"failed"` | +| `FAIL_REASON` | 失败原因(仅失败时设置) | +| `BODY` | 最后一条 AI 助手回复的文本内容 | +| `TITLE` | 会话标题(对应 resume 列表中的标题) | ```json { @@ -137,17 +137,16 @@ MCP(Model Context Protocol)服务器配置。值是键值对,键为服务 } ``` -| McpServerConfig 字段 | 类型 | 必填 | 说明 | -| -------------------- | -------- | ---- | -------------------------------------------------------------------- | -| `command` | string | 是 | 可执行文件路径或命令(如 `npx`、`node`、`python`) | -| `args` | string[] | 否 | 传递给命令的参数列表 | -| `env` | object | 否 | 传递给 MCP 服务器进程的环境变量 | +| McpServerConfig 字段 | 类型 | 必填 | 说明 | +| -------------------- | -------- | ---- | -------------------------------------------------- | +| `command` | string | 是 | 可执行文件路径或命令(如 `npx`、`node`、`python`) | +| `args` | string[] | 否 | 传递给命令的参数列表 | +| `env` | object | 否 | 传递给 MCP 服务器进程的环境变量 | > 当 `command` 为 `npx` 时,Deep Code 会自动在参数前补充 `-y`。 详细 MCP 使用说明请参考 [mcp.md](mcp.md)。 - #### `debugLogEnabled` — 调试日志 设为 `true` 可让程序输出详细的调试日志(默认 `false`),用于排查 API 调用和工具执行的问题。 @@ -171,6 +170,7 @@ DEEPCODE_TELEMETRY_ENABLED=0 deepcode 环境变量优先级遵循“越具体、越局部的配置,优先级越高”和“env文件默认保护现有环境,系统变量高于env文件”的覆盖逻辑。(settings.json的env对象可以认为是一种env文件) 优先级层级 (由低到高) + 1. settings.json 外层的 env:这是针对整个工具及其所有子进程的通用配置(全局变量)。可被外层环境变量覆盖,但环境变量KEY会移除`DEEPCODE_`前缀。 2. settings.json mcpServers 内定义的 env:这是针对特定 MCP 服务的最具体配置(局部变量)。可被外层环境变量覆盖,但环境变量KEY会移除`MCP_`前缀。 3. Shell 环境系统变量:操作系统层面的环境变量。 diff --git a/templates/skills/bundled/deepcode-self-refer/references/configuration_en.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/configuration_en.md similarity index 71% rename from templates/skills/bundled/deepcode-self-refer/references/configuration_en.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/configuration_en.md index fac8c349..2c58b5d0 100644 --- a/templates/skills/bundled/deepcode-self-refer/references/configuration_en.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/references/configuration_en.md @@ -4,53 +4,53 @@ Configuration is applied in the following priority order (lower-numbered sources are overridden by higher-numbered ones): -| Layer | Configuration Source | Description | -| ----- | -------------------- | ---------------------------------------------- | -| 1 | Defaults | Hardcoded defaults within the application | -| 2 | User settings file | Global settings for the current user | -| 3 | Project settings file| Project-specific settings | -| 4 | Environment variables| System-wide or session-specific variables | +| Layer | Configuration Source | Description | +| ----- | --------------------- | ----------------------------------------- | +| 1 | Defaults | Hardcoded defaults within the application | +| 2 | User settings file | Global settings for the current user | +| 3 | Project settings file | Project-specific settings | +| 4 | Environment variables | System-wide or session-specific variables | ## Settings File Deep Code uses the `settings.json` file for persistent configuration, supporting two storage locations: -| File Type | Location | Scope | -| ------------------- | ----------------------------------------- | --------------------------------------------------------------------- | -| User settings file | `~/.deepcode/settings.json` | Applies to all Deep Code sessions for the current user. | +| File Type | Location | Scope | +| --------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| User settings file | `~/.deepcode/settings.json` | Applies to all Deep Code sessions for the current user. | | Project settings file | `/.deepcode/settings.json` | Takes effect only when running Deep Code in that specific project. Project settings override user settings. | ### Available Settings in `settings.json` The following are all the top-level fields supported in `settings.json`, along with the sub-fields inside `env`: -| Field | Type | Description | -| ------------------ | ------- | --------------------------------------------------------------------------- | -| `env` | object | Group of environment variables (see sub-field table below) | -| `model` | string | Model name. Takes precedence over `env.MODEL` | -| `thinkingEnabled` | boolean | Whether to enable thinking mode (enabled by default for DeepSeek V4 series)| -| `reasoningEffort` | string | Reasoning intensity, either `"high"` or `"max"` (default `"max"`) | -| `debugLogEnabled` | boolean | Enable debug log output (default `false`) | -| `telemetryEnabled` | boolean | Enable anonymous usage reporting (default `true`) | -| `notify` | string | Full path to a task-completion notification script (e.g., Slack notification script) | -| `webSearchTool` | string | Full path to a custom web search script | +| Field | Type | Description | +| ------------------ | ------- | -------------------------------------------------------------------------------------- | +| `env` | object | Group of environment variables (see sub-field table below) | +| `model` | string | Model name. Takes precedence over `env.MODEL` | +| `thinkingEnabled` | boolean | Whether to enable thinking mode (enabled by default for DeepSeek V4 series) | +| `reasoningEffort` | string | Reasoning intensity, either `"high"` or `"max"` (default `"max"`) | +| `debugLogEnabled` | boolean | Enable debug log output (default `false`) | +| `telemetryEnabled` | boolean | Enable anonymous usage reporting (default `true`) | +| `notify` | string | Full path to a task-completion notification script (e.g., Slack notification script) | +| `webSearchTool` | string | Full path to a custom web search script | | `mcpServers` | object | MCP server configurations (keys are service names, values are McpServerConfig objects) | -| `temperature` | number | Sampling temperature for LLM, from `0` to `2` | -| `enabledSkills` | object | Per-skill enable/disable map, keyed by skill name | +| `temperature` | number | Sampling temperature for LLM, from `0` to `2` | +| `enabledSkills` | object | Per-skill enable/disable map, keyed by skill name | #### `env` Sub-fields -| Field | Type | Description | -| ----------------- | ------ | ---------------------------------------------------------------- | -| `MODEL` | string | Model name, e.g. `"deepseek-v4-pro"`, `"deepseek-v4-flash"` | -| `BASE_URL` | string | Base URL for API requests, e.g. `"https://api.deepseek.com"` | -| `API_KEY` | string | API key | -| `TEMPERATURE` | string | Sampling temperature for chat completions, from `"0"` to `"2"` | -| `THINKING_ENABLED`| string | Enable thinking mode | -| `REASONING_EFFORT`| string | Reasoning intensity | -| `DEBUG_LOG_ENABLED`| string| Enable debug log output | -| `TELEMETRY_ENABLED`| string| Enable anonymous usage reporting | -| `` | string | Custom environment variable | +| Field | Type | Description | +| ------------------- | ------ | -------------------------------------------------------------- | +| `MODEL` | string | Model name, e.g. `"deepseek-v4-pro"`, `"deepseek-v4-flash"` | +| `BASE_URL` | string | Base URL for API requests, e.g. `"https://api.deepseek.com"` | +| `API_KEY` | string | API key | +| `TEMPERATURE` | string | Sampling temperature for chat completions, from `"0"` to `"2"` | +| `THINKING_ENABLED` | string | Enable thinking mode | +| `REASONING_EFFORT` | string | Reasoning intensity | +| `DEBUG_LOG_ENABLED` | string | Enable debug log output | +| `TELEMETRY_ENABLED` | string | Enable anonymous usage reporting | +| `` | string | Custom environment variable | #### `thinkingEnabled` — Thinking Mode @@ -63,10 +63,10 @@ Whether to enable DeepSeek thinking mode. Set to `true` to enable, `false` to di When thinking mode is enabled, controls the depth of the model’s reasoning: -| Value | Description | -| ------ | --------------------------------------------------------- | -| `max` | Maximum reasoning depth (default) | -| `high` | Higher reasoning depth with relatively lower token usage | +| Value | Description | +| ------ | -------------------------------------------------------- | +| `max` | Maximum reasoning depth (default) | +| `high` | Higher reasoning depth with relatively lower token usage | #### `notify` — Task Completion Notification @@ -74,13 +74,13 @@ Set a full path to a shell script. When the AI assistant finishes a round of tas The following context is injected as environment variables when the notify script runs: -| Variable | Description | -|----------|-------------| -| `DURATION` | Session duration in seconds (integer) | -| `STATUS` | Session status: `"completed"` or `"failed"` | -| `FAIL_REASON` | Failure reason (only set on failure) | -| `BODY` | The text content of the last AI assistant reply | -| `TITLE` | Session title (matches the resume list title) | +| Variable | Description | +| ------------- | ----------------------------------------------- | +| `DURATION` | Session duration in seconds (integer) | +| `STATUS` | Session status: `"completed"` or `"failed"` | +| `FAIL_REASON` | Failure reason (only set on failure) | +| `BODY` | The text content of the last AI assistant reply | +| `TITLE` | Session title (matches the resume list title) | ```json { @@ -137,11 +137,11 @@ Configuration for MCP (Model Context Protocol) servers. The value is a key-value } ``` -| McpServerConfig field | Type | Required | Description | -| --------------------- | -------- | -------- | ------------------------------------------------------------------------ | -| `command` | string | Yes | Executable path or command (e.g. `npx`, `node`, `python`) | -| `args` | string[] | No | List of arguments passed to the command | -| `env` | object | No | Environment variables passed to the MCP server process | +| McpServerConfig field | Type | Required | Description | +| --------------------- | -------- | -------- | --------------------------------------------------------- | +| `command` | string | Yes | Executable path or command (e.g. `npx`, `node`, `python`) | +| `args` | string[] | No | List of arguments passed to the command | +| `env` | object | No | Environment variables passed to the MCP server process | > When `command` is `npx`, Deep Code automatically prepends `-y` to the arguments. @@ -170,6 +170,7 @@ Environment variables are a common way to configure applications, especially for Environment variable priority follows the logic of “the more specific and localized the configuration, the higher the priority”, and the override rule of “env files protect existing environment by default, system variables override env files”. (The `env` object in settings.json can be thought of as a type of env file.) Priority levels (from lowest to highest): + 1. `env` defined at the top level of `settings.json` – this is a general configuration for the entire tool and all its subprocesses (global variables). Can be overridden by outer environment variables, but the environment variable KEY has the `DEEPCODE_` prefix removed. 2. `env` defined inside `mcpServers` in `settings.json` – this is the most specific configuration for a particular MCP service (local variables). Can be overridden by outer environment variables, but the KEY has the `MCP_` prefix removed. 3. Shell/system environment variables – operating system level. diff --git a/templates/skills/bundled/deepcode-self-refer/references/mcp.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/mcp.md similarity index 100% rename from templates/skills/bundled/deepcode-self-refer/references/mcp.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/mcp.md diff --git a/templates/skills/bundled/deepcode-self-refer/references/mcp_en.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/mcp_en.md similarity index 96% rename from templates/skills/bundled/deepcode-self-refer/references/mcp_en.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/mcp_en.md index 03c4b30c..7933db6a 100644 --- a/templates/skills/bundled/deepcode-self-refer/references/mcp_en.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/references/mcp_en.md @@ -41,11 +41,11 @@ Edit `~/.deepcode/settings.json` and add the `mcpServers` field: ### Configuration Fields -| Field | Type | Required | Description | -| --------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Field | Type | Required | Description | +| --------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `command` | string | Yes | Path or command of the MCP server executable (e.g., `npx`, `node`, `python`). When the command is `npx`, Deep Code automatically prepends `-y` to the arguments. | -| `args` | string[] | No | List of arguments to pass to the command | -| `env` | object | No | Environment variables (e.g., API keys) to pass to the MCP server process | +| `args` | string[] | No | List of arguments to pass to the command | +| `env` | object | No | Environment variables (e.g., API keys) to pass to the MCP server process | ## Common MCP Examples @@ -160,12 +160,12 @@ The AI will automatically invoke the `mcp__github__search_issues` tool to comple An MCP tool name consists of three parts: `mcp____` -| Service | Tool Name | Full Invocation Name | -| ---------- | ----------------------- | ------------------------------------------- | -| github | search_code | `mcp__github__search_code` | -| github | create_pull_request | `mcp__github__create_pull_request` | -| playwright | browser_navigate | `mcp__playwright__browser_navigate` | -| playwright | browser_take_screenshot | `mcp__playwright__browser_take_screenshot` | +| Service | Tool Name | Full Invocation Name | +| ---------- | ----------------------- | ------------------------------------------ | +| github | search_code | `mcp__github__search_code` | +| github | create_pull_request | `mcp__github__create_pull_request` | +| playwright | browser_navigate | `mcp__playwright__browser_navigate` | +| playwright | browser_take_screenshot | `mcp__playwright__browser_take_screenshot` | You can view the list of tools provided by each server using `/mcp`. @@ -197,4 +197,4 @@ MCP servers follow the [Model Context Protocol](https://modelcontextprotocol.io/ 2. `tools/list` — Return the list of available tools 3. `tools/call` — Execute a tool call -For more information, see the [official MCP documentation](https://modelcontextprotocol.io/). \ No newline at end of file +For more information, see the [official MCP documentation](https://modelcontextprotocol.io/). diff --git a/templates/skills/bundled/deepcode-self-refer/references/notify.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/notify.md similarity index 91% rename from templates/skills/bundled/deepcode-self-refer/references/notify.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/notify.md index d73eef45..553722f3 100644 --- a/templates/skills/bundled/deepcode-self-refer/references/notify.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/references/notify.md @@ -8,13 +8,13 @@ ## 注入的环境变量 -| 环境变量 | 说明 | -|----------|------| -| `DURATION` | 会话耗时,单位秒(整数) | -| `STATUS` | 会话状态:`"completed"` 或 `"failed"` | -| `FAIL_REASON` | 失败原因(仅失败时设置) | -| `BODY` | 最后一条 AI 助手回复的文本内容 | -| `TITLE` | 会话标题(对应 resume 列表中的标题) | +| 环境变量 | 说明 | +| ------------- | ------------------------------------- | +| `DURATION` | 会话耗时,单位秒(整数) | +| `STATUS` | 会话状态:`"completed"` 或 `"failed"` | +| `FAIL_REASON` | 失败原因(仅失败时设置) | +| `BODY` | 最后一条 AI 助手回复的文本内容 | +| `TITLE` | 会话标题(对应 resume 列表中的标题) | ## 配置方法 diff --git a/templates/skills/bundled/deepcode-self-refer/references/notify_en.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/notify_en.md similarity index 91% rename from templates/skills/bundled/deepcode-self-refer/references/notify_en.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/notify_en.md index b949161c..90fcf706 100644 --- a/templates/skills/bundled/deepcode-self-refer/references/notify_en.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/references/notify_en.md @@ -8,13 +8,13 @@ Configure the `notify` field in `settings.json` with the full path to an executa ## Injected Environment Variables -| Variable | Description | -|----------|-------------| -| `DURATION` | Session duration in seconds (integer) | -| `STATUS` | Session status: `"completed"` or `"failed"` | -| `FAIL_REASON` | Failure reason (only set on failure) | -| `BODY` | The text content of the last AI assistant reply | -| `TITLE` | Session title (matches the resume list title) | +| Variable | Description | +| ------------- | ----------------------------------------------- | +| `DURATION` | Session duration in seconds (integer) | +| `STATUS` | Session status: `"completed"` or `"failed"` | +| `FAIL_REASON` | Failure reason (only set on failure) | +| `BODY` | The text content of the last AI assistant reply | +| `TITLE` | Session title (matches the resume list title) | ## Configuration diff --git a/templates/skills/bundled/deepcode-self-refer/references/permission.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/permission.md similarity index 61% rename from templates/skills/bundled/deepcode-self-refer/references/permission.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/permission.md index 91c19c6f..e315c47c 100644 --- a/templates/skills/bundled/deepcode-self-refer/references/permission.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/references/permission.md @@ -14,18 +14,18 @@ Deep Code 内置了一套细粒度的权限控制机制,在 AI 助手执行工 Deep Code 定义了以下 10 种权限范围,覆盖了工具调用的各类风险场景: -| 权限范围 | 说明 | -| -------- | ---- | -| `read-in-cwd` | 读取当前工作区内的文件 | -| `read-out-cwd` | 读取当前工作区外的文件 | -| `write-in-cwd` | 在当前工作区内创建或覆写文件 | -| `write-out-cwd` | 在当前工作区外创建或覆写文件 | -| `delete-in-cwd` | 删除当前工作区内的文件 | -| `delete-out-cwd` | 删除当前工作区外的文件 | -| `query-git-log` | 查询 Git 历史(如 `git log`、`git show`、`git blame`) | +| 权限范围 | 说明 | +| ---------------- | --------------------------------------------------------- | +| `read-in-cwd` | 读取当前工作区内的文件 | +| `read-out-cwd` | 读取当前工作区外的文件 | +| `write-in-cwd` | 在当前工作区内创建或覆写文件 | +| `write-out-cwd` | 在当前工作区外创建或覆写文件 | +| `delete-in-cwd` | 删除当前工作区内的文件 | +| `delete-out-cwd` | 删除当前工作区外的文件 | +| `query-git-log` | 查询 Git 历史(如 `git log`、`git show`、`git blame`) | | `mutate-git-log` | 修改 Git 历史(如 `git commit`、`git rebase`、`git tag`) | -| `network` | 访问网络(如 `curl`、`npm install` 等联网操作) | -| `mcp` | 调用 MCP 外部工具 | +| `network` | 访问网络(如 `curl`、`npm install` 等联网操作) | +| `mcp` | 调用 MCP 外部工具 | 此外还有一个特殊的 `unknown` 范围,当 LLM 无法准确分类命令的副作用时使用,**`unknown` 总是触发询问**。 @@ -46,11 +46,11 @@ Deep Code 定义了以下 10 种权限范围,覆盖了工具调用的各类风 ### 配置项说明 -| 字段 | 类型 | 说明 | -| ---- | ---- | ---- | -| `allow` | `string[]` | 始终自动放行的权限范围列表 | -| `deny` | `string[]` | 始终自动拒绝的权限范围列表 | -| `ask` | `string[]` | 始终弹出询问的权限范围列表 | +| 字段 | 类型 | 说明 | +| ------------- | -------------------------- | --------------------------------------------------------------------------------- | +| `allow` | `string[]` | 始终自动放行的权限范围列表 | +| `deny` | `string[]` | 始终自动拒绝的权限范围列表 | +| `ask` | `string[]` | 始终弹出询问的权限范围列表 | | `defaultMode` | `"allowAll"` \| `"askAll"` | 未在 `allow`/`deny`/`ask` 中明确列出的权限范围的默认处理方式。默认为 `"allowAll"` | ### 优先级规则 @@ -86,10 +86,10 @@ Deep Code 定义了以下 10 种权限范围,覆盖了工具调用的各类风 ``` 此配置的效果: + - 工作区内读写、Git 查询 → 自动放行 - 其他操作都需要用户确认。 - ## 持久化机制 当用户在权限提示中选择 "Yes, and always allow" 后,对应的权限范围会被写入当前项目的 `.deepcode/settings.json` 文件中: diff --git a/templates/skills/bundled/deepcode-self-refer/references/permission_en.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/permission_en.md similarity index 64% rename from templates/skills/bundled/deepcode-self-refer/references/permission_en.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/permission_en.md index dae739c0..1298a1d6 100644 --- a/templates/skills/bundled/deepcode-self-refer/references/permission_en.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/references/permission_en.md @@ -14,18 +14,18 @@ Each time the AI assistant invokes a tool, the system automatically analyzes the Deep Code defines the following 10 permission scopes, covering various risk scenarios for tool calls: -| Permission Scope | Description | -| ---------------- | ----------- | -| `read-in-cwd` | Read files inside the current workspace | -| `read-out-cwd` | Read files outside the current workspace | -| `write-in-cwd` | Create or overwrite files inside the current workspace | -| `write-out-cwd` | Create or overwrite files outside the current workspace | -| `delete-in-cwd` | Delete files inside the current workspace | -| `delete-out-cwd` | Delete files outside the current workspace | -| `query-git-log` | Query Git history (e.g., `git log`, `git show`, `git blame`) | +| Permission Scope | Description | +| ---------------- | ---------------------------------------------------------------- | +| `read-in-cwd` | Read files inside the current workspace | +| `read-out-cwd` | Read files outside the current workspace | +| `write-in-cwd` | Create or overwrite files inside the current workspace | +| `write-out-cwd` | Create or overwrite files outside the current workspace | +| `delete-in-cwd` | Delete files inside the current workspace | +| `delete-out-cwd` | Delete files outside the current workspace | +| `query-git-log` | Query Git history (e.g., `git log`, `git show`, `git blame`) | | `mutate-git-log` | Mutate Git history (e.g., `git commit`, `git rebase`, `git tag`) | -| `network` | Access the network (e.g., `curl`, `npm install`) | -| `mcp` | Invoke MCP external tools | +| `network` | Access the network (e.g., `curl`, `npm install`) | +| `mcp` | Invoke MCP external tools | There is also a special `unknown` scope used when the LLM cannot classify a command's side effects — **`unknown` always triggers a prompt**. @@ -46,11 +46,11 @@ Configure permissions in `~/.deepcode/settings.json` (user-level) or `.deepcode/ ### Configuration Fields -| Field | Type | Description | -| ----- | ---- | ----------- | -| `allow` | `string[]` | Permission scopes that are always auto-allowed | -| `deny` | `string[]` | Permission scopes that are always auto-denied | -| `ask` | `string[]` | Permission scopes that always trigger a confirmation prompt | +| Field | Type | Description | +| ------------- | -------------------------- | --------------------------------------------------------------------------------------------------- | +| `allow` | `string[]` | Permission scopes that are always auto-allowed | +| `deny` | `string[]` | Permission scopes that are always auto-denied | +| `ask` | `string[]` | Permission scopes that always trigger a confirmation prompt | | `defaultMode` | `"allowAll"` \| `"askAll"` | Default behavior for scopes not explicitly listed in `allow`/`deny`/`ask`. Defaults to `"allowAll"` | ### Priority Rules @@ -86,6 +86,7 @@ Default behavior: all operations are auto-allowed with no confirmation required. ``` With this configuration: + - Reading/writing inside the workspace and querying Git history → auto-allowed - All other operations → require user confirmation diff --git a/templates/skills/bundled/deepcode-self-refer/references/session-persistence.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/session-persistence.md similarity index 75% rename from templates/skills/bundled/deepcode-self-refer/references/session-persistence.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/session-persistence.md index 835d2881..1c629e4d 100644 --- a/templates/skills/bundled/deepcode-self-refer/references/session-persistence.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/references/session-persistence.md @@ -14,11 +14,11 @@ Deep Code 会把每个项目的会话记录保存在本机用户目录中。会 项目存储目录包含以下主要文件和目录: -| 路径 | 说明 | -| ---- | ---- | +| 路径 | 说明 | +| --------------------- | ------------------------------------------------------ | | `sessions-index.json` | 当前项目的会话索引,保存会话列表和每个会话的概要信息。 | -| `.jsonl` | 单个会话的消息记录。每一行是一条 JSON 格式的消息。 | -| `file-history/.git` | 用于代码快照的内部 Git 仓库,供 `/undo` 恢复文件内容。 | +| `.jsonl` | 单个会话的消息记录。每一行是一条 JSON 格式的消息。 | +| `file-history/.git` | 用于代码快照的内部 Git 仓库,供 `/undo` 恢复文件内容。 | ## 持久化内容 @@ -38,18 +38,18 @@ Deep Code 会把每个项目的会话记录保存在本机用户目录中。会 每个会话有一个独立的 JSONL 消息文件,文件名是 `.jsonl`。消息按追加顺序写入,常见字段包括: -| 字段 | 说明 | -| ---- | ---- | -| `id` | 消息 ID。 | -| `sessionId` | 所属会话 ID。 | -| `role` | 消息角色:`system`、`user`、`assistant` 或 `tool`。 | -| `content` | 文本内容。 | -| `contentParams` | 结构化内容,例如图片输入。 | -| `messageParams` | 模型消息参数,例如 tool call ID、tool calls、reasoning content。 | -| `visible` | 是否在界面中显示。 | -| `compacted` | 是否已经被长会话压缩替代。 | -| `checkpointHash` | 与 `/undo` 关联的代码快照哈希。 | -| `meta` | 工具展示、skill、权限、摘要等附加信息。 | +| 字段 | 说明 | +| ---------------- | ---------------------------------------------------------------- | +| `id` | 消息 ID。 | +| `sessionId` | 所属会话 ID。 | +| `role` | 消息角色:`system`、`user`、`assistant` 或 `tool`。 | +| `content` | 文本内容。 | +| `contentParams` | 结构化内容,例如图片输入。 | +| `messageParams` | 模型消息参数,例如 tool call ID、tool calls、reasoning content。 | +| `visible` | 是否在界面中显示。 | +| `compacted` | 是否已经被长会话压缩替代。 | +| `checkpointHash` | 与 `/undo` 关联的代码快照哈希。 | +| `meta` | 工具展示、skill、权限、摘要等附加信息。 | 读取消息文件时,Deep Code 会逐行解析 JSON;无法解析的行会被忽略,以便尽量保留其余可用历史。 @@ -113,11 +113,11 @@ Deep Code 使用 `file-history/.git` 保存代码快照。这个仓库只作为 根据选择,Deep Code 可以执行以下操作: -| 操作 | 行为 | -| ---- | ---- | +| 操作 | 行为 | +| -------- | ------------------------------------------------------------------- | | 恢复对话 | 截断所选用户消息之前的消息历史,并更新索引中的最新 assistant 信息。 | -| 恢复代码 | 从 `file-history/.git` 中读取所选快照,并还原被跟踪文件。 | -| 同时恢复 | 先恢复代码,再截断对话历史。 | +| 恢复代码 | 从 `file-history/.git` 中读取所选快照,并还原被跟踪文件。 | +| 同时恢复 | 先恢复代码,再截断对话历史。 | 恢复对话会重写该会话的 JSONL 文件;恢复代码会修改工作区中被快照跟踪的文件。 diff --git a/templates/skills/bundled/deepcode-self-refer/references/session-persistence_en.md b/packages/core/templates/skills/bundled/deepcode-self-refer/references/session-persistence_en.md similarity index 72% rename from templates/skills/bundled/deepcode-self-refer/references/session-persistence_en.md rename to packages/core/templates/skills/bundled/deepcode-self-refer/references/session-persistence_en.md index 071a5353..865bf04b 100644 --- a/templates/skills/bundled/deepcode-self-refer/references/session-persistence_en.md +++ b/packages/core/templates/skills/bundled/deepcode-self-refer/references/session-persistence_en.md @@ -14,11 +14,11 @@ Each project has its own storage directory: The project storage directory contains these main files and directories: -| Path | Description | -| ---- | ----------- | +| Path | Description | +| --------------------- | --------------------------------------------------------------------------------------- | | `sessions-index.json` | Session index for the current project, including the session list and summary metadata. | -| `.jsonl` | Message log for one session. Each line is one JSON message. | -| `file-history/.git` | Internal Git repository used for code checkpoints restored by `/undo`. | +| `.jsonl` | Message log for one session. Each line is one JSON message. | +| `file-history/.git` | Internal Git repository used for code checkpoints restored by `/undo`. | ## Persisted Data @@ -38,18 +38,18 @@ The default session title comes from the first 100 characters of the first user Each session has a separate JSONL message file named `.jsonl`. Messages are appended in order. Common fields include: -| Field | Description | -| ----- | ----------- | -| `id` | Message ID. | -| `sessionId` | Owning session ID. | -| `role` | Message role: `system`, `user`, `assistant`, or `tool`. | -| `content` | Text content. | -| `contentParams` | Structured content, such as image input. | -| `messageParams` | Model message parameters, such as tool call IDs, tool calls, and reasoning content. | -| `visible` | Whether the message is shown in the UI. | -| `compacted` | Whether the message has been replaced by long-session compaction. | -| `checkpointHash` | Code checkpoint hash associated with `/undo`. | -| `meta` | Extra metadata for tool display, skills, permissions, summaries, and related features. | +| Field | Description | +| ---------------- | -------------------------------------------------------------------------------------- | +| `id` | Message ID. | +| `sessionId` | Owning session ID. | +| `role` | Message role: `system`, `user`, `assistant`, or `tool`. | +| `content` | Text content. | +| `contentParams` | Structured content, such as image input. | +| `messageParams` | Model message parameters, such as tool call IDs, tool calls, and reasoning content. | +| `visible` | Whether the message is shown in the UI. | +| `compacted` | Whether the message has been replaced by long-session compaction. | +| `checkpointHash` | Code checkpoint hash associated with `/undo`. | +| `meta` | Extra metadata for tool display, skills, permissions, summaries, and related features. | When loading a message file, Deep Code parses JSON one line at a time. Malformed lines are ignored so the remaining usable history can still be loaded. @@ -113,11 +113,11 @@ These states are persisted in `sessions-index.json`, so they remain visible in t Depending on the selected mode, Deep Code can perform these operations: -| Operation | Behavior | -| --------- | -------- | +| Operation | Behavior | +| -------------------- | -------------------------------------------------------------------------------------------------------------- | | Restore conversation | Truncates message history before the selected user message and updates the latest assistant data in the index. | -| Restore code | Reads the selected checkpoint from `file-history/.git` and restores tracked files. | -| Restore both | Restores code first, then truncates the conversation history. | +| Restore code | Reads the selected checkpoint from `file-history/.git` and restores tracked files. | +| Restore both | Restores code first, then truncates the conversation history. | Restoring conversation rewrites the session JSONL file. Restoring code modifies workspace files tracked by the selected checkpoint. diff --git a/templates/skills/bundled/plan/SKILL.md b/packages/core/templates/skills/bundled/plan/SKILL.md similarity index 78% rename from templates/skills/bundled/plan/SKILL.md rename to packages/core/templates/skills/bundled/plan/SKILL.md index b73c1abc..41c43013 100644 --- a/templates/skills/bundled/plan/SKILL.md +++ b/packages/core/templates/skills/bundled/plan/SKILL.md @@ -5,7 +5,7 @@ description: Plan tasks through a strict non-mutating collaboration workflow bef # Plan Mode (Conversational) -You work in 3 phases, and you should *chat your way* to a great plan before finalizing it. A great plan is very detailed—intent- and implementation-wise—so that it can be handed to another engineer or agent to be implemented right away. It must be **decision complete**, where the implementer does not need to make any decisions. +You work in 3 phases, and you should _chat your way_ to a great plan before finalizing it. A great plan is very detailed—intent- and implementation-wise—so that it can be handed to another engineer or agent to be implemented right away. It must be **decision complete**, where the implementer does not need to make any decisions. ## Mode rules (strict) @@ -27,19 +27,19 @@ You may explore and execute **non-mutating** actions that improve the plan. You Actions that gather truth, reduce ambiguity, or validate feasibility without changing repo-tracked state. Examples: -* Reading or searching files, configs, schemas, types, manifests, and docs -* Static analysis, inspection, and repo exploration -* Dry-run style commands when they do not edit repo-tracked files -* Tests, builds, or checks that may write to caches or build artifacts (for example, `target/`, `.cache/`, or snapshots) so long as they do not edit repo-tracked files +- Reading or searching files, configs, schemas, types, manifests, and docs +- Static analysis, inspection, and repo exploration +- Dry-run style commands when they do not edit repo-tracked files +- Tests, builds, or checks that may write to caches or build artifacts (for example, `target/`, `.cache/`, or snapshots) so long as they do not edit repo-tracked files ### Not allowed (mutating, plan-executing) Actions that implement the plan or change repo-tracked state. Examples: -* Editing or writing files -* Running formatters or linters that rewrite files -* Applying patches, migrations, or codegen that updates repo-tracked files -* Side-effectful commands whose purpose is to carry out the plan rather than refine it +- Editing or writing files +- Running formatters or linters that rewrite files +- Applying patches, migrations, or codegen that updates repo-tracked files +- Side-effectful commands whose purpose is to carry out the plan rather than refine it When in doubt: if the action would reasonably be described as "doing the work" rather than "planning the work," do not do it. @@ -55,27 +55,27 @@ Do not ask questions that can be answered from the repo or system (for example, ## PHASE 2 — Intent chat (what they actually want) -* Keep asking until you can clearly state: goal + success criteria, audience, in/out of scope, constraints, current state, and the key preferences/tradeoffs. -* Bias toward questions over guessing: if any high-impact ambiguity remains, do NOT plan yet—ask. +- Keep asking until you can clearly state: goal + success criteria, audience, in/out of scope, constraints, current state, and the key preferences/tradeoffs. +- Bias toward questions over guessing: if any high-impact ambiguity remains, do NOT plan yet—ask. ## PHASE 3 — Implementation chat (what/how we’ll build) -* Once intent is stable, keep asking until the spec is decision complete: approach, interfaces (APIs/schemas/I/O), data flow, edge cases/failure modes, testing + acceptance criteria, rollout/monitoring, and any migrations/compat constraints. +- Once intent is stable, keep asking until the spec is decision complete: approach, interfaces (APIs/schemas/I/O), data flow, edge cases/failure modes, testing + acceptance criteria, rollout/monitoring, and any migrations/compat constraints. ## Asking questions Critical rules: -* Strongly prefer using the `AskUserQuestion` tool to ask any questions. -* Offer only meaningful multiple‑choice options; don’t include filler choices that are obviously wrong or irrelevant. -* In rare cases where an unavoidable, important question can’t be expressed with reasonable multiple‑choice options (due to extreme ambiguity), you may ask it directly without the tool. +- Strongly prefer using the `AskUserQuestion` tool to ask any questions. +- Offer only meaningful multiple‑choice options; don’t include filler choices that are obviously wrong or irrelevant. +- In rare cases where an unavoidable, important question can’t be expressed with reasonable multiple‑choice options (due to extreme ambiguity), you may ask it directly without the tool. You SHOULD ask many questions, but each question must: -* materially change the spec/plan, OR -* confirm/lock an assumption, OR -* choose between meaningful tradeoffs. -* not be answerable by non-mutating commands. +- materially change the spec/plan, OR +- confirm/lock an assumption, OR +- choose between meaningful tradeoffs. +- not be answerable by non-mutating commands. Use the `AskUserQuestion` tool only for decisions that materially change the plan, for confirming important assumptions, or for information that cannot be discovered via non-mutating exploration. Ask one question at a time when possible, provide concrete options with `label` and optional `description`, and use `multiSelect` only when multiple choices can be combined. @@ -83,16 +83,16 @@ Use the `AskUserQuestion` tool only for decisions that materially change the pla 1. **Discoverable facts** (repo/system truth): explore first. - * Before asking, run targeted searches and check likely sources of truth (configs/manifests/entrypoints/schemas/types/constants). - * Ask only if: multiple plausible candidates; nothing found but you need a missing identifier/context; or ambiguity is actually product intent. - * If asking, present concrete candidates (paths/service names) + recommend one. - * Never ask questions you can answer from your environment (e.g., “where is this struct”). + - Before asking, run targeted searches and check likely sources of truth (configs/manifests/entrypoints/schemas/types/constants). + - Ask only if: multiple plausible candidates; nothing found but you need a missing identifier/context; or ambiguity is actually product intent. + - If asking, present concrete candidates (paths/service names) + recommend one. + - Never ask questions you can answer from your environment (e.g., “where is this struct”). 2. **Preferences/tradeoffs** (not discoverable): ask early. - * These are intent or implementation preferences that cannot be derived from exploration. - * Provide 2–4 mutually exclusive options + a recommended default. - * If unanswered, proceed with the recommended option and record it as an assumption in the final plan. + - These are intent or implementation preferences that cannot be derived from exploration. + - Provide 2–4 mutually exclusive options + a recommended default. + - If unanswered, proceed with the recommended option and record it as an assumption in the final plan. ## Finalization rule @@ -100,11 +100,11 @@ Only output the final plan when it is decision complete and leaves no decisions When you present the official plan, wrap it in a `` block so the client can render it specially: -1) The opening tag must be on its own line. -2) Start the plan content on the next line (no text on the same line as the tag). -3) The closing tag must be on its own line. -4) Use Markdown inside the block. -5) Keep the tags exactly as `` and `` (do not translate or rename them), even if the plan content is in another language. +1. The opening tag must be on its own line. +2. Start the plan content on the next line (no text on the same line as the tag). +3. The closing tag must be on its own line. +4. Use Markdown inside the block. +5. Keep the tags exactly as `` and `` (do not translate or rename them), even if the plan content is in another language. Example: @@ -114,11 +114,11 @@ plan content plan content should be human and agent digestible. The final plan must be plan-only, concise by default, and include: -* A clear title -* A brief summary section -* Important changes or additions to public APIs/interfaces/types -* Test cases and scenarios -* Explicit assumptions and defaults chosen where needed +- A clear title +- A brief summary section +- Important changes or additions to public APIs/interfaces/types +- Test cases and scenarios +- Explicit assumptions and defaults chosen where needed When possible, prefer a compact structure with 3-5 short sections, usually: Summary, Key Changes or Implementation Changes, Test Plan, and Assumptions. Do not include a separate Scope section unless scope boundaries are genuinely important to avoid mistakes. diff --git a/templates/skills/bundled/skill-digester/SKILL.md b/packages/core/templates/skills/bundled/skill-digester/SKILL.md similarity index 89% rename from templates/skills/bundled/skill-digester/SKILL.md rename to packages/core/templates/skills/bundled/skill-digester/SKILL.md index 6e9016d1..3bef806b 100644 --- a/templates/skills/bundled/skill-digester/SKILL.md +++ b/packages/core/templates/skills/bundled/skill-digester/SKILL.md @@ -22,6 +22,7 @@ Whenever user input is needed, call the `AskUserQuestion` tool. Do not ask follo ``` If this skill is loaded from a project-level or different user-level path, use the `scripts/find-skill.js` file next to this `SKILL.md` instead. + - The script searches the same roots Deep Code CLI scans, in priority order: 1. Project native skills: `./.deepcode/skills//SKILL.md` 2. Project interoperable skills: `./.agents/skills//SKILL.md` @@ -89,11 +90,35 @@ Use one question at a time unless two decisions are tightly coupled. Each questi Examples: ```json -{"questions":[{"question":"请选择您偏好的语言。","options":[{"label":"中文","description":"后续询问和推荐描述都使用中文。"},{"label":"English","description":"Use English for follow-up questions and the recommended description."}]}]} +{ + "questions": [ + { + "question": "请选择您偏好的语言。", + "options": [ + { "label": "中文", "description": "后续询问和推荐描述都使用中文。" }, + { "label": "English", "description": "Use English for follow-up questions and the recommended description." } + ] + } + ] +} ``` ```json -{"questions":[{"question":"How should I proceed with this description recommendation?","options":[{"label":"Apply change","description":"Update only the description field in the native digest output SKILL.md."},{"label":"Abandon change","description":"Leave the file unchanged."},{"label":"Discuss wording","description":"Continue refining the proposed description before editing."}]}]} +{ + "questions": [ + { + "question": "How should I proceed with this description recommendation?", + "options": [ + { + "label": "Apply change", + "description": "Update only the description field in the native digest output SKILL.md." + }, + { "label": "Abandon change", "description": "Leave the file unchanged." }, + { "label": "Discuss wording", "description": "Continue refining the proposed description before editing." } + ] + } + ] +} ``` ## Review Heuristics @@ -112,4 +137,3 @@ Avoid descriptions that are only generic labels, marketing copy, or internal imp - Never save the digested output under `.agents/skills`; `.agents/skills` is only a source root for digestion. - Never move a skill between project and user level during digestion. - Never change the target skill's language preference after confirmation unless the user asks. - diff --git a/templates/skills/bundled/skill-digester/scripts/find-skill.js b/packages/core/templates/skills/bundled/skill-digester/scripts/find-skill.js similarity index 100% rename from templates/skills/bundled/skill-digester/scripts/find-skill.js rename to packages/core/templates/skills/bundled/skill-digester/scripts/find-skill.js diff --git a/templates/skills/bundled/skill-writer/SKILL.md b/packages/core/templates/skills/bundled/skill-writer/SKILL.md similarity index 99% rename from templates/skills/bundled/skill-writer/SKILL.md rename to packages/core/templates/skills/bundled/skill-writer/SKILL.md index 1a7801c3..ca2adc41 100644 --- a/templates/skills/bundled/skill-writer/SKILL.md +++ b/packages/core/templates/skills/bundled/skill-writer/SKILL.md @@ -10,6 +10,7 @@ This Skill helps you create well-structured Agent Skills for AI agents that foll ## When to use this Skill Use this Skill when: + - Creating a new Agent Skill - Writing or updating SKILL.md files - Designing skill structure and frontmatter @@ -37,11 +38,13 @@ First, understand what the Skill should do: Determine where to create the Skill: **Personal Skills** (`~/.agents/skills/`): + - Individual workflows and preferences - Experimental Skills - Personal productivity tools **Project Skills** (`.agents/skills/`): + - Team workflows and conventions - Project-specific expertise - Shared utilities (committed to git) @@ -59,6 +62,7 @@ mkdir -p .agents/skills/skill-name ``` For multi-file Skills: + ``` skill-name/ ├── SKILL.md (required) @@ -116,22 +120,26 @@ The description is critical for AI agents to discover your Skill. **Examples**: ✅ **Good**: + ```yaml description: Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction. ``` ✅ **Good**: + ```yaml description: Analyze Excel spreadsheets, create pivot tables, and generate charts. Use when working with Excel files, spreadsheets, or analyzing tabular data in .xlsx format. ``` ❌ **Too vague**: + ```yaml description: Helps with documents description: For data analysis ``` **Tips**: + - Include specific file extensions (.pdf, .xlsx, .json) - Mention common user phrases ("analyze", "extract", "generate") - List concrete operations (not generic verbs) @@ -141,7 +149,7 @@ description: For data analysis Use clear Markdown sections: -```markdown +````markdown # Skill Name Brief overview of what this Skill does. @@ -153,6 +161,7 @@ Provide a simple example to get started immediately. ## Instructions Step-by-step guidance for AI agents: + 1. First step with clear action 2. Second step with expected outcome 3. Handle edge cases @@ -170,14 +179,17 @@ Show concrete usage examples with code or commands. ## Requirements List any dependencies or prerequisites: + ```bash pip install package-name ``` +```` ## Advanced usage For complex scenarios, see [reference.md](reference.md). -``` + +```` ### Step 7: Add supporting files (optional) @@ -196,17 +208,19 @@ Run the helper script: \`\`\`bash python scripts/helper.py input.txt \`\`\` -``` +```` ### Step 8: Validate the Skill Check these requirements: ✅ **File structure**: + - [ ] SKILL.md exists in correct location - [ ] Directory name matches frontmatter `name` ✅ **YAML frontmatter**: + - [ ] Opening `---` on line 1 - [ ] Closing `---` before content - [ ] Valid YAML (no tabs, correct indentation) @@ -214,12 +228,14 @@ Check these requirements: - [ ] `description` is specific and < 1024 chars ✅ **Content quality**: + - [ ] Clear instructions for AI agents - [ ] Concrete examples provided - [ ] Edge cases handled - [ ] Dependencies listed (if any) ✅ **Testing**: + - [ ] Description matches user questions - [ ] Skill activates on relevant queries - [ ] Instructions are clear and actionable @@ -229,6 +245,7 @@ Check these requirements: 1. **Restart AI agents** (if running) to load the Skill 2. **Ask relevant questions** that match the description: + ``` Can you help me extract text from this PDF? ``` @@ -247,6 +264,7 @@ If AI agents doesn't use the Skill: - Mention common user phrases 2. **Check file location**: + ```bash ls ~/.agents/skills/skill-name/SKILL.md ls .agents/skills/skill-name/SKILL.md @@ -343,16 +361,19 @@ Before finalizing a Skill, verify: ## Troubleshooting **Skill doesn't activate**: + - Make description more specific with trigger words - Include file types and operations in description - Add "Use when..." clause with user phrases **Multiple Skills conflict**: + - Make descriptions more distinct - Use different trigger words - Narrow the scope of each Skill **Skill has errors**: + - Check YAML syntax (no tabs, proper indentation) - Verify file paths (use forward slashes) - Ensure scripts have execute permissions @@ -361,6 +382,7 @@ Before finalizing a Skill, verify: ## Examples See the documentation for complete examples: + - Simple single-file Skill (commit-helper) - Skill with tool permissions (code-reviewer) - Multi-file Skill (pdf-processing) @@ -378,4 +400,3 @@ When creating a Skill, I will: 7. Validate against all requirements The result will be a complete, working Skill that follows all best practices and validation rules. - diff --git a/templates/skills/karpathy-guidelines.md b/packages/core/templates/skills/karpathy-guidelines.md similarity index 97% rename from templates/skills/karpathy-guidelines.md rename to packages/core/templates/skills/karpathy-guidelines.md index 41e23d73..8f5d86bf 100644 --- a/templates/skills/karpathy-guidelines.md +++ b/packages/core/templates/skills/karpathy-guidelines.md @@ -14,6 +14,7 @@ Behavioral guidelines to reduce common LLM coding mistakes. **Don't assume. Don't hide confusion. Surface tradeoffs.** Before implementing: + - State your assumptions explicitly. If uncertain, ask. - If multiple interpretations exist, present them - don't pick silently. - If a simpler approach exists, say so. Push back when warranted. @@ -36,12 +37,14 @@ Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, sim **Touch only what you must. Clean up only your own mess.** When editing existing code: + - Don't "improve" adjacent code, comments, or formatting. - Don't refactor things that aren't broken. - Match existing style, even if you'd do it differently. - If you notice unrelated dead code, mention it - don't delete it. When your changes create orphans: + - Remove imports/variables/functions that YOUR changes made unused. - Don't remove pre-existing dead code unless asked. @@ -52,15 +55,17 @@ The test: Every changed line should trace directly to the user's request. **Define success criteria. Loop until verified.** Transform tasks into verifiable goals: + - "Add validation" → "Write tests for invalid inputs, then make them pass" - "Fix the bug" → "Write a test that reproduces it, then make it pass" - "Refactor X" → "Ensure tests pass before and after" For multi-step tasks, state a brief plan: + ``` 1. [Step] → verify: [check] 2. [Step] → verify: [check] 3. [Step] → verify: [check] ``` -Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. \ No newline at end of file +Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. diff --git a/templates/tools/ask-user-question.md b/packages/core/templates/tools/ask-user-question.md similarity index 99% rename from templates/tools/ask-user-question.md rename to packages/core/templates/tools/ask-user-question.md index 7e072982..bcf4ebcc 100644 --- a/templates/tools/ask-user-question.md +++ b/packages/core/templates/tools/ask-user-question.md @@ -1,12 +1,14 @@ ## AskUserQuestion Use this tool when you need to ask the user questions during execution. This allows you to: + 1. Gather user preferences or requirements 2. Clarify ambiguous instructions 3. Get decisions on implementation choices as you work 4. Offer choices to the user about what direction to take. Usage notes: + - Users will always be able to select "Other" to provide custom text input - Use multiSelect: true to allow multiple answers to be selected for a question - If you recommend a specific option, make that the first option in the list and add "(Recommended)" at the end of the label diff --git a/templates/tools/bash.md b/packages/core/templates/tools/bash.md similarity index 54% rename from templates/tools/bash.md rename to packages/core/templates/tools/bash.md index 12f52af3..c69d7cd0 100644 --- a/templates/tools/bash.md +++ b/packages/core/templates/tools/bash.md @@ -7,6 +7,7 @@ On Windows, Bash runs through Git Bash. Use POSIX commands and quote Windows pat IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead. IMPORTANT: Before reaching for generic shell pipelines, prefer purpose-built CLI tools when they make the task more accurate, safer, faster, or easier to understand: + - Use `ripgrep` (`rg`) when you need to search file contents by text or regex across the workspace; prefer it over slower tools like `grep`. - Use `jq` when you need to inspect, filter, or transform JSON output; prefer it over ad-hoc parsing with `sed`, `awk`, or Python one-liners. @@ -27,35 +28,36 @@ Before executing the command, please follow these steps: - Capture the output of the command. Usage notes: - - The command argument is required. - - The sideEffects argument is required. Declare the minimum permission scopes the command may need. - - You can use `run_in_background: true` to run a command in the background. Only use this if you need to perform a blocking task, like running a server for the upcoming test scripts. - - When using `run_in_background`, do NOT add `&` to the command. Output is written to a log file. - - Before your final response, stop background tasks that has not reported a completed state, unless the user explicitly asks to keep it running. - - To stop a background command, use the `stopCommand` returned in the tool result metadata. - - Use `sideEffects: []` only for commands that do not read, write, delete, query Git history, mutate Git history, or access the network, such as `date` or `node --version`. - - Use `*-out-cwd` when the command accesses paths outside the current workspace. For example, `cat /etc/hosts` requires `["read-out-cwd"]`. - - Use `query-git-log` for commands such as `git log`, `git show HEAD`, `git blame`, or history diffs. Use `mutate-git-log` for commands such as `git commit`, `git reset`, `git rebase`, `git merge`, `git cherry-pick`, or `git tag`. - - Use `["unknown"]` when you cannot classify the command safely. - - It is very helpful if you write a clear, concise description of what this command does. For simple commands, keep it brief (5-10 words). For complex commands (piped commands, obscure flags, or anything hard to understand at a glance), add enough context to clarify what it does. - - If the output exceeds 30000 characters, output will be truncated before being returned to you. - - Always prefer using the dedicated tools for these commands: - - Read files: Use Read (NOT cat/head/tail) - - Edit files: Use Edit (NOT sed/awk) - - Write files: Use Write (NOT echo >/cat < - pytest /foo/bar/tests - - - cd /foo/bar && pytest tests - + +- The command argument is required. +- The sideEffects argument is required. Declare the minimum permission scopes the command may need. +- You can use `run_in_background: true` to run a command in the background. Only use this if you need to perform a blocking task, like running a server for the upcoming test scripts. +- When using `run_in_background`, do NOT add `&` to the command. Output is written to a log file. +- Before your final response, stop background tasks that has not reported a completed state, unless the user explicitly asks to keep it running. +- To stop a background command, use the `stopCommand` returned in the tool result metadata. +- Use `sideEffects: []` only for commands that do not read, write, delete, query Git history, mutate Git history, or access the network, such as `date` or `node --version`. +- Use `*-out-cwd` when the command accesses paths outside the current workspace. For example, `cat /etc/hosts` requires `["read-out-cwd"]`. +- Use `query-git-log` for commands such as `git log`, `git show HEAD`, `git blame`, or history diffs. Use `mutate-git-log` for commands such as `git commit`, `git reset`, `git rebase`, `git merge`, `git cherry-pick`, or `git tag`. +- Use `["unknown"]` when you cannot classify the command safely. +- It is very helpful if you write a clear, concise description of what this command does. For simple commands, keep it brief (5-10 words). For complex commands (piped commands, obscure flags, or anything hard to understand at a glance), add enough context to clarify what it does. +- If the output exceeds 30000 characters, output will be truncated before being returned to you. +- Always prefer using the dedicated tools for these commands: + - Read files: Use Read (NOT cat/head/tail) + - Edit files: Use Edit (NOT sed/awk) + - Write files: Use Write (NOT echo >/cat < + pytest /foo/bar/tests + + + cd /foo/bar && pytest tests + ```json { @@ -95,10 +97,7 @@ Usage notes: "type": "boolean" } }, - "required": [ - "command", - "sideEffects" - ], + "required": ["command", "sideEffects"], "additionalProperties": false } ``` diff --git a/templates/tools/edit.md b/packages/core/templates/tools/edit.md similarity index 97% rename from templates/tools/edit.md rename to packages/core/templates/tools/edit.md index efa8574d..4f039127 100644 --- a/templates/tools/edit.md +++ b/packages/core/templates/tools/edit.md @@ -3,6 +3,7 @@ Performs scoped string replacements in files. Usage: + - You must use `Read` tool at least once in the conversation before editing to get the required `snippet_id`. This tool will error if you attempt an edit without reading the file. - `snippet_id` defines the search scope. Provide `file_path` only as an optional guard that the snippet belongs to the expected file. - When editing text from Read tool output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. The line number prefix format is: spaces + line number + tab. Everything after that tab is the actual file content to match. Never include any part of the line number prefix in the old_string or new_string. @@ -43,11 +44,7 @@ Usage: "type": "number" } }, - "required": [ - "snippet_id", - "old_string", - "new_string" - ], + "required": ["snippet_id", "old_string", "new_string"], "additionalProperties": false } ``` diff --git a/templates/tools/read.md.ejs b/packages/core/templates/tools/read.md.ejs similarity index 100% rename from templates/tools/read.md.ejs rename to packages/core/templates/tools/read.md.ejs diff --git a/templates/tools/update-plan.md b/packages/core/templates/tools/update-plan.md similarity index 97% rename from templates/tools/update-plan.md rename to packages/core/templates/tools/update-plan.md index 0c74b367..9459242e 100644 --- a/templates/tools/update-plan.md +++ b/packages/core/templates/tools/update-plan.md @@ -3,6 +3,7 @@ Updates the current task plan and progress display. Usage: + - Use this tool for non-trivial multi-step tasks when a task list helps track execution progress. - Pass the complete current task list every time. The latest call replaces the previous visible plan. - The `plan` argument is a markdown string, not an array of step objects. If the requirement is in Chinese, then use Chinese for the markdown as well. @@ -25,9 +26,7 @@ Usage: "type": "string" } }, - "required": [ - "plan" - ], + "required": ["plan"], "additionalProperties": false } ``` diff --git a/templates/tools/web-search.md b/packages/core/templates/tools/web-search.md similarity index 99% rename from templates/tools/web-search.md rename to packages/core/templates/tools/web-search.md index 92e22753..e5eabf0f 100644 --- a/templates/tools/web-search.md +++ b/packages/core/templates/tools/web-search.md @@ -19,9 +19,11 @@ JSON schema: ``` Usage: + - Do not reduce `query` to space-separated keywords. Typical use cases: + - Confirm recent SDK, framework, or API changes - Check current compatibility, deprecations, or migration notes - Look up active issue tracker discussions or recent regressions diff --git a/templates/tools/write.md b/packages/core/templates/tools/write.md similarity index 86% rename from templates/tools/write.md rename to packages/core/templates/tools/write.md index 1a969754..ce774eb3 100644 --- a/templates/tools/write.md +++ b/packages/core/templates/tools/write.md @@ -3,12 +3,13 @@ Writes a file to the local filesystem. Usage: + - This tool will overwrite the existing file if there is one at the provided path. - If this is an existing file, you MUST read the full file first. A partial read is not enough for overwriting an existing file. - `content` must be a single string. If you are writing JSON, serialize the full document to text before calling this tool. - Prefer `Edit` for updating existing files. Use `Write` for new files or intentional full-file rewrites. - ALWAYS prefer editing existing files in the codebase. NEVER write new files unless explicitly required. -- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User. +- NEVER proactively create documentation files (\*.md) or README files. Only create documentation files if explicitly requested by the User. - NEVER proactively create one-off test script. Only create one-off test script files if explicitly requested by the User. - Only use emojis if the user explicitly requests it. Avoid writing emojis to files unless asked. @@ -26,10 +27,7 @@ Usage: "type": "string" } }, - "required": [ - "file_path", - "content" - ], + "required": ["file_path", "content"], "additionalProperties": false } ``` diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json new file mode 100644 index 00000000..ac00d953 --- /dev/null +++ b/packages/core/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ES2022"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "composite": true, + "declaration": true, + "declarationMap": true, + "outDir": "./dist", + "rootDir": "./src", + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist", "src/tests"] +} diff --git a/packages/core/tsconfig.tsbuildinfo b/packages/core/tsconfig.tsbuildinfo new file mode 100644 index 00000000..5bef9a8e --- /dev/null +++ b/packages/core/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["../../node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/typescript/lib/lib.es2021.d.ts","../../node_modules/typescript/lib/lib.es2022.d.ts","../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../node_modules/typescript/lib/lib.es2025.float16.d.ts","../../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","./src/common/model-capabilities.ts","./src/settings.ts","../../node_modules/gray-matter/gray-matter.d.ts","../../node_modules/@types/ejs/index.d.ts","../../node_modules/openai/internal/builtin-types.d.mts","../../node_modules/openai/internal/types.d.mts","../../node_modules/openai/internal/headers.d.mts","../../node_modules/openai/internal/shim-types.d.mts","../../node_modules/openai/core/streaming.d.mts","../../node_modules/openai/internal/request-options.d.mts","../../node_modules/openai/internal/utils/log.d.mts","../../node_modules/openai/resources/shared.d.mts","../../node_modules/openai/core/error.d.mts","../../node_modules/openai/pagination.d.mts","../../node_modules/openai/internal/parse.d.mts","../../node_modules/openai/core/api-promise.d.mts","../../node_modules/openai/core/pagination.d.mts","../../node_modules/openai/auth/types.d.mts","../../node_modules/openai/internal/uploads.d.mts","../../node_modules/openai/internal/to-file.d.mts","../../node_modules/openai/core/uploads.d.mts","../../node_modules/openai/resources/chat/chat.d.mts","../../node_modules/openai/resources/chat/index.d.mts","../../node_modules/openai/resources/admin/organization/admin-api-keys.d.mts","../../node_modules/openai/resources/admin/organization/audit-logs.d.mts","../../node_modules/openai/resources/admin/organization/certificates.d.mts","../../node_modules/openai/resources/admin/organization/data-retention.d.mts","../../node_modules/openai/resources/admin/organization/invites.d.mts","../../node_modules/openai/resources/admin/organization/roles.d.mts","../../node_modules/openai/resources/admin/organization/spend-alerts.d.mts","../../node_modules/openai/resources/admin/organization/usage.d.mts","../../node_modules/openai/resources/admin/organization/groups/roles.d.mts","../../node_modules/openai/resources/admin/organization/groups/users.d.mts","../../node_modules/openai/resources/admin/organization/groups/groups.d.mts","../../node_modules/openai/resources/admin/organization/projects/api-keys.d.mts","../../node_modules/openai/resources/admin/organization/projects/certificates.d.mts","../../node_modules/openai/resources/admin/organization/projects/data-retention.d.mts","../../node_modules/openai/resources/admin/organization/projects/hosted-tool-permissions.d.mts","../../node_modules/openai/resources/admin/organization/projects/model-permissions.d.mts","../../node_modules/openai/resources/admin/organization/projects/rate-limits.d.mts","../../node_modules/openai/resources/admin/organization/projects/roles.d.mts","../../node_modules/openai/resources/admin/organization/projects/service-accounts.d.mts","../../node_modules/openai/resources/admin/organization/projects/spend-alerts.d.mts","../../node_modules/openai/resources/admin/organization/projects/groups/roles.d.mts","../../node_modules/openai/resources/admin/organization/projects/groups/groups.d.mts","../../node_modules/openai/resources/admin/organization/users/roles.d.mts","../../node_modules/openai/resources/admin/organization/users/users.d.mts","../../node_modules/openai/resources/admin/organization/projects/users/roles.d.mts","../../node_modules/openai/resources/admin/organization/projects/users/users.d.mts","../../node_modules/openai/resources/admin/organization/projects/projects.d.mts","../../node_modules/openai/resources/admin/organization/organization.d.mts","../../node_modules/openai/resources/admin/admin.d.mts","../../node_modules/openai/resources/audio/speech.d.mts","../../node_modules/openai/resources/audio/transcriptions.d.mts","../../node_modules/openai/resources/audio/translations.d.mts","../../node_modules/openai/resources/audio/audio.d.mts","../../node_modules/openai/resources/batches.d.mts","../../node_modules/openai/resources/beta/threads/messages.d.mts","../../node_modules/openai/resources/beta/threads/runs/steps.d.mts","../../node_modules/openai/error.d.mts","../../node_modules/openai/lib/eventstream.d.mts","../../node_modules/openai/lib/assistantstream.d.mts","../../node_modules/openai/resources/beta/threads/runs/runs.d.mts","../../node_modules/openai/resources/beta/threads/threads.d.mts","../../node_modules/openai/resources/beta/assistants.d.mts","../../node_modules/openai/resources/beta/realtime/sessions.d.mts","../../node_modules/openai/resources/beta/realtime/transcription-sessions.d.mts","../../node_modules/openai/resources/beta/realtime/realtime.d.mts","../../node_modules/openai/resources/beta/chatkit/threads.d.mts","../../node_modules/openai/resources/beta/chatkit/sessions.d.mts","../../node_modules/openai/resources/beta/chatkit/chatkit.d.mts","../../node_modules/openai/resources/beta/beta.d.mts","../../node_modules/openai/resources/completions.d.mts","../../node_modules/openai/lib/parser.d.mts","../../node_modules/openai/lib/responsesparser.d.mts","../../node_modules/openai/azure.d.mts","../../node_modules/openai/bedrock.d.mts","../../node_modules/openai/index.d.mts","../../node_modules/openai/lib/responses/eventtypes.d.mts","../../node_modules/openai/lib/responses/responsestream.d.mts","../../node_modules/openai/resources/responses/input-items.d.mts","../../node_modules/openai/resources/responses/input-tokens.d.mts","../../node_modules/openai/resources/responses/responses.d.mts","../../node_modules/openai/resources/containers/files/content.d.mts","../../node_modules/openai/resources/containers/files/files.d.mts","../../node_modules/openai/resources/containers/containers.d.mts","../../node_modules/openai/resources/conversations/items.d.mts","../../node_modules/openai/resources/conversations/conversations.d.mts","../../node_modules/openai/resources/embeddings.d.mts","../../node_modules/openai/resources/graders/grader-models.d.mts","../../node_modules/openai/resources/evals/runs/output-items.d.mts","../../node_modules/openai/resources/evals/runs/runs.d.mts","../../node_modules/openai/resources/evals/evals.d.mts","../../node_modules/openai/resources/files.d.mts","../../node_modules/openai/resources/fine-tuning/methods.d.mts","../../node_modules/openai/resources/fine-tuning/alpha/graders.d.mts","../../node_modules/openai/resources/fine-tuning/alpha/alpha.d.mts","../../node_modules/openai/resources/fine-tuning/checkpoints/permissions.d.mts","../../node_modules/openai/resources/fine-tuning/checkpoints/checkpoints.d.mts","../../node_modules/openai/resources/fine-tuning/jobs/checkpoints.d.mts","../../node_modules/openai/resources/fine-tuning/jobs/jobs.d.mts","../../node_modules/openai/resources/fine-tuning/fine-tuning.d.mts","../../node_modules/openai/resources/graders/graders.d.mts","../../node_modules/openai/resources/images.d.mts","../../node_modules/openai/resources/models.d.mts","../../node_modules/openai/resources/moderations.d.mts","../../node_modules/openai/resources/realtime/calls.d.mts","../../node_modules/openai/resources/realtime/client-secrets.d.mts","../../node_modules/openai/resources/realtime/realtime.d.mts","../../node_modules/openai/resources/skills/content.d.mts","../../node_modules/openai/resources/skills/versions/content.d.mts","../../node_modules/openai/resources/skills/versions/versions.d.mts","../../node_modules/openai/resources/skills/skills.d.mts","../../node_modules/openai/resources/uploads/parts.d.mts","../../node_modules/openai/resources/uploads/uploads.d.mts","../../node_modules/openai/uploads.d.mts","../../node_modules/openai/resources/vector-stores/files.d.mts","../../node_modules/openai/resources/vector-stores/file-batches.d.mts","../../node_modules/openai/resources/vector-stores/vector-stores.d.mts","../../node_modules/openai/resources/videos.d.mts","../../node_modules/openai/resources/webhooks/webhooks.d.mts","../../node_modules/openai/resources/webhooks/index.d.mts","../../node_modules/openai/resources/webhooks.d.mts","../../node_modules/openai/resources/index.d.mts","../../node_modules/openai/client.d.mts","../../node_modules/openai/core/resource.d.mts","../../node_modules/openai/resources/chat/completions/messages.d.mts","../../node_modules/openai/lib/abstractchatcompletionrunner.d.mts","../../node_modules/openai/lib/chatcompletionstream.d.mts","../../node_modules/openai/lib/chatcompletionstreamingrunner.d.mts","../../node_modules/openai/lib/jsonschema.d.mts","../../node_modules/openai/lib/runnablefunction.d.mts","../../node_modules/openai/lib/chatcompletionrunner.d.mts","../../node_modules/openai/resources/chat/completions/completions.d.mts","../../node_modules/openai/resources/chat/completions/index.d.mts","../../node_modules/openai/resources/chat/completions.d.mts","./src/common/notify.ts","./src/common/openai-thinking.ts","./src/common/shell-utils.ts","./src/common/state.ts","./src/common/file-utils.ts","./src/prompt.ts","./src/tools/ask-user-question-handler.ts","./src/common/bash-timeout.ts","./src/common/process-tree.ts","./src/tools/bash-handler.ts","../../node_modules/zod/v4/core/json-schema.d.cts","../../node_modules/zod/v4/core/standard-schema.d.cts","../../node_modules/zod/v4/core/registries.d.cts","../../node_modules/zod/v4/core/to-json-schema.d.cts","../../node_modules/zod/v4/core/util.d.cts","../../node_modules/zod/v4/core/versions.d.cts","../../node_modules/zod/v4/core/schemas.d.cts","../../node_modules/zod/v4/core/checks.d.cts","../../node_modules/zod/v4/core/errors.d.cts","../../node_modules/zod/v4/core/core.d.cts","../../node_modules/zod/v4/core/parse.d.cts","../../node_modules/zod/v4/core/regexes.d.cts","../../node_modules/zod/v4/locales/ar.d.cts","../../node_modules/zod/v4/locales/az.d.cts","../../node_modules/zod/v4/locales/be.d.cts","../../node_modules/zod/v4/locales/bg.d.cts","../../node_modules/zod/v4/locales/ca.d.cts","../../node_modules/zod/v4/locales/cs.d.cts","../../node_modules/zod/v4/locales/da.d.cts","../../node_modules/zod/v4/locales/de.d.cts","../../node_modules/zod/v4/locales/el.d.cts","../../node_modules/zod/v4/locales/en.d.cts","../../node_modules/zod/v4/locales/eo.d.cts","../../node_modules/zod/v4/locales/es.d.cts","../../node_modules/zod/v4/locales/fa.d.cts","../../node_modules/zod/v4/locales/fi.d.cts","../../node_modules/zod/v4/locales/fr.d.cts","../../node_modules/zod/v4/locales/fr-ca.d.cts","../../node_modules/zod/v4/locales/he.d.cts","../../node_modules/zod/v4/locales/hr.d.cts","../../node_modules/zod/v4/locales/hu.d.cts","../../node_modules/zod/v4/locales/hy.d.cts","../../node_modules/zod/v4/locales/id.d.cts","../../node_modules/zod/v4/locales/is.d.cts","../../node_modules/zod/v4/locales/it.d.cts","../../node_modules/zod/v4/locales/ja.d.cts","../../node_modules/zod/v4/locales/ka.d.cts","../../node_modules/zod/v4/locales/kh.d.cts","../../node_modules/zod/v4/locales/km.d.cts","../../node_modules/zod/v4/locales/ko.d.cts","../../node_modules/zod/v4/locales/lt.d.cts","../../node_modules/zod/v4/locales/mk.d.cts","../../node_modules/zod/v4/locales/ms.d.cts","../../node_modules/zod/v4/locales/nl.d.cts","../../node_modules/zod/v4/locales/no.d.cts","../../node_modules/zod/v4/locales/ota.d.cts","../../node_modules/zod/v4/locales/ps.d.cts","../../node_modules/zod/v4/locales/pl.d.cts","../../node_modules/zod/v4/locales/pt.d.cts","../../node_modules/zod/v4/locales/ro.d.cts","../../node_modules/zod/v4/locales/ru.d.cts","../../node_modules/zod/v4/locales/sl.d.cts","../../node_modules/zod/v4/locales/sv.d.cts","../../node_modules/zod/v4/locales/ta.d.cts","../../node_modules/zod/v4/locales/th.d.cts","../../node_modules/zod/v4/locales/tr.d.cts","../../node_modules/zod/v4/locales/ua.d.cts","../../node_modules/zod/v4/locales/uk.d.cts","../../node_modules/zod/v4/locales/ur.d.cts","../../node_modules/zod/v4/locales/uz.d.cts","../../node_modules/zod/v4/locales/vi.d.cts","../../node_modules/zod/v4/locales/zh-cn.d.cts","../../node_modules/zod/v4/locales/zh-tw.d.cts","../../node_modules/zod/v4/locales/yo.d.cts","../../node_modules/zod/v4/locales/index.d.cts","../../node_modules/zod/v4/core/doc.d.cts","../../node_modules/zod/v4/core/api.d.cts","../../node_modules/zod/v4/core/json-schema-processors.d.cts","../../node_modules/zod/v4/core/json-schema-generator.d.cts","../../node_modules/zod/v4/core/index.d.cts","../../node_modules/zod/v4/classic/errors.d.cts","../../node_modules/zod/v4/classic/parse.d.cts","../../node_modules/zod/v4/classic/schemas.d.cts","../../node_modules/zod/v4/classic/checks.d.cts","../../node_modules/zod/v4/classic/compat.d.cts","../../node_modules/zod/v4/classic/from-json-schema.d.cts","../../node_modules/zod/v4/classic/iso.d.cts","../../node_modules/zod/v4/classic/coerce.d.cts","../../node_modules/zod/v4/classic/external.d.cts","../../node_modules/zod/index.d.cts","./src/common/tool-types.ts","./src/common/validate.ts","./src/tools/edit-handler.ts","./node_modules/ignore/index.d.ts","./src/tools/read-handler.ts","./src/tools/update-plan-handler.ts","./src/tools/web-search-handler.ts","./src/tools/write-handler.ts","./src/mcp/mcp-client.ts","./src/mcp/mcp-manager.ts","./src/tools/executor.ts","./src/common/error-logger.ts","./src/common/debug-logger.ts","./src/common/file-history.ts","./src/common/permissions.ts","./src/common/telemetry.ts","./src/common/openai-message-converter.ts","./src/session.ts","../../node_modules/undici/types/utility.d.ts","../../node_modules/undici/types/header.d.ts","../../node_modules/undici/types/readable.d.ts","../../node_modules/@types/node/compatibility/iterators.d.ts","../../node_modules/@types/node/globals.typedarray.d.ts","../../node_modules/@types/node/buffer.buffer.d.ts","../../node_modules/@types/node/globals.d.ts","../../node_modules/@types/node/web-globals/abortcontroller.d.ts","../../node_modules/@types/node/web-globals/blob.d.ts","../../node_modules/@types/node/web-globals/console.d.ts","../../node_modules/@types/node/web-globals/crypto.d.ts","../../node_modules/@types/node/web-globals/domexception.d.ts","../../node_modules/@types/node/web-globals/encoding.d.ts","../../node_modules/@types/node/web-globals/events.d.ts","../../node_modules/undici-types/utility.d.ts","../../node_modules/undici-types/header.d.ts","../../node_modules/undici-types/readable.d.ts","../../node_modules/undici-types/fetch.d.ts","../../node_modules/undici-types/formdata.d.ts","../../node_modules/undici-types/connector.d.ts","../../node_modules/undici-types/client-stats.d.ts","../../node_modules/undici-types/client.d.ts","../../node_modules/undici-types/errors.d.ts","../../node_modules/undici-types/dispatcher.d.ts","../../node_modules/undici-types/global-dispatcher.d.ts","../../node_modules/undici-types/global-origin.d.ts","../../node_modules/undici-types/pool-stats.d.ts","../../node_modules/undici-types/pool.d.ts","../../node_modules/undici-types/handlers.d.ts","../../node_modules/undici-types/balanced-pool.d.ts","../../node_modules/undici-types/round-robin-pool.d.ts","../../node_modules/undici-types/h2c-client.d.ts","../../node_modules/undici-types/agent.d.ts","../../node_modules/undici-types/mock-interceptor.d.ts","../../node_modules/undici-types/mock-call-history.d.ts","../../node_modules/undici-types/mock-agent.d.ts","../../node_modules/undici-types/mock-client.d.ts","../../node_modules/undici-types/mock-pool.d.ts","../../node_modules/undici-types/snapshot-agent.d.ts","../../node_modules/undici-types/mock-errors.d.ts","../../node_modules/undici-types/proxy-agent.d.ts","../../node_modules/undici-types/socks5-proxy-agent.d.ts","../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../node_modules/undici-types/retry-handler.d.ts","../../node_modules/undici-types/retry-agent.d.ts","../../node_modules/undici-types/api.d.ts","../../node_modules/undici-types/cache-interceptor.d.ts","../../node_modules/undici-types/interceptors.d.ts","../../node_modules/undici-types/util.d.ts","../../node_modules/undici-types/cookies.d.ts","../../node_modules/undici-types/patch.d.ts","../../node_modules/undici-types/websocket.d.ts","../../node_modules/undici-types/eventsource.d.ts","../../node_modules/undici-types/diagnostics-channel.d.ts","../../node_modules/undici-types/content-type.d.ts","../../node_modules/undici-types/cache.d.ts","../../node_modules/undici-types/index.d.ts","../../node_modules/@types/node/web-globals/fetch.d.ts","../../node_modules/@types/node/web-globals/importmeta.d.ts","../../node_modules/@types/node/web-globals/messaging.d.ts","../../node_modules/@types/node/web-globals/navigator.d.ts","../../node_modules/@types/node/web-globals/performance.d.ts","../../node_modules/@types/node/web-globals/storage.d.ts","../../node_modules/@types/node/web-globals/streams.d.ts","../../node_modules/@types/node/web-globals/timers.d.ts","../../node_modules/@types/node/web-globals/url.d.ts","../../node_modules/@types/node/assert.d.ts","../../node_modules/@types/node/assert/strict.d.ts","../../node_modules/@types/node/async_hooks.d.ts","../../node_modules/@types/node/buffer.d.ts","../../node_modules/@types/node/child_process.d.ts","../../node_modules/@types/node/cluster.d.ts","../../node_modules/@types/node/console.d.ts","../../node_modules/@types/node/constants.d.ts","../../node_modules/@types/node/crypto.d.ts","../../node_modules/@types/node/dgram.d.ts","../../node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/@types/node/dns.d.ts","../../node_modules/@types/node/dns/promises.d.ts","../../node_modules/@types/node/domain.d.ts","../../node_modules/@types/node/events.d.ts","../../node_modules/@types/node/fs.d.ts","../../node_modules/@types/node/fs/promises.d.ts","../../node_modules/@types/node/http.d.ts","../../node_modules/@types/node/http2.d.ts","../../node_modules/@types/node/https.d.ts","../../node_modules/@types/node/inspector.d.ts","../../node_modules/@types/node/inspector.generated.d.ts","../../node_modules/@types/node/inspector/promises.d.ts","../../node_modules/@types/node/module.d.ts","../../node_modules/@types/node/net.d.ts","../../node_modules/buffer/index.d.ts","../../node_modules/@types/node/os.d.ts","../../node_modules/@types/node/path.d.ts","../../node_modules/@types/node/path/posix.d.ts","../../node_modules/@types/node/path/win32.d.ts","../../node_modules/@types/node/perf_hooks.d.ts","../../node_modules/@types/node/process.d.ts","../../node_modules/@types/node/punycode.d.ts","../../node_modules/@types/node/querystring.d.ts","../../node_modules/@types/node/quic.d.ts","../../node_modules/@types/node/readline.d.ts","../../node_modules/@types/node/readline/promises.d.ts","../../node_modules/@types/node/repl.d.ts","../../node_modules/@types/node/sea.d.ts","../../node_modules/@types/node/sqlite.d.ts","../../node_modules/@types/node/stream.d.ts","../../node_modules/@types/node/stream/consumers.d.ts","../../node_modules/@types/node/stream/iter.d.ts","../../node_modules/@types/node/stream/promises.d.ts","../../node_modules/@types/node/stream/web.d.ts","../../node_modules/@types/node/string_decoder.d.ts","../../node_modules/@types/node/test.d.ts","../../node_modules/@types/node/test/reporters.d.ts","../../node_modules/@types/node/timers.d.ts","../../node_modules/@types/node/timers/promises.d.ts","../../node_modules/@types/node/tls.d.ts","../../node_modules/@types/node/trace_events.d.ts","../../node_modules/@types/node/tty.d.ts","../../node_modules/@types/node/url.d.ts","../../node_modules/@types/node/util.d.ts","../../node_modules/@types/node/util/types.d.ts","../../node_modules/@types/node/v8.d.ts","../../node_modules/@types/node/vm.d.ts","../../node_modules/@types/node/wasi.d.ts","../../node_modules/@types/node/worker_threads.d.ts","../../node_modules/@types/node/zlib.d.ts","../../node_modules/@types/node/zlib/iter.d.ts","../../node_modules/@types/node/index.d.ts","../../node_modules/undici/types/fetch.d.ts","../../node_modules/undici/types/formdata.d.ts","../../node_modules/undici/types/connector.d.ts","../../node_modules/undici/types/client-stats.d.ts","../../node_modules/undici/types/client.d.ts","../../node_modules/undici/types/errors.d.ts","../../node_modules/undici/types/dispatcher.d.ts","../../node_modules/undici/types/global-dispatcher.d.ts","../../node_modules/undici/types/global-origin.d.ts","../../node_modules/undici/types/pool-stats.d.ts","../../node_modules/undici/types/pool.d.ts","../../node_modules/undici/types/handlers.d.ts","../../node_modules/undici/types/balanced-pool.d.ts","../../node_modules/undici/types/round-robin-pool.d.ts","../../node_modules/undici/types/h2c-client.d.ts","../../node_modules/undici/types/agent.d.ts","../../node_modules/undici/types/mock-interceptor.d.ts","../../node_modules/undici/types/mock-call-history.d.ts","../../node_modules/undici/types/mock-agent.d.ts","../../node_modules/undici/types/mock-client.d.ts","../../node_modules/undici/types/mock-pool.d.ts","../../node_modules/undici/types/snapshot-agent.d.ts","../../node_modules/undici/types/mock-errors.d.ts","../../node_modules/undici/types/proxy-agent.d.ts","../../node_modules/undici/types/socks5-proxy-agent.d.ts","../../node_modules/undici/types/env-http-proxy-agent.d.ts","../../node_modules/undici/types/retry-handler.d.ts","../../node_modules/undici/types/retry-agent.d.ts","../../node_modules/undici/types/api.d.ts","../../node_modules/undici/types/cache-interceptor.d.ts","../../node_modules/undici/types/interceptors.d.ts","../../node_modules/undici/types/util.d.ts","../../node_modules/undici/types/cookies.d.ts","../../node_modules/undici/types/patch.d.ts","../../node_modules/undici/types/websocket.d.ts","../../node_modules/undici/types/eventsource.d.ts","../../node_modules/undici/types/diagnostics-channel.d.ts","../../node_modules/undici/types/content-type.d.ts","../../node_modules/undici/types/cache.d.ts","../../node_modules/undici/types/index.d.ts","../../node_modules/undici/index.d.ts","./src/common/openai-client.ts","./src/index.ts"],"fileIdsList":[[309,373,381,385,388,390,391,392,405,434],[309,370,371,373,381,385,388,390,391,392,405,434],[309,372,373,381,385,388,390,391,392,405,434],[373,381,385,388,390,391,392,405,434],[309,373,381,385,388,390,391,392,405,414,434],[309,373,374,379,381,384,385,388,390,391,392,394,405,410,423,434],[309,373,374,375,381,384,385,388,390,391,392,405,434],[309,373,376,381,385,388,390,391,392,405,424,434],[309,373,377,378,381,385,388,390,391,392,396,405,434],[309,373,378,381,385,388,390,391,392,405,410,420,434],[309,373,379,381,384,385,388,390,391,392,394,405,434],[309,372,373,380,381,385,388,390,391,392,405,434],[309,373,381,382,385,388,390,391,392,405,434],[309,373,381,383,384,385,388,390,391,392,405,434],[309,372,373,381,384,385,388,390,391,392,405,434],[309,373,381,384,385,386,388,390,391,392,405,410,423,434],[309,373,381,384,385,386,388,390,391,392,405,410,412,414,434],[309,360,373,381,384,385,387,388,390,391,392,394,405,410,423,434],[309,373,381,384,385,387,388,390,391,392,394,405,410,420,423,434],[309,373,381,385,387,388,389,390,391,392,405,410,420,423,434],[307,308,309,310,311,312,313,314,315,316,317,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,434],[309,373,381,384,385,388,390,391,392,405,434],[309,373,381,385,388,390,392,405,434],[309,373,381,385,388,390,391,392,393,405,423,434],[309,373,381,384,385,388,390,391,392,394,405,410,434],[309,373,381,385,388,390,391,392,396,405,434],[309,373,381,385,388,390,391,392,397,405,434],[309,373,381,384,385,388,390,391,392,400,405,434],[309,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,434],[309,373,381,385,388,390,391,392,402,405,434],[309,373,381,385,388,390,391,392,403,405,434],[309,373,378,381,385,388,390,391,392,394,405,414,434],[309,373,381,384,385,388,390,391,392,405,406,434],[309,373,381,385,388,390,391,392,405,407,424,427,434],[309,373,381,384,385,388,390,391,392,405,410,413,414,434],[309,373,381,385,388,390,391,392,405,411,414,434],[309,373,381,385,388,390,391,392,405,412,434],[309,373,381,385,388,390,391,392,405,414,424,434],[309,373,381,385,388,390,391,392,405,415,434],[309,370,373,381,385,388,390,391,392,405,410,417,423,434],[309,373,381,385,388,390,391,392,405,410,416,434],[309,373,381,384,385,388,390,391,392,405,418,419,434],[309,373,381,385,388,390,391,392,405,418,419,434],[309,373,378,381,385,388,390,391,392,394,405,410,420,434],[309,373,381,385,388,390,391,392,405,421,434],[309,373,381,385,388,390,391,392,394,405,422,434],[309,373,381,385,387,388,390,391,392,403,405,423,434],[309,373,381,385,388,390,391,392,405,424,425,434],[309,373,378,381,385,388,390,391,392,405,425,434],[309,373,381,385,388,390,391,392,405,410,426,434],[309,373,381,385,388,390,391,392,393,405,427,434],[309,373,381,385,388,390,391,392,405,428,434],[309,373,376,381,385,388,390,391,392,405,434],[309,373,378,381,385,388,390,391,392,405,434],[309,373,381,385,388,390,391,392,405,424,434],[309,360,373,381,385,388,390,391,392,405,434],[309,373,381,385,388,390,391,392,405,423,434],[309,373,381,385,388,390,391,392,405,429,434],[309,373,381,385,388,390,391,392,400,405,434],[309,373,381,385,388,390,391,392,405,419,434],[309,360,373,381,384,385,386,388,390,391,392,400,405,410,414,423,426,427,429,434],[309,373,381,385,388,390,391,392,405,410,430,434],[309,373,381,385,388,390,391,392,405,412,431,434],[64,66,69,184,309,373,381,385,388,390,391,392,405,434],[66,69,184,309,373,381,385,388,390,391,392,405,434],[64,65,66,69,70,72,75,76,77,80,81,111,115,116,131,132,142,145,147,148,152,153,161,162,163,164,165,168,172,174,178,179,180,183,193,309,373,381,385,388,390,391,392,405,434],[65,74,184,309,373,381,385,388,390,391,392,405,434],[71,309,373,381,385,388,390,391,392,405,434],[69,74,75,184,309,373,381,385,388,390,391,392,405,434],[184,309,373,381,385,388,390,391,392,405,434],[67,184,309,373,381,385,388,390,391,392,405,434],[78,79,309,373,381,385,388,390,391,392,405,434],[72,309,373,381,385,388,390,391,392,405,434],[72,75,76,80,135,136,184,309,373,381,385,388,390,391,392,405,434],[69,73,184,309,373,381,385,388,390,391,392,405,434],[64,65,66,68,309,373,381,385,388,390,391,392,405,434],[64,309,373,381,385,388,390,391,392,405,434],[64,69,184,309,373,381,385,388,390,391,392,405,434],[69,184,309,373,381,385,388,390,391,392,405,434],[69,120,132,137,189,191,192,195,309,373,381,385,388,390,391,392,405,434],[67,69,117,118,120,122,123,124,309,373,381,385,388,390,391,392,405,434],[133,137,187,191,195,309,373,381,385,388,390,391,392,405,434],[67,69,137,187,193,195,309,373,381,385,388,390,391,392,405,434],[67,133,137,187,188,191,195,309,373,381,385,388,390,391,392,405,434],[119,309,373,381,385,388,390,391,392,405,434],[71,142,195,309,373,381,385,388,390,391,392,405,434],[142,309,373,381,385,388,390,391,392,405,434],[69,120,134,137,138,142,309,373,381,385,388,390,391,392,405,434],[133,142,195,309,373,381,385,388,390,391,392,405,434],[189,190,192,309,373,381,385,388,390,391,392,405,434],[76,309,373,381,385,388,390,391,392,405,434],[110,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,185,309,373,381,385,388,390,391,392,405,434],[69,76,185,309,373,381,385,388,390,391,392,405,434],[69,75,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,91,92,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,88,185,309,373,381,385,388,390,391,392,405,434],[83,84,85,86,87,88,89,90,93,106,109,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,103,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,94,95,96,97,98,99,100,101,102,104,108,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,88,106,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,107,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,105,185,309,373,381,385,388,390,391,392,405,434],[112,113,114,185,309,373,381,385,388,390,391,392,405,434],[68,69,75,80,113,115,185,309,373,381,385,388,390,391,392,405,434],[69,75,80,113,115,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,116,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,117,118,121,122,123,185,309,373,381,385,388,390,391,392,405,434],[123,124,127,130,185,309,373,381,385,388,390,391,392,405,434],[128,129,185,309,373,381,385,388,390,391,392,405,434],[69,75,128,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,130,185,309,373,381,385,388,390,391,392,405,434],[71,125,126,127,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,124,185,309,373,381,385,388,390,391,392,405,434],[68,69,71,75,76,117,118,121,122,123,124,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,118,185,309,373,381,385,388,390,391,392,405,434],[68,69,71,75,117,121,122,123,124,185,309,373,381,385,388,390,391,392,405,434],[71,185,193,309,373,381,385,388,390,391,392,405,434],[194,309,373,381,385,388,390,391,392,405,434],[68,69,71,75,76,132,133,185,186,187,188,189,191,192,193,309,373,381,385,388,390,391,392,405,434],[186,193,309,373,381,385,388,390,391,392,405,434],[69,76,185,193,309,373,381,385,388,390,391,392,405,434],[81,194,309,373,381,385,388,390,391,392,405,434],[68,69,75,132,185,193,309,373,381,385,388,390,391,392,405,434],[69,75,76,142,144,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,80,143,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,142,146,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,142,147,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,142,149,151,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,151,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,142,149,150,185,193,309,373,381,385,388,390,391,392,405,434],[69,75,76,80,185,309,373,381,385,388,390,391,392,405,434],[155,185,309,373,381,385,388,390,391,392,405,434],[69,75,149,185,309,373,381,385,388,390,391,392,405,434],[157,185,309,373,381,385,388,390,391,392,405,434],[154,156,158,160,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,154,159,185,309,373,381,385,388,390,391,392,405,434],[149,185,309,373,381,385,388,390,391,392,405,434],[71,142,149,185,309,373,381,385,388,390,391,392,405,434],[68,69,75,80,163,185,309,373,381,385,388,390,391,392,405,434],[71,82,111,115,116,131,132,142,145,147,148,152,153,161,162,163,164,165,168,172,174,178,179,182,309,373,381,385,388,390,391,392,405,434],[69,75,142,168,185,309,373,381,385,388,390,391,392,405,434],[69,75,142,167,168,185,309,373,381,385,388,390,391,392,405,434],[71,142,166,167,168,185,309,373,381,385,388,390,391,392,405,434],[69,76,142,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,142,185,309,373,381,385,388,390,391,392,405,434],[68,69,71,75,76,134,139,140,141,142,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,80,169,171,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,80,170,185,309,373,381,385,388,390,391,392,405,434],[69,75,80,185,309,373,381,385,388,390,391,392,405,434],[69,75,153,173,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,175,176,178,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,175,178,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,176,177,185,309,373,381,385,388,390,391,392,405,434],[181,309,373,381,385,388,390,391,392,405,434],[180,309,373,381,385,388,390,391,392,405,434],[66,185,309,373,381,385,388,390,391,392,405,434],[80,309,373,381,385,388,390,391,392,405,434],[309,324,327,330,331,373,381,385,388,390,391,392,405,423,434],[309,327,373,381,385,388,390,391,392,405,410,423,434],[309,327,331,373,381,385,388,390,391,392,405,423,434],[309,373,381,385,388,390,391,392,405,410,434],[309,321,373,381,385,388,390,391,392,405,434],[309,325,373,381,385,388,390,391,392,405,434],[309,323,324,327,373,381,385,388,390,391,392,405,423,434],[309,373,381,385,388,390,391,392,394,405,420,434],[309,373,381,385,388,390,391,392,405,432,434],[309,321,373,381,385,388,390,391,392,405,432,434],[309,323,327,373,381,385,388,390,391,392,394,405,423,434],[309,318,319,320,322,326,373,381,384,385,388,390,391,392,405,410,423,434],[309,327,336,344,373,381,385,388,390,391,392,405,434],[309,319,325,373,381,385,388,390,391,392,405,434],[309,327,354,355,373,381,385,388,390,391,392,405,434],[309,319,322,327,373,381,385,388,390,391,392,405,414,423,432,434],[309,327,373,381,385,388,390,391,392,405,434],[309,323,327,373,381,385,388,390,391,392,405,423,434],[309,318,373,381,385,388,390,391,392,405,434],[309,321,322,323,325,326,327,328,329,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,355,356,357,358,359,373,381,385,388,390,391,392,405,434],[309,327,347,350,373,381,385,388,390,391,392,405,434],[309,327,336,337,338,373,381,385,388,390,391,392,405,434],[309,325,327,337,339,373,381,385,388,390,391,392,405,434],[309,326,373,381,385,388,390,391,392,405,434],[309,319,321,327,373,381,385,388,390,391,392,405,434],[309,327,331,337,339,373,381,385,388,390,391,392,405,434],[309,331,373,381,385,388,390,391,392,405,434],[309,325,327,330,373,381,385,388,390,391,392,405,423,434],[309,319,323,327,336,373,381,385,388,390,391,392,405,434],[309,327,347,373,381,385,388,390,391,392,405,434],[309,339,373,381,385,388,390,391,392,405,434],[309,319,323,327,331,373,381,385,388,390,391,392,405,434],[309,321,327,354,373,381,385,388,390,391,392,405,414,429,432,434],[309,373,381,385,388,390,391,392,405,434,472],[309,373,381,385,388,390,391,392,405,423,434,436,439,442,443],[309,373,381,385,388,390,391,392,405,410,423,434,439],[309,373,381,385,388,390,391,392,405,423,434,439,443],[309,373,381,385,388,390,391,392,405,433,434],[309,373,381,385,388,390,391,392,405,434,437],[309,373,381,385,388,390,391,392,405,423,434,435,436,439],[309,373,381,385,388,390,391,392,405,432,433,434],[309,373,381,385,388,390,391,392,394,405,423,434,435,439],[304,305,306,309,373,381,384,385,388,390,391,392,405,410,423,434,438],[309,373,381,385,388,390,391,392,405,434,439,448,456],[305,309,373,381,385,388,390,391,392,405,434,437],[309,373,381,385,388,390,391,392,405,434,439,466,467],[305,309,373,381,385,388,390,391,392,405,414,423,432,434,439],[309,373,381,385,388,390,391,392,405,434,439],[309,373,381,385,388,390,391,392,405,423,434,435,439],[304,309,373,381,385,388,390,391,392,405,434],[309,373,381,385,388,390,391,392,405,433,434,435,437,438,439,440,441,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,467,468,469,470,471],[309,373,381,385,388,390,391,392,405,434,439,459,462],[309,373,381,385,388,390,391,392,405,434,439,448,449,450],[309,373,381,385,388,390,391,392,405,434,437,439,449,451],[309,373,381,385,388,390,391,392,405,434,438],[305,309,373,381,385,388,390,391,392,405,433,434,439],[309,373,381,385,388,390,391,392,405,434,439,443,449,451],[309,373,381,385,388,390,391,392,405,434,443],[309,373,381,385,388,390,391,392,405,423,434,437,439,442],[305,309,373,381,385,388,390,391,392,405,434,435,439,448],[309,373,381,385,388,390,391,392,405,434,439,459],[309,373,381,385,388,390,391,392,405,434,451],[305,309,373,381,385,388,390,391,392,405,434,435,439,443],[309,373,381,385,388,390,391,392,405,414,429,432,433,434,439,466],[284,309,373,381,385,388,390,391,392,405,434],[275,309,373,381,385,388,390,391,392,405,434],[275,278,309,373,381,385,388,390,391,392,405,434],[210,270,273,275,276,277,278,279,280,281,282,283,309,373,381,385,388,390,391,392,405,434],[206,208,278,309,373,381,385,388,390,391,392,405,434],[275,276,309,373,381,385,388,390,391,392,405,434],[207,275,277,309,373,381,385,388,390,391,392,405,434],[208,210,212,213,214,215,309,373,381,385,388,390,391,392,405,434],[210,212,214,215,309,373,381,385,388,390,391,392,405,434],[210,212,214,309,373,381,385,388,390,391,392,405,434],[207,210,212,213,215,309,373,381,385,388,390,391,392,405,434],[206,208,209,210,211,212,213,214,215,216,217,270,271,272,273,274,309,373,381,385,388,390,391,392,405,434],[206,208,209,212,309,373,381,385,388,390,391,392,405,434],[208,209,212,309,373,381,385,388,390,391,392,405,434],[212,215,309,373,381,385,388,390,391,392,405,434],[206,207,209,210,211,213,214,215,309,373,381,385,388,390,391,392,405,434],[206,207,208,212,275,309,373,381,385,388,390,391,392,405,434],[212,213,214,215,309,373,381,385,388,390,391,392,405,434],[214,309,373,381,385,388,390,391,392,405,434],[218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,309,373,381,385,388,390,391,392,405,434],[309,373,381,385,388,390,391,392,396,397,405,434],[309,373,374,378,381,385,388,390,391,392,397,405,434],[199,309,373,381,385,388,390,391,392,397,405,434],[309,373,374,381,385,388,390,391,392,405,434],[61,137,309,373,381,385,388,390,391,392,396,397,405,434,473],[60,195,303,309,373,381,385,388,390,391,392,405,434],[61,309,373,381,385,388,390,391,392,405,434],[61,199,309,373,381,385,388,390,391,392,397,405,434],[309,373,374,381,385,388,390,391,392,396,397,399,405,434],[198,200,309,373,381,385,388,390,391,392,397,405,434],[61,137,309,373,381,385,388,390,391,392,405,434],[285,286,309,373,381,385,388,390,391,392,405,434],[60,61,196,197,198,199,200,201,202,203,204,205,286,287,288,290,291,292,293,294,295,296,297,298,299,300,301,302,303,309,373,381,385,388,390,391,392,405,434,474],[204,309,373,374,381,385,388,390,391,392,397,405,434],[61,294,309,373,378,381,385,388,390,391,392,405,434],[60,62,63,198,303,309,373,374,381,385,388,390,391,392,396,397,405,423,434],[60,61,62,63,195,196,197,199,200,201,204,205,295,296,297,298,299,300,301,302,309,373,378,381,385,388,390,391,392,396,397,405,434],[60,309,373,381,385,388,390,391,392,396,397,405,434],[296,309,373,381,385,388,390,391,392,405,434],[198,203,204,296,309,373,374,378,381,385,388,390,391,392,396,397,405,434],[197,199,200,285,287,296,309,373,381,385,388,390,391,392,405,434],[202,205,286,288,290,291,292,293,295,309,373,381,385,388,390,391,392,405,434],[199,200,289,296,309,373,381,385,388,390,391,392,397,405,434],[285,287,296,309,373,381,385,388,390,391,392,405,434],[137,296,309,373,374,378,381,385,388,390,391,392,405,434],[199,200,285,287,296,309,373,381,385,388,390,391,392,405,434]],"fileInfos":[{"version":"bcd24271a113971ba9eb71ff8cb01bc6b0f872a85c23fdbe5d93065b375933cd","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f88bedbeb09c6f5a6645cb24c7c55f1aa22d19ae96c8e6959cbd8b85a707bc6","impliedFormat":1},{"version":"7fe93b39b810eadd916be8db880dd7f0f7012a5cc6ffb62de8f62a2117fa6f1f","impliedFormat":1},{"version":"bb0074cc08b84a2374af33d8bf044b80851ccc9e719a5e202eacf40db2c31600","impliedFormat":1},{"version":"1a7daebe4f45fb03d9ec53d60008fbf9ac45a697fdc89e4ce218bc94b94f94d6","impliedFormat":1},{"version":"f94b133a3cb14a288803be545ac2683e0d0ff6661bcd37e31aaaec54fc382aed","impliedFormat":1},{"version":"f59d0650799f8782fd74cf73c19223730c6d1b9198671b1c5b3a38e1188b5953","impliedFormat":1},{"version":"8a15b4607d9a499e2dbeed9ec0d3c0d7372c850b2d5f1fb259e8f6d41d468a84","impliedFormat":1},{"version":"26e0fe14baee4e127f4365d1ae0b276f400562e45e19e35fd2d4c296684715e6","impliedFormat":1},{"version":"eadcffda2aa84802c73938e589b9e58248d74c59cb7fcbca6474e3435ac15504","affectsGlobalScope":true,"impliedFormat":1},{"version":"105ba8ff7ba746404fe1a2e189d1d3d2e0eb29a08c18dded791af02f29fb4711","affectsGlobalScope":true,"impliedFormat":1},{"version":"00343ca5b2e3d48fa5df1db6e32ea2a59afab09590274a6cccb1dbae82e60c7c","affectsGlobalScope":true,"impliedFormat":1},{"version":"ebd9f816d4002697cb2864bea1f0b70a103124e18a8cd9645eeccc09bdf80ab4","affectsGlobalScope":true,"impliedFormat":1},{"version":"2c1afac30a01772cd2a9a298a7ce7706b5892e447bb46bdbeef720f7b5da77ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"7b0225f483e4fa685625ebe43dd584bb7973bbd84e66a6ba7bbe175ee1048b4f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0a4b8ac6ce74679c1da2b3795296f5896e31c38e888469a8e0f99dc3305de60","affectsGlobalScope":true,"impliedFormat":1},{"version":"3084a7b5f569088e0146533a00830e206565de65cae2239509168b11434cd84f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5079c53f0f141a0698faa903e76cb41cd664e3efb01cc17a5c46ec2eb0bef42","affectsGlobalScope":true,"impliedFormat":1},{"version":"32cafbc484dea6b0ab62cf8473182bbcb23020d70845b406f80b7526f38ae862","affectsGlobalScope":true,"impliedFormat":1},{"version":"fca4cdcb6d6c5ef18a869003d02c9f0fd95df8cfaf6eb431cd3376bc034cad36","affectsGlobalScope":true,"impliedFormat":1},{"version":"b93ec88115de9a9dc1b602291b85baf825c85666bf25985cc5f698073892b467","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5c06dcc3fe849fcb297c247865a161f995cc29de7aa823afdd75aaaddc1419b","affectsGlobalScope":true,"impliedFormat":1},{"version":"b77e16112127a4b169ef0b8c3a4d730edf459c5f25fe52d5e436a6919206c4d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"fbffd9337146eff822c7c00acbb78b01ea7ea23987f6c961eba689349e744f8c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a995c0e49b721312f74fdfb89e4ba29bd9824c770bbb4021d74d2bf560e4c6bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"c7b3542146734342e440a84b213384bfa188835537ddbda50d30766f0593aff9","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce6180fa19b1cccd07ee7f7dbb9a367ac19c0ed160573e4686425060b6df7f57","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f02e2476bccb9dbe21280d6090f0df17d2f66b74711489415a8aa4df73c9675","affectsGlobalScope":true,"impliedFormat":1},{"version":"45e3ab34c1c013c8ab2dc1ba4c80c780744b13b5676800ae2e3be27ae862c40c","affectsGlobalScope":true,"impliedFormat":1},{"version":"805c86f6cca8d7702a62a844856dbaa2a3fd2abef0536e65d48732441dde5b5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e42e397f1a5a77994f0185fd1466520691456c772d06bf843e5084ceb879a0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"f4c2b41f90c95b1c532ecc874bd3c111865793b23aebcc1c3cbbabcd5d76ffb0","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab26191cfad5b66afa11b8bf935ef1cd88fabfcb28d30b2dfa6fad877d050332","affectsGlobalScope":true,"impliedFormat":1},{"version":"2088bc26531e38fb05eedac2951480db5309f6be3fa4a08d2221abb0f5b4200d","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb9d366c425fea79716a8fb3af0d78e6b22ebbab3bd64d25063b42dc9f531c1e","affectsGlobalScope":true,"impliedFormat":1},{"version":"500934a8089c26d57ebdb688fc9757389bb6207a3c8f0674d68efa900d2abb34","affectsGlobalScope":true,"impliedFormat":1},{"version":"689da16f46e647cef0d64b0def88910e818a5877ca5379ede156ca3afb780ac3","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc21cc8b6fee4f4c2440d08035b7ea3c06b3511314c8bab6bef7a92de58a2593","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ca53d13d2957003abb47922a71866ba7cb2068f8d154877c596d63c359fed25","affectsGlobalScope":true,"impliedFormat":1},{"version":"54725f8c4df3d900cb4dac84b64689ce29548da0b4e9b7c2de61d41c79293611","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5594bc3076ac29e6c1ebda77939bc4c8833de72f654b6e376862c0473199323","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f3eb332c2d73e729f3364fcc0c2b375e72a121e8157d25a82d67a138c83a95c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f4427f9642ce8d500970e4e69d1397f64072ab73b97e476b4002a646ac743b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"48915f327cd1dea4d7bd358d9dc7732f58f9e1626a29cc0c05c8c692419d9bb7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7bf9377723203b5a6a4b920164df22d56a43f593269ba6ae1fdc97774b68855","affectsGlobalScope":true,"impliedFormat":1},{"version":"db9709688f82c9e5f65a119c64d835f906efe5f559d08b11642d56eb85b79357","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b25b8c874acd1a4cf8444c3617e037d444d19080ac9f634b405583fd10ce1f7","affectsGlobalScope":true,"impliedFormat":1},{"version":"37be57d7c90cf1f8112ee2636a068d8fd181289f82b744160ec56a7dc158a9f5","affectsGlobalScope":true,"impliedFormat":1},{"version":"a917a49ac94cd26b754ab84e113369a75d1a47a710661d7cd25e961cc797065f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d3261badeb7843d157ef3e6f5d1427d0eeb0af0cf9df84a62cfd29fd47ac86e","affectsGlobalScope":true,"impliedFormat":1},{"version":"195daca651dde22f2167ac0d0a05e215308119a3100f5e6268e8317d05a92526","affectsGlobalScope":true,"impliedFormat":1},{"version":"8b11e4285cd2bb164a4dc09248bdec69e9842517db4ca47c1ba913011e44ff2f","affectsGlobalScope":true,"impliedFormat":1},{"version":"0508571a52475e245b02bc50fa1394065a0a3d05277fbf5120c3784b85651799","affectsGlobalScope":true,"impliedFormat":1},{"version":"8f9af488f510c3015af3cc8c267a9e9d96c4dd38a1fdff0e11dc5a544711415b","affectsGlobalScope":true,"impliedFormat":1},{"version":"fc611fea8d30ea72c6bbfb599c9b4d393ce22e2f5bfef2172534781e7d138104","affectsGlobalScope":true,"impliedFormat":1},{"version":"f128dae7c44d8f35ee42e0a437000a57c9f06cc04f8b4fb42eebf44954d53dc8","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ecb8e347cb6b2a8927c09b86263663289418df375f5e68e11a0ae683776978f","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ce14b81c5cc821994aa8ec1d42b220dd41b27fcc06373bce3958af7421b77d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3a048b3e9302ef9a34ef4ebb9aecfb28b66abb3bce577206a79fee559c230da","affectsGlobalScope":true,"impliedFormat":1},{"version":"d5c693c7241b88f974795daf08b61244f552f065ec93344f0a87bb2ea8b9c23c","signature":"9033850caf9a677b88e949247cc7bb10baf88436c87597478bb6e23eed521742"},{"version":"4743a6dba8d31255325d84ef0d5687997755332b5fe042c908bf56d8b22535cc","signature":"427af1572cfe2b3dd93c53285141b662f6ca5c5b16ee9a10b7aaeb6f523de244"},{"version":"a52c5f687d788d283ea1fa38bdc2fabe0eac863135a7dfe175ec52b309f61892","impliedFormat":1},{"version":"f2a60d253f7206372203b736144906bf135762100a2b3d1b415776ebf6575d07","impliedFormat":1},{"version":"86d4ff8ba66b5ea1df375fe6092d2b167682ccd5dd0d9b003a7d30d95a0cda32","impliedFormat":99},{"version":"652071821de280fae0ba53f0abcdd7350b1bda286f8fcd39394f5d4250de44ce","impliedFormat":99},{"version":"2b5368217b57528a60433558585186a925d9842fe64c1262adde8eac5cb8de33","impliedFormat":99},{"version":"e22273698b7aad4352f0eb3c981d510b5cf6b17fde2eeaa5c018bb065d15558f","impliedFormat":99},{"version":"0249cc57fb4f04fcc725481b5f273fe4a18d943e108724b216c762aaf311c255","impliedFormat":99},{"version":"c674b1e72c7f6879711bb0e920319b2760dacb7125fac4653702a1aa37a8b283","impliedFormat":99},{"version":"91c093343733c2c2d40bee28dc793eff3071af0cb53897651f8459ad25ad01da","impliedFormat":99},{"version":"6cc2be65d508f5404dae184fbe1bc5fc6287f2af93195feba921e619721f56a0","impliedFormat":99},{"version":"17c51065e7822de999ed5ff702aead6057c172067e485e8ffe9721bfe5010f0a","impliedFormat":99},{"version":"5c9a2aec7cf29c39450fe23930e192bb58a90b36c3f169481c3ef25f2fcf79e2","impliedFormat":99},{"version":"f4fc36916b3eac2ea0180532b46283808604e4b6ff11e5031494d05aa6661cc6","impliedFormat":99},{"version":"82e23a5d9f36ccdac5322227cd970a545b8c23179f2035388a1524f82f96d8d0","impliedFormat":99},{"version":"45160eb8c4c54610c5f43c103ff539e204d12aeed21c6cbe74c0fdf63741b5db","impliedFormat":99},{"version":"67cce3d39642e38f36602ab04d683b8a0c5e3a943eb03ac288e3d68c31596014","impliedFormat":99},{"version":"bfce32506c0d081212ff9d27ec466fa6135a695ba61d5a02738abd2442566231","impliedFormat":99},{"version":"ddaf5d3ddc45282b19fb0fecec91c87fc9b4d1f45c2ee611677345c81383c5c5","impliedFormat":99},{"version":"5668033966c8247576fc316629df131d6175d24ccf22940324c19c159671e1c1","impliedFormat":99},{"version":"7630b6a1c0ebaec2ef8e8abff850e1d6c551c47d1c345340a8ab95667460fc95","impliedFormat":99},{"version":"597b0a9ef02a28f5b1195305ec9f20a4f9948bd90ec3291d0343d1e5c0b4bd16","impliedFormat":99},{"version":"5c4081cb959a116933350a69585eff8a3eeb8c98c9b8fb0b9659a0ab51ab0be5","impliedFormat":99},{"version":"eb06d1cb283278811a37f17dc35047db62bcfa69e75f752ae170e318e4704f55","impliedFormat":99},{"version":"9bda3cb21c5022c86d2325885672085a8282a08c9df21688f7d3c6eff58efd40","impliedFormat":99},{"version":"e600e54a07ac7bcf9f0fd67722865bda454f5325ca4742e08e7c321a848fc5b0","impliedFormat":99},{"version":"ddd904d24dff387d2484b69e0643541102a0e3a4f750bb2d517f46adabf84bd7","impliedFormat":99},{"version":"045b2cdfaf5cf84f5be6bde21862add9503e104b252c6dc91efae422d4e8f975","impliedFormat":99},{"version":"19f21a767c89a4f3d8721ae698ce2a61b31d0809c1633d43c89b5aad30027b95","impliedFormat":99},{"version":"d2c24000d0dadcba27d36e6b6fed7abc2c6a9b3ed6b4a8e069be303812e86bba","impliedFormat":99},{"version":"ceaaae220b5495a8fbc15cb3925107a2b1c6f5a7ca1f4de63c439d91e7726f71","impliedFormat":99},{"version":"6496e6e04c8719315d51cb1c98452f8fcbab340a46cc859e94f3b3a5e2368ea9","impliedFormat":99},{"version":"1c521e08d75a9f4ec24e0ed84c7e7d7dfee4ab5e51aa9a4dbae76283a66d0c49","impliedFormat":99},{"version":"dbcde4d0b3a3fa5b64aaf3dc80370e76b00e8e8935a9bf1f4381a2e6299cd388","impliedFormat":99},{"version":"9242750c276f71a51c8d1ca11e4bc2df24ce1c988537c9c914fdd8ec8bb9715a","impliedFormat":99},{"version":"c4bb4f8d6dfff722a008022b3157c8e921b114d6befd8651add3028df40a00e4","impliedFormat":99},{"version":"a6d7338f7fd9035f468bc64f071edbf8ad8c6363c3bfb875c3e1c0f4f5f36b5f","impliedFormat":99},{"version":"d479a5591022bf7b46d90d10e23cbf004b2e1a30ad9b675dbd96721aafb78441","impliedFormat":99},{"version":"c7af3aec3d4a4607a9e23c63d802b77235dfe6f066f912c1347e06ce5868d919","impliedFormat":99},{"version":"d2e351dc6d967923dc6ff200bfbb20dfa92f0c23331ccf34eef1ea7d4b1d8e9b","impliedFormat":99},{"version":"0c8e28a077e369f1c26e00a3c2f76824c0ac7f55cfada1a6ff42f40b5eec0c98","impliedFormat":99},{"version":"bb8194f799c99acb6c3dc6b40866ef69cc2ce063f63666c9d1a55f6b4bb6f352","impliedFormat":99},{"version":"242cda707d18d4bd715c1916eed6ef3ab3d3c107bce17c771c803ff898dabd8c","impliedFormat":99},{"version":"7116b824716ea8c11ab831cb599e27cccd1ea083689d7085ce26954d86f392d4","impliedFormat":99},{"version":"25123c80bcb4c0f874ad6d2facf40f7cfd5e27c08a3107b18302307b7a131016","impliedFormat":99},{"version":"5fb5756d1c11073dcf4b2c76eecc0e48f0331bcb43e02ecb35a7c80f53bcb677","impliedFormat":99},{"version":"121cf1f1c42afca44d5aeedb4469d525ffeb013b78031c4a9089d64acb7a1394","impliedFormat":99},{"version":"908cb76e7cace05e1622e08912e2978c9284444ebedcdf8cd341fa75e31f007e","impliedFormat":99},{"version":"f93fe279ba4ac525dcc682b54923999538090ae9eecfeb0001b8009c70c15295","impliedFormat":99},{"version":"7e5217864cf444cb86d59472a218f6781f402c60436d823541360caa64c02244","impliedFormat":99},{"version":"37f61ebbaac9cc1bee0e3c11bf9a9b5207f8e1aa066eedb2860f108961987a49","impliedFormat":99},{"version":"263a89f026d661b338a22517a0375a19af55abb09651e73e9d7940025e2402bc","impliedFormat":99},{"version":"f9bf95954745207c3a305a59f3a8f7e36290c742d006d1ce447a41dc772ba3c3","impliedFormat":99},{"version":"732e1c24c3f5a76e61b075bfee7d2b3e5714d4960f8587b0cf989e7e151dc1ea","impliedFormat":99},{"version":"4cc5c2fb807317de6f88edae5cc2b24b705cdce764bbc1cc23aeec15d91a7a49","impliedFormat":99},{"version":"53cae4e7f0a5716f296870e5eef84af8832d5700b23ff79f349c0d1b4aa40d25","impliedFormat":99},{"version":"775e97f58cc774218eb4e979ff7f73b2fb4d958521df4707ae382b32fce5f55b","impliedFormat":99},{"version":"d93588a85b0b0eef4e6ab906fa37caa21efa1d30647aef292567c078b2e3a0a9","impliedFormat":99},{"version":"2eaf0dcaaa03f1cce8c4069c98d198b4730d6e842d393031328aefd1ed7becb1","impliedFormat":99},{"version":"d62b09cb6f1ceb87ec6c26f3789bc38f8be9fb0ce3126fd0bf89b003d0cba371","impliedFormat":99},{"version":"4a5d9348012a3e46c03888e71b0d318cda7e7db25869731375f90edad8dcea02","impliedFormat":99},{"version":"61b3add3d48dfc79324531ede7da59203059a62986070f97645a83acd3f20aa0","impliedFormat":99},{"version":"6cd8356a92fd9f1edcbfbd3b891f50228738522e79bfdad16e7fb7cfd4a66932","impliedFormat":99},{"version":"347efb60859c806ef954a67ee7520c9aa33e1881eedd40d236298af775deef50","impliedFormat":99},{"version":"fc391876e409d362cc43a7468226a9eb83440de09873b284bf09fbfb261ec259","impliedFormat":99},{"version":"d06f5012d5ac1bc25c5033f7e916fe42cc0253d6b523b9747809b71676069370","impliedFormat":99},{"version":"5d35840bd540fad886e21ddaf9b078a44c21a827dec9abc08d2d2c1a3ff27d44","impliedFormat":99},{"version":"a02182b20bcb1966fc15eac80506f617b71fdd0e279ccff44b27f2ee366b2823","impliedFormat":99},{"version":"32563899782c456f03cadc7a9508b9b6468dd678404b093bd7557d6c6e143218","impliedFormat":99},{"version":"f613a93e0685802f7f7e248156ae93ff9088d45abeff0b21b656520699b79f06","impliedFormat":99},{"version":"5471b59fcb6ad04c41f6bf57075e88f3094d9d498e51595b4341d8bfcb729bf5","impliedFormat":99},{"version":"6aeb85043e6a5d2c3768c413a01885b0fc3dbfb4b3817fde5bb93601f5efb303","impliedFormat":99},{"version":"b6ff37737d006b86082f2f7176eb0a771001e9dde9152a26ef9ea8fd80e6eba0","impliedFormat":99},{"version":"491d5f012b1de793c45e75a930f5cdef1ff0e7875968e743fa6bd5dd7d31cb3b","impliedFormat":99},{"version":"1fd56873ada3f2bf6049ae741cf4efc1c90693015a6dc3467d6c995e5a6db03a","impliedFormat":99},{"version":"8074e5e85360339cc57e7a9b6db5f49af9ef8d6d0ee3c28a02d5e0ad5c21920b","impliedFormat":99},{"version":"43db9ade57eeeb241749f460e5eec4cc4eca8e8f3c35a0542a5a746eb2bcaf86","impliedFormat":99},{"version":"53c86b81daa463deacb0046fee490b6d589438ac71311050b74dcee99afca0f6","impliedFormat":99},{"version":"70587241a4cc2e08ffc30e60c20f3eb38bd5af7e3d99640568ffe2993f933485","impliedFormat":99},{"version":"dd01943d0fe191b3b2020438367709333ff08a69d285e2f715a60711dcf83b61","impliedFormat":99},{"version":"9c7188dc07bc5ce82bbe5b75495f44a7887b0a4945f63696661fffeddca0c0e9","impliedFormat":99},{"version":"93ea079d0b9af94efc1578a95aa0299ec4054f617fb31d243f66255e221276fd","impliedFormat":99},{"version":"4ecb0eb653de7093f2eb589cea5b35fdea6e2bbd62bc3d9fafdc5702850f7714","impliedFormat":99},{"version":"69ed52603ad6430aaffbc9dec25e0d01df733aaa32ab4d57d37987aedc94c349","impliedFormat":99},{"version":"6f8acb191da449d8dbec7a4e9c317bdb6b8af104a60a101950643ea52cfa3c85","impliedFormat":99},{"version":"4c01241847f841eddf3d727aac5686d8d1e06c92124002de9d9ed2ad3c590420","impliedFormat":99},{"version":"8bba80ef1e0e9ae8c061728626309824023e85eaafcd8c285a6fa89dc6881573","impliedFormat":99},{"version":"ada6bd808581a783390b1aabc2cc836136a5d214af0d924cc57d9f29b5733ce9","impliedFormat":99},{"version":"283336202f1a6a4e13271dc83b776718cf5d4a4137b28e2d013498e3020f7170","impliedFormat":99},{"version":"54a6a3e98b7ec00fec7bd7e42ad50c16014805576ccbe33bfee04f0aac9965da","impliedFormat":99},{"version":"7c90a7108c4319b0475d5419d52f2a2c9bf499234a2a15d5b8504983e141041b","impliedFormat":99},{"version":"67fc5d1b6877a799de1e3943ed2c3669b72a6ab3b17c7b0b0387bdd6e4c1a01f","impliedFormat":99},{"version":"8ac25d431d9b1bbe3ded6c578651cc43acbdbf19c435fbbe185b827ae74ba3df","impliedFormat":99},{"version":"953ee863def1b11f321dcb17a7a91686aa582e69dd4ec370e9e33fbad2adcfd3","impliedFormat":99},{"version":"392e72d77ae33ee322d5b0b907398f2200f72d36adaca1ca62dfa7e22f744ac3","impliedFormat":99},{"version":"e452b617664fc3d2db96f64ef3addadb8c1ef275eff7946373528b1d6c86a217","impliedFormat":99},{"version":"c6a811837fef3d4ba22e7e4adcb16f12caf30252047b133404d698bf8f0e883a","impliedFormat":99},{"version":"2f722a3a421baf9a7c175d8ae6a3118dfd14c5f36474e03f99e3df5800065030","impliedFormat":99},{"version":"f9511d2a891b0a017ae31674977b053f42ca7221dedd012f6de6f75e7cb9aa3e","impliedFormat":99},{"version":"d8f262b549f3ed95402297d10b84f0f86e3113d6d570b03364d2cfca1f75e5d8","impliedFormat":99},{"version":"f216cb46ebeff3f767183626f70d18242307b2c3aab203841ae1d309277aad6b","impliedFormat":99},{"version":"d6d95f96dd5b374484fd000228288cbcfb80aa47cb74ebd3e19ea94a36e8260a","impliedFormat":99},{"version":"9abda1f0836e696725c31ea63d36a6c7c54e0f762d5e387f52b27186dff81cab","impliedFormat":99},{"version":"92fb8aa5d61dca9ab2008d49397a639dbf71c7746da23c02245523cfec4a99ef","impliedFormat":99},{"version":"9e6cd6dc690d6e6c89b17b295cabf8a5a08011ae79a7a56578a429e5ae27b8dc","impliedFormat":99},{"version":"4c7eafc682ffbd45ac24d056c63a622993048ac272c76ba1721118dc601ab629","impliedFormat":99},{"version":"f72b0af7e81183c17d799cdea2ab0d81580dfe96a98343a21d746984c3b21933","impliedFormat":99},{"version":"3841ca1577c0927f59fac8faa7cd195485c5362d99ec2b16ff9b86ec4974a3e5","impliedFormat":99},{"version":"58c5a2a520ae555e0573873a5e6303b0f1a1e70f3b376e5ac9094eaad0623d8a","impliedFormat":99},{"version":"5f8217240c95e3f3007d9968104904616287f30d853bac73874759c1dfad4017","impliedFormat":99},{"version":"7ebc96af203f866e829b528e5cffb32111a1a1ff4662bc60c3b53696e89c67f4","impliedFormat":99},{"version":"9f5ee7c037b58964c1cee63c1849fa11757f693208444be0f2d9f08defe859cd","impliedFormat":99},{"version":"33a4085365aa21a995ea4721ffff814128b126e8e346e5f064d87bfcdd0ff7ce","impliedFormat":99},{"version":"3adf214b4b307152af85b77e441d36ede388dadba2bd9962671bf933738d2a25","impliedFormat":99},{"version":"9a2cc98a7884cb530a704f6cd16a83db9aa89360a2b391a49e498b5179443dc6","impliedFormat":99},{"version":"250998ae18ea49b8745d327e7739f56464a4318783129daab90b3299bf6f8a55","impliedFormat":99},{"version":"76b3afd1f2748ff725c277bd4701f442af697c0586e1b491e6a67383a246ffad","impliedFormat":99},{"version":"4df5fc6fc2438b8e3418cb25c8c0e863d1f92e4470297d6a8756394c597af844","impliedFormat":99},{"version":"92b5f0879161f1206e30a0c219dd8f23d736f2a74a4e015885e8e3f3b3c9a3e7","impliedFormat":99},{"version":"374d12016302e312ffccd3d38e6f3df1b412378bff6e6266f3e5844af450859c","impliedFormat":99},{"version":"18d0c2293aa57e33923fc1b10970650c6d6932dbfa711a3ffd67600b3caf924b","impliedFormat":99},{"version":"17758b72f880ed66754e3ff4aeade0b82417ec546b72bf3a326cadf4e56c1915","impliedFormat":99},{"version":"ffa547cbf7599d89b6ac4c2f038f99978e0dff46bb9850df46168ce6809a5b24","impliedFormat":99},{"version":"981240d6d3015e8de441325b90c07588a302f2d9c377bccfc61e4680b726f962","impliedFormat":99},{"version":"493c39c5f9e9c050c10930448fda1be8de10a0d9b34dcd24ff17a1713c282162","impliedFormat":99},{"version":"73e4673f2da8677556210e5a127b2637bf030ab73da222ea2a19979f89d9d40a","impliedFormat":99},{"version":"e9d27f2b7d5171f512053f153cadc303d1b84d00c98e917664ba68eca9b7af6a","impliedFormat":99},{"version":"4899d2cf406cd68748c5d536b736c90339a39f996945126d8a11355eba5f56f3","impliedFormat":99},{"version":"29c4e9ce50026f15c4e58637d8668ced90f82ce7605ca2fd7b521667caa4a12c","impliedFormat":99},{"version":"8575340c8560a52c3309956add745660ad319dbd67309fa268f5af9b1c7551f5","impliedFormat":99},{"version":"3b56bc74e48ec8704af54db1f6ecfee746297ee344b12e990ba5f406431014c1","impliedFormat":99},{"version":"9e4991da8b398fa3ee9b889b272b4fe3c21e898d873916b89c641c0717caed10","impliedFormat":99},{"version":"35290a0ba8d9287d4f3635948e7e84bcf14223239ad07902d111684dfafffaf4","impliedFormat":99},{"version":"dbf3d90c21c08217509df631336881a3105740033b0592dcc47036490f95e51c","impliedFormat":99},{"version":"e6ad9376e7d088ce1dc6d3183ba5f0b3fb67ee586aa824cc8519b52f2341307a","impliedFormat":99},{"version":"2391f2f7e3819f74e51039e431d4d68dd261e40e677810316008f08e778492e8","signature":"7446741158fcd0894addb90d6f00769719782745e713ad5b201eb0132cfb6551"},{"version":"0ca51b5dc00aa2c6a3551c5b511e7ca9a1a08e12d25422bd974c2ce1707ff959","signature":"399852f50bf374c4e4c8efb4274260a0b29c3ec863e71d6a754d69818276eb59"},{"version":"ad35da447be046219c92634332ceb694b52dbc37eed13536fd18bd802ff4ed53","signature":"16d5bdedef7ac1bafc90ef5edcb5a524f7a067285e3c68b742c3def1dc8a0909"},{"version":"5be00abdcbb4485dbe416d5301421f7086cca3689dadb5ece2a53676c1d17623","signature":"9693c11eef0516a468debb1a89eaa23472061a106a7586e3465fc840909e8f03"},{"version":"91243a5cf61d442103e43100007078aaf4634840971462b7df19faa687ece79a","signature":"4e01fdfcfa9d19e0f9522f61174233fad5db2988f030045fa80a73e32dfca9fd"},{"version":"750adbd023894fa6e7af9b6eddecf7de74b5e4b537ad46f220879eb937b8244a","signature":"f24da613e5429ab6caa9687e57745be0bd9e54d5760a66f3a116f2988a79f001"},{"version":"1e693a098c4d53ddd27d499ca4d8b3ee935663aa191e62d50eeff08b26146532","signature":"99662eb2cba010fdf1202a3e222c89b8492ff68e8e206a2296f6c6ec3ee6608c"},{"version":"fe8fcf43c4614dc877d3e56d518e95d69defa07f357b2af4c385b5fb1c591929","signature":"4c0b88ca9250fa0e0fa0ce791c837487fe6b100992833f19555048cb1b47eb18"},{"version":"324df572195e93def72d9867f75dc80446d6bbaf2c9a9f0f3a45fe5b5bd8af21","signature":"dc91ed21005509f86ef528d8c3bc026e5829206e558b30ac479c6109ff0ceee4"},{"version":"f2867aef276fc96e82476403721c7cc0725df14a4e47351b93be31a28da8a7c0","signature":"a8721a1ee15a172d5d0221d47f3f1746879713898dbd7f40f3ec95fdfd379f2c"},{"version":"c1a2e05eb6d7ca8d7e4a7f4c93ccf0c2857e842a64c98eaee4d85841ee9855e6","impliedFormat":1},{"version":"835fb2909ce458740fb4a49fc61709896c6864f5ce3db7f0a88f06c720d74d02","impliedFormat":1},{"version":"6e5857f38aa297a859cab4ec891408659218a5a2610cd317b6dcbef9979459cc","impliedFormat":1},{"version":"ead8e39c2e11891f286b06ae2aa71f208b1802661fcdb2425cffa4f494a68854","impliedFormat":1},{"version":"40ba6c32eb732a09e4446ade5cb6ad0c147f186f9c9dc6878b90b4418ad9f6ea","impliedFormat":1},{"version":"fdd814741843f85c98281522c58f5a646590ba9019fad2efaa95987655e0611b","impliedFormat":1},{"version":"c78aff4fb58b28b8f642d5095fc7eeb79f00e652a67caa19693af1adabb833c9","impliedFormat":1},{"version":"f80a08ced8818dc99359c0acd5b3f12762e1ce53758007759b0d4e503cbf4a5e","impliedFormat":1},{"version":"37935fa7564bcc6e0bc845b766a24391098d26f7c8245d6e8ab37bc016816e94","impliedFormat":1},{"version":"68add36d9632bc096d7245d24d6b0b8ad5f125183016102a3dad4c9c2438ccb0","impliedFormat":1},{"version":"3a819c2928ee06bbcc84e2797fd3558ae2ebb7e0ed8d87f71732fb2e2acc87b4","impliedFormat":1},{"version":"0f8a263f4c8595c8a07de52e3f3927640c44386c1aa2984de9eae50d75e613b2","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"346fffde7c32da87c2196eb7494422449dc2ca82d3b4e6bf55be1d1a33ffc2b0","impliedFormat":1},{"version":"add0ce7b77ba5b308492fa68f77f24d1ed1d9148534bdf05ac17c30763fc1a79","impliedFormat":1},{"version":"8b5875e4958528042103fdd775e106a7f76bafc29709f0690df9a7d2241d52a7","impliedFormat":1},{"version":"2f67911e4bf4e0717dc2ded248ce2d5e4398d945ee13889a6852c1233ea41508","impliedFormat":1},{"version":"d8430c275b0f59417ea8e173cfb888a4477b430ec35b595bf734f3ec7a7d729f","impliedFormat":1},{"version":"69364df1c776372d7df1fb46a6cb3a6bf7f55e700f533a104e3f9d70a32bec18","impliedFormat":1},{"version":"6042774c61ece4ba77b3bf375f15942eb054675b7957882a00c22c0e4fe5865c","impliedFormat":1},{"version":"5a3bd57ed7a9d9afef74c75f77fce79ba3c786401af9810cdf45907c4e93f30e","impliedFormat":1},{"version":"aef26cf95593c8ace1c62c4724f9afac77bdfa756fb8a00613cd152117cb2f43","impliedFormat":1},{"version":"30db853bb2e60170ba11e39ab48bacecb32d06d4def89eedf17e58ebab762a65","impliedFormat":1},{"version":"e27451b24234dfed45f6cf22112a04955183a99c42a2691fb4936d63cfe42761","impliedFormat":1},{"version":"2316301dd223d31962d917999acf8e543e0119c5d24ec984c9f22cb23247160c","impliedFormat":1},{"version":"58d65a2803c3b6629b0e18c8bf1bc883a686fcf0333230dd0151ab6e85b74307","impliedFormat":1},{"version":"e818471014c77c103330aee11f00a7a00b37b35500b53ea6f337aefacd6174c9","impliedFormat":1},{"version":"268fd6d9f2e807a39a6c5aa654b00f949feb63d3faa7dd0f9bba7dde9172159c","impliedFormat":1},{"version":"29f823cbe0166e10e7176a94afe609a24b9e5af3858628c541ff8ce1727023cd","impliedFormat":1},{"version":"dc9cc4abaabd5cfd8d2749c9478d0abc7055e1b1fd922dff872e6e95a4175201","signature":"2651a6c04c20c6b829234047caa3db2f1b697af6365b3387872c3f5700dc28a4"},{"version":"12262a57c1c71f8d1bc50d5508ab3c53ad4afd89fd29d97e27ebf46035b3da3e","signature":"c4d6f8fba3839bb1e5ee491b43906b9183d7b8959baebd3ec5913fef4f40b635"},{"version":"decbb658d7b354b7fdc59db5ab541e6327b20ec00c96e891769e50f77d925523","signature":"be8b6bee4b407e0540537b69d6a4874eaf930d6a8b70ecc065c796fd1437c846"},{"version":"8b61608c154f87e13c88b21b5208a3acb906ddcee5e3001f3b27ef13703b61e8","impliedFormat":1},{"version":"f6b6e3d4ec6532a05ccad69c2605b792e7473039b9f16261a199b9dcf1c33084","signature":"c3196bfd12c96e513ae6baf5c945b3bfbaa2e8695693b3628414fc732cbe9fab"},{"version":"ab30e3e6030f247c9ead0b2e6928001e1be20907637719b3559c5da617002798","signature":"8fa424847eae1e9607dad437ba29f73de7ed8a64b60f26feddf422f3e9656655"},{"version":"b39529dc70f822883c8805eba3be4b896603b8be5c21fa9a5e8456853a9cac24","signature":"11b670ed51a4a4a6847d013b9dc50601581fa09816ba6d060c8f13a94df71c3e"},{"version":"7c45a0cff6182af8c36f68d2a3523c0d74c9019b32cd0aa071e236e774b67a71","signature":"fc6cb9ca05da11c96a920ca17e25d9aef74a7fe8e523b8046c5cea481255aeec"},{"version":"e8a7565fa8cc70df160ab9ffcab5098d0cf1b3e646ed266be197f0eacc857b34","signature":"8c4244dae03efb90eb6008beb0eec636d1d5bd8576d80a7c39a4c63e389e88ee"},{"version":"4e63aa0af8005027ec3e47a329ba2bce4ad30a7866f33fa3bc9f13a702022770","signature":"ee324efc620efe75b8389fb704c27a77e6dd246ef3cb238f1151f9768de30764"},{"version":"e6c8c2edceaf3627f7816caf15dcf6393e444ba776e8902e5f65b74d451b5cc6","signature":"d7e0473f2a6a61a3ecd75e7e79efac2edb2df3c3821a437b607d0757da48bd69"},{"version":"a23023a5093a3f8a871a80c958c0948b4bb98bf0a29972758b3c902f830457a2","signature":"9ebfe9eb079314c554dc22cec3fe0071c22226c5cffebfc4308ad406883466dc"},{"version":"952c21e8d1e308d08bf902e415daba0eeb927e60321d023e94c15cb2e211d043","signature":"afdb5288a1739d52d50c117da8b6caedb777042a5fa11f02ade7b4a5bf72d224"},{"version":"6e80e675b53df355531159abae68e983264ed2364f078e27edee37df7bd051da","signature":"a6afd1c9a3668eb51fc397e00dec8dc655aa4dc52479d5dfa95afd821e9b16f6"},{"version":"e2b671779a5c5304390d08a28d3f96338e05e418c4c18624ada291261c1a4d56","signature":"b985c9126287c3b7342fd7316a8a2899cf50d3996dff2cc901000965c9f19b8f"},{"version":"71ad1cc06270386d90b3c21b1bf1f99d65cb8a31851e8e912eb68193cf60e766","signature":"a3d4dd864c61c246a59b05bce5d84c3d219567f85f9a32e539c4a2be8dd58029"},{"version":"485e4b9a91ec3ec31512ee4d7b9aaa7aaac2886bb4770c8022f9f3e20a6e1a03","signature":"17f679537f92a306af086a40d952e8a3cf2c5f99e1fd05eb6674babe31b54ed5"},{"version":"4623d7cf72b29b7f5b223b97cb8618f9c11a6013f9e3ff6519889a423994519b","signature":"bd9508d745eb868afbc50c1a262379fd19b8c8e467c21612b246b8c3b84a4d7b"},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"156a859e21ef3244d13afeeba4e49760a6afa035c149dda52f0c45ea8903b338","impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"0ccdaa19852d25ecd84eec365c3bfa16e7859cadecf6e9ca6d0dbbbee439743f","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc2110f7decca6bfb9392e30421cfa1436479e4a6756e8fec6cbc22625d4f881","affectsGlobalScope":true,"impliedFormat":1},{"version":"096116f8fedc1765d5bd6ef360c257b4a9048e5415054b3bf3c41b07f8951b0b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5e01375c9e124a83b52ee4b3244ed1a4d214a6cfb54ac73e164a823a4a7860a","affectsGlobalScope":true,"impliedFormat":1},{"version":"f90ae2bbce1505e67f2f6502392e318f5714bae82d2d969185c4a6cecc8af2fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b58e207b93a8f1c88bbf2a95ddc686ac83962b13830fe8ad3f404ffc7051fb4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1fefabcb2b06736a66d2904074d56268753654805e829989a46a0161cd8412c5","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"c18a99f01eb788d849ad032b31cafd49de0b19e083fe775370834c5675d7df8e","affectsGlobalScope":true,"impliedFormat":1},{"version":"5247874c2a23b9a62d178ae84f2db6a1d54e6c9a2e7e057e178cc5eea13757fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"156a859e21ef3244d13afeeba4e49760a6afa035c149dda52f0c45ea8903b338","impliedFormat":1},{"version":"10ec5e82144dfac6f04fa5d1d6c11763b3e4dbbac6d99101427219ab3e2ae887","impliedFormat":1},{"version":"615754924717c0b1e293e083b83503c0a872717ad5aa60ed7f1a699eb1b4ea5c","impliedFormat":1},{"version":"14e9acf826baba0ef4b5665704084896e7bcc06f65a9ab13af7e93d27d6b7069","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"21adf13435b9b748529c8cedf80f884e5130b9684188120a686cd2b26a2059c7","impliedFormat":1},{"version":"eec76bf6b9346f3f95fa402621b889489e96930e72295b0369022f332e9b4a6a","impliedFormat":1},{"version":"0ecd58f413f9bc3b7d4383eae31b0c8fc576985cd7404d6f99f8c643543ade74","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"9c32412007b5662fd34a8eb04292fb5314ec370d7016d1c2fb8aa193c807fe22","impliedFormat":1},{"version":"7fd1b31fd35876b0aa650811c25ec2c97a3c6387e5473eb18004bed86cdd76b6","impliedFormat":1},{"version":"4d327f7d72ad0918275cea3eee49a6a8dc8114ae1d5b7f3f5d0774de75f7439a","impliedFormat":1},{"version":"6ebe8ebb8659aaa9d1acbf3710d7dae3e923e97610238b9511c25dc39023a166","impliedFormat":1},{"version":"e85d7f8068f6a26710bff0cc8c0fc5e47f71089c3780fbede05857331d2ddec9","impliedFormat":1},{"version":"7befaf0e76b5671be1d47b77fcc65f2b0aad91cc26529df1904f4a7c46d216e9","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"d33ce35e3f9cfcc1d94eca415bdd3bde94d5b153ffdd33e6c4455c029986c630","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"8aee8b6d4f9f62cf3776cda1305fb18763e2aade7e13cea5bbe699112df85214","impliedFormat":1},{"version":"98498b101803bb3dde9f76a56e65c14b75db1cc8bec5f4db72be541570f74fc5","impliedFormat":1},{"version":"4dc59f6e1dbf3d5f66660fceabe6c174d3261b37b696ae1854f0dbaf255fc753","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"436d7b4543b340b0f3eef4310d524242e41369b9652aa9c70428767c4dcac455","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"12950411eeab8563b349cb7959543d92d8d02c289ed893d78499a19becb5a8cc","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"114f493b30f364255290472111b5a4791d5902c308645670cd0401429cbc6930","impliedFormat":1},{"version":"c3f5289820990ab66b70c7fb5b63cb674001009ff84b13de40619619a9c8175f","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3275d55fac10b799c9546804126239baf020d220136163f763b55a74e50e750","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa68a0a3b7cb32c00e39ee3cd31f8f15b80cac97dce51b6ee7fc14a1e8deb30b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"6c36e755bced82df7fb6ce8169265d0a7bb046ab4e2cb6d0da0cb72b22033e89","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7a93de4ff8a63bafe62ba86b89af1df0ccb5e40bb85b0c67d6bbcfdcf96bf3d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"90e85f9bc549dfe2b5749b45fe734144e96cd5d04b38eae244028794e142a77e","affectsGlobalScope":true,"impliedFormat":1},{"version":"e0a5deeb610b2a50a6350bd23df6490036a1773a8a71d70f2f9549ab009e67ee","affectsGlobalScope":true,"impliedFormat":1},{"version":"d2ae155afe8a01cc0ae612d99117cf8ef16692ba7c4366590156fdec1bcf2d8c","impliedFormat":1},{"version":"3f5e5d9be35913db9fea42a63f3df0b7e3c8703b97670a2125587b4dbbd56d7c","impliedFormat":1},{"version":"c8b8968311ec4e5e97b7b5fb8a65efaba455db9bdcfd7fff7fb15f6e317bfba0","impliedFormat":1},{"version":"57c23df0b5f7a8e26363a3849b0bc7763f6b241207157c8e40089d1df4116f35","affectsGlobalScope":true,"impliedFormat":1},{"version":"3b8bc0c17b54081b0878673989216229e575d67a10874e84566a21025a2461ee","impliedFormat":1},{"version":"5b0db5a58b73498792a29bfebc333438e61906fef75da898b410e24e52229e6f","impliedFormat":1},{"version":"dbe055b2b29a7bab2c1ca8f259436306adb43f469dca7e639a02cd3695d3f621","impliedFormat":1},{"version":"1678b04557dca52feab73cc67610918a7f5e25bfdba3e7fa081acd625d93106d","impliedFormat":1},{"version":"aecbf1d9e6a18dab7d92ef8a89a1444b47e1eb6134cb2bb776a26d55ff58c29a","impliedFormat":1},{"version":"2ea729503db9793f2691162fec3dd1118cab62e96d025f8eeb376d43ec293395","impliedFormat":1},{"version":"9ec87fea42b92894b0f209931a880789d43c3397d09dd99c631ae40a2f7071d1","impliedFormat":1},{"version":"c68e88cdfadfb6c8ba5fc38e58a3a166b0beae77b1f05b7d921150a32a5ffb8d","impliedFormat":1},{"version":"2bc7aa4fba46df0bd495425a7c8201437a7d465f83854fac859df2d67f664df3","impliedFormat":1},{"version":"41d17e1ad9a002feb11c8cdd2777e5bbc0cdb1e3f595d237e4dded0b6949983b","impliedFormat":1},{"version":"1fede9296beac11ce8e6b425396a1791f64341f2be85deebb6286faf6e16306e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce697b6a251d9cad53998c7fd3098072df883b525ec45d83530e434dc6d80dc6","impliedFormat":1},{"version":"719412f054e6ecc35489462c9a21bab0323d173a7d04e55b0ace4b5d86fbeb07","impliedFormat":1},{"version":"0eb5d0cbf09de5d34542b977fd6a933bb2e0817bffe8e1a541b2f1ad1b9af1ff","impliedFormat":1},{"version":"3db996ecdee7aabecc5385976cc07eb66216034a273c07b17d1a85292e9bab0c","impliedFormat":1},{"version":"2c2bdaa1d8ead9f68628d6d9d250e46ee8e81aa4898b4769a36956ae15e060fe","impliedFormat":1},{"version":"c32c840c62d8bd7aeb3147aa6754cd2d922b990a6b6634530cb2ebdce5adc8e9","impliedFormat":1},{"version":"5ff4433a2deae4f85ab1377e90a7554ce6b47ae51c69a84ca30a6e22fae85834","impliedFormat":1},{"version":"82b91e4e42e6c41bc7fc1b6c2dc5eba6a2ba98375eb1f210e6ff6bba2d54177e","impliedFormat":1},{"version":"c1fa52b3d014001e8662fa2669d90ea15373958a288e3b83a3b621733d25292a","affectsGlobalScope":true,"impliedFormat":1},{"version":"cbed824fec91efefc7bbdcb8b43d1a531fdbebd0e2ef19481501ff365a93cb70","impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"d0716593b3f2b0451bcf0c24cfa86dec2235c325c89f201934248b7c742715fc","impliedFormat":1},{"version":"ec501101c2a96133a6c695f934c8f6642149cc728571b29cbb7b770984c1088e","impliedFormat":1},{"version":"b214ebcf76c51b115453f69729ee8aa7b7f8eccdae2a922b568a45c2d7ff52f7","impliedFormat":1},{"version":"429c9cdfa7d126255779efd7e6d9057ced2d69c81859bbab32073bad52e9ba76","impliedFormat":1},{"version":"2991bca2cc0f0628a278df2a2ccdb8d6cbcb700f3761abbed62bba137d5b1790","impliedFormat":1},{"version":"5e66972e83eb4dc7123939bf816e6cbd9ad81af5552db1cab84e6bd9c64d2ecc","affectsGlobalScope":true,"impliedFormat":1},{"version":"230763250f20449fa7b3c9273e1967adb0023dc890d4be1553faca658ee65971","impliedFormat":1},{"version":"c3e9078b60cb329d1221f5878e88cecfa3e74460550e605a58fcfb41a66029ff","impliedFormat":1},{"version":"8413d0641f293aed551c7464615b770d34a02dedede889b9591172287d68e773","impliedFormat":1},{"version":"0ea59f7d3e51440baa64f429253759b106cfcbaf51e474cae606e02265b37cf8","impliedFormat":1},{"version":"bc18a1991ba681f03e13285fa1d7b99b03b67ee671b7bc936254467177543890","impliedFormat":1},{"version":"1b241e24f3227d078c06aeda6e050187ad59a4e591f4467abed44d92b084e08d","impliedFormat":1},{"version":"fa94bbf532b7af8f394b95fa310980d6e20bd2d4c871c6a6cb9f70f03750a44b","impliedFormat":1},{"version":"7fde0e1be5c8be204ffbf428abfcf01da2eb0f130e1bc3f539eb7275f4fd1f58","impliedFormat":1},{"version":"e284328553df5f425a5d33d36a0c3fa66b46af9d097cad6f4d2e8696dfdeb0f1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7fa2214bb0d64701bc6f9ce8cde2fd2ff8c571e0b23065fa04a8a5a6beb91511","impliedFormat":1},{"version":"f36b3fbe2be150a9ca140da48593f21e6a8172004f92ddc549b43efec39f3e54","impliedFormat":1},{"version":"f1c93e046fb3d9b7f8249629f4b63dc068dd839b824dd0aa39a5e68476dc9420","impliedFormat":1},{"version":"016b29bf4926b80255a108c53a1451717350059da04fcae64d1075f5e93bbb39","impliedFormat":1},{"version":"841983e39bd4cbb463be385e92fda11057cab368bf27100a801c492f1d86cbaa","impliedFormat":1},{"version":"1c4f139ade4f6ebf45463505f8155173e5d7a5305e50e0aae0a5e712d6ff3b48","impliedFormat":1},{"version":"e16b319e5aca1031168de823c4946ff8e29629c4c8cc0ec0fcfe2a8ab2155043","impliedFormat":1},{"version":"e4156ddb25aa0e3b5303d372f26957b36778f0f6bbd4326359269873295e3058","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc1b433a84cae05ddc5672d4823170af78606ad21ecef60dbc4570190cbf1357","impliedFormat":1},{"version":"9d3821bc75c59577e52643324cec92fc2145642e8d17cf7ee07a3181f21d985d","impliedFormat":1},{"version":"7f78cfb2b343838612c192cb251746e3a7c62ac7675726a47e130d9b213f6580","impliedFormat":1},{"version":"201db9cf1687fab1adf5282fcba861f382b32303dc4f67c89d59655e78a25461","impliedFormat":1},{"version":"2c3c5c0f54055e87640f5d233716fd889f3034fc7911d603b642369b0dbeb2a7","impliedFormat":1},{"version":"0a20eaf2e4b1e3c1e1f87f7bccb0c936375b23b022baeea750519b7c9bc6ce83","impliedFormat":1},{"version":"b484ec11ba00e3a2235562a41898d55372ccabe607986c6fa4f4aba72093749f","impliedFormat":1},{"version":"a16b91b27bd6b706c687c88cbc8a7d4ee98e5ed6043026d6b84bda923c0aed67","impliedFormat":1},{"version":"1c9e5b1a17b1fc9b3711fb36e0690421261ab2880f15b145155b5b2ba2ab6c2d","impliedFormat":1},{"version":"99ab6d0d660ce4d21efb52288a39fd35bb3f556980ec5463b1ae8f304a3bbc85","impliedFormat":1},{"version":"6eeded8c7e352be6e0efb83f4935ec752513c4d22043b52522b90849a49a3a11","impliedFormat":1},{"version":"6c1ad90050ffbb151cacc68e2d06ea1a26a945659391e32651f5d42b86fd7f2c","impliedFormat":1},{"version":"afa1c49f8e559e413d57343339db857d2a8159435cf9cf7d4deb41718fff1b88","impliedFormat":1},{"version":"6953d7597831d0860c7034cf4f0419687d263b6b98a4b32e37ce6d49615c36e2","impliedFormat":1},{"version":"3ac40516c33b87f751f7507346933081a26cdb8a3e11a6b3aa07d23f803c85db","impliedFormat":1},{"version":"4ac80270b6787c2b77a2d98a9714a71f4363c24b5890314f3ba582c94bfbe779","impliedFormat":1},{"version":"14e9acf826baba0ef4b5665704084896e7bcc06f65a9ab13af7e93d27d6b7069","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"21adf13435b9b748529c8cedf80f884e5130b9684188120a686cd2b26a2059c7","impliedFormat":1},{"version":"eec76bf6b9346f3f95fa402621b889489e96930e72295b0369022f332e9b4a6a","impliedFormat":1},{"version":"171b96f31e3fbdb55fe570f2a29a5ee47223fdca95a84ea2142e4cc4feaf9dfe","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"9c32412007b5662fd34a8eb04292fb5314ec370d7016d1c2fb8aa193c807fe22","impliedFormat":1},{"version":"d243db6b25788f439e7e2f03c05688e92f46764351673bb0e7b2f3631232e186","impliedFormat":1},{"version":"4d327f7d72ad0918275cea3eee49a6a8dc8114ae1d5b7f3f5d0774de75f7439a","impliedFormat":1},{"version":"6ebe8ebb8659aaa9d1acbf3710d7dae3e923e97610238b9511c25dc39023a166","impliedFormat":1},{"version":"e85d7f8068f6a26710bff0cc8c0fc5e47f71089c3780fbede05857331d2ddec9","impliedFormat":1},{"version":"7befaf0e76b5671be1d47b77fcc65f2b0aad91cc26529df1904f4a7c46d216e9","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"d33ce35e3f9cfcc1d94eca415bdd3bde94d5b153ffdd33e6c4455c029986c630","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"8aee8b6d4f9f62cf3776cda1305fb18763e2aade7e13cea5bbe699112df85214","impliedFormat":1},{"version":"98498b101803bb3dde9f76a56e65c14b75db1cc8bec5f4db72be541570f74fc5","impliedFormat":1},{"version":"4dc59f6e1dbf3d5f66660fceabe6c174d3261b37b696ae1854f0dbaf255fc753","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"436d7b4543b340b0f3eef4310d524242e41369b9652aa9c70428767c4dcac455","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"12950411eeab8563b349cb7959543d92d8d02c289ed893d78499a19becb5a8cc","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"114f493b30f364255290472111b5a4791d5902c308645670cd0401429cbc6930","impliedFormat":1},{"version":"b3fb72492a07a76f7bfa29ecadd029eea081df11512e4dfe6f930a5a9cb1fb75","impliedFormat":1},{"version":"cd6db591e858b53f23faad85346a4f43732bb33d6dff5f3f4dc47c4a448804ae","signature":"ad2664f941e8db7e19f9bae8100db326d4d1ed5701d56c4579331e575a43718e"},{"version":"328b1b71f3bedfca3331d6253b6f89aa207d876f1486a1017beebfa39fc8d418","signature":"47b10209e6f074245affea091a75da917d59c0e9bee84a78618c3a46359dc229"}],"root":[60,61,[196,205],[286,288],[290,303],474,475],"options":{"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"module":99,"outDir":"./dist","rootDir":"./src","skipLibCheck":true,"strict":true,"target":9},"referencedMap":[[63,1],[370,2],[371,2],[372,3],[309,4],[373,5],[374,6],[375,7],[307,1],[376,8],[377,9],[378,10],[379,11],[380,12],[381,13],[382,13],[383,14],[384,15],[385,16],[386,17],[310,1],[308,1],[387,18],[388,19],[389,20],[432,21],[390,22],[391,23],[392,22],[393,24],[394,25],[396,26],[397,27],[398,27],[399,27],[400,28],[401,29],[402,30],[403,31],[404,32],[405,33],[406,33],[407,34],[408,1],[409,1],[410,35],[411,36],[412,37],[413,35],[414,38],[415,39],[416,40],[417,41],[418,42],[419,43],[420,44],[421,45],[422,46],[423,47],[424,48],[425,49],[426,50],[427,51],[428,52],[311,22],[312,1],[313,53],[314,54],[315,1],[316,55],[317,1],[361,56],[362,57],[363,58],[364,58],[365,59],[366,1],[367,5],[368,60],[369,57],[429,61],[430,62],[431,63],[395,1],[62,1],[77,1],[135,64],[136,65],[184,66],[75,67],[72,68],[76,69],[185,70],[68,71],[80,72],[119,73],[137,74],[64,1],[66,1],[74,75],[69,76],[67,5],[79,77],[65,1],[78,78],[70,79],[187,80],[121,81],[192,82],[188,83],[189,84],[120,85],[190,1],[133,86],[138,87],[139,88],[134,89],[191,90],[73,91],[111,92],[83,93],[84,94],[85,93],[86,95],[93,96],[91,97],[92,93],[87,93],[110,98],[94,93],[95,94],[96,95],[104,99],[103,97],[97,95],[98,95],[109,100],[99,93],[100,97],[101,93],[102,93],[107,101],[108,102],[88,93],[89,93],[90,95],[105,101],[106,103],[115,104],[112,95],[113,105],[114,106],[116,107],[124,108],[131,109],[130,110],[129,111],[128,112],[127,113],[125,95],[126,95],[117,114],[122,115],[118,116],[123,117],[81,118],[195,119],[193,120],[194,121],[186,122],[82,123],[132,124],[145,125],[143,95],[144,126],[147,127],[146,128],[148,95],[152,129],[150,130],[151,131],[153,132],[156,133],[155,134],[158,135],[157,93],[161,136],[159,94],[160,137],[154,138],[149,139],[162,138],[163,140],[183,141],[164,93],[165,95],[166,142],[167,143],[168,144],[140,145],[141,146],[142,147],[71,1],[169,95],[172,148],[170,95],[171,149],[173,150],[174,151],[177,152],[176,153],[178,154],[179,132],[182,155],[181,156],[180,157],[175,158],[58,1],[59,1],[11,1],[10,1],[2,1],[12,1],[13,1],[14,1],[15,1],[16,1],[17,1],[18,1],[19,1],[3,1],[20,1],[21,1],[4,1],[22,1],[26,1],[23,1],[24,1],[25,1],[27,1],[28,1],[29,1],[5,1],[30,1],[31,1],[32,1],[33,1],[6,1],[37,1],[34,1],[35,1],[36,1],[38,1],[7,1],[39,1],[44,1],[45,1],[40,1],[41,1],[42,1],[43,1],[8,1],[49,1],[46,1],[47,1],[48,1],[50,1],[9,1],[51,1],[52,1],[53,1],[55,1],[54,1],[56,1],[1,1],[57,1],[336,159],[349,160],[333,161],[350,162],[359,163],[324,164],[325,165],[323,166],[358,167],[353,168],[357,169],[327,170],[346,171],[326,172],[356,173],[321,174],[322,168],[328,175],[329,1],[335,176],[332,175],[319,177],[360,178],[351,179],[339,180],[338,175],[340,181],[343,182],[337,183],[341,184],[354,167],[330,185],[331,186],[344,187],[320,162],[348,188],[347,175],[334,186],[342,189],[345,190],[352,1],[318,1],[355,191],[473,192],[448,193],[461,194],[445,195],[462,162],[471,196],[436,197],[437,198],[435,166],[470,167],[465,199],[469,200],[439,201],[458,202],[438,203],[468,204],[433,205],[434,199],[440,206],[441,1],[447,207],[444,206],[305,208],[472,209],[463,210],[451,211],[450,206],[452,212],[455,213],[449,214],[453,215],[466,167],[442,216],[443,217],[456,218],[306,162],[460,219],[459,206],[446,217],[454,220],[457,221],[464,1],[304,1],[467,222],[285,223],[279,224],[283,225],[280,225],[276,224],[284,226],[281,227],[282,225],[277,228],[278,229],[272,230],[213,231],[215,232],[271,1],[214,233],[275,234],[274,235],[273,236],[206,1],[216,231],[217,1],[208,237],[212,238],[207,1],[209,239],[210,240],[211,1],[218,241],[219,241],[220,241],[221,241],[222,241],[223,241],[224,241],[225,241],[226,241],[227,241],[228,241],[229,241],[230,241],[231,241],[233,241],[232,241],[234,241],[235,241],[236,241],[237,241],[238,241],[270,242],[239,241],[240,241],[241,241],[242,241],[243,241],[244,241],[245,241],[246,241],[247,241],[248,241],[249,241],[250,241],[251,241],[253,241],[252,241],[254,241],[255,241],[256,241],[257,241],[258,241],[259,241],[260,241],[261,241],[262,241],[263,241],[264,241],[265,241],[266,241],[269,241],[267,241],[268,241],[289,1],[203,1],[298,243],[297,243],[299,244],[200,245],[60,1],[196,246],[474,247],[302,248],[197,249],[300,250],[204,246],[198,251],[199,252],[301,1],[286,253],[287,254],[475,255],[294,256],[295,257],[201,258],[303,259],[61,260],[202,261],[205,262],[288,263],[296,264],[290,265],[291,266],[292,267],[293,268]],"latestChangedDtsFile":"./dist/tools/write-handler.d.ts","version":"6.0.3"} \ No newline at end of file diff --git a/packages/vscode-ide-companion/.vscodeignore b/packages/vscode-ide-companion/.vscodeignore new file mode 100644 index 00000000..68a0eac7 --- /dev/null +++ b/packages/vscode-ide-companion/.vscodeignore @@ -0,0 +1,8 @@ +.vscode/** +.vscodeignore +node_modules/** +src/** +tsconfig*.json +**/*.ts +!dist/** +!LICENSE diff --git a/packages/vscode-ide-companion/LICENSE b/packages/vscode-ide-companion/LICENSE new file mode 100644 index 00000000..7fd7a206 --- /dev/null +++ b/packages/vscode-ide-companion/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 lessweb + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/packages/vscode-ide-companion/README.md b/packages/vscode-ide-companion/README.md new file mode 100644 index 00000000..ee11be0f --- /dev/null +++ b/packages/vscode-ide-companion/README.md @@ -0,0 +1,94 @@ +# Deep Code + +[Deep Code](https://marketplace.visualstudio.com/items?itemName=vegamo.deepcode-vscode) 是 Visual Studio Code 的 AI 编码助手扩展,专门为最新的 `deepseek-v4` 模型优化。 + +## 配置 + +创建 `~/.deepcode/settings.json` 文件,内容如下: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-..." + }, + "thinkingEnabled": true, + "reasoningEffort": "max" +} +``` + +## 主要功能 + +### **Skills** +Deep Code 支持 agent skills,允许您扩展助手的能力: + +- **User-level Skills**:从 `~/.agents/skills/` 目录中发现并激活 skills。 +- **Project-level Skills**:从 `./.agents/skills/` 目录中加载项目专属 skills,并兼容旧的 `./.deepcode/skills/` 目录。 + +### **为 DeepSeek 优化** +- 专门为 DeepSeek 模型性能调优。 +- 通过使用[上下文缓存](https://api-docs.deepseek.com/guides/kv_cache)来降低成本。 +- 原生支持[思考模式](https://api-docs.deepseek.com/guides/thinking_mode)和思考强度控制。 + +## 支持的模型 + +- `deepseek-v4-pro`(推荐使用) +- `deepseek-v4-flash` +- 任何其他 OpenAI 兼容模型 + +## 截图示例 + +![screenshot](resources/deepcode_screenshot.png) + +## Deep Code CLI + +```bash +npm install -g @vegamo/deepcode-cli +``` + +![intro1](https://raw.githubusercontent.com/lessweb/deepcode-cli/main/resources/intro1.png) + +> VSCode插件和CLI共享配置文件和数据,但运行时没有依赖。 + +- GitHub: https://github.com/lessweb/deepcode-cli + +## 常见问题 + +### 如何将 Deep Code 从左侧边栏移动到右侧边栏(Secondary Side Bar)? + +![faq1](resources/faq1.gif) + +### Deep Code是否支持理解图片? + +Deep Code支持多模态,但目前deepseek-v4不支持多模态。有些模型虽然有多模态能力,但对多轮对话请求的限制太严。目前多模态输入推荐使用火山方舟的Doubao-Seed-2.0-pro模型,适配效果最好。 + +### 怎样在任务完成后自动给Slack发消息? + +编写一个调用Slack webhook的Shell通知脚本,然后在`~/.deepcode/settings.json`中将`notify`字段设为该脚本的完整路径即可。详细步骤可参考:https://binfer.net/share/jby5xnc-so6g + +### 是否支持Coding Plan? + +支持。只要把`~/.deepcode/settings.json`的env.BASE_URL配置为OpenAI兼容的接口地址就行。以火山方舟的Coding Plan为例,`~/.deepcode/settings.json`这样配置: + +```json +{ + "env": { + "MODEL": "ark-code-latest", + "BASE_URL": "https://ark.cn-beijing.volces.com/api/coding/v3", + "API_KEY": "**************" + }, + "thinkingEnabled": true +} +``` + +## 获取帮助 +- 在 GitHub Issues 上报告错误或请求功能 (https://github.com/lessweb/deepcode/issues) + +## 支持我们 + +如果你觉得这个插件对你有帮助,请考虑通过以下方式支持我们: + +- 在 GitHub 上给我们一个 Star (https://github.com/lessweb/deepcode) +- 向我们提交反馈和建议 +- 分享给你的朋友和同事 diff --git a/packages/vscode-ide-companion/README_cn.md b/packages/vscode-ide-companion/README_cn.md new file mode 100644 index 00000000..ee11be0f --- /dev/null +++ b/packages/vscode-ide-companion/README_cn.md @@ -0,0 +1,94 @@ +# Deep Code + +[Deep Code](https://marketplace.visualstudio.com/items?itemName=vegamo.deepcode-vscode) 是 Visual Studio Code 的 AI 编码助手扩展,专门为最新的 `deepseek-v4` 模型优化。 + +## 配置 + +创建 `~/.deepcode/settings.json` 文件,内容如下: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-..." + }, + "thinkingEnabled": true, + "reasoningEffort": "max" +} +``` + +## 主要功能 + +### **Skills** +Deep Code 支持 agent skills,允许您扩展助手的能力: + +- **User-level Skills**:从 `~/.agents/skills/` 目录中发现并激活 skills。 +- **Project-level Skills**:从 `./.agents/skills/` 目录中加载项目专属 skills,并兼容旧的 `./.deepcode/skills/` 目录。 + +### **为 DeepSeek 优化** +- 专门为 DeepSeek 模型性能调优。 +- 通过使用[上下文缓存](https://api-docs.deepseek.com/guides/kv_cache)来降低成本。 +- 原生支持[思考模式](https://api-docs.deepseek.com/guides/thinking_mode)和思考强度控制。 + +## 支持的模型 + +- `deepseek-v4-pro`(推荐使用) +- `deepseek-v4-flash` +- 任何其他 OpenAI 兼容模型 + +## 截图示例 + +![screenshot](resources/deepcode_screenshot.png) + +## Deep Code CLI + +```bash +npm install -g @vegamo/deepcode-cli +``` + +![intro1](https://raw.githubusercontent.com/lessweb/deepcode-cli/main/resources/intro1.png) + +> VSCode插件和CLI共享配置文件和数据,但运行时没有依赖。 + +- GitHub: https://github.com/lessweb/deepcode-cli + +## 常见问题 + +### 如何将 Deep Code 从左侧边栏移动到右侧边栏(Secondary Side Bar)? + +![faq1](resources/faq1.gif) + +### Deep Code是否支持理解图片? + +Deep Code支持多模态,但目前deepseek-v4不支持多模态。有些模型虽然有多模态能力,但对多轮对话请求的限制太严。目前多模态输入推荐使用火山方舟的Doubao-Seed-2.0-pro模型,适配效果最好。 + +### 怎样在任务完成后自动给Slack发消息? + +编写一个调用Slack webhook的Shell通知脚本,然后在`~/.deepcode/settings.json`中将`notify`字段设为该脚本的完整路径即可。详细步骤可参考:https://binfer.net/share/jby5xnc-so6g + +### 是否支持Coding Plan? + +支持。只要把`~/.deepcode/settings.json`的env.BASE_URL配置为OpenAI兼容的接口地址就行。以火山方舟的Coding Plan为例,`~/.deepcode/settings.json`这样配置: + +```json +{ + "env": { + "MODEL": "ark-code-latest", + "BASE_URL": "https://ark.cn-beijing.volces.com/api/coding/v3", + "API_KEY": "**************" + }, + "thinkingEnabled": true +} +``` + +## 获取帮助 +- 在 GitHub Issues 上报告错误或请求功能 (https://github.com/lessweb/deepcode/issues) + +## 支持我们 + +如果你觉得这个插件对你有帮助,请考虑通过以下方式支持我们: + +- 在 GitHub 上给我们一个 Star (https://github.com/lessweb/deepcode) +- 向我们提交反馈和建议 +- 分享给你的朋友和同事 diff --git a/packages/vscode-ide-companion/README_en.md b/packages/vscode-ide-companion/README_en.md new file mode 100644 index 00000000..40b199bc --- /dev/null +++ b/packages/vscode-ide-companion/README_en.md @@ -0,0 +1,87 @@ +# Deep Code + +[Deep Code](https://marketplace.visualstudio.com/items?itemName=vegamo.deepcode-vscode) is an AI coding assistant extension for Visual Studio Code, specifically optimized for the latest `deepseek-v4` model. + +## Configuration + +Create `~/.deepcode/settings.json` with: + +```json +{ + "env": { + "MODEL": "deepseek-v4-pro", + "BASE_URL": "https://api.deepseek.com", + "API_KEY": "sk-..." + }, + "thinkingEnabled": true, + "reasoningEffort": "max" +} +``` + +## Key Features + +### **Skills** +Deep Code supports agent skills that allows you to extend the assistant's capabilities: + +- **User-level Skills**: discovered and activated from `~/.agents/skills/`. +- **Project-level Skills**: loaded from `./.agents/skills/` for project-specific workflows, with legacy `./.deepcode/skills/` compatibility. + +### **Optimized for DeepSeek** +- Specifically tuned for DeepSeek model performance. +- Reduce costs by using [Context Caching](https://api-docs.deepseek.com/guides/kv_cache). +- Natively supports [Thinking Mode](https://api-docs.deepseek.com/guides/thinking_mode) and Thinking Effort Control. + +## Supported Models + +- `deepseek-v4-pro` (Recommended) +- `deepseek-v4-flash` +- `deepseek-chat` +- Any other OpenAI-compatible model + +## Screenshot + +![screenshot](resources/deepcode_screenshot.png) + +## Deep Code CLI + +```bash +npm install -g @vegamo/deepcode-cli +``` + +![intro1](https://raw.githubusercontent.com/lessweb/deepcode-cli/main/resources/intro1.png) + +> The VSCode plugin and CLI share configuration and data, but they have no dependencies at runtime. + +- GitHub: https://github.com/lessweb/deepcode-cli + +## FAQ + +### How can I move Deep Code from the left sidebar to the right (Secondary Side Bar) in VS Code? + +![faq1](resources/faq1.gif) + +### Does Deep Code support understanding images? + +Deep Code supports multimodal, but `deepseek-v4` does not support multimodal yet. Some models have multimodal capabilities but impose strict limits on multi-turn dialogue requests. For multimodal input, we recommend using the Volcano Ark `Doubao-Seed-2.0-pro` model, which has the best integration. + +### How to automatically send a Slack message after a task completes? + +Write a shell notification script that calls a Slack webhook, then set the `notify` field in `~/.deepcode/settings.json` to the full path of the script. For detailed steps, refer to: https://binfer.net/share/jby5xnc-so6g + +### Does it support Coding Plan? + +Yes. Just set `env.BASE_URL` in `~/.deepcode/settings.json` to an OpenAI-compatible API endpoint. Take Volcano Ark's Coding Plan as an example, configure `~/.deepcode/settings.json` as follows: + +```json +{ + "env": { + "MODEL": "ark-code-latest", + "BASE_URL": "https://ark.cn-beijing.volces.com/api/coding/v3", + "API_KEY": "**************" + }, + "thinkingEnabled": true +} +``` + +## Getting Help +- Report bugs or request features on GitHub Issues (https://github.com/lessweb/deepcode/issues) diff --git a/packages/vscode-ide-companion/package.json b/packages/vscode-ide-companion/package.json new file mode 100644 index 00000000..78ff140e --- /dev/null +++ b/packages/vscode-ide-companion/package.json @@ -0,0 +1,85 @@ +{ + "name": "deepcode-vscode", + "version": "0.1.22", + "publisher": "vegamo", + "displayName": "Deep Code", + "description": "Deep Code VSCode companion — AI-assisted development in your editor", + "license": "MIT", + "type": "commonjs", + "main": "./out/extension.js", + "repository": { + "type": "git", + "url": "git+https://github.com/lessweb/deepcode-cli.git" + }, + "engines": { + "vscode": "^1.85.0" + }, + "categories": [ + "Other" + ], + "icon": "resources/deepcoding_icon.png", + "activationEvents": [], + "files": [ + "out/extension.js", + "resources/**", + "README.md", + "README_cn.md", + "README_en.md", + "LICENSE" + ], + "contributes": { + "commands": [ + { + "command": "deepcode.openView", + "title": "Open Deep Code", + "icon": { + "light": "resources/deepcoding_icon.svg", + "dark": "resources/deepcoding_icon.svg" + } + } + ], + "viewsContainers": { + "activitybar": [ + { + "id": "deepcode", + "title": "Deep Code", + "icon": "resources/deepcoding_icon.png" + } + ] + }, + "views": { + "deepcode": [ + { + "id": "deepcode.chatView", + "name": "Deep Code", + "icon": "resources/deepcoding_icon.png", + "type": "webview" + } + ] + }, + "menus": { + "editor/title": [ + { + "command": "deepcode.openView", + "group": "navigation@100" + } + ] + } + }, + "scripts": { + "typecheck": "tsc -p ./ --noEmit", + "build": "node ../../scripts/esbuild-vscode.config.js", + "prepublishOnly": "npm run build", + "package": "vsce package --no-dependencies", + "test": "node src/tests/run-tests.mjs" + }, + "dependencies": { + "@vegamo/deepcode-core": "file:../core", + "markdown-it": "^14.2.0" + }, + "devDependencies": { + "@types/markdown-it": "^14.1.1", + "@types/vscode": "^1.85.0", + "@vscode/vsce": "^3.6.0" + } +} diff --git a/packages/vscode-ide-companion/resources/deepcode_screenshot.png b/packages/vscode-ide-companion/resources/deepcode_screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..3e1f2a9d4cfbb0390034474d1daddd1897cf6568 GIT binary patch literal 357519 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 z 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%0D24v6 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ÄutX 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%0AY4-%#+&uKg;9Rbbb=< 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ÒSH8jAuPoT5xQOjUtomB(r)!!7>o#(F0UPw7D11g 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

d<(5R zfWVOdlj6ccMrP*kqy)cP|L^9mW|0CioiDKo39Gu5x)3!%&>Kz4Vpe!#OS?RU&}AnL z+iz0(2jRF2Kj=JvQXl8NpJuE~QCs3aO)aO#9e&WCc+3fmCde9AzBiyZq0BpJrya>n z>tDdVoNT58KEFlph!J=N7od@mxnigOz#f@LH4H;K9`6 zi*>$HLOPOr(({+)z+k;r#Mk`~TGV3;ydcOa=U|-=&E1F=rVyd$^${YbsB!UFXhu{i zm^0I>7B=tdIrLd1eHu6`B+&xukBP&;I>Pmb5;HVYF7~8dAd%&wu({$nbG<^n)54d0 zOIE1I3&~I!_gL=D`2gZ65!kOBd6f6RnG^olABP?RtB}p>=y9tW@(3x8WP{%>Jzk4= zL{#yLpNBuG5du1RLm+@WQB5I$=^kgAY&a0irsFFe8hT!6oV zT_KcO$aq57elJ~0N6%_xg2kBU=NREuO^P$6tvbapSiet<^J;|f77nA2>i8*`#GcmU zBPayd%`HFqYZ-KIM3bKAzWI%?9V4!dv{&t0{8}N%t@Qd>|{O L2r85K`04)vaX67( literal 0 HcmV?d00001 diff --git a/packages/vscode-ide-companion/resources/deepcoding_icon.png b/packages/vscode-ide-companion/resources/deepcoding_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7268ce7e8928fc179bbd2df71d29769e8988af13 GIT binary patch literal 77727 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�MEsfSEJc?6qjCTdMZ`}9o2s7sE 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 \ No newline at end of file diff --git a/packages/vscode-ide-companion/resources/faq1.gif b/packages/vscode-ide-companion/resources/faq1.gif new file mode 100644 index 0000000000000000000000000000000000000000..93d694497af26e6122e1e3ff50940990bbf84953 GIT binary patch literal 186246 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⪙ouSZ)M+%iGF!$ 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 { + const reader = new FileReader(); + reader.onload = () => resolve(typeof reader.result === "string" ? reader.result : ""); + reader.onerror = () => reject(reader.error || new Error("Failed to read file.")); + reader.readAsDataURL(file); + }); + } + + function pickImageFileFromClipboard(event) { + const items = Array.from(event.clipboardData?.items || []); + for (const item of items) { + if (item.kind !== "file") { + continue; + } + const file = item.getAsFile(); + if (isImageFile(file)) { + return file; + } + } + return null; + } + + function createPromptAttachmentManager(options) { + const promptInput = options?.promptInput; + const inputWrap = options?.inputWrap; + const toolsLine = options?.toolsLine; + const onAttachmentChange = + typeof options?.onAttachmentChange === "function" ? options.onAttachmentChange : function () {}; + + if (!promptInput || !inputWrap || !toolsLine) { + throw new Error("Prompt attachment manager requires promptInput, inputWrap, and toolsLine."); + } + + let attachment = null; + let previewPopup = null; + let previewImage = null; + + function ensurePreviewPopup() { + if (previewPopup) { + return; + } + + previewPopup = createElement("div", "chat-attached-context-preview"); + previewImage = createElement("img", "chat-attached-context-preview-image"); + previewImage.alt = ATTACHMENT_LABEL; + previewPopup.appendChild(previewImage); + document.body.appendChild(previewPopup); + } + + function hidePreview() { + if (!previewPopup) { + return; + } + previewPopup.classList.remove("show"); + } + + function updatePreviewPosition(anchor) { + if (!previewPopup || !anchor) { + return; + } + + const rect = anchor.getBoundingClientRect(); + const popupRect = previewPopup.getBoundingClientRect(); + const viewportWidth = window.innerWidth; + const viewportHeight = window.innerHeight; + + let left = rect.left; + let top = rect.top - popupRect.height - PREVIEW_OFFSET; + + if (left + popupRect.width > viewportWidth - 12) { + left = viewportWidth - popupRect.width - 12; + } + if (left < 12) { + left = 12; + } + if (top < 12) { + top = rect.bottom + PREVIEW_OFFSET; + } + if (top + popupRect.height > viewportHeight - 12) { + top = Math.max(12, viewportHeight - popupRect.height - 12); + } + + previewPopup.style.left = left + "px"; + previewPopup.style.top = top + "px"; + } + + function showPreview(anchor) { + if (!attachment) { + return; + } + + ensurePreviewPopup(); + previewImage.src = attachment.dataUrl; + previewPopup.classList.add("show"); + updatePreviewPosition(anchor); + } + + function emitChange() { + onAttachmentChange({ + hasAttachments: Boolean(attachment), + attachments: attachment ? [attachment] : [], + }); + } + + function clear() { + attachment = null; + toolsLine.innerHTML = ""; + toolsLine.classList.remove("has-attachment"); + hidePreview(); + emitChange(); + } + + function createAttachmentNode() { + const wrapper = createElement("div", "chat-attached-context-attachment show-file-icons"); + wrapper.tabIndex = 0; + wrapper.setAttribute("role", "button"); + wrapper.setAttribute("aria-label", ATTACHMENT_LABEL + " (删除)"); + wrapper.draggable = true; + + const removeButton = createElement("a", "monaco-button codicon codicon-close"); + removeButton.tabIndex = -1; + removeButton.setAttribute("role", "button"); + removeButton.setAttribute("aria-label", "从上下文中移除"); + removeButton.href = "#"; + removeButton.textContent = "×"; + removeButton.addEventListener("click", (event) => { + event.preventDefault(); + event.stopPropagation(); + clear(); + }); + + const iconLabel = createElement("div", "monaco-icon-label"); + const iconLabelContainer = createElement("div", "monaco-icon-label-container"); + const iconNameContainer = createElement("span", "monaco-icon-name-container"); + iconLabelContainer.appendChild(iconNameContainer); + iconLabel.appendChild(iconLabelContainer); + + const pill = createElement("div", "chat-attached-context-pill"); + const image = createElement("img", "chat-attached-context-pill-image"); + image.src = attachment.dataUrl; + image.alt = ATTACHMENT_LABEL; + pill.appendChild(image); + + const text = createElement("span", "chat-attached-context-custom-text"); + text.textContent = ATTACHMENT_LABEL; + + wrapper.appendChild(removeButton); + wrapper.appendChild(iconLabel); + wrapper.appendChild(pill); + wrapper.appendChild(text); + + const show = () => showPreview(wrapper); + wrapper.addEventListener("mouseenter", show); + wrapper.addEventListener("focus", show); + wrapper.addEventListener("mouseleave", hidePreview); + wrapper.addEventListener("blur", hidePreview); + wrapper.addEventListener("dragstart", (event) => { + event.preventDefault(); + }); + wrapper.addEventListener("keydown", (event) => { + if (event.key === "Delete" || event.key === "Backspace") { + event.preventDefault(); + clear(); + } + }); + + return wrapper; + } + + function render() { + toolsLine.innerHTML = ""; + toolsLine.classList.toggle("has-attachment", Boolean(attachment)); + if (!attachment) { + hidePreview(); + return; + } + toolsLine.appendChild(createAttachmentNode()); + } + + function setAttachmentData(data) { + if (!data?.dataUrl) { + return false; + } + + attachment = { + name: data.name || ATTACHMENT_LABEL, + mimeType: data.mimeType || "image/png", + dataUrl: data.dataUrl, + label: ATTACHMENT_LABEL, + }; + render(); + emitChange(); + return true; + } + + async function setAttachmentFromFile(file) { + if (!isImageFile(file)) { + return false; + } + + const dataUrl = await readFileAsDataUrl(file); + return setAttachmentData({ + name: file.name || ATTACHMENT_LABEL, + mimeType: file.type || "image/png", + dataUrl, + label: ATTACHMENT_LABEL, + }); + } + + async function handlePaste(event) { + const file = pickImageFileFromClipboard(event); + if (!file) { + return; + } + + event.preventDefault(); + try { + await setAttachmentFromFile(file); + } catch (error) { + console.error("Failed to attach pasted image.", error); + } + } + + promptInput.addEventListener("paste", handlePaste); + + window.addEventListener("resize", () => { + const attachmentNode = toolsLine.querySelector(".chat-attached-context-attachment"); + if (previewPopup?.classList.contains("show") && attachmentNode) { + updatePreviewPosition(attachmentNode); + } + }); + + window.addEventListener( + "scroll", + () => { + const attachmentNode = toolsLine.querySelector(".chat-attached-context-attachment"); + if (previewPopup?.classList.contains("show") && attachmentNode) { + updatePreviewPosition(attachmentNode); + } + }, + true + ); + + return { + clear, + hasAttachments() { + return Boolean(attachment); + }, + getImageUrls() { + return attachment ? [attachment.dataUrl] : []; + }, + }; + } + + window.createPromptAttachmentManager = createPromptAttachmentManager; +})(); diff --git a/packages/vscode-ide-companion/resources/webview.css b/packages/vscode-ide-companion/resources/webview.css new file mode 100644 index 00000000..ea1d71a2 --- /dev/null +++ b/packages/vscode-ide-companion/resources/webview.css @@ -0,0 +1,1604 @@ +/* CSS Variables */ +:root { + --bg: var(--vscode-editor-background); + --panel: var(--vscode-sideBar-background); + --panel-2: var(--vscode-editor-inactiveSelectionBackground); + --muted: var(--vscode-descriptionForeground); + --accent: var(--vscode-focusBorder); + --accent-2: var(--vscode-button-background); + --danger: var(--vscode-errorForeground); + --shadow: rgba(0, 0, 0, 0.15); + --border-color: var(--vscode-panel-border); + --prompt-line-height: 18px; + --prompt-min-height: calc(var(--prompt-line-height) * 3 + 20px); + --prompt-max-height: calc(var(--prompt-line-height) * 10 + 20px); +} + +/* Global Styles */ +* { + box-sizing: border-box; +} + +body { + margin: 0; + padding: 0; + height: 100vh; + overflow-x: hidden; + background: var(--bg); + color: var(--vscode-foreground); + font-family: var(--vscode-font-family); + font-size: var(--vscode-font-size); +} + +/* App Container */ +.app { + height: 100vh; + display: flex; + flex-direction: column; + position: relative; + overflow-x: hidden; +} + +/* Header Container */ +.header-container { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 4px 16px; + background: var(--vscode-sideBar-background); + border-bottom: 1px solid var(--border-color); + flex-shrink: 0; + position: relative; +} + +.header-left { + position: relative; + min-width: 0; +} + +/* Session Selector */ +.session-selector { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 10px; + background: transparent; + border: none; + border-radius: 4px; + cursor: pointer; + transition: background 0.2s; + width: 100%; +} + +.session-selector:hover { + background: var(--vscode-toolbar-hoverBackground); +} + +.session-selector.open .session-selector-icon { + transform: rotate(180deg); +} + +.session-selector-title { + display: flex; + align-items: center; + gap: 8px; + font-size: 13px; + color: var(--vscode-foreground); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-align: left; +} + +.session-logo { + width: 16px; + height: 16px; + flex-shrink: 0; +} + +.session-title-text { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; +} + +.session-selector-icon { + width: 16px; + height: 16px; + fill: var(--vscode-foreground); + transition: transform 0.2s; + flex-shrink: 0; +} + +/* Header New Button */ +.header-new-btn { + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 12px; + transition: background 0.2s; + background: none; + display: flex; + align-items: center; + justify-content: center; + padding: 6px; + flex-shrink: 0; +} + +.header-new-btn:hover { + background: var(--vscode-toolbar-hoverBackground); +} + +.header-new-icon { + width: 16px; + height: 16px; + fill: var(--vscode-foreground); +} + +/* Session Dropdown */ +.session-dropdown { + position: absolute; + top: calc(100% + 8px); + left: 16px; + right: 16px; + background: var(--vscode-dropdown-background); + border: 1px solid var(--border-color); + border-radius: 4px; + max-height: 400px; + z-index: 10000; + display: none; + box-shadow: 0 4px 12px var(--shadow); + flex-direction: column; +} + +.session-dropdown.show { + display: flex; +} + +.session-search-box { + padding: 8px; + flex-shrink: 0; +} + +.session-search-input { + width: 100%; + padding: 6px 10px; + background: var(--vscode-input-background); + color: var(--vscode-input-foreground); + border: 1px solid var(--vscode-input-border); + border-radius: 4px; + font-size: 13px; + outline: none; + font-family: var(--vscode-font-family); + outline: none; +} + +.session-search-input:focus { + border-color: var(--vscode-focusBorder); + outline: none; +} + +.session-search-input::placeholder { + color: var(--vscode-input-placeholderForeground); +} + +.session-dropdown-list { + flex: 1; + overflow-y: auto; + min-height: 0; + padding: 8px 12px 12px; +} + +.session-dropdown-group { + margin-bottom: 12px; +} + +.session-dropdown-group:last-child { + margin-bottom: 0; +} + +.session-dropdown-group-title { + font-size: 11px; + font-weight: 500; + color: var(--vscode-descriptionForeground); + letter-spacing: 0.5px; + padding: 6px 6px 8px; + margin-bottom: 2px; +} + +.session-dropdown-empty { + padding: 20px; + text-align: center; + color: var(--vscode-descriptionForeground); + font-size: 13px; +} + +.session-dropdown-item { + padding: 6px; + cursor: pointer; + transition: background 0.2s; + display: flex; + gap: 12px; + margin-bottom: 6px; + border-radius: 4px; + align-items: center; +} + +.session-dropdown-item:last-child { + margin-bottom: 0; +} + +.session-dropdown-item:hover { + background: var(--vscode-list-hoverBackground); +} + +.session-dropdown-item.active { + background: var(--vscode-list-activeSelectionBackground); +} + +.session-dropdown-item.active .session-dropdown-summary { + color: var(--vscode-list-activeSelectionForeground); +} + +.session-dropdown-item.active .session-dropdown-time { + color: var(--vscode-list-activeSelectionForeground); + opacity: 0.8; +} + +.session-dropdown-summary { + font-size: 13px; + color: var(--vscode-foreground); + margin-bottom: 4px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + flex: 1; + font-weight: 500; +} + +.session-dropdown-time { + font-size: 11px; + color: var(--vscode-descriptionForeground); +} + +.session-dropdown-summary mark { + background-color: var(--vscode-editor-findMatchHighlightBackground); + color: var(--vscode-editor-foreground); + padding: 0 2px; + border-radius: 2px; +} + +/* Chat Container */ +.chat-container { + display: flex; + flex-direction: column; + flex: 1; + overflow: hidden; + overflow-x: hidden; +} + +.chat-container.hidden { + display: none; +} + +/* Messages */ +.messages { + flex: 1; + overflow-y: auto; + overflow-x: hidden; + padding: 16px; + display: flex; + flex-direction: column; + gap: 1px; + background: var(--vscode-sideBar-background); +} + +/* Message Bubbles */ +.bubble { + padding: 16px; + font-size: 13px; + width: 100%; + border: 1px solid transparent; + color: var(--vscode-foreground); + border-radius: 6px; + position: relative; + overflow-wrap: break-word; + word-break: break-word; +} + +/* Collapsible Bubble */ +.bubble-collapsible-header { + display: flex; + align-items: flex-start; + gap: 8px; + cursor: pointer; + user-select: none; + padding: 4px 0; + position: relative; +} + +.bubble-collapsible-header:hover .bubble-title-text { + opacity: 0.8; +} + +.bubble-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background-color: var(--vscode-descriptionForeground); + flex-shrink: 0; + margin-top: 6px; + position: relative; + z-index: 3; +} + +.bubble-dot.success { + background-color: var(--vscode-terminal-ansiGreen); +} + +.bubble-dot.error { + background-color: var(--vscode-terminal-ansiRed); +} + +/* 连接线:只在有 connect-to-prev class 时显示向上的连接线 */ +.bubble-dot.connect-to-prev::before { + content: ""; + position: absolute; + left: 3.5px; + bottom: 8px; + width: 1px; + height: var(--line-height, 0px); + background-color: var(--vscode-panel-border); + z-index: 0; +} + +.bubble-title { + flex: 1; + font-size: 13px; + color: var(--vscode-foreground); + display: flex; + align-items: center; + gap: 6px; + flex-wrap: nowrap; + min-width: 0; + overflow: visible; +} + +.bubble-title-text { + display: inline-flex; + align-items: center; + gap: 6px; + flex: 1; + min-width: 0; + overflow: visible; +} + +.bubble-title-text b { + text-transform: capitalize; + flex-shrink: 0; +} + +.bubble-title .tool-params { + color: var(--vscode-descriptionForeground); + font-weight: normal; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + flex: 1; + min-width: 0; + position: relative; + display: inline-block; +} + +/* Tooltip styles */ +.tooltip { + position: fixed; + padding: 4px 8px; + background: var(--vscode-editorHoverWidget-background); + color: var(--vscode-editorHoverWidget-foreground); + border: 1px solid var(--vscode-editorHoverWidget-border); + border-radius: 4px; + font-size: 12px; + white-space: normal; + word-break: break-word; + max-width: 400px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + z-index: 10000; + pointer-events: none; + opacity: 0; + visibility: hidden; + transition: + opacity 0.5s, + visibility 0.5s; +} + +.tooltip.show { + opacity: 1; + visibility: visible; +} + +.bubble-toggle { + display: inline-flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + flex-shrink: 0; + color: var(--vscode-descriptionForeground); + font-size: 12px; +} + +.bubble-toggle svg { + width: 12px; + height: 12px; + fill: var(--vscode-descriptionForeground); + transition: transform 0.2s; +} + +.bubble-toggle.expanded svg { + transform: rotate(180deg); +} + +.bubble-collapsible-content { + margin-top: 8px; + margin-left: 24px; + padding: 8px 12px; + background: var(--vscode-textCodeBlock-background); + border: 1px solid var(--border-color); + border-radius: 4px; + overflow: auto; + max-width: calc(100% - 24px); + font-family: var(--vscode-editor-font-family); + font-size: 12px; + white-space: pre-wrap; + word-break: break-word; + max-height: 300px; +} + +.tool-result-details { + display: flex; + flex-direction: column; + gap: 10px; + font-family: var(--vscode-font-family); + white-space: normal; +} + +.tool-result-summary { + color: var(--vscode-foreground); + line-height: 1.5; +} + +.update-plan-result { + border: 1px solid var(--border-color); + border-radius: 6px; + background: var(--vscode-editor-background); + color: var(--vscode-editor-foreground); + font-family: var(--vscode-font-family); + font-size: 13px; + line-height: 1.45; + padding: 10px; + white-space: normal; +} + +.update-plan-heading { + color: var(--vscode-foreground); + font-size: 13px; + font-weight: 650; + line-height: 1.35; + margin: 0 0 8px; +} + +.update-plan-heading:not(:first-child) { + margin-top: 12px; +} + +.update-plan-spacer { + height: 6px; +} + +.update-plan-paragraph { + margin: 4px 0; +} + +.update-plan-task, +.update-plan-bullet { + display: grid; + grid-template-columns: 18px 1fr; + gap: 8px; + align-items: flex-start; + margin: 5px 0; + padding-left: calc(var(--plan-indent, 0) * 18px); +} + +.update-plan-status { + width: 14px; + height: 14px; + margin-top: 2px; + border: 1px solid var(--vscode-descriptionForeground); + border-radius: 50%; + color: var(--vscode-editor-background); + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 10px; + font-weight: 700; + line-height: 1; +} + +.update-plan-task.status-done .update-plan-status { + background: var(--vscode-testing-iconPassed, #2ea043); + border-color: var(--vscode-testing-iconPassed, #2ea043); +} + +.update-plan-task.status-active .update-plan-status { + background: var(--vscode-charts-blue, #3794ff); + border-color: var(--vscode-charts-blue, #3794ff); +} + +.update-plan-task.status-attention .update-plan-status { + background: var(--vscode-testing-iconFailed, #f85149); + border-color: var(--vscode-testing-iconFailed, #f85149); +} + +.update-plan-task.status-todo .update-plan-status { + background: transparent; +} + +.update-plan-task.status-done .update-plan-task-text { + color: var(--vscode-descriptionForeground); + text-decoration: line-through; +} + +.update-plan-bullet-marker { + color: var(--vscode-descriptionForeground); + line-height: 1.45; + text-align: center; +} + +.update-plan-markdown code { + border-radius: 3px; + background: var(--vscode-textCodeBlock-background); + font-family: var(--vscode-editor-font-family); + font-size: 0.92em; + padding: 1px 4px; +} + +.tool-result-file-row { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; +} + +.tool-result-label { + color: var(--vscode-descriptionForeground); + font-size: 11px; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; +} + +.tool-result-filepath { + border: none; + background: none; + color: var(--vscode-textLink-foreground, var(--vscode-button-background)); + cursor: pointer; + font: inherit; + padding: 0; + text-decoration: underline; + text-underline-offset: 2px; + word-break: break-all; +} + +.tool-result-filepath:hover { + color: var(--vscode-textLink-activeForeground, var(--vscode-button-hoverBackground)); +} + +.tool-result-diff { + display: flex; + flex-direction: column; + gap: 6px; +} + +.diff-preview { + border: 1px solid var(--border-color); + border-radius: 6px; + overflow: hidden; + background: var(--vscode-editor-background); +} + +.diff-line { + display: grid; + grid-template-columns: 20px 1fr; + gap: 0; + font-family: var(--vscode-editor-font-family); + font-size: 12px; + line-height: 1.2; +} + +.diff-line-marker { + display: flex; + align-items: flex-start; + justify-content: center; + padding: 1px 0; + color: var(--vscode-descriptionForeground); + user-select: none; +} + +.diff-line-content { + display: block; + padding: 1px 10px 1px 0; + white-space: pre-wrap; + word-break: break-word; +} + +.diff-line.added { + background: color-mix( + in srgb, + var(--vscode-diffEditor-insertedLineBackground, rgba(46, 160, 67, 0.18)) 100%, + transparent + ); +} + +.diff-line.removed { + background: color-mix( + in srgb, + var(--vscode-diffEditor-removedLineBackground, rgba(248, 81, 73, 0.16)) 100%, + transparent + ); +} + +.diff-line.context { + background: var(--vscode-editor-background); +} + +/* assistant 角色的展开内容无边框 */ +.bubble.assistant .bubble-collapsible-content { + border: none; + background: transparent; + padding: 8px 0; +} + +.bubble-collapsible-content.collapsed { + display: none; +} + +/* 普通assistant气泡布局 */ +.bubble.assistant:has(.bubble-normal-content) { + display: flex; + align-items: flex-start; + gap: 8px; +} + +.bubble.assistant:has(.bubble-normal-content) > .bubble-dot { + margin-top: 6px; +} + +.bubble-normal-content { + flex: 1; + min-width: 0; +} + +/* 复制按钮 */ +.bubble-copy-btn { + display: none; + position: absolute; + top: 8px; + right: 8px; + width: 26px; + height: 26px; + border: 1px solid var(--border-color); + border-radius: 4px; + background: var(--vscode-editor-background); + color: var(--vscode-descriptionForeground); + cursor: pointer; + align-items: center; + justify-content: center; + transition: + opacity 0.15s, + background 0.15s; + z-index: 5; +} + +.bubble-copy-btn:hover { + background: var(--vscode-toolbar-hoverBackground); + color: var(--vscode-foreground); +} + +.bubble-copy-btn.copied { + color: var(--vscode-testing-iconPassed, #2ea043); + border-color: var(--vscode-testing-iconPassed, #2ea043); +} + +.bubble-copy-btn svg { + width: 14px; + height: 14px; + fill: currentColor; + pointer-events: none; +} + +.bubble.assistant:hover .bubble-copy-btn { + display: flex; +} + +.bubble.user { + background: var(--vscode-editor-background); + border-color: var(--vscode-panel-border); + padding: 4px 6px; + margin: 12px 0 12px auto; + white-space: pre-wrap; + word-break: break-word; + width: fit-content; + max-width: 80%; +} + +.bubble.system { + background: transparent; + border-color: transparent; + padding: 4px 16px; +} + +.bubble.assistant { + background: transparent; + border-color: transparent; + padding: 4px 16px; +} + +.bubble.tool { + background: transparent; + border-color: transparent; + padding: 4px 16px; +} + +.bubble p { + margin: 8px 0; + overflow-wrap: break-word; + word-break: break-word; +} + +.bubble p:first-of-type { + margin-top: 0; +} + +.bubble p:last-of-type { + margin-bottom: 0; +} + +.bubble pre { + padding: 12px; + border-radius: 4px; + overflow-x: auto; + max-width: 100%; + color: var(--vscode-editor-foreground); + background: var(--vscode-textCodeBlock-background); + margin: 8px 0; + border: 1px solid var(--vscode-panel-border); + white-space: pre-wrap; + word-break: break-word; +} + +.bubble code { + font-family: var(--vscode-editor-font-family); + font-size: 12px; + color: var(--vscode-editor-foreground); + background-color: unset; + overflow-wrap: break-word; + word-break: break-word; +} + +.ask-user-question { + display: flex; + flex-direction: column; + gap: 12px; + font-family: var(--vscode-font-family); + font-size: 13px; + white-space: normal; +} + +.ask-user-question-intro { + color: var(--vscode-descriptionForeground); +} + +.ask-user-question-form { + display: flex; + flex-direction: column; + gap: 12px; +} + +.ask-user-question-content { + overflow: visible; + max-height: none; +} + +.ask-user-question-block { + border: 1px solid var(--border-color); + border-radius: 6px; + padding: 12px; + margin: 0; + display: flex; + flex-direction: column; + gap: 8px; +} + +.ask-user-question-title { + padding: 0 4px; + font-weight: 600; +} + +.ask-user-question-option { + display: flex; + align-items: flex-start; + gap: 8px; + cursor: pointer; +} + +.ask-user-question-option input { + margin: 2px 0 0; +} + +.ask-user-question-option-text { + display: flex; + flex-direction: column; + gap: 2px; +} + +.ask-user-question-option-description { + color: var(--vscode-descriptionForeground); + font-size: 12px; +} + +.ask-user-question-other { + display: flex; + flex-direction: column; + gap: 6px; +} + +.ask-user-question-other-label { + font-size: 12px; + color: var(--vscode-descriptionForeground); +} + +.ask-user-question-other textarea { + min-height: 56px; + max-height: 120px; + resize: none; + padding: 8px 10px; + border: 1px solid var(--border-color); + border-radius: 4px; + background: var(--vscode-input-background); + color: var(--vscode-input-foreground); +} + +.ask-user-question-actions { + margin-top: 10px; +} + +.ask-user-question-error { + color: var(--vscode-errorForeground); + font-size: 12px; + display: none; + margin-bottom: 6px; +} + +.ask-user-question-error:not(:empty) { + display: block; +} + +.ask-user-question-submit { + align-self: flex-start; + border: 1px solid transparent; + border-radius: 4px; + background: var(--vscode-button-background); + color: var(--vscode-button-foreground); + padding: 6px 12px; + cursor: pointer; + font-size: 12px; +} + +.ask-user-question-submit:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.ask-user-question-empty { + color: var(--vscode-descriptionForeground); +} + +.permission-prompt-host { + margin-bottom: 10px; +} + +.permission-card { + border: 1px solid var(--vscode-panel-border); + border-left: 3px solid var(--vscode-notificationsWarningIcon-foreground, #f59e0b); + border-radius: 6px; + background: var(--vscode-input-background); + box-shadow: 0 4px 14px var(--shadow); + padding: 12px; +} + +.permission-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; +} + +.permission-title { + color: var(--vscode-notificationsWarningIcon-foreground, #f59e0b); + font-weight: 700; +} + +.permission-progress { + margin-top: 2px; + color: var(--vscode-descriptionForeground); + font-size: 11px; +} + +.permission-close { + border: none; + border-radius: 4px; + background: transparent; + color: var(--vscode-descriptionForeground); + cursor: pointer; + font-size: 18px; + line-height: 1; + padding: 0 4px; +} + +.permission-close:hover { + background: var(--vscode-toolbar-hoverBackground); + color: var(--vscode-foreground); +} + +.permission-tool { + margin-top: 10px; + font-weight: 700; +} + +.permission-command { + margin-top: 6px; + border-radius: 4px; + background: var(--vscode-textCodeBlock-background); + color: var(--vscode-editor-foreground); + font-family: var(--vscode-editor-font-family); + font-size: 12px; + line-height: 1.45; + padding: 8px; + white-space: pre-wrap; + word-break: break-word; +} + +.permission-description { + margin-top: 8px; + color: var(--vscode-descriptionForeground); + line-height: 1.45; +} + +.permission-scope { + display: inline-flex; + align-items: center; + margin-top: 10px; + border-radius: 999px; + font-size: 11px; + font-weight: 700; + padding: 3px 8px; +} + +.permission-scope.risk-low { + background: rgba(34, 197, 94, 0.14); + color: #22c55e; +} + +.permission-scope.risk-medium { + background: rgba(245, 158, 11, 0.14); + color: #f59e0b; +} + +.permission-scope.risk-high { + background: rgba(239, 68, 68, 0.14); + color: #ef4444; +} + +.permission-question { + margin-top: 10px; + font-weight: 600; +} + +.permission-actions { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 10px; +} + +.permission-action { + border: 1px solid var(--vscode-button-border, transparent); + border-radius: 4px; + background: var(--vscode-button-secondaryBackground); + color: var(--vscode-button-secondaryForeground); + cursor: pointer; + font-size: 12px; + padding: 6px 10px; +} + +.permission-action:hover { + background: var(--vscode-button-secondaryHoverBackground); +} + +.permission-allow, +.permission-always { + background: var(--vscode-button-background); + color: var(--vscode-button-foreground); +} + +.permission-allow:hover, +.permission-always:hover { + background: var(--vscode-button-hoverBackground); +} + +.permission-deny { + border-color: var(--vscode-inputValidation-errorBorder, #ef4444); + color: var(--vscode-errorForeground, #ef4444); +} + +.permission-denied-card { + border-left-color: var(--vscode-errorForeground, #ef4444); +} + +.permission-denied-card .permission-title { + color: var(--vscode-errorForeground, #ef4444); +} + +/* Spinner dot for live thinking bubble */ +.bubble-dot.spinner-dot { + background: transparent !important; +} + +/* 旋转环用 ::after 实现,不影响 ::before 连线 */ +.bubble-dot.spinner-dot::after { + content: ""; + position: absolute; + top: -2px; + left: -2px; + width: calc(100% + 4px); + height: calc(100% + 4px); + border-radius: 50%; + border: 2px solid var(--vscode-progressBar-background); + border-top-color: var(--accent); + animation: spin 0.8s linear infinite; + box-sizing: border-box; + pointer-events: none; + z-index: 1; +} + +/* Thinking bubble: 标题和内容同行显示 */ +.bubble[data-thinking-live="true"] .thinking-status { + color: var(--vscode-descriptionForeground); + font-weight: normal; + font-size: 12px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + flex: 1; + min-width: 0; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +/* Composer */ +.composer { + position: relative; + padding: 12px 16px 16px; + background: var(--vscode-sideBar-background); + flex-shrink: 0; +} + +.input-wrap { + position: relative; + display: flex; + flex-direction: column; + min-height: calc(var(--prompt-min-height) + 42px); + border-radius: 4px; + border: 1px solid var(--border-color); + background: var(--vscode-input-background); + transition: + border-color 0.15s ease, + outline-color 0.15s ease, + background-color 0.15s ease; +} + +.input-wrap:focus-within { + border-color: var(--vscode-focusBorder); + outline: 1px solid var(--vscode-focusBorder); +} + +.tools-line { + display: none; + align-items: center; + gap: 8px; + min-height: 0; + padding: 0 12px; +} + +.tools-line.has-attachment { + display: flex; + min-height: 34px; + padding: 10px 12px 0; +} + +.composer-footer { + display: flex; + height: 42px; + width: 100%; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 6px 12px; + position: relative; +} + +/* Textarea */ +textarea { + width: 100%; + min-height: var(--prompt-min-height); + max-height: var(--prompt-max-height); + resize: none; + overflow-y: hidden; + border: none; + border-radius: 4px; + background: var(--vscode-input-background); + color: var(--vscode-input-foreground); + padding: 10px 12px; + font-size: 13px; + line-height: var(--prompt-line-height); + outline: none; + font-family: var(--vscode-font-family); +} + +textarea:focus { + outline: none; +} + +textarea::placeholder { + color: var(--vscode-input-placeholderForeground); +} + +.chat-attached-context-attachment { + display: inline-flex; + align-items: center; + gap: 6px; + min-width: 0; + max-width: 100%; + padding: 4px; + border: 1px solid var(--vscode-editorWidget-background, var(--vscode-input-background)); + border-radius: 6px; + color: var(--vscode-foreground); +} + +.chat-attached-context-attachment:hover { + border-color: var(--vscode-focusBorder); +} + +.chat-attached-context-attachment .monaco-button.codicon-close { + display: inline-flex; + justify-content: center; + width: 18px; + height: 18px; + border-radius: 50%; + color: var(--vscode-descriptionForeground); + text-decoration: none; + flex-shrink: 0; +} + +.chat-attached-context-attachment .monaco-button.codicon-close:hover { + background: var(--vscode-toolbar-hoverBackground); + color: var(--vscode-foreground); +} + +.monaco-icon-label, +.monaco-icon-label-container, +.monaco-icon-name-container { + display: none; +} + +.chat-attached-context-pill { + width: 13px; + height: 13px; + border-radius: 4px; + overflow: hidden; + flex-shrink: 0; + background: var(--vscode-editor-background); +} + +.chat-attached-context-pill-image { + display: block; + width: 13px; + height: 13px; + margin: 1.5px; + object-fit: cover; + border-radius: 2px; +} + +.chat-attached-context-custom-text { + font-size: 12px; + line-height: 1.2; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.chat-attached-context-preview { + position: fixed; + display: none; + padding: 10px; + border: 1px solid var(--border-color); + border-radius: 12px; + background: var(--vscode-editorHoverWidget-background, var(--vscode-editorWidget-background)); + box-shadow: 0 8px 24px var(--shadow); + z-index: 10001; + pointer-events: none; +} + +.chat-attached-context-preview.show { + display: block; +} + +.chat-attached-context-preview-image { + display: block; + max-width: min(520px, 70vw); + max-height: min(420px, 65vh); + border-radius: 6px; + object-fit: contain; +} + +/* Send Button */ +.send-button { + width: 30px; + height: 30px; + border-radius: 50%; + border: none; + cursor: pointer; + display: grid; + place-items: center; + background: transparent; +} + +.context-meter { + position: relative; + width: 18px; + height: 18px; + display: grid; + place-items: center; + flex-shrink: 0; + z-index: 3; +} + +.context-meter-ring { + --context-percent: 0%; + width: 14px; + height: 14px; + border-radius: 50%; + background: + radial-gradient(circle at center, var(--vscode-input-background) 36%, transparent 38%), + conic-gradient( + var(--vscode-descriptionForeground) 0 var(--context-percent), + var(--vscode-editorWidget-border, var(--vscode-panel-border)) var(--context-percent) 100% + ); +} + +.context-meter:hover .context-meter-ring { + filter: brightness(1.1); +} + +.context-meter-tooltip { + position: fixed; + left: 16px; + bottom: calc(100% + 10px); + display: none; + width: min(360px, calc(100vw - 32px)); + max-height: min(420px, 70vh); + overflow: auto; + padding: 12px 14px; + border: 1px solid var(--vscode-editorHoverWidget-border, var(--border-color)); + border-radius: 12px; + background: var(--vscode-editorHoverWidget-background, var(--vscode-editorWidget-background)); + color: var(--vscode-editorHoverWidget-foreground, var(--vscode-foreground)); + box-shadow: 0 8px 24px var(--shadow); + font-size: 12px; + line-height: 1.4; + pointer-events: none; + z-index: 10002; +} + +.context-meter:hover .context-meter-tooltip { + display: block; +} + +.context-tooltip-title { + text-align: center; + color: var(--vscode-descriptionForeground); + font-size: 13px; + margin-bottom: 4px; +} + +.context-tooltip-summary { + text-align: center; + font-size: 16px; + font-weight: 600; + margin-bottom: 10px; +} +.context-tooltip-section { + margin-top: 10px; + padding-top: 8px; + border-top: 1px solid var(--border-color); + color: var(--vscode-descriptionForeground); + font-weight: 600; +} + +.context-tooltip-row { + display: flex; + justify-content: space-between; + gap: 12px; + margin-top: 4px; +} + +.context-tooltip-label { + min-width: 0; + color: var(--vscode-descriptionForeground); + overflow-wrap: anywhere; +} + +.context-tooltip-value { + max-width: 55%; + text-align: right; + font-family: var(--vscode-editor-font-family); + overflow-wrap: anywhere; +} + +.send-button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.send-icon { + width: 26px; + height: 26px; + fill: currentColor; + color: var(--vscode-foreground); + transition: opacity 0.2s; +} + +#sendIcon { + color: var(--vscode-descriptionForeground); +} + +#stopIcon { + display: none; + color: var(--vscode-foreground); +} + +.send-icon.empty { + opacity: 0.6; +} + +/* Skills Button */ +.skills-button { + height: 22px; + border-radius: 4px; + border: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + gap: 4px; + background: transparent; + padding: 0; + transition: opacity 0.2s; + flex-shrink: 0; + color: var(--vscode-foreground); +} + +.skills-button span { + margin-top: 4px; +} + +.skills-button:hover { + opacity: 0.8; +} + +.skills-button svg { + width: 16px; + height: 16px; + fill: var(--vscode-foreground); +} + +/* Skills Popup */ +.skills-popup { + position: absolute; + bottom: calc(100% + 8px); + left: 16px; + right: 16px; + background: var(--vscode-dropdown-background); + border: 1px solid var(--border-color); + border-radius: 4px; + max-height: 300px; + overflow-y: auto; + z-index: 10000; + display: none; + box-shadow: 0 4px 12px var(--shadow); +} + +.skills-popup.show { + display: block; +} + +.skills-popup-header { + padding: 8px 12px; + font-size: 12px; + font-weight: 500; + color: var(--vscode-descriptionForeground); + border-bottom: 1px solid var(--border-color); +} + +.skills-popup-list { + padding: 8px; + display: flex; + flex-direction: column; + gap: 4px; +} + +.skills-popup-empty { + padding: 12px; + text-align: center; + color: var(--vscode-descriptionForeground); + font-size: 13px; +} + +.skills-popup-item { + display: flex; + align-items: center; + padding: 6px 10px; + cursor: pointer; + border-radius: 4px; + font-size: 13px; + transition: background 0.2s; + gap: 8px; +} + +.skills-popup-item:hover { + background: var(--vscode-list-hoverBackground); +} + +.skills-popup-item.selected { + background: var(--vscode-list-activeSelectionBackground); + color: var(--vscode-list-activeSelectionForeground); +} + +.skills-popup-item-name { + flex: 0 0 120px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.skills-popup-item-path { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: var(--vscode-descriptionForeground); + font-size: 12px; +} + +.skills-popup-item:hover .skills-popup-item-path, +.skills-popup-item.selected .skills-popup-item-path { + color: inherit; +} + +.skills-popup-item-loaded { + color: var(--vscode-testing-icon-success); + font-weight: bold; + font-size: 14px; + margin-left: 4px; +} + +/* Skills Bar (contains button and tags) */ +.skills-bar { + display: flex; + align-items: center; + gap: 8px; + width: calc(100% - 60px); +} + +/* Skills Tags */ +.skills-tags { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 6px; + flex: 1; + min-width: 0; +} + +.skills-tags-inner { + width: 100%; + overflow: auto; + white-space: nowrap; + scrollbar-width: none; + -ms-overflow-style: none; +} + +.skills-tags-inner::-webkit-scrollbar { + width: 0; + height: 0; +} + +.skill-tag { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 6px; + background: var(--vscode-button-background); + color: var(--vscode-button-foreground); + border-radius: 4px; + font-size: 12px; + margin-right: 4px; +} + +.skill-tag-name { + max-width: 120px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.skill-tag-remove { + cursor: pointer; + font-size: 14px; + line-height: 1; + opacity: 0.7; + transition: opacity 0.2s; +} + +.skill-tag-remove:hover { + opacity: 1; +} + +/* Prevent horizontal overflow for all markdown content */ +.bubble table { + display: block; + overflow-x: auto; + max-width: 100%; +} + +.bubble img { + max-width: 100%; + height: auto; +} + +.bubble ul, +.bubble ol { + padding-left: 1.5em; + overflow-wrap: break-word; +} + +.bubble li { + overflow-wrap: break-word; + word-break: break-word; +} + +.bubble blockquote { + overflow-wrap: break-word; + word-break: break-word; +} + +.bubble a { + overflow-wrap: break-word; + word-break: break-all; +} diff --git a/packages/vscode-ide-companion/resources/webview.html b/packages/vscode-ide-companion/resources/webview.html new file mode 100644 index 00000000..1290f8d6 --- /dev/null +++ b/packages/vscode-ide-companion/resources/webview.html @@ -0,0 +1,2354 @@ + + + + + + + Deep Code + + + +

+ + + + + diff --git a/packages/vscode-ide-companion/src/extension.ts b/packages/vscode-ide-companion/src/extension.ts new file mode 100644 index 00000000..44542e79 --- /dev/null +++ b/packages/vscode-ide-companion/src/extension.ts @@ -0,0 +1,562 @@ +import * as vscode from "vscode"; +import * as fs from "fs"; +import * as path from "path"; +import * as os from "os"; +import OpenAI from "openai"; +import MarkdownIt from "markdown-it"; +import type { SessionMessage } from "@vegamo/deepcode-core"; +import { + SessionManager, + getCompactPromptTokenThreshold, + type LlmStreamProgress, + type PermissionScope, + type SessionEntry, + type SkillInfo, + type UserPromptContent, + type UserToolPermission, + resolveSettingsSources, + type DeepcodingSettings, + type ReasoningEffort, + type ResolvedDeepcodingSettings, + setShellIfWindows, +} from "@vegamo/deepcode-core"; +import { getNonce } from "./utils.js"; +import { handleWebviewMessage } from "./provider.js"; + +const DEFAULT_MODEL = "deepseek-v4-pro"; +const DEFAULT_BASE_URL = "https://api.deepseek.com"; + +type ReasoningMessageParams = { + reasoning_content?: string; +}; + +export class DeepCodeViewProvider implements vscode.WebviewViewProvider { + public static readonly viewType = "deepcode.chatView"; + + private readonly context: vscode.ExtensionContext; + private webviewView: vscode.WebviewView | undefined; + private readonly md: MarkdownIt; + private readonly sessionManager: SessionManager; + + constructor(context: vscode.ExtensionContext) { + this.context = context; + this.md = new MarkdownIt({ + html: false, + linkify: false, + breaks: true, + }); + this.sessionManager = new SessionManager({ + projectRoot: this.getWorkspaceRoot(), + createOpenAIClient: () => this.createOpenAIClient(), + getResolvedSettings: () => this.resolveCurrentSettings(), + renderMarkdown: (text) => this.md.render(text), + onAssistantMessage: (message: SessionMessage, shouldConnect: boolean) => { + if (!this.webviewView) { + return; + } + if (message.visible === false) { + return; + } + if (message.role !== "tool") { + const reasoningContent = (message.messageParams as ReasoningMessageParams | null)?.reasoning_content; + message.html = this.md.render(message.content || reasoningContent || ""); + } + this.webviewView.webview.postMessage({ type: "appendMessage", message, shouldConnect }); + }, + onSessionEntryUpdated: (entry) => { + if (!this.webviewView) { + return; + } + this.webviewView.webview.postMessage({ + type: "sessionStatus", + sessionId: entry.id, + status: entry.status, + askPermissions: entry.askPermissions, + processes: this.serializeProcesses(entry.processes), + tokenTelemetry: this.buildTokenTelemetry(entry), + }); + }, + onLlmStreamProgress: (progress: LlmStreamProgress) => { + if (!this.webviewView) { + return; + } + this.webviewView.webview.postMessage({ + type: "llmStreamProgress", + progress, + }); + }, + }); + void this.initializeMcpServers(); + } + + dispose(): void { + this.sessionManager.dispose(); + } + + resolveWebviewView(webviewView: vscode.WebviewView): void { + this.webviewView = webviewView; + + webviewView.webview.options = { + enableScripts: true, + localResourceRoots: [this.context.extensionUri], + }; + + webviewView.webview.html = this.getWebviewHtml(webviewView.webview); + + webviewView.webview.onDidReceiveMessage(async (message) => { + const msg = message as Record | undefined; + + // openFile requires vscode API, handle here directly + if (msg?.type === "openFile") { + const filePath = String(msg.filePath || "").trim(); + const line = Number(msg.line || 1); + if (filePath) { + await this.openFileInEditor(filePath, line); + } + return; + } + + const handled = await handleWebviewMessage(message, { + sessionManager: this.sessionManager, + postMessage: (m) => this.webviewView?.webview.postMessage(m), + renderMarkdown: (text) => this.md.render(text), + copyToClipboard: (text) => void vscode.env.clipboard.writeText(text), + }); + + if (!handled) { + // unrecognized message type — no-op + } + }); + } + + private async loadInitialSession(): Promise { + const sessions = this.sessionManager.listSessions(); + const sessionsList = sessions.map((s) => ({ + id: s.id, + summary: s.summary || "Untitled", + createTime: s.createTime, + updateTime: s.updateTime, + status: s.status, + })); + + if (sessions.length === 0) { + // 没有历史会话,显示新对话界面 + this.sendMessage({ + type: "initializeEmpty", + sessions: sessionsList, + status: null, + tokenTelemetry: this.buildTokenTelemetry(null), + }); + return; + } + + // 显示最新的对话 + const latestSession = sessions[0]; + this.loadSession(latestSession.id); + } + + private loadSession(sessionId: string): void { + const session = this.sessionManager.getSession(sessionId); + if (!session) { + return; + } + + // 设置为活动会话 + this.sessionManager.setActiveSessionId(sessionId); + + const messages = this.sessionManager.listSessionMessages(sessionId); + + // 获取所有会话列表 + const sessions = this.sessionManager.listSessions(); + const sessionsList = sessions.map((s) => ({ + id: s.id, + summary: s.summary || "Untitled", + createTime: s.createTime, + updateTime: s.updateTime, + status: s.status, + })); + + // 发送对话信息到 webview + this.sendMessage({ + type: "loadSession", + sessionId, + summary: session.summary || "Untitled", + status: session.status, + askPermissions: session.askPermissions, + processes: this.serializeProcesses(session.processes), + tokenTelemetry: this.buildTokenTelemetry(session), + sessions: sessionsList, + messages: messages + .filter((m) => m.visible) + .map((m) => ({ + role: m.role, + content: m.content, + html: + m.role !== "tool" + ? this.md.render(m.content || (m.messageParams as ReasoningMessageParams | null)?.reasoning_content || "") + : undefined, + meta: m.meta, + })), + }); + } + + private showSessionsList(): void { + const sessions = this.sessionManager.listSessions(); + this.sendMessage({ + type: "showSessionsList", + sessions: sessions.map((s) => ({ + id: s.id, + summary: s.summary || "Untitled", + createTime: s.createTime, + updateTime: s.updateTime, + status: s.status, + })), + }); + } + + private async createNewSession(): Promise { + // 清除当前活动会话 + this.sessionManager.setActiveSessionId(null); + + // 获取所有会话列表 + const sessions = this.sessionManager.listSessions(); + const sessionsList = sessions.map((s) => ({ + id: s.id, + summary: s.summary || "Untitled", + createTime: s.createTime, + updateTime: s.updateTime, + status: s.status, + })); + + this.sendMessage({ + type: "initializeEmpty", + sessions: sessionsList, + status: null, + tokenTelemetry: this.buildTokenTelemetry(null), + }); + await this.sendSkillsList(); + } + + private sendMessage(message: unknown): void { + if (!this.webviewView) { + return; + } + this.webviewView.webview.postMessage(message); + } + + private async sendSkillsList(sessionId?: string): Promise { + if (!this.webviewView) { + return; + } + const skills = await this.sessionManager.listSkills( + sessionId ?? this.sessionManager.getActiveSessionId() ?? undefined + ); + this.sendMessage({ type: "skillsList", skills }); + } + + private async handlePrompt( + prompt: string, + skills?: SkillInfo[], + imageUrls?: string[], + options: { permissions?: UserToolPermission[]; alwaysAllows?: PermissionScope[] } = {} + ): Promise { + if (!this.webviewView) { + return; + } + + const webview = this.webviewView.webview; + const normalizedImages = Array.isArray(imageUrls) ? imageUrls.filter(Boolean) : []; + const displayPrompt = prompt || (normalizedImages.length > 0 ? "粘贴的图像" : ""); + const isPermissionContinue = + prompt === "/continue" && + normalizedImages.length === 0 && + ((options.permissions?.length ?? 0) > 0 || (options.alwaysAllows?.length ?? 0) > 0); + + // 先显示用户消息(原始文本,不做 HTML 格式化) + if (displayPrompt && !isPermissionContinue) { + webview.postMessage({ type: "userMessage", content: displayPrompt }); + } + + webview.postMessage({ type: "loading", value: true }); + + try { + const userPrompt: UserPromptContent = { + text: prompt, + skills, + imageUrls: normalizedImages, + permissions: options.permissions, + alwaysAllows: options.alwaysAllows, + }; + await this.sessionManager.handleUserPrompt(userPrompt); + await this.sendSkillsList(); + + const activeSessionId = this.sessionManager.getActiveSessionId(); + const activeSession = activeSessionId ? this.sessionManager.getSession(activeSessionId) : null; + if (activeSessionId && activeSession) { + webview.postMessage({ + type: "sessionStatus", + sessionId: activeSessionId, + status: activeSession.status, + askPermissions: activeSession.askPermissions, + processes: this.serializeProcesses(activeSession.processes), + tokenTelemetry: this.buildTokenTelemetry(activeSession), + }); + } + + // 发送更新后的会话列表(可能创建了新会话) + const sessions = this.sessionManager.listSessions(); + const sessionsList = sessions.map((s) => ({ + id: s.id, + summary: s.summary || "Untitled", + createTime: s.createTime, + updateTime: s.updateTime, + status: s.status, + })); + webview.postMessage({ + type: "showSessionsList", + sessions: sessionsList, + }); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + webview.postMessage({ + type: "assistant", + html: this.md.render(`Request failed: ${message}`), + }); + } finally { + webview.postMessage({ type: "loading", value: false }); + } + } + + private handlePermissionDenied(sessionId: string): void { + this.sessionManager.denySessionPermission(sessionId); + const session = this.sessionManager.getSession(sessionId); + if (session) { + this.sendMessage({ + type: "sessionStatus", + sessionId, + status: session.status, + askPermissions: session.askPermissions, + processes: this.serializeProcesses(session.processes), + tokenTelemetry: this.buildTokenTelemetry(session), + }); + } + this.showSessionsList(); + } + + private createOpenAIClient(): { + client: OpenAI | null; + model: string; + baseURL: string; + thinkingEnabled: boolean; + reasoningEffort: ReasoningEffort; + debugLogEnabled: boolean; + notify?: string; + webSearchTool?: string; + env?: Record; + machineId?: string; + } { + const settings = this.resolveCurrentSettings(); + + const { apiKey, baseURL, model, thinkingEnabled, reasoningEffort, debugLogEnabled, notify, webSearchTool, env } = + settings; + const machineId = vscode.env.machineId; + + if (!apiKey) { + return { + client: null, + model, + baseURL, + thinkingEnabled, + reasoningEffort, + debugLogEnabled, + notify, + webSearchTool, + env, + machineId, + }; + } + + const client = new OpenAI({ + apiKey, + baseURL: baseURL || undefined, + }); + + return { + client, + model, + baseURL, + thinkingEnabled, + reasoningEffort, + debugLogEnabled, + notify, + webSearchTool, + env, + machineId, + }; + } + + private buildTokenTelemetry(session: SessionEntry | null): { + model: string; + thinkingEnabled: boolean; + reasoningEffort: ReasoningEffort; + activeTokens: number; + compactPromptTokenThreshold: number; + usage: unknown | null; + } { + const settings = this.resolveCurrentSettings(); + return { + model: settings.model, + thinkingEnabled: settings.thinkingEnabled, + reasoningEffort: settings.reasoningEffort, + activeTokens: session?.activeTokens ?? 0, + compactPromptTokenThreshold: getCompactPromptTokenThreshold(settings.model), + usage: session?.usage ?? null, + }; + } + + private async initializeMcpServers(): Promise { + try { + await this.sessionManager.initMcpServers(this.resolveCurrentSettings().mcpServers); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + void vscode.window.showErrorMessage(`Failed to initialize MCP servers: ${message}`); + } + } + + private resolveCurrentSettings(): ResolvedDeepcodingSettings { + return resolveSettingsSources( + this.readUserSettings(), + this.readProjectSettings(), + { + model: DEFAULT_MODEL, + baseURL: DEFAULT_BASE_URL, + }, + process.env + ); + } + + private readUserSettings(): DeepcodingSettings | null { + try { + const settingsPath = path.join(os.homedir(), ".deepcode", "settings.json"); + if (!fs.existsSync(settingsPath)) { + return null; + } + + const raw = fs.readFileSync(settingsPath, "utf8"); + return JSON.parse(raw) as DeepcodingSettings; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + vscode.window.showErrorMessage(`Failed to read ~/.deepcode/settings.json: ${message}`); + return null; + } + } + + private readProjectSettings(): DeepcodingSettings | null { + const workspaceRoot = this.getWorkspaceRoot(); + try { + const settingsPath = path.join(workspaceRoot, ".deepcode", "settings.json"); + if (!fs.existsSync(settingsPath)) { + return null; + } + + const raw = fs.readFileSync(settingsPath, "utf8"); + return JSON.parse(raw) as DeepcodingSettings; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + vscode.window.showErrorMessage( + `Failed to read ${path.join(workspaceRoot, ".deepcode", "settings.json")}: ${message}` + ); + return null; + } + } + + private getWorkspaceRoot(): string { + const workspace = vscode.workspace.workspaceFolders?.[0]; + if (workspace) { + return workspace.uri.fsPath; + } + return process.cwd(); + } + + private serializeProcesses( + processes: Map | null + ): Record | null { + if (!processes || processes.size === 0) { + return null; + } + + const serialized: Record = {}; + for (const [pid, entry] of processes.entries()) { + serialized[pid] = entry; + } + return serialized; + } + + private getWebviewHtml(webview: vscode.Webview): string { + const nonce = getNonce(); + const csp = webview.cspSource; + + // 读取 HTML 模板文件 + const htmlPath = vscode.Uri.joinPath(this.context.extensionUri, "resources", "webview.html"); + let html = fs.readFileSync(htmlPath.fsPath, "utf8"); + + // 获取 CSS 文件 URI + const cssPath = vscode.Uri.joinPath(this.context.extensionUri, "resources", "webview.css"); + const cssUri = webview.asWebviewUri(cssPath); + const attachmentsJsPath = vscode.Uri.joinPath(this.context.extensionUri, "resources", "prompt-attachments.js"); + const attachmentsJsUri = webview.asWebviewUri(attachmentsJsPath); + + // 获取 Logo 文件 URI + const iconPath = vscode.Uri.joinPath(this.context.extensionUri, "resources", "deepcoding_icon.png"); + const iconUri = webview.asWebviewUri(iconPath); + + // 替换占位符 + html = html.replace(/\{\{nonce\}\}/g, nonce); + html = html.replace(/\{\{cspSource\}\}/g, csp); + html = html.replace(/\{\{cssUri\}\}/g, cssUri.toString()); + html = html.replace(/\{\{attachmentsJsUri\}\}/g, attachmentsJsUri.toString()); + html = html.replace(/\{\{iconUri\}\}/g, iconUri.toString()); + html = html.replace(/\{\{workspaceRoot\}\}/g, JSON.stringify(this.getWorkspaceRoot())); + + return html; + } + + private async openFileInEditor(filePath: string, line: number): Promise { + const document = await vscode.workspace.openTextDocument(vscode.Uri.file(filePath)); + const editor = await vscode.window.showTextDocument(document, { + preview: false, + preserveFocus: false, + }); + + const targetLine = Number.isFinite(line) && line > 0 ? Math.floor(line) - 1 : 0; + const safeLine = Math.min(Math.max(0, targetLine), Math.max(0, document.lineCount - 1)); + const position = new vscode.Position(safeLine, 0); + const selection = new vscode.Selection(position, position); + editor.selection = selection; + editor.revealRange(new vscode.Range(position, position), vscode.TextEditorRevealType.InCenter); + } +} + +export function activate(context: vscode.ExtensionContext): void { + process.env.NoDefaultCurrentDirectoryInExePath = "1"; + try { + setShellIfWindows(); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + void vscode.window.showErrorMessage(message); + } + + const provider = new DeepCodeViewProvider(context); + context.subscriptions.push(provider); + context.subscriptions.push(vscode.window.registerWebviewViewProvider(DeepCodeViewProvider.viewType, provider)); + context.subscriptions.push( + vscode.commands.registerCommand("deepcode.openView", async () => { + await vscode.commands.executeCommand("workbench.view.extension.deepcode"); + await vscode.commands.executeCommand("deepcode.chatView.focus"); + }) + ); +} + +export function deactivate(): void { + // no-op +} diff --git a/packages/vscode-ide-companion/src/provider.ts b/packages/vscode-ide-companion/src/provider.ts new file mode 100644 index 00000000..91aee0e4 --- /dev/null +++ b/packages/vscode-ide-companion/src/provider.ts @@ -0,0 +1,319 @@ +/** + * Message handling logic for the Deepcoding webview provider. + * Extracted from extension.ts for testability — no direct vscode dependency. + */ +import type { SessionManager } from "@vegamo/deepcode-core"; +import type { PermissionScope, SkillInfo, UserToolPermission } from "@vegamo/deepcode-core"; +import { parseUserToolPermissions, parsePermissionScopes } from "./utils.js"; + +export interface PostMessageFn { + (message: unknown): void; +} + +export interface ProviderDeps { + sessionManager: Pick< + SessionManager, + | "listSessions" + | "getSession" + | "getActiveSessionId" + | "setActiveSessionId" + | "listSessionMessages" + | "handleUserPrompt" + | "interruptActiveSession" + | "denySessionPermission" + | "listSkills" + >; + postMessage: PostMessageFn; + renderMarkdown: (text: string) => string; + copyToClipboard: (text: string) => void; +} + +export interface SessionSummary { + id: string; + summary: string; + createTime: string; + updateTime: string; + status: string; +} + +function toSessionList( + sessions: Array<{ id: string; summary?: string | null; createTime: string; updateTime: string; status: string }> +): SessionSummary[] { + return sessions.map((s) => ({ + id: s.id, + summary: s.summary || "Untitled", + createTime: s.createTime, + updateTime: s.updateTime, + status: s.status, + })); +} + +/** + * Routes incoming webview messages to the appropriate handler. + * Returns true if the message was handled. + */ +export async function handleWebviewMessage(message: unknown, deps: ProviderDeps): Promise { + const { sessionManager, postMessage, renderMarkdown, copyToClipboard } = deps; + + if (!message || typeof message !== "object") { + return false; + } + + const msg = message as Record; + + if (msg.type === "ready") { + loadInitialSession(sessionManager, postMessage); + await sendSkillsList(sessionManager, postMessage); + return true; + } + + if (msg.type === "requestSkills") { + await sendSkillsList(sessionManager, postMessage); + return true; + } + + if (msg.type === "userPrompt") { + const prompt = String(msg.prompt || "").trim(); + const images = Array.isArray(msg.images) + ? (msg.images as unknown[]).filter((image): image is string => typeof image === "string" && image.length > 0) + : []; + const permissions = parseUserToolPermissions(msg.permissions); + const alwaysAllows = parsePermissionScopes(msg.alwaysAllows); + if (!prompt && images.length === 0 && permissions.length === 0 && alwaysAllows.length === 0) { + return true; + } + const skills = (msg.skills as SkillInfo[]) || []; + await handlePrompt(prompt, skills, images, sessionManager, postMessage, renderMarkdown, { + permissions: permissions.length > 0 ? permissions : undefined, + alwaysAllows: alwaysAllows.length > 0 ? alwaysAllows : undefined, + }); + return true; + } + + if (msg.type === "interrupt") { + sessionManager.interruptActiveSession(); + return true; + } + + if (msg.type === "denyPermission") { + const sessionId = String(msg.sessionId || sessionManager.getActiveSessionId() || "").trim(); + if (sessionId) { + handlePermissionDenied(sessionId, sessionManager, postMessage); + } + return true; + } + + if (msg.type === "createNewSession") { + await createNewSession(sessionManager, postMessage); + return true; + } + + if (msg.type === "selectSession") { + const sessionId = String(msg.sessionId || "").trim(); + if (sessionId) { + loadSession(sessionId, sessionManager, postMessage, renderMarkdown); + await sendSkillsList(sessionManager, postMessage, sessionId); + } + return true; + } + + if (msg.type === "backToList") { + showSessionsList(sessionManager, postMessage); + return true; + } + + if (msg.type === "openFile") { + // openFile requires vscode API — handled by the caller + return false; + } + + if (msg.type === "copyText") { + const text = String(msg.text || ""); + if (text) { + copyToClipboard(text); + } + return true; + } + + return false; +} + +function loadInitialSession(sessionManager: ProviderDeps["sessionManager"], postMessage: PostMessageFn): void { + const sessions = sessionManager.listSessions(); + const sessionsList = toSessionList(sessions); + + if (sessions.length === 0) { + postMessage({ + type: "initializeEmpty", + sessions: sessionsList, + status: null, + }); + return; + } + + const latestSession = sessions[0]; + loadSession(latestSession.id, sessionManager, postMessage, (t) => t); +} + +export function loadSession( + sessionId: string, + sessionManager: ProviderDeps["sessionManager"], + postMessage: PostMessageFn, + renderMarkdown: (text: string) => string +): void { + const session = sessionManager.getSession(sessionId); + if (!session) { + return; + } + + sessionManager.setActiveSessionId(sessionId); + const messages = sessionManager.listSessionMessages(sessionId); + const sessions = sessionManager.listSessions(); + + postMessage({ + type: "loadSession", + sessionId, + summary: session.summary || "Untitled", + status: session.status, + askPermissions: session.askPermissions, + processes: serializeProcesses(session.processes), + sessions: toSessionList(sessions), + messages: messages + .filter((m) => m.visible) + .map((m) => ({ + role: m.role, + content: m.content, + html: + m.role !== "tool" + ? renderMarkdown( + m.content || (m.messageParams as { reasoning_content?: string } | null)?.reasoning_content || "" + ) + : undefined, + meta: m.meta, + })), + }); +} + +function showSessionsList(sessionManager: ProviderDeps["sessionManager"], postMessage: PostMessageFn): void { + const sessions = sessionManager.listSessions(); + postMessage({ + type: "showSessionsList", + sessions: toSessionList(sessions), + }); +} + +async function createNewSession( + sessionManager: ProviderDeps["sessionManager"], + postMessage: PostMessageFn +): Promise { + sessionManager.setActiveSessionId(null); + const sessions = sessionManager.listSessions(); + + postMessage({ + type: "initializeEmpty", + sessions: toSessionList(sessions), + status: null, + }); + await sendSkillsList(sessionManager, postMessage); +} + +async function sendSkillsList( + sessionManager: ProviderDeps["sessionManager"], + postMessage: PostMessageFn, + sessionId?: string +): Promise { + const skills = await sessionManager.listSkills(sessionId ?? sessionManager.getActiveSessionId() ?? undefined); + postMessage({ type: "skillsList", skills }); +} + +async function handlePrompt( + prompt: string, + skills: SkillInfo[], + imageUrls: string[], + sessionManager: ProviderDeps["sessionManager"], + postMessage: PostMessageFn, + renderMarkdown: (text: string) => string, + options: { permissions?: UserToolPermission[]; alwaysAllows?: PermissionScope[] } = {} +): Promise { + const normalizedImages = imageUrls.filter(Boolean); + const displayPrompt = prompt || (normalizedImages.length > 0 ? "粘贴的图像" : ""); + const isPermissionContinue = + prompt === "/continue" && + normalizedImages.length === 0 && + ((options.permissions?.length ?? 0) > 0 || (options.alwaysAllows?.length ?? 0) > 0); + + if (displayPrompt && !isPermissionContinue) { + postMessage({ type: "userMessage", content: displayPrompt }); + } + + postMessage({ type: "loading", value: true }); + + try { + await sessionManager.handleUserPrompt({ + text: prompt, + skills, + imageUrls: normalizedImages, + permissions: options.permissions, + alwaysAllows: options.alwaysAllows, + }); + await sendSkillsList(sessionManager, postMessage); + + const activeSessionId = sessionManager.getActiveSessionId(); + const activeSession = activeSessionId ? sessionManager.getSession(activeSessionId) : null; + if (activeSessionId && activeSession) { + postMessage({ + type: "sessionStatus", + sessionId: activeSessionId, + status: activeSession.status, + askPermissions: activeSession.askPermissions, + processes: serializeProcesses(activeSession.processes), + }); + } + + const sessions = sessionManager.listSessions(); + postMessage({ + type: "showSessionsList", + sessions: toSessionList(sessions), + }); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + postMessage({ + type: "assistant", + html: renderMarkdown(`Request failed: ${message}`), + }); + } finally { + postMessage({ type: "loading", value: false }); + } +} + +function handlePermissionDenied( + sessionId: string, + sessionManager: ProviderDeps["sessionManager"], + postMessage: PostMessageFn +): void { + sessionManager.denySessionPermission(sessionId); + const session = sessionManager.getSession(sessionId); + if (session) { + postMessage({ + type: "sessionStatus", + sessionId, + status: session.status, + askPermissions: session.askPermissions, + processes: serializeProcesses(session.processes), + }); + } + showSessionsList(sessionManager, postMessage); +} + +function serializeProcesses( + processes: Map | null +): Record | null { + if (!processes || processes.size === 0) { + return null; + } + const serialized: Record = {}; + for (const [pid, entry] of processes.entries()) { + serialized[pid] = entry; + } + return serialized; +} diff --git a/packages/vscode-ide-companion/src/tests/extension-utils.test.ts b/packages/vscode-ide-companion/src/tests/extension-utils.test.ts new file mode 100644 index 00000000..8dea36de --- /dev/null +++ b/packages/vscode-ide-companion/src/tests/extension-utils.test.ts @@ -0,0 +1,132 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { VALID_PERMISSION_SCOPES, parseUserToolPermissions, parsePermissionScopes, getNonce } from "../utils.js"; + +// --- VALID_PERMISSION_SCOPES --- + +test("VALID_PERMISSION_SCOPES contains all expected scopes", () => { + const expected = [ + "read-in-cwd", + "read-out-cwd", + "write-in-cwd", + "write-out-cwd", + "delete-in-cwd", + "delete-out-cwd", + "query-git-log", + "mutate-git-log", + "network", + "mcp", + ]; + assert.equal(VALID_PERMISSION_SCOPES.size, expected.length); + for (const scope of expected) { + assert.ok(VALID_PERMISSION_SCOPES.has(scope as any), `missing scope: ${scope}`); + } +}); + +// --- parseUserToolPermissions --- + +test("parseUserToolPermissions returns empty array for non-array input", () => { + assert.deepEqual(parseUserToolPermissions(undefined), []); + assert.deepEqual(parseUserToolPermissions(null), []); + assert.deepEqual(parseUserToolPermissions("string"), []); + assert.deepEqual(parseUserToolPermissions(123), []); + assert.deepEqual(parseUserToolPermissions({}), []); +}); + +test("parseUserToolPermissions returns empty array for empty array", () => { + assert.deepEqual(parseUserToolPermissions([]), []); +}); + +test("parseUserToolPermissions parses valid permissions", () => { + const input = [ + { toolCallId: "call-1", permission: "allow" }, + { toolCallId: "call-2", permission: "deny" }, + ]; + const result = parseUserToolPermissions(input); + assert.equal(result.length, 2); + assert.deepEqual(result[0], { toolCallId: "call-1", permission: "allow" }); + assert.deepEqual(result[1], { toolCallId: "call-2", permission: "deny" }); +}); + +test("parseUserToolPermissions filters out invalid items", () => { + const input = [ + null, + 123, + "string", + {}, + { toolCallId: "", permission: "allow" }, // empty toolCallId + { toolCallId: " ", permission: "allow" }, // whitespace-only toolCallId + { toolCallId: "call-1" }, // missing permission + { toolCallId: "call-2", permission: "invalid" }, // invalid permission value + { permission: "allow" }, // missing toolCallId + { toolCallId: "call-3", permission: "allow" }, // valid + ]; + const result = parseUserToolPermissions(input); + assert.equal(result.length, 1); + assert.deepEqual(result[0], { toolCallId: "call-3", permission: "allow" }); +}); + +test("parseUserToolPermissions preserves toolCallId with leading/trailing spaces", () => { + const input = [{ toolCallId: " call-1 ", permission: "allow" }]; + const result = parseUserToolPermissions(input); + // trimmed toolCallId " " fails the .trim() check, so this item is filtered + // Wait, " call-1 ".trim() = "call-1" which is truthy, so it passes + assert.equal(result.length, 1); + assert.equal(result[0].toolCallId, " call-1 "); +}); + +// --- parsePermissionScopes --- + +test("parsePermissionScopes returns empty array for non-array input", () => { + assert.deepEqual(parsePermissionScopes(undefined), []); + assert.deepEqual(parsePermissionScopes(null), []); + assert.deepEqual(parsePermissionScopes("string"), []); + assert.deepEqual(parsePermissionScopes(123), []); + assert.deepEqual(parsePermissionScopes({}), []); +}); + +test("parsePermissionScopes returns empty array for empty array", () => { + assert.deepEqual(parsePermissionScopes([]), []); +}); + +test("parsePermissionScopes parses valid scopes", () => { + const input = ["read-in-cwd", "write-in-cwd", "network"]; + const result = parsePermissionScopes(input); + assert.equal(result.length, 3); + assert.deepEqual(result, ["read-in-cwd", "write-in-cwd", "network"]); +}); + +test("parsePermissionScopes filters out invalid values", () => { + const input = ["read-in-cwd", "invalid-scope", 123, null, undefined, {}, "mcp"]; + const result = parsePermissionScopes(input); + assert.equal(result.length, 2); + assert.deepEqual(result, ["read-in-cwd", "mcp"]); +}); + +test("parsePermissionScopes deduplicates scopes", () => { + const input = ["read-in-cwd", "write-in-cwd", "read-in-cwd", "network", "network"]; + const result = parsePermissionScopes(input); + assert.equal(result.length, 3); + assert.deepEqual(result, ["read-in-cwd", "write-in-cwd", "network"]); +}); + +// --- getNonce --- + +test("getNonce returns a 32-character string", () => { + const nonce = getNonce(); + assert.equal(nonce.length, 32); +}); + +test("getNonce only contains alphanumeric characters", () => { + const nonce = getNonce(); + assert.ok(/^[A-Za-z0-9]+$/.test(nonce), `nonce contains non-alphanumeric chars: ${nonce}`); +}); + +test("getNonce returns different values on successive calls", () => { + const nonces = new Set(); + for (let i = 0; i < 100; i++) { + nonces.add(getNonce()); + } + // With 62^32 possible values, 100 calls should almost certainly be unique + assert.ok(nonces.size > 90, `Expected mostly unique nonces, got ${nonces.size} unique out of 100`); +}); diff --git a/packages/vscode-ide-companion/src/tests/extension.test.ts b/packages/vscode-ide-companion/src/tests/extension.test.ts new file mode 100644 index 00000000..4f8d6e03 --- /dev/null +++ b/packages/vscode-ide-companion/src/tests/extension.test.ts @@ -0,0 +1,445 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { handleWebviewMessage, loadSession, type ProviderDeps } from "../provider.js"; + +// --- Helpers --- + +function createMockSessionManager(options?: { sessions?: any[]; messages?: any[]; skills?: any[] }) { + const sessions = options?.sessions ?? [ + { + id: "session-1", + summary: "Test Session", + status: "idle", + askPermissions: null, + processes: null, + activeTokens: 100, + usage: null, + createTime: "2025-01-01T00:00:00Z", + updateTime: "2025-01-01T00:00:00Z", + }, + ]; + const messages = options?.messages ?? []; + const skills = options?.skills ?? []; + let activeSessionId: string | null = sessions[0]?.id ?? null; + + return { + dispose: () => {}, + listSessions: () => sessions, + getSession: (id: string) => sessions.find((s: any) => s.id === id) ?? null, + getActiveSessionId: () => activeSessionId, + setActiveSessionId: (id: string | null) => { + activeSessionId = id; + }, + listSessionMessages: (_sessionId: string) => messages, + handleUserPrompt: () => Promise.resolve(), + interruptActiveSession: () => {}, + denySessionPermission: (_sessionId: string) => {}, + listSkills: () => Promise.resolve(skills), + initMcpServers: () => Promise.resolve(), + }; +} + +function createDeps(options?: Parameters[0]): ProviderDeps & { messages: unknown[] } { + const messages: unknown[] = []; + return { + sessionManager: createMockSessionManager(options), + postMessage: (msg: unknown) => { + messages.push(msg); + }, + renderMarkdown: (text: string) => `

${text}

`, + copyToClipboard: () => {}, + messages, + }; +} + +// --- handleWebviewMessage routing --- + +test("handleWebviewMessage returns false for null message", async () => { + const deps = createDeps(); + const result = await handleWebviewMessage(null, deps); + assert.equal(result, false); +}); + +test("handleWebviewMessage returns false for non-object message", async () => { + const deps = createDeps(); + assert.equal(await handleWebviewMessage("string", deps), false); + assert.equal(await handleWebviewMessage(123, deps), false); +}); + +test("handleWebviewMessage returns false for unknown message type", async () => { + const deps = createDeps(); + assert.equal(await handleWebviewMessage({ type: "unknownType" }, deps), false); +}); + +test("ready message triggers loadInitialSession and sendSkillsList", async () => { + const deps = createDeps(); + const handled = await handleWebviewMessage({ type: "ready" }, deps); + + assert.equal(handled, true); + const types = deps.messages.map((m: any) => m.type); + // With sessions present, should send loadSession + skillsList + assert.ok(types.includes("loadSession"), `Expected loadSession, got: ${types.join(", ")}`); + assert.ok(types.includes("skillsList"), `Expected skillsList, got: ${types.join(", ")}`); +}); + +test("ready with no sessions sends initializeEmpty", async () => { + const deps = createDeps({ sessions: [] }); + await handleWebviewMessage({ type: "ready" }, deps); + + const types = deps.messages.map((m: any) => m.type); + assert.ok(types.includes("initializeEmpty"), `Expected initializeEmpty, got: ${types.join(", ")}`); +}); + +test("requestSkills sends skillsList", async () => { + const deps = createDeps({ skills: [{ name: "test-skill" }] }); + await handleWebviewMessage({ type: "requestSkills" }, deps); + + const skillsMsg = deps.messages.find((m: any) => m.type === "skillsList"); + assert.ok(skillsMsg, "Should send skillsList"); + assert.deepEqual((skillsMsg as any).skills, [{ name: "test-skill" }]); +}); + +test("interrupt calls interruptActiveSession", async () => { + const deps = createDeps(); + let interrupted = false; + (deps.sessionManager as any).interruptActiveSession = () => { + interrupted = true; + }; + + const handled = await handleWebviewMessage({ type: "interrupt" }, deps); + assert.equal(handled, true); + assert.ok(interrupted, "interruptActiveSession should be called"); +}); + +test("createNewSession clears active session and sends initializeEmpty", async () => { + const deps = createDeps(); + let cleared = false; + (deps.sessionManager as any).setActiveSessionId = (id: string | null) => { + if (id === null) cleared = true; + }; + + await handleWebviewMessage({ type: "createNewSession" }, deps); + + assert.ok(cleared, "setActiveSessionId(null) should be called"); + const types = deps.messages.map((m: any) => m.type); + assert.ok(types.includes("initializeEmpty"), `Expected initializeEmpty, got: ${types.join(", ")}`); + assert.ok(types.includes("skillsList"), `Expected skillsList, got: ${types.join(", ")}`); +}); + +test("selectSession loads session and sends skillsList", async () => { + const deps = createDeps(); + let loadedId: string | null = null; + (deps.sessionManager as any).setActiveSessionId = (id: string) => { + loadedId = id; + }; + + await handleWebviewMessage({ type: "selectSession", sessionId: "session-1" }, deps); + + assert.equal(loadedId, "session-1"); + const types = deps.messages.map((m: any) => m.type); + assert.ok(types.includes("loadSession"), `Expected loadSession, got: ${types.join(", ")}`); + assert.ok(types.includes("skillsList"), `Expected skillsList, got: ${types.join(", ")}`); +}); + +test("selectSession with empty sessionId does nothing", async () => { + const deps = createDeps(); + await handleWebviewMessage({ type: "selectSession", sessionId: "" }, deps); + assert.equal(deps.messages.length, 0, "No messages for empty sessionId"); +}); + +test("selectSession with non-existent session does not send loadSession", async () => { + const deps = createDeps(); + (deps.sessionManager as any).getSession = () => null; + + await handleWebviewMessage({ type: "selectSession", sessionId: "non-existent" }, deps); + + const types = deps.messages.map((m: any) => m.type); + assert.ok(!types.includes("loadSession"), "Should not send loadSession for non-existent session"); +}); + +test("backToList sends showSessionsList", async () => { + const deps = createDeps(); + await handleWebviewMessage({ type: "backToList" }, deps); + + const msg = deps.messages.find((m: any) => m.type === "showSessionsList"); + assert.ok(msg, "Should send showSessionsList"); + assert.ok(Array.isArray((msg as any).sessions), "sessions should be an array"); +}); + +test("denyPermission calls denySessionPermission and sends sessionStatus", async () => { + const deps = createDeps(); + let deniedId: string | null = null; + (deps.sessionManager as any).denySessionPermission = (id: string) => { + deniedId = id; + }; + + await handleWebviewMessage({ type: "denyPermission", sessionId: "session-1" }, deps); + + assert.equal(deniedId, "session-1"); + const types = deps.messages.map((m: any) => m.type); + assert.ok(types.includes("sessionStatus"), `Expected sessionStatus, got: ${types.join(", ")}`); + assert.ok(types.includes("showSessionsList"), `Expected showSessionsList, got: ${types.join(", ")}`); +}); + +test("denyPermission with empty sessionId does nothing", async () => { + const deps = createDeps(); + (deps.sessionManager as any).getActiveSessionId = () => null; + + await handleWebviewMessage({ type: "denyPermission", sessionId: "" }, deps); + + // No sessionStatus should be sent + const types = deps.messages.map((m: any) => m.type); + assert.ok(!types.includes("sessionStatus"), "Should not send sessionStatus for empty sessionId"); +}); + +test("copyText calls copyToClipboard", async () => { + const deps = createDeps(); + let copiedText: string | null = null; + deps.copyToClipboard = (text: string) => { + copiedText = text; + }; + + const handled = await handleWebviewMessage({ type: "copyText", text: "hello" }, deps); + assert.equal(handled, true); + assert.equal(copiedText, "hello"); +}); + +test("copyText with empty text does not call copyToClipboard", async () => { + const deps = createDeps(); + let copied = false; + deps.copyToClipboard = () => { + copied = true; + }; + + await handleWebviewMessage({ type: "copyText", text: "" }, deps); + assert.ok(!copied, "Should not copy empty text"); +}); + +test("openFile returns false (handled by caller)", async () => { + const deps = createDeps(); + const result = await handleWebviewMessage({ type: "openFile", filePath: "/some/file.ts" }, deps); + assert.equal(result, false); +}); + +// --- userPrompt --- + +test("userPrompt with empty prompt and no images/permissions is handled without messages", async () => { + const deps = createDeps(); + const handled = await handleWebviewMessage( + { type: "userPrompt", prompt: "", images: [], permissions: [], alwaysAllows: [] }, + deps + ); + assert.equal(handled, true); + assert.equal(deps.messages.length, 0, "No messages for empty prompt"); +}); + +test("userPrompt with text sends userMessage and loading states", async () => { + const deps = createDeps(); + await handleWebviewMessage({ type: "userPrompt", prompt: "hello" }, deps); + + const types = deps.messages.map((m: any) => m.type); + assert.ok(types.includes("userMessage"), `Expected userMessage, got: ${types.join(", ")}`); + assert.ok(types.includes("loading"), `Expected loading, got: ${types.join(", ")}`); + + // Should end with loading: false + const lastLoading = [...deps.messages].reverse().find((m: any) => m.type === "loading"); + assert.deepEqual(lastLoading, { type: "loading", value: false }); +}); + +test("userPrompt with images sends userMessage with image placeholder", async () => { + const deps = createDeps(); + await handleWebviewMessage({ type: "userPrompt", prompt: "", images: ["data:image/png;base64,abc"] }, deps); + + const userMsg = deps.messages.find((m: any) => m.type === "userMessage"); + assert.ok(userMsg, "Should send userMessage for images"); + assert.equal((userMsg as any).content, "粘贴的图像"); +}); + +test("userPrompt with permissions (continue) does not send userMessage", async () => { + const deps = createDeps(); + await handleWebviewMessage( + { + type: "userPrompt", + prompt: "/continue", + images: [], + permissions: [{ toolCallId: "call-1", permission: "allow" }], + }, + deps + ); + + const userMsg = deps.messages.find((m: any) => m.type === "userMessage"); + assert.ok(!userMsg, "Should not send userMessage for /continue with permissions"); +}); + +test("userPrompt sends sessionStatus after handling", async () => { + const deps = createDeps(); + await handleWebviewMessage({ type: "userPrompt", prompt: "hello" }, deps); + + const types = deps.messages.map((m: any) => m.type); + assert.ok(types.includes("sessionStatus"), `Expected sessionStatus, got: ${types.join(", ")}`); +}); + +test("userPrompt sends showSessionsList after handling", async () => { + const deps = createDeps(); + await handleWebviewMessage({ type: "userPrompt", prompt: "hello" }, deps); + + const sessionsMsg = deps.messages.find((m: any) => m.type === "showSessionsList"); + assert.ok(sessionsMsg, "Should send showSessionsList"); + assert.ok(Array.isArray((sessionsMsg as any).sessions), "sessions should be an array"); +}); + +test("userPrompt on error sends assistant error message", async () => { + const deps = createDeps(); + (deps.sessionManager as any).handleUserPrompt = () => Promise.reject(new Error("API failed")); + + await handleWebviewMessage({ type: "userPrompt", prompt: "hello" }, deps); + + const assistantMsg = deps.messages.find((m: any) => m.type === "assistant"); + assert.ok(assistantMsg, "Should send assistant error message"); + assert.ok((assistantMsg as any).html.includes("API failed"), "Error message should contain the error text"); +}); + +test("userPrompt always sends loading: false even on error", async () => { + const deps = createDeps(); + (deps.sessionManager as any).handleUserPrompt = () => Promise.reject(new Error("fail")); + + await handleWebviewMessage({ type: "userPrompt", prompt: "hello" }, deps); + + const lastLoading = [...deps.messages].reverse().find((m: any) => m.type === "loading"); + assert.deepEqual(lastLoading, { type: "loading", value: false }); +}); + +// --- loadSession --- + +test("loadSession sends loadSession with correct fields", () => { + const sessionManager = createMockSessionManager(); + const messages: unknown[] = []; + const postMessage = (msg: unknown) => { + messages.push(msg); + }; + + loadSession("session-1", sessionManager, postMessage, (t) => t); + + const msg = messages.find((m: any) => m.type === "loadSession") as any; + assert.ok(msg, "Should send loadSession"); + assert.equal(msg.sessionId, "session-1"); + assert.equal(msg.summary, "Test Session"); + assert.equal(msg.status, "idle"); + assert.ok(Array.isArray(msg.sessions), "sessions should be an array"); + assert.ok(Array.isArray(msg.messages), "messages should be an array"); +}); + +test("loadSession with non-existent session does nothing", () => { + const sessionManager = createMockSessionManager(); + const messages: unknown[] = []; + const postMessage = (msg: unknown) => { + messages.push(msg); + }; + + (sessionManager as any).getSession = () => null; + loadSession("non-existent", sessionManager, postMessage, (t) => t); + + assert.equal(messages.length, 0, "No messages for non-existent session"); +}); + +test("loadSession sets active session id", () => { + const sessionManager = createMockSessionManager(); + const messages: unknown[] = []; + let setTo: string | null = null; + (sessionManager as any).setActiveSessionId = (id: string) => { + setTo = id; + }; + + loadSession( + "session-1", + sessionManager, + (msg) => messages.push(msg), + (t) => t + ); + + assert.equal(setTo, "session-1"); +}); + +test("loadSession filters out invisible messages", () => { + const sessionManager = createMockSessionManager({ + messages: [ + { role: "user", content: "visible", visible: true }, + { role: "assistant", content: "hidden", visible: false }, + { role: "user", content: "also visible", visible: true }, + ], + }); + const messages: unknown[] = []; + loadSession( + "session-1", + sessionManager, + (msg) => messages.push(msg), + (t) => t + ); + + const loadMsg = messages.find((m: any) => m.type === "loadSession") as any; + assert.equal(loadMsg.messages.length, 2, "Should filter out invisible messages"); +}); + +// --- serializeProcesses --- + +test("loadSession serializes processes map to object", () => { + const sessionManager = createMockSessionManager({ + sessions: [ + { + id: "session-1", + summary: "Test", + status: "idle", + askPermissions: null, + processes: new Map([ + ["123", { startTime: "2025-01-01", command: "ls" }], + ["456", { startTime: "2025-01-02", command: "cat" }], + ]), + activeTokens: 0, + usage: null, + createTime: "2025-01-01", + updateTime: "2025-01-01", + }, + ], + }); + const messages: unknown[] = []; + loadSession( + "session-1", + sessionManager, + (msg) => messages.push(msg), + (t) => t + ); + + const loadMsg = messages.find((m: any) => m.type === "loadSession") as any; + assert.deepEqual(loadMsg.processes, { + "123": { startTime: "2025-01-01", command: "ls" }, + "456": { startTime: "2025-01-02", command: "cat" }, + }); +}); + +test("loadSession returns null for empty processes", () => { + const sessionManager = createMockSessionManager({ + sessions: [ + { + id: "session-1", + summary: "Test", + status: "idle", + askPermissions: null, + processes: null, + activeTokens: 0, + usage: null, + createTime: "2025-01-01", + updateTime: "2025-01-01", + }, + ], + }); + const messages: unknown[] = []; + loadSession( + "session-1", + sessionManager, + (msg) => messages.push(msg), + (t) => t + ); + + const loadMsg = messages.find((m: any) => m.type === "loadSession") as any; + assert.equal(loadMsg.processes, null); +}); diff --git a/packages/vscode-ide-companion/src/tests/run-tests.mjs b/packages/vscode-ide-companion/src/tests/run-tests.mjs new file mode 100644 index 00000000..73034d8a --- /dev/null +++ b/packages/vscode-ide-companion/src/tests/run-tests.mjs @@ -0,0 +1,15 @@ +// Test runner for @vegamo/deepcode-vscode +import { globSync } from "glob"; +import { spawnSync } from "child_process"; +import { fileURLToPath } from "url"; +import * as path from "path"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const testFiles = globSync("*.test.ts", { cwd: __dirname }); + +const result = spawnSync(process.execPath, ["--import", "tsx", "--test", ...testFiles], { + stdio: "inherit", + cwd: __dirname, +}); + +process.exit(result.status ?? 1); diff --git a/packages/vscode-ide-companion/src/utils.ts b/packages/vscode-ide-companion/src/utils.ts new file mode 100644 index 00000000..7fc126e8 --- /dev/null +++ b/packages/vscode-ide-companion/src/utils.ts @@ -0,0 +1,61 @@ +import type { PermissionScope, UserToolPermission } from "@vegamo/deepcode-core"; + +export const VALID_PERMISSION_SCOPES = new Set([ + "read-in-cwd", + "read-out-cwd", + "write-in-cwd", + "write-out-cwd", + "delete-in-cwd", + "delete-out-cwd", + "query-git-log", + "mutate-git-log", + "network", + "mcp", +]); + +export function parseUserToolPermissions(value: unknown): UserToolPermission[] { + if (!Array.isArray(value)) { + return []; + } + const result: UserToolPermission[] = []; + for (const item of value) { + if (!item || typeof item !== "object") { + continue; + } + const record = item as { toolCallId?: unknown; permission?: unknown }; + if (typeof record.toolCallId !== "string" || !record.toolCallId.trim()) { + continue; + } + if (record.permission !== "allow" && record.permission !== "deny") { + continue; + } + result.push({ toolCallId: record.toolCallId, permission: record.permission }); + } + return result; +} + +export function parsePermissionScopes(value: unknown): PermissionScope[] { + if (!Array.isArray(value)) { + return []; + } + const result: PermissionScope[] = []; + for (const item of value) { + if (typeof item !== "string" || !VALID_PERMISSION_SCOPES.has(item as PermissionScope)) { + continue; + } + const scope = item as PermissionScope; + if (!result.includes(scope)) { + result.push(scope); + } + } + return result; +} + +export function getNonce(): string { + let text = ""; + const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for (let i = 0; i < 32; i += 1) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return text; +} diff --git a/packages/vscode-ide-companion/tsconfig.build.json b/packages/vscode-ide-companion/tsconfig.build.json new file mode 100644 index 00000000..8601700a --- /dev/null +++ b/packages/vscode-ide-companion/tsconfig.build.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "ignoreDeprecations": "6.0", + "lib": ["ES2022"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "composite": true, + "declaration": true, + "outDir": "./dist", + "rootDir": "./src", + "types": ["node", "vscode"] + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/vscode-ide-companion/tsconfig.json b/packages/vscode-ide-companion/tsconfig.json new file mode 100644 index 00000000..c0d84433 --- /dev/null +++ b/packages/vscode-ide-companion/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "ignoreDeprecations": "6.0", + "lib": ["ES2022"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "noEmit": true, + "types": ["node", "vscode"], + "baseUrl": ".", + "paths": { + "@vegamo/deepcode-core": ["../core/src/index.ts"], + "@vegamo/deepcode-core/*": ["../core/src/*"] + } + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules", ".vscode-test", "out"] +} diff --git a/scripts/build-vscode-companion.js b/scripts/build-vscode-companion.js new file mode 100644 index 00000000..7288c786 --- /dev/null +++ b/scripts/build-vscode-companion.js @@ -0,0 +1,23 @@ +import { spawnSync } from "node:child_process"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const root = join(dirname(fileURLToPath(import.meta.url)), ".."); + +function run(command, args, label) { + console.log(`\n[${label}] ${command} ${args.join(" ")}`); + const result = spawnSync(command, args, { stdio: "inherit", cwd: root, shell: true }); + if (result.status !== 0) { + process.exit(result.status ?? 1); + } +} + +console.log("========================================="); +console.log(" Deep Code — Build VSCode Companion"); +console.log("========================================="); + +run("npm", ["run", "build", "--workspace=@vegamo/deepcode-core"], "1/3 Build core"); +run("node", ["scripts/esbuild-vscode.config.js"], "2/3 Bundle extension"); +run("npm", ["run", "package", "--workspace=deepcode-vscode"], "3/3 Package .vsix"); + +console.log("\n✅ VSCode companion build complete.\n\n"); diff --git a/scripts/build.js b/scripts/build.js new file mode 100644 index 00000000..080e2e54 --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,23 @@ +import { spawnSync } from "node:child_process"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); + +function run(command, args, label) { + process.stdout.write(`\n[${label}] ${command} ${args.join(" ")}\n`); + const result = spawnSync(command, args, { stdio: "inherit", cwd: root, shell: true }); + if (result.status !== 0) { + process.exit(result.status ?? 1); + } +} + +console.log("========================================="); +console.log(" Deep Code CLI — Build"); +console.log("========================================="); + +run("npm", ["run", "build", "--workspace=@vegamo/deepcode-core"], "1/2"); +run("npm", ["run", "bundle"], "2/2"); + +console.log("\n✅ Build complete.\n\n"); diff --git a/scripts/clean.js b/scripts/clean.js new file mode 100644 index 00000000..db532c3b --- /dev/null +++ b/scripts/clean.js @@ -0,0 +1,39 @@ +import { rmSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { globSync } from "glob"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); +const RMRF = { recursive: true, force: true }; + +console.log("Cleaning build artifacts...\n"); + +// Root artifacts +rmSync(join(root, "node_modules"), RMRF); +console.log(" rm node_modules/"); + +// Generated version files +for (const pkg of ["cli", "core", "vscode-ide-companion"]) { + rmSync(join(root, "packages", pkg, "src", "generated"), RMRF); + console.log(` rm packages/${pkg}/src/generated/`); +} + +// All workspace dist/ and tsbuildinfo +const packageDirs = globSync("packages/*", { cwd: root, absolute: true }); +for (const pkgDir of packageDirs) { + rmSync(join(pkgDir, "dist"), RMRF); + console.log(` rm ${join(pkgDir, "dist")}`); + rmSync(join(pkgDir, "tsconfig.tsbuildinfo"), { force: true }); +} + +// Clean up vscode-ide-companion package +rmSync(join(root, "packages/vscode-ide-companion/node_modules"), RMRF); +// VSCode .vsix files +const vsixFiles = globSync("packages/vscode-ide-companion/*.vsix", { cwd: root }); +for (const vsixFile of vsixFiles) { + rmSync(join(root, vsixFile), RMRF); + console.log(` rm ${vsixFile}`); +} + +console.log("\n✅ Clean complete.\n\n"); diff --git a/scripts/copy_bundle_assets.js b/scripts/copy-bundle-assets.js similarity index 62% rename from scripts/copy_bundle_assets.js rename to scripts/copy-bundle-assets.js index 0e1dd948..88315484 100644 --- a/scripts/copy_bundle_assets.js +++ b/scripts/copy-bundle-assets.js @@ -2,12 +2,11 @@ import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; -/* global console, process */ - const __dirname = dirname(fileURLToPath(import.meta.url)); const root = join(__dirname, ".."); -const distDir = join(root, "dist"); -const bundledSkillsSrc = join(root, "templates", "skills", "bundled"); +const cliRoot = join(root, "packages", "cli"); +const distDir = join(cliRoot, "dist"); +const bundledSkillsSrc = join(root, "packages", "core", "templates", "skills", "bundled"); const bundledSkillsDest = join(distDir, "bundled"); if (!existsSync(distDir)) { @@ -15,8 +14,8 @@ if (!existsSync(distDir)) { } if (!existsSync(bundledSkillsSrc)) { - console.warn(`Bundled skills directory not found at ${bundledSkillsSrc}`); - process.exit(0); + console.error(`Bundled skills directory not found at ${bundledSkillsSrc}`); + process.exit(1); } rmSync(bundledSkillsDest, { recursive: true, force: true }); @@ -24,4 +23,5 @@ cpSync(bundledSkillsSrc, bundledSkillsDest, { recursive: true, dereference: true, }); -console.log("Copied bundled built-in skills to dist/bundled/"); + +console.log("\n✅ All bundle assets copied to dist/bundled/"); diff --git a/scripts/esbuild-vscode.config.js b/scripts/esbuild-vscode.config.js new file mode 100644 index 00000000..25cd2bc2 --- /dev/null +++ b/scripts/esbuild-vscode.config.js @@ -0,0 +1,29 @@ +import { build } from "esbuild"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); + +const vscodeRoot = join(root, "packages", "vscode-ide-companion"); +const entry = join(vscodeRoot, "src", "extension.ts"); +const outfile = join(vscodeRoot, "out", "extension.js"); + +await build({ + entryPoints: [entry], + bundle: true, + platform: "node", + format: "cjs", + target: "node18", + outfile, + external: ["vscode"], + sourcemap: true, + footer: { + js: "module.exports = { activate, deactivate };", + }, + logOverride: { + "empty-import-meta": "silent", + }, +}); + +console.log(`\n✅ ${outfile} built successfully\n\n`); diff --git a/scripts/esbuild.config.js b/scripts/esbuild.config.js new file mode 100644 index 00000000..bf814a32 --- /dev/null +++ b/scripts/esbuild.config.js @@ -0,0 +1,28 @@ +import { build } from "esbuild"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); + +const cliRoot = join(root, "packages", "cli"); +const entry = join(cliRoot, "src", "cli.tsx"); +const outfile = join(cliRoot, "dist", "cli.js"); + +await build({ + entryPoints: [entry], + bundle: true, + platform: "node", + format: "esm", + target: "node22", + outfile, + banner: { js: "#!/usr/bin/env node" }, + jsx: "automatic", + jsxImportSource: "react", + packages: "external", + logOverride: { + "empty-import-meta": "silent", + }, +}); + +console.log(`\n✅ ${outfile} built successfully\n\n`); diff --git a/scripts/generate-git-commit-info.js b/scripts/generate-git-commit-info.js new file mode 100644 index 00000000..ac029533 --- /dev/null +++ b/scripts/generate-git-commit-info.js @@ -0,0 +1,46 @@ +import { execSync } from "node:child_process"; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { dirname, join, relative } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); +const scriptPath = relative(root, fileURLToPath(import.meta.url)); + +const generatedCliDir = join(root, "packages", "cli", "src", "generated"); +const cliGitCommitFile = join(generatedCliDir, "git-commit.ts"); + +let gitCommitInfo = "N/A"; +let cliVersion = "UNKNOWN"; + +if (!existsSync(generatedCliDir)) { + mkdirSync(generatedCliDir, { recursive: true }); +} + +try { + const gitHash = execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim(); + if (gitHash) { + gitCommitInfo = gitHash; + } + + const pkg = JSON.parse(readFileSync(join(root, "packages", "cli", "package.json"), "utf-8")); + cliVersion = pkg.version ?? "UNKNOWN"; +} catch { + // ignore +} + +const fileContent = [ + "/**", + " * @license", + ` * Copyright ${new Date().getFullYear()} @vegamo deepcode`, + " */", + "", + `// Auto-generated by ${scriptPath}. Do not edit.`, + `export const GIT_COMMIT_INFO = "${gitCommitInfo}";`, + `export const CLI_VERSION = "${cliVersion}";`, + "", +].join("\n"); + +writeFileSync(cliGitCommitFile, fileContent); + +console.log(`Generated version info: ${cliVersion} (${gitCommitInfo})`); diff --git a/scripts/start.js b/scripts/start.js new file mode 100644 index 00000000..b3d83be1 --- /dev/null +++ b/scripts/start.js @@ -0,0 +1,22 @@ +import { existsSync } from "node:fs"; +import { spawn } from "node:child_process"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); +const cliDist = join(root, "packages", "cli", "dist", "cli.js"); + +if (!existsSync(cliDist)) { + console.error(`Error: ${cliDist} not found. Run 'npm run build' first.`); + process.exit(1); +} + +console.log("Starting Deep Code CLI...\n"); + +const child = spawn("node", [cliDist, ...process.argv.slice(2)], { + stdio: "inherit", + cwd: root, +}); + +child.on("exit", (code) => process.exit(code ?? 1)); diff --git a/src/tests/run-tests.mjs b/src/tests/run-tests.mjs deleted file mode 100644 index 4d09f5b5..00000000 --- a/src/tests/run-tests.mjs +++ /dev/null @@ -1,13 +0,0 @@ -// Cross-platform test runner: finds all *.test.ts files and runs them via tsx. -// Uses the glob package for reliable cross-platform pattern expansion (Node 20+). -/* eslint-disable */ - -import { globSync } from "glob"; -import { spawnSync } from "child_process"; - -const cwd = new URL("../..", import.meta.url); -const testFiles = globSync("src/tests/*.test.ts", { cwd }); - -const result = spawnSync(process.execPath, ["--import", "tsx", "--test", ...testFiles], { stdio: "inherit", cwd }); - -process.exit(result.status ?? 1); diff --git a/tsconfig.json b/tsconfig.json index 24a6a1d1..9076eecf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,21 +1,38 @@ { "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "ignoreDeprecations": "6.0", - "lib": ["ES2022"], - "jsx": "react-jsx", "strict": true, "esModuleInterop": true, "skipLibCheck": true, + "noImplicitAny": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noImplicitThis": true, "forceConsistentCasingInFileNames": true, + "noPropertyAccessFromIndexSignature": true, + "noUnusedLocals": true, + "strictBindCallApply": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, "resolveJsonModule": true, - "noEmit": true, - "isolatedModules": true, + "sourceMap": true, + "composite": true, + "incremental": true, + "declaration": true, "allowSyntheticDefaultImports": true, - "types": ["node"] + "verbatimModuleSyntax": true, + "lib": ["ES2023"], + "module": "ESNext", + "moduleResolution": "bundler", + "target": "ES2022", + "types": ["node"], + "jsx": "react-jsx" }, - "include": ["src/**/*.ts", "src/**/*.tsx"], - "exclude": ["node_modules", "dist"] + "include": [], + "exclude": ["node_modules", "dist"], + "references": [ + { "path": "./packages/core" }, + { "path": "./packages/cli" }, + { "path": "./packages/vscode-ide-companion" } + ] } From b4d89efbf43f519a46689873ea99590731ec7e62 Mon Sep 17 00:00:00 2001 From: hcyang Date: Tue, 16 Jun 2026 14:32:46 +0800 Subject: [PATCH 25/72] fix: update package-lock.json to sync with workspace name change --- package-lock.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3e6afcbc..f63d16b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1964,10 +1964,6 @@ "resolved": "packages/core", "link": true }, - "node_modules/@vegamo/deepcode-vscode": { - "resolved": "packages/vscode-ide-companion", - "link": true - }, "node_modules/@vscode/vsce": { "version": "3.9.2", "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-3.9.2.tgz", @@ -2922,6 +2918,10 @@ "dev": true, "license": "MIT" }, + "node_modules/deepcode-vscode": { + "resolved": "packages/vscode-ide-companion", + "link": true + }, "node_modules/default-browser": { "version": "5.5.0", "resolved": "https://registry.npmmirror.com/default-browser/-/default-browser-5.5.0.tgz", @@ -7508,7 +7508,7 @@ } }, "packages/vscode-ide-companion": { - "name": "@vegamo/deepcode-vscode", + "name": "deepcode-vscode", "version": "0.1.22", "license": "MIT", "dependencies": { From 6014c9506891d0485ad717ce10e0e8245c23867c Mon Sep 17 00:00:00 2001 From: hcyang Date: Tue, 16 Jun 2026 14:34:49 +0800 Subject: [PATCH 26/72] fix: remove .vscodeignore to resolve conflict with files property --- packages/vscode-ide-companion/.vscodeignore | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 packages/vscode-ide-companion/.vscodeignore diff --git a/packages/vscode-ide-companion/.vscodeignore b/packages/vscode-ide-companion/.vscodeignore deleted file mode 100644 index 68a0eac7..00000000 --- a/packages/vscode-ide-companion/.vscodeignore +++ /dev/null @@ -1,8 +0,0 @@ -.vscode/** -.vscodeignore -node_modules/** -src/** -tsconfig*.json -**/*.ts -!dist/** -!LICENSE From b8ab68bbf43f9104753868ad0b7f238a4b76a377 Mon Sep 17 00:00:00 2001 From: hcyang Date: Tue, 16 Jun 2026 14:55:31 +0800 Subject: [PATCH 27/72] fix: use double quotes in scripts for Windows compatibility --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index a0e4e793..d017874d 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,10 @@ "typecheck": "npm run typecheck --workspaces --if-present", "generate": "node scripts/generate-git-commit-info.js", "bundle": "npm run generate && node scripts/esbuild.config.js && node scripts/copy-bundle-assets.js", - "lint": "eslint 'packages/*/src/**/*.{ts,tsx}' 'scripts/*.js'", - "lint:fix": "eslint 'packages/*/src/**/*.{ts,tsx}' 'scripts/*.js' --fix", - "format": "prettier --write 'packages/*/src/**/*.{ts,tsx}' 'scripts/*.js'", - "format:check": "prettier --check 'packages/*/src/**/*.{ts,tsx}' 'scripts/*.js'", + "lint": "eslint \"packages/*/src/**/*.{ts,tsx}\" \"scripts/*.js\"", + "lint:fix": "eslint \"packages/*/src/**/*.{ts,tsx}\" \"scripts/*.js\" --fix", + "format": "prettier --write \"packages/*/src/**/*.{ts,tsx}\" \"scripts/*.js\"", + "format:check": "prettier --check \"packages/*/src/**/*.{ts,tsx}\" \"scripts/*.js\"", "check": "npm run typecheck && npm run lint && npm run format:check", "clean": "node scripts/clean.js", "build": "node scripts/build.js", From 1779c6e01c43e6fc4e3c71b8432b0ec2e9600c90 Mon Sep 17 00:00:00 2001 From: hcyang Date: Tue, 16 Jun 2026 15:49:06 +0800 Subject: [PATCH 28/72] =?UTF-8?q?chore(core):=20=E6=9B=B4=E6=96=B0=20skill?= =?UTF-8?q?-digester=20=E8=AF=B4=E6=98=8E=E5=8F=8A=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 扩展 skill-digester 的 description 以覆盖技能安装和消化两大功能 - 细化消化技能的工作流步骤,增加更多操作细节和示例命令 - 新增安装 Agent Skill 工作流,规范安装路径及用户交互方式 - 规范使用 AskUserQuestion 提问,涵盖语言选择、修改确认与安装范围选择 - 修正示例 JSON 格式,统一提问选项结构 - 强化技能识别与路径匹配规则,避免误修改及覆盖风险 - 升级包版本号至 0.1.31,并统一项目包名为 @vegamo/deepcode --- package.json | 2 +- packages/cli/package.json | 2 +- packages/core/package.json | 2 +- .../skills/bundled/skill-digester/SKILL.md | 207 ++++++++++-------- 4 files changed, 122 insertions(+), 91 deletions(-) diff --git a/package.json b/package.json index d017874d..e2a722c0 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "deepcode", + "name": "@vegamo/deepcode", "description": "Deep Code — CLI, core library, and VSCode companion", "license": "MIT", "packageManager": "npm@10.9.4", diff --git a/packages/cli/package.json b/packages/cli/package.json index 21e7ae8e..654038ee 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@vegamo/deepcode-cli", - "version": "0.1.30", + "version": "0.1.31", "description": "Deep Code CLI - Vibe coding for the deepseek-v4 model in your terminal", "license": "MIT", "type": "module", diff --git a/packages/core/package.json b/packages/core/package.json index eb73e22a..1f924389 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@vegamo/deepcode-core", - "version": "0.1.30", + "version": "0.1.31", "description": "Deep Code core library — LLM session management, tool execution, and shared utilities", "license": "MIT", "type": "module", diff --git a/packages/core/templates/skills/bundled/skill-digester/SKILL.md b/packages/core/templates/skills/bundled/skill-digester/SKILL.md index 3bef806b..9a0f2675 100644 --- a/packages/core/templates/skills/bundled/skill-digester/SKILL.md +++ b/packages/core/templates/skills/bundled/skill-digester/SKILL.md @@ -1,87 +1,136 @@ --- name: skill-digester -description: Reviews and improves another DeepCode skill's SKILL.md description field against the Agent Skills description-field rules. Use when the user asks to "digest" a skill, including requests like "digest the pdf skill" or "消化 pdf 技能". +description: Reviews and improves another DeepCode skill's SKILL.md description field, and guides Agent Skill installation into user or project .agents/skills roots. Use when the user asks to digest a skill, install an Agent Skill, install a skill to user/project scope, or says "消化技能" or "安装 agent skill". --- # Skill Digester -Use this skill to review and optionally rewrite the `description` field of another DeepCode skill. +Use this skill for two related tasks: + +- Review and optionally rewrite the `description` field of another DeepCode skill. +- Guide installation of an Agent Skill into an interoperable `.agents/skills` root. ## Interaction Rule -Whenever user input is needed, call the `AskUserQuestion` tool. Do not ask follow-up questions as plain assistant text. This includes missing skill names, language preference, duplicate matches, malformed frontmatter decisions, and whether to apply a recommended rewrite. +Whenever user input is needed, call the `AskUserQuestion` tool. Do not ask follow-up questions as plain assistant text. This includes missing skill names or paths, install scope, language preference, duplicate matches, malformed frontmatter decisions, and whether to apply a recommended rewrite. ## Workflow +First classify the request: + +- If the user asks to install, add, copy, or place an Agent Skill, use the [Install Agent Skill Workflow](#install-agent-skill-workflow). +- Otherwise, use the [Digest Description Workflow](#digest-description-workflow). + +## Digest Description Workflow + 1. Identify the target skill from the user's request. - - If the user did not provide a skill name, use `AskUserQuestion` to ask for one. - - Locate the skill by running the bundled Node script from this skill directory: - - ```bash - node ~/.deepcode/skills/skill-digester/scripts/find-skill.js "" "" - ``` - - If this skill is loaded from a project-level or different user-level path, use the `scripts/find-skill.js` file next to this `SKILL.md` instead. - - - The script searches the same roots Deep Code CLI scans, in priority order: - 1. Project native skills: `./.deepcode/skills//SKILL.md` - 2. Project interoperable skills: `./.agents/skills//SKILL.md` - 3. User native skills: `~/.deepcode/skills//SKILL.md` - 4. User interoperable skills: `~/.agents/skills//SKILL.md` - - Treat `./` as the current Deep Code project root only; do not scan parent directories unless the running project root is changed. - - The script resolves each candidate's skill name the way Deep Code does: use the trimmed frontmatter `name` when present, otherwise use the folder name with underscores converted to hyphens. - - Match the user's input against the resolved skill name first. If needed, also consider the folder name or an explicit path the user provided. - - Treat the matched skill's `path` as the source `SKILL.md` to review. - - Treat the matched skill's `digestTarget.path` as the only output `SKILL.md` path to create or edit. - - `digestTarget.path` always points to the same scope's native Deep Code root: - - Project sources from `./.deepcode/skills` or `./.agents/skills` digest to `./.deepcode/skills//SKILL.md`. - - User sources from `~/.deepcode/skills` or `~/.agents/skills` digest to `~/.deepcode/skills//SKILL.md`. - - If the script returns one active match, use its `path` for reading and `digestTarget.path` for writing. - - If the script returns active and shadowed matches, present each source path and digest target path, then use `AskUserQuestion` before using a shadowed source. - - If the script returns no match, state that the skill was not found in Deep Code's scanned skill roots and use `AskUserQuestion` to ask whether the user wants to try another name. + - If the user did not provide a skill name, use `AskUserQuestion` to ask for one. + - Locate the skill by running the bundled Node script from this skill directory: + + ```bash + node ~/.deepcode/skills/skill-digester/scripts/find-skill.js "" "" + ``` + + If this skill is loaded from a project-level or different user-level path, use the `scripts/find-skill.js` file next to this `SKILL.md` instead. + - The script searches the same roots Deep Code CLI scans, in priority order: + 1. Project native skills: `./.deepcode/skills//SKILL.md` + 2. Project interoperable skills: `./.agents/skills//SKILL.md` + 3. User native skills: `~/.deepcode/skills//SKILL.md` + 4. User interoperable skills: `~/.agents/skills//SKILL.md` + - Treat `./` as the current Deep Code project root only; do not scan parent directories unless the running project root is changed. + - The script resolves each candidate's skill name the way Deep Code does: use the trimmed frontmatter `name` when present, otherwise use the folder name with underscores converted to hyphens. + - Match the user's input against the resolved skill name first. If needed, also consider the folder name or an explicit path the user provided. + - Treat the matched skill's `path` as the source `SKILL.md` to review. + - Treat the matched skill's `digestTarget.path` as the only output `SKILL.md` path to create or edit. + - `digestTarget.path` always points to the same scope's native Deep Code root: + - Project sources from `./.deepcode/skills` or `./.agents/skills` digest to `./.deepcode/skills//SKILL.md`. + - User sources from `~/.deepcode/skills` or `~/.agents/skills` digest to `~/.deepcode/skills//SKILL.md`. + - If the script returns one active match, use its `path` for reading and `digestTarget.path` for writing. + - If the script returns active and shadowed matches, present each source path and digest target path, then use `AskUserQuestion` before using a shadowed source. + - If the script returns no match, state that the skill was not found in Deep Code's scanned skill roots and use `AskUserQuestion` to ask whether the user wants to try another name. 2. Infer the user's preferred language before reviewing. - - Infer a likely language from the user's wording. For example, if the user says `消化pdf技能`, infer Chinese. - - Confirm the language with `AskUserQuestion` in the inferred language. For Chinese, ask: `请选择您偏好的语言。` - - Offer the inferred language first and include `English` as a fallback. The UI provides an `Other` option, so the user can type a different language. - - Use the confirmed preferred language for every later question, recommendation, and rewritten `description` field. + - Infer a likely language from the user's wording. For example, if the user says `消化pdf技能`, infer Chinese. + - Confirm the language with `AskUserQuestion` in the inferred language. For Chinese, ask: `请选择您偏好的语言。` + - Offer the inferred language first and include `English` as a fallback. The UI provides an `Other` option, so the user can type a different language. + - Use the confirmed preferred language for every later question, recommendation, and rewritten `description` field. 3. Read the source `SKILL.md`. - - Parse the YAML frontmatter and Markdown body from the matched source path. - - Preserve all frontmatter fields and body content except for the `description` field if the user approves a rewrite. - - If frontmatter is missing or malformed, explain the issue and use `AskUserQuestion` before making structural repairs. + - Parse the YAML frontmatter and Markdown body from the matched source path. + - Preserve all frontmatter fields and body content except for the `description` field if the user approves a rewrite. + - If frontmatter is missing or malformed, explain the issue and use `AskUserQuestion` before making structural repairs. 4. Review the current `description` field against the Agent Skills specification. - - Required constraints: - - It must be non-empty. - - It must be 1-1024 characters. - - It should describe what the skill does. - - It should describe when to use the skill. - - It should include specific keywords that help agents identify relevant tasks. - - Compare the description with the actual `SKILL.md` body. Flag mismatches, missing capabilities, overbroad activation language, vague wording, or important trigger keywords that are absent. - - Do not rewrite for style alone if the existing description is accurate, specific, and useful. + - Required constraints: + - It must be non-empty. + - It must be 1-1024 characters. + - It should describe what the skill does. + - It should describe when to use the skill. + - It should include specific keywords that help agents identify relevant tasks. + - Compare the description with the actual `SKILL.md` body. Flag mismatches, missing capabilities, overbroad activation language, vague wording, or important trigger keywords that are absent. + - Do not rewrite for style alone if the existing description is accurate, specific, and useful. 5. Present the review and recommendation. - - If the description is already good, say so and do not change the file unless the user asks. - - If improvements are useful, show: - - The current description. - - Concise review findings. - - A recommended replacement written in the preferred language. - - The source path being reviewed. - - The digest output path that would be created or edited. - - Use `AskUserQuestion` to ask the user to choose one of three actions in the preferred language: - - Apply the recommended change. - - Abandon the change. - - Continue discussing the wording. + - If the description is already good, say so and do not change the file unless the user asks. + - If improvements are useful, show: + - The current description. + - Concise review findings. + - A recommended replacement written in the preferred language. + - The source path being reviewed. + - The digest output path that would be created or edited. + - Use `AskUserQuestion` to ask the user to choose one of three actions in the preferred language: + - Apply the recommended change. + - Abandon the change. + - Continue discussing the wording. 6. Apply the change only after explicit approval. - - Write only to `digestTarget.path`; never write the digested result to `.agents/skills`. - - If `digestTarget.sameAsSource` is true, update only the `description` field in that existing native `SKILL.md`. - - If `digestTarget.sameAsSource` is false and `digestTarget.exists` is false, create the native target skill directory by copying the source skill directory first, then update only the target `SKILL.md` description. This preserves bundled scripts, references, and assets. - - If `digestTarget.sameAsSource` is false and `digestTarget.exists` is true, update only the `description` field in the existing native target `SKILL.md`; do not overwrite its body or bundled files unless the user explicitly asks. - - Keep the original `name` and any other frontmatter fields unchanged in the file being written. - - Preserve body content exactly unless the user separately asks to edit it. - - After editing, report the source path, updated digest output path, and final description. + - Write only to `digestTarget.path`; never write the digested result to `.agents/skills`. + - If `digestTarget.sameAsSource` is true, update only the `description` field in that existing native `SKILL.md`. + - If `digestTarget.sameAsSource` is false and `digestTarget.exists` is false, create the native target skill directory by copying the source skill directory first, then update only the target `SKILL.md` description. This preserves bundled scripts, references, and assets. + - If `digestTarget.sameAsSource` is false and `digestTarget.exists` is true, update only the `description` field in the existing native target `SKILL.md`; do not overwrite its body or bundled files unless the user explicitly asks. + - Keep the original `name` and any other frontmatter fields unchanged in the file being written. + - Preserve body content exactly unless the user separately asks to edit it. + - After editing, report the source path, updated digest output path, and final description. + +## Install Agent Skill Workflow + +Use this workflow when the user asks to install an Agent Skill. Installation always writes to `.agents/skills`, not `.deepcode/skills`. + +1. Identify the source skill directory. + - If the user provided an explicit file or directory path, resolve it: + - `~/...` relative to the user's home directory. + - `./...` relative to the current project root. + - Absolute paths as written. + - A `SKILL.md` path means its parent directory is the source skill directory. + - If the user provided a skill name instead of a path, locate it with `scripts/find-skill.js` using the same command and match rules as the digest workflow. + - If the user did not provide a skill name or path, use `AskUserQuestion` to ask for the source skill name or path. + - The source directory must contain `SKILL.md`. If it does not, report that the path is not an Agent Skill and ask for another source only if the user still wants to install. + +2. Determine the installed skill folder name. + - Parse the source `SKILL.md` frontmatter. + - Use the trimmed frontmatter `name` when present. + - Otherwise use the source folder name with underscores converted to hyphens. + - Use that resolved name as the target folder name. + +3. Ask exactly one installation scope question. + - Use `AskUserQuestion` to ask whether to install the skill at user level or project level. + - Offer only these scope choices: + - User-level install: `~/.agents/skills//` + - Project-level install: `./.agents/skills//` + - Do not ask any other installation preference before copying. + +4. Copy the complete skill directory. + - User-level destination: `~/.agents/skills//`. + - Project-level destination: `./.agents/skills//`. + - Copy the whole source skill directory, including `SKILL.md`, `references/`, `scripts/`, `templates/`, examples, assets, and other support files. + - Preserve file contents and relative paths exactly. + - Create the `.agents/skills` parent directory if needed. + - If the destination directory already exists, stop and report the conflict. Do not overwrite or merge files unless the user explicitly asks in a later message. + +5. Report the result. + - Report the source directory and installation destination. + - Mention that the agent client may need to reload or restart before the installed skill appears. + - Do not digest, rewrite, or normalize the installed skill unless the user separately asks for that. ## AskUserQuestion Patterns @@ -90,35 +139,15 @@ Use one question at a time unless two decisions are tightly coupled. Each questi Examples: ```json -{ - "questions": [ - { - "question": "请选择您偏好的语言。", - "options": [ - { "label": "中文", "description": "后续询问和推荐描述都使用中文。" }, - { "label": "English", "description": "Use English for follow-up questions and the recommended description." } - ] - } - ] -} +{"questions":[{"question":"请选择您偏好的语言。","options":[{"label":"中文","description":"后续询问和推荐描述都使用中文。"},{"label":"English","description":"Use English for follow-up questions and the recommended description."}]}]} +``` + +```json +{"questions":[{"question":"How should I proceed with this description recommendation?","options":[{"label":"Apply change","description":"Update only the description field in the native digest output SKILL.md."},{"label":"Abandon change","description":"Leave the file unchanged."},{"label":"Discuss wording","description":"Continue refining the proposed description before editing."}]}]} ``` ```json -{ - "questions": [ - { - "question": "How should I proceed with this description recommendation?", - "options": [ - { - "label": "Apply change", - "description": "Update only the description field in the native digest output SKILL.md." - }, - { "label": "Abandon change", "description": "Leave the file unchanged." }, - { "label": "Discuss wording", "description": "Continue refining the proposed description before editing." } - ] - } - ] -} +{"questions":[{"question":"Where should I install this Agent Skill?","options":[{"label":"User-level","description":"Install to ~/.agents/skills so it is available across projects."},{"label":"Project-level","description":"Install to ./.agents/skills so it is available in this project."}]}]} ``` ## Review Heuristics @@ -135,5 +164,7 @@ Avoid descriptions that are only generic labels, marketing copy, or internal imp - Never modify a different skill with a similar name without asking. - Never save the digested output under `.agents/skills`; `.agents/skills` is only a source root for digestion. +- Never save installed Agent Skills under `.deepcode/skills`; installation writes only to `.agents/skills`. - Never move a skill between project and user level during digestion. -- Never change the target skill's language preference after confirmation unless the user asks. +- Never overwrite or merge an existing installed skill directory unless the user explicitly asks after seeing the conflict. +- Never change the target skill's language preference after confirmation unless the user asks. \ No newline at end of file From 1d7abe7c363461d884c8eb7eb142738e21a621ab Mon Sep 17 00:00:00 2001 From: hcyang Date: Wed, 17 Jun 2026 17:26:01 +0800 Subject: [PATCH 29/72] =?UTF-8?q?chore(vscode-ide-companion):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20package.json=20=E5=88=86=E7=B1=BB=E5=92=8C=E5=85=B3?= =?UTF-8?q?=E9=94=AE=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将扩展类别从 "Other" 修改为 "AI" - 添加关键词列表,包括 deep-code、deep code、deep、code、cli、ide integration、ide companion - 设置扩展图标路径为 resources/deepcoding_icon.png --- packages/vscode-ide-companion/package.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/vscode-ide-companion/package.json b/packages/vscode-ide-companion/package.json index 78ff140e..5ad51fb7 100644 --- a/packages/vscode-ide-companion/package.json +++ b/packages/vscode-ide-companion/package.json @@ -15,7 +15,16 @@ "vscode": "^1.85.0" }, "categories": [ - "Other" + "AI" + ], + "keywords": [ + "deep-code", + "deep code", + "deep", + "code", + "cli", + "ide integration", + "ide companion" ], "icon": "resources/deepcoding_icon.png", "activationEvents": [], From 8979f072560bbf3cd43dbc252d1c1e890c47d0dd Mon Sep 17 00:00:00 2001 From: hcyang Date: Wed, 17 Jun 2026 17:28:40 +0800 Subject: [PATCH 30/72] =?UTF-8?q?chore(git):=20=E6=9B=B4=E6=96=B0.gitignor?= =?UTF-8?q?e=E4=BB=A5=E5=BF=BD=E7=95=A5=E7=94=9F=E6=88=90=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加了对 packages/cli/src/generated/ 目录的忽略规则 - 添加了对 packages/core/src/generated/ 目录的忽略规则 - 添加了对 packages/vscode-ide-companion/ 下所有 .vsix 文件的忽略规则 --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index cd80bbf9..2052d018 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,9 @@ src/generated/ *.log *.vsix .deepcode/settings.json + + +# Generated files +packages/cli/src/generated/ +packages/core/src/generated/ +packages/vscode-ide-companion/*.vsix \ No newline at end of file From 1081e1bfb81c0558cfe2535861f65cdd53ff7bfd Mon Sep 17 00:00:00 2001 From: hcyang Date: Wed, 17 Jun 2026 17:29:52 +0800 Subject: [PATCH 31/72] =?UTF-8?q?chore(git):=20=E6=9B=B4=E6=96=B0.gitignor?= =?UTF-8?q?e=E4=BB=A5=E5=BF=BD=E7=95=A5=E7=94=9F=E6=88=90=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加了对 packages/cli/src/generated/ 目录的忽略规则 - 添加了对 packages/core/src/generated/ 目录的忽略规则 - 添加了对 packages/vscode-ide-companion/ 下所有 .vsix 文件的忽略规则 --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 2052d018..cceec9f7 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ src/generated/ *.vsix .deepcode/settings.json +# TypeScript build info files +*.tsbuildinfo # Generated files packages/cli/src/generated/ From c0a2c903f379592d77689e9d34d4e1ae231a5662 Mon Sep 17 00:00:00 2001 From: hcyang Date: Wed, 17 Jun 2026 17:30:39 +0800 Subject: [PATCH 32/72] =?UTF-8?q?refactor(generated):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90=E7=9A=84git=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E4=BF=A1=E6=81=AF=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除packages/cli中的git-commit.ts自动生成文件 - 删除packages/core中的git-commit.ts自动生成文件 - 清理无用的自动生成代码以简化项目结构 --- packages/cli/src/generated/git-commit.ts | 8 -------- packages/core/src/generated/git-commit.ts | 8 -------- packages/core/tsconfig.tsbuildinfo | 1 - 3 files changed, 17 deletions(-) delete mode 100644 packages/cli/src/generated/git-commit.ts delete mode 100644 packages/core/src/generated/git-commit.ts delete mode 100644 packages/core/tsconfig.tsbuildinfo diff --git a/packages/cli/src/generated/git-commit.ts b/packages/cli/src/generated/git-commit.ts deleted file mode 100644 index e32594c8..00000000 --- a/packages/cli/src/generated/git-commit.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @license - * Copyright 2026 @vegamo deepcode - */ - -// Auto-generated by scripts/generate-git-commit-info.js. Do not edit. -export const GIT_COMMIT_INFO = "cc7b0c3"; -export const CLI_VERSION = "0.1.30"; diff --git a/packages/core/src/generated/git-commit.ts b/packages/core/src/generated/git-commit.ts deleted file mode 100644 index e32594c8..00000000 --- a/packages/core/src/generated/git-commit.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @license - * Copyright 2026 @vegamo deepcode - */ - -// Auto-generated by scripts/generate-git-commit-info.js. Do not edit. -export const GIT_COMMIT_INFO = "cc7b0c3"; -export const CLI_VERSION = "0.1.30"; diff --git a/packages/core/tsconfig.tsbuildinfo b/packages/core/tsconfig.tsbuildinfo deleted file mode 100644 index 5bef9a8e..00000000 --- a/packages/core/tsconfig.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"fileNames":["../../node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/typescript/lib/lib.es2021.d.ts","../../node_modules/typescript/lib/lib.es2022.d.ts","../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../node_modules/typescript/lib/lib.es2025.float16.d.ts","../../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","./src/common/model-capabilities.ts","./src/settings.ts","../../node_modules/gray-matter/gray-matter.d.ts","../../node_modules/@types/ejs/index.d.ts","../../node_modules/openai/internal/builtin-types.d.mts","../../node_modules/openai/internal/types.d.mts","../../node_modules/openai/internal/headers.d.mts","../../node_modules/openai/internal/shim-types.d.mts","../../node_modules/openai/core/streaming.d.mts","../../node_modules/openai/internal/request-options.d.mts","../../node_modules/openai/internal/utils/log.d.mts","../../node_modules/openai/resources/shared.d.mts","../../node_modules/openai/core/error.d.mts","../../node_modules/openai/pagination.d.mts","../../node_modules/openai/internal/parse.d.mts","../../node_modules/openai/core/api-promise.d.mts","../../node_modules/openai/core/pagination.d.mts","../../node_modules/openai/auth/types.d.mts","../../node_modules/openai/internal/uploads.d.mts","../../node_modules/openai/internal/to-file.d.mts","../../node_modules/openai/core/uploads.d.mts","../../node_modules/openai/resources/chat/chat.d.mts","../../node_modules/openai/resources/chat/index.d.mts","../../node_modules/openai/resources/admin/organization/admin-api-keys.d.mts","../../node_modules/openai/resources/admin/organization/audit-logs.d.mts","../../node_modules/openai/resources/admin/organization/certificates.d.mts","../../node_modules/openai/resources/admin/organization/data-retention.d.mts","../../node_modules/openai/resources/admin/organization/invites.d.mts","../../node_modules/openai/resources/admin/organization/roles.d.mts","../../node_modules/openai/resources/admin/organization/spend-alerts.d.mts","../../node_modules/openai/resources/admin/organization/usage.d.mts","../../node_modules/openai/resources/admin/organization/groups/roles.d.mts","../../node_modules/openai/resources/admin/organization/groups/users.d.mts","../../node_modules/openai/resources/admin/organization/groups/groups.d.mts","../../node_modules/openai/resources/admin/organization/projects/api-keys.d.mts","../../node_modules/openai/resources/admin/organization/projects/certificates.d.mts","../../node_modules/openai/resources/admin/organization/projects/data-retention.d.mts","../../node_modules/openai/resources/admin/organization/projects/hosted-tool-permissions.d.mts","../../node_modules/openai/resources/admin/organization/projects/model-permissions.d.mts","../../node_modules/openai/resources/admin/organization/projects/rate-limits.d.mts","../../node_modules/openai/resources/admin/organization/projects/roles.d.mts","../../node_modules/openai/resources/admin/organization/projects/service-accounts.d.mts","../../node_modules/openai/resources/admin/organization/projects/spend-alerts.d.mts","../../node_modules/openai/resources/admin/organization/projects/groups/roles.d.mts","../../node_modules/openai/resources/admin/organization/projects/groups/groups.d.mts","../../node_modules/openai/resources/admin/organization/users/roles.d.mts","../../node_modules/openai/resources/admin/organization/users/users.d.mts","../../node_modules/openai/resources/admin/organization/projects/users/roles.d.mts","../../node_modules/openai/resources/admin/organization/projects/users/users.d.mts","../../node_modules/openai/resources/admin/organization/projects/projects.d.mts","../../node_modules/openai/resources/admin/organization/organization.d.mts","../../node_modules/openai/resources/admin/admin.d.mts","../../node_modules/openai/resources/audio/speech.d.mts","../../node_modules/openai/resources/audio/transcriptions.d.mts","../../node_modules/openai/resources/audio/translations.d.mts","../../node_modules/openai/resources/audio/audio.d.mts","../../node_modules/openai/resources/batches.d.mts","../../node_modules/openai/resources/beta/threads/messages.d.mts","../../node_modules/openai/resources/beta/threads/runs/steps.d.mts","../../node_modules/openai/error.d.mts","../../node_modules/openai/lib/eventstream.d.mts","../../node_modules/openai/lib/assistantstream.d.mts","../../node_modules/openai/resources/beta/threads/runs/runs.d.mts","../../node_modules/openai/resources/beta/threads/threads.d.mts","../../node_modules/openai/resources/beta/assistants.d.mts","../../node_modules/openai/resources/beta/realtime/sessions.d.mts","../../node_modules/openai/resources/beta/realtime/transcription-sessions.d.mts","../../node_modules/openai/resources/beta/realtime/realtime.d.mts","../../node_modules/openai/resources/beta/chatkit/threads.d.mts","../../node_modules/openai/resources/beta/chatkit/sessions.d.mts","../../node_modules/openai/resources/beta/chatkit/chatkit.d.mts","../../node_modules/openai/resources/beta/beta.d.mts","../../node_modules/openai/resources/completions.d.mts","../../node_modules/openai/lib/parser.d.mts","../../node_modules/openai/lib/responsesparser.d.mts","../../node_modules/openai/azure.d.mts","../../node_modules/openai/bedrock.d.mts","../../node_modules/openai/index.d.mts","../../node_modules/openai/lib/responses/eventtypes.d.mts","../../node_modules/openai/lib/responses/responsestream.d.mts","../../node_modules/openai/resources/responses/input-items.d.mts","../../node_modules/openai/resources/responses/input-tokens.d.mts","../../node_modules/openai/resources/responses/responses.d.mts","../../node_modules/openai/resources/containers/files/content.d.mts","../../node_modules/openai/resources/containers/files/files.d.mts","../../node_modules/openai/resources/containers/containers.d.mts","../../node_modules/openai/resources/conversations/items.d.mts","../../node_modules/openai/resources/conversations/conversations.d.mts","../../node_modules/openai/resources/embeddings.d.mts","../../node_modules/openai/resources/graders/grader-models.d.mts","../../node_modules/openai/resources/evals/runs/output-items.d.mts","../../node_modules/openai/resources/evals/runs/runs.d.mts","../../node_modules/openai/resources/evals/evals.d.mts","../../node_modules/openai/resources/files.d.mts","../../node_modules/openai/resources/fine-tuning/methods.d.mts","../../node_modules/openai/resources/fine-tuning/alpha/graders.d.mts","../../node_modules/openai/resources/fine-tuning/alpha/alpha.d.mts","../../node_modules/openai/resources/fine-tuning/checkpoints/permissions.d.mts","../../node_modules/openai/resources/fine-tuning/checkpoints/checkpoints.d.mts","../../node_modules/openai/resources/fine-tuning/jobs/checkpoints.d.mts","../../node_modules/openai/resources/fine-tuning/jobs/jobs.d.mts","../../node_modules/openai/resources/fine-tuning/fine-tuning.d.mts","../../node_modules/openai/resources/graders/graders.d.mts","../../node_modules/openai/resources/images.d.mts","../../node_modules/openai/resources/models.d.mts","../../node_modules/openai/resources/moderations.d.mts","../../node_modules/openai/resources/realtime/calls.d.mts","../../node_modules/openai/resources/realtime/client-secrets.d.mts","../../node_modules/openai/resources/realtime/realtime.d.mts","../../node_modules/openai/resources/skills/content.d.mts","../../node_modules/openai/resources/skills/versions/content.d.mts","../../node_modules/openai/resources/skills/versions/versions.d.mts","../../node_modules/openai/resources/skills/skills.d.mts","../../node_modules/openai/resources/uploads/parts.d.mts","../../node_modules/openai/resources/uploads/uploads.d.mts","../../node_modules/openai/uploads.d.mts","../../node_modules/openai/resources/vector-stores/files.d.mts","../../node_modules/openai/resources/vector-stores/file-batches.d.mts","../../node_modules/openai/resources/vector-stores/vector-stores.d.mts","../../node_modules/openai/resources/videos.d.mts","../../node_modules/openai/resources/webhooks/webhooks.d.mts","../../node_modules/openai/resources/webhooks/index.d.mts","../../node_modules/openai/resources/webhooks.d.mts","../../node_modules/openai/resources/index.d.mts","../../node_modules/openai/client.d.mts","../../node_modules/openai/core/resource.d.mts","../../node_modules/openai/resources/chat/completions/messages.d.mts","../../node_modules/openai/lib/abstractchatcompletionrunner.d.mts","../../node_modules/openai/lib/chatcompletionstream.d.mts","../../node_modules/openai/lib/chatcompletionstreamingrunner.d.mts","../../node_modules/openai/lib/jsonschema.d.mts","../../node_modules/openai/lib/runnablefunction.d.mts","../../node_modules/openai/lib/chatcompletionrunner.d.mts","../../node_modules/openai/resources/chat/completions/completions.d.mts","../../node_modules/openai/resources/chat/completions/index.d.mts","../../node_modules/openai/resources/chat/completions.d.mts","./src/common/notify.ts","./src/common/openai-thinking.ts","./src/common/shell-utils.ts","./src/common/state.ts","./src/common/file-utils.ts","./src/prompt.ts","./src/tools/ask-user-question-handler.ts","./src/common/bash-timeout.ts","./src/common/process-tree.ts","./src/tools/bash-handler.ts","../../node_modules/zod/v4/core/json-schema.d.cts","../../node_modules/zod/v4/core/standard-schema.d.cts","../../node_modules/zod/v4/core/registries.d.cts","../../node_modules/zod/v4/core/to-json-schema.d.cts","../../node_modules/zod/v4/core/util.d.cts","../../node_modules/zod/v4/core/versions.d.cts","../../node_modules/zod/v4/core/schemas.d.cts","../../node_modules/zod/v4/core/checks.d.cts","../../node_modules/zod/v4/core/errors.d.cts","../../node_modules/zod/v4/core/core.d.cts","../../node_modules/zod/v4/core/parse.d.cts","../../node_modules/zod/v4/core/regexes.d.cts","../../node_modules/zod/v4/locales/ar.d.cts","../../node_modules/zod/v4/locales/az.d.cts","../../node_modules/zod/v4/locales/be.d.cts","../../node_modules/zod/v4/locales/bg.d.cts","../../node_modules/zod/v4/locales/ca.d.cts","../../node_modules/zod/v4/locales/cs.d.cts","../../node_modules/zod/v4/locales/da.d.cts","../../node_modules/zod/v4/locales/de.d.cts","../../node_modules/zod/v4/locales/el.d.cts","../../node_modules/zod/v4/locales/en.d.cts","../../node_modules/zod/v4/locales/eo.d.cts","../../node_modules/zod/v4/locales/es.d.cts","../../node_modules/zod/v4/locales/fa.d.cts","../../node_modules/zod/v4/locales/fi.d.cts","../../node_modules/zod/v4/locales/fr.d.cts","../../node_modules/zod/v4/locales/fr-ca.d.cts","../../node_modules/zod/v4/locales/he.d.cts","../../node_modules/zod/v4/locales/hr.d.cts","../../node_modules/zod/v4/locales/hu.d.cts","../../node_modules/zod/v4/locales/hy.d.cts","../../node_modules/zod/v4/locales/id.d.cts","../../node_modules/zod/v4/locales/is.d.cts","../../node_modules/zod/v4/locales/it.d.cts","../../node_modules/zod/v4/locales/ja.d.cts","../../node_modules/zod/v4/locales/ka.d.cts","../../node_modules/zod/v4/locales/kh.d.cts","../../node_modules/zod/v4/locales/km.d.cts","../../node_modules/zod/v4/locales/ko.d.cts","../../node_modules/zod/v4/locales/lt.d.cts","../../node_modules/zod/v4/locales/mk.d.cts","../../node_modules/zod/v4/locales/ms.d.cts","../../node_modules/zod/v4/locales/nl.d.cts","../../node_modules/zod/v4/locales/no.d.cts","../../node_modules/zod/v4/locales/ota.d.cts","../../node_modules/zod/v4/locales/ps.d.cts","../../node_modules/zod/v4/locales/pl.d.cts","../../node_modules/zod/v4/locales/pt.d.cts","../../node_modules/zod/v4/locales/ro.d.cts","../../node_modules/zod/v4/locales/ru.d.cts","../../node_modules/zod/v4/locales/sl.d.cts","../../node_modules/zod/v4/locales/sv.d.cts","../../node_modules/zod/v4/locales/ta.d.cts","../../node_modules/zod/v4/locales/th.d.cts","../../node_modules/zod/v4/locales/tr.d.cts","../../node_modules/zod/v4/locales/ua.d.cts","../../node_modules/zod/v4/locales/uk.d.cts","../../node_modules/zod/v4/locales/ur.d.cts","../../node_modules/zod/v4/locales/uz.d.cts","../../node_modules/zod/v4/locales/vi.d.cts","../../node_modules/zod/v4/locales/zh-cn.d.cts","../../node_modules/zod/v4/locales/zh-tw.d.cts","../../node_modules/zod/v4/locales/yo.d.cts","../../node_modules/zod/v4/locales/index.d.cts","../../node_modules/zod/v4/core/doc.d.cts","../../node_modules/zod/v4/core/api.d.cts","../../node_modules/zod/v4/core/json-schema-processors.d.cts","../../node_modules/zod/v4/core/json-schema-generator.d.cts","../../node_modules/zod/v4/core/index.d.cts","../../node_modules/zod/v4/classic/errors.d.cts","../../node_modules/zod/v4/classic/parse.d.cts","../../node_modules/zod/v4/classic/schemas.d.cts","../../node_modules/zod/v4/classic/checks.d.cts","../../node_modules/zod/v4/classic/compat.d.cts","../../node_modules/zod/v4/classic/from-json-schema.d.cts","../../node_modules/zod/v4/classic/iso.d.cts","../../node_modules/zod/v4/classic/coerce.d.cts","../../node_modules/zod/v4/classic/external.d.cts","../../node_modules/zod/index.d.cts","./src/common/tool-types.ts","./src/common/validate.ts","./src/tools/edit-handler.ts","./node_modules/ignore/index.d.ts","./src/tools/read-handler.ts","./src/tools/update-plan-handler.ts","./src/tools/web-search-handler.ts","./src/tools/write-handler.ts","./src/mcp/mcp-client.ts","./src/mcp/mcp-manager.ts","./src/tools/executor.ts","./src/common/error-logger.ts","./src/common/debug-logger.ts","./src/common/file-history.ts","./src/common/permissions.ts","./src/common/telemetry.ts","./src/common/openai-message-converter.ts","./src/session.ts","../../node_modules/undici/types/utility.d.ts","../../node_modules/undici/types/header.d.ts","../../node_modules/undici/types/readable.d.ts","../../node_modules/@types/node/compatibility/iterators.d.ts","../../node_modules/@types/node/globals.typedarray.d.ts","../../node_modules/@types/node/buffer.buffer.d.ts","../../node_modules/@types/node/globals.d.ts","../../node_modules/@types/node/web-globals/abortcontroller.d.ts","../../node_modules/@types/node/web-globals/blob.d.ts","../../node_modules/@types/node/web-globals/console.d.ts","../../node_modules/@types/node/web-globals/crypto.d.ts","../../node_modules/@types/node/web-globals/domexception.d.ts","../../node_modules/@types/node/web-globals/encoding.d.ts","../../node_modules/@types/node/web-globals/events.d.ts","../../node_modules/undici-types/utility.d.ts","../../node_modules/undici-types/header.d.ts","../../node_modules/undici-types/readable.d.ts","../../node_modules/undici-types/fetch.d.ts","../../node_modules/undici-types/formdata.d.ts","../../node_modules/undici-types/connector.d.ts","../../node_modules/undici-types/client-stats.d.ts","../../node_modules/undici-types/client.d.ts","../../node_modules/undici-types/errors.d.ts","../../node_modules/undici-types/dispatcher.d.ts","../../node_modules/undici-types/global-dispatcher.d.ts","../../node_modules/undici-types/global-origin.d.ts","../../node_modules/undici-types/pool-stats.d.ts","../../node_modules/undici-types/pool.d.ts","../../node_modules/undici-types/handlers.d.ts","../../node_modules/undici-types/balanced-pool.d.ts","../../node_modules/undici-types/round-robin-pool.d.ts","../../node_modules/undici-types/h2c-client.d.ts","../../node_modules/undici-types/agent.d.ts","../../node_modules/undici-types/mock-interceptor.d.ts","../../node_modules/undici-types/mock-call-history.d.ts","../../node_modules/undici-types/mock-agent.d.ts","../../node_modules/undici-types/mock-client.d.ts","../../node_modules/undici-types/mock-pool.d.ts","../../node_modules/undici-types/snapshot-agent.d.ts","../../node_modules/undici-types/mock-errors.d.ts","../../node_modules/undici-types/proxy-agent.d.ts","../../node_modules/undici-types/socks5-proxy-agent.d.ts","../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../node_modules/undici-types/retry-handler.d.ts","../../node_modules/undici-types/retry-agent.d.ts","../../node_modules/undici-types/api.d.ts","../../node_modules/undici-types/cache-interceptor.d.ts","../../node_modules/undici-types/interceptors.d.ts","../../node_modules/undici-types/util.d.ts","../../node_modules/undici-types/cookies.d.ts","../../node_modules/undici-types/patch.d.ts","../../node_modules/undici-types/websocket.d.ts","../../node_modules/undici-types/eventsource.d.ts","../../node_modules/undici-types/diagnostics-channel.d.ts","../../node_modules/undici-types/content-type.d.ts","../../node_modules/undici-types/cache.d.ts","../../node_modules/undici-types/index.d.ts","../../node_modules/@types/node/web-globals/fetch.d.ts","../../node_modules/@types/node/web-globals/importmeta.d.ts","../../node_modules/@types/node/web-globals/messaging.d.ts","../../node_modules/@types/node/web-globals/navigator.d.ts","../../node_modules/@types/node/web-globals/performance.d.ts","../../node_modules/@types/node/web-globals/storage.d.ts","../../node_modules/@types/node/web-globals/streams.d.ts","../../node_modules/@types/node/web-globals/timers.d.ts","../../node_modules/@types/node/web-globals/url.d.ts","../../node_modules/@types/node/assert.d.ts","../../node_modules/@types/node/assert/strict.d.ts","../../node_modules/@types/node/async_hooks.d.ts","../../node_modules/@types/node/buffer.d.ts","../../node_modules/@types/node/child_process.d.ts","../../node_modules/@types/node/cluster.d.ts","../../node_modules/@types/node/console.d.ts","../../node_modules/@types/node/constants.d.ts","../../node_modules/@types/node/crypto.d.ts","../../node_modules/@types/node/dgram.d.ts","../../node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/@types/node/dns.d.ts","../../node_modules/@types/node/dns/promises.d.ts","../../node_modules/@types/node/domain.d.ts","../../node_modules/@types/node/events.d.ts","../../node_modules/@types/node/fs.d.ts","../../node_modules/@types/node/fs/promises.d.ts","../../node_modules/@types/node/http.d.ts","../../node_modules/@types/node/http2.d.ts","../../node_modules/@types/node/https.d.ts","../../node_modules/@types/node/inspector.d.ts","../../node_modules/@types/node/inspector.generated.d.ts","../../node_modules/@types/node/inspector/promises.d.ts","../../node_modules/@types/node/module.d.ts","../../node_modules/@types/node/net.d.ts","../../node_modules/buffer/index.d.ts","../../node_modules/@types/node/os.d.ts","../../node_modules/@types/node/path.d.ts","../../node_modules/@types/node/path/posix.d.ts","../../node_modules/@types/node/path/win32.d.ts","../../node_modules/@types/node/perf_hooks.d.ts","../../node_modules/@types/node/process.d.ts","../../node_modules/@types/node/punycode.d.ts","../../node_modules/@types/node/querystring.d.ts","../../node_modules/@types/node/quic.d.ts","../../node_modules/@types/node/readline.d.ts","../../node_modules/@types/node/readline/promises.d.ts","../../node_modules/@types/node/repl.d.ts","../../node_modules/@types/node/sea.d.ts","../../node_modules/@types/node/sqlite.d.ts","../../node_modules/@types/node/stream.d.ts","../../node_modules/@types/node/stream/consumers.d.ts","../../node_modules/@types/node/stream/iter.d.ts","../../node_modules/@types/node/stream/promises.d.ts","../../node_modules/@types/node/stream/web.d.ts","../../node_modules/@types/node/string_decoder.d.ts","../../node_modules/@types/node/test.d.ts","../../node_modules/@types/node/test/reporters.d.ts","../../node_modules/@types/node/timers.d.ts","../../node_modules/@types/node/timers/promises.d.ts","../../node_modules/@types/node/tls.d.ts","../../node_modules/@types/node/trace_events.d.ts","../../node_modules/@types/node/tty.d.ts","../../node_modules/@types/node/url.d.ts","../../node_modules/@types/node/util.d.ts","../../node_modules/@types/node/util/types.d.ts","../../node_modules/@types/node/v8.d.ts","../../node_modules/@types/node/vm.d.ts","../../node_modules/@types/node/wasi.d.ts","../../node_modules/@types/node/worker_threads.d.ts","../../node_modules/@types/node/zlib.d.ts","../../node_modules/@types/node/zlib/iter.d.ts","../../node_modules/@types/node/index.d.ts","../../node_modules/undici/types/fetch.d.ts","../../node_modules/undici/types/formdata.d.ts","../../node_modules/undici/types/connector.d.ts","../../node_modules/undici/types/client-stats.d.ts","../../node_modules/undici/types/client.d.ts","../../node_modules/undici/types/errors.d.ts","../../node_modules/undici/types/dispatcher.d.ts","../../node_modules/undici/types/global-dispatcher.d.ts","../../node_modules/undici/types/global-origin.d.ts","../../node_modules/undici/types/pool-stats.d.ts","../../node_modules/undici/types/pool.d.ts","../../node_modules/undici/types/handlers.d.ts","../../node_modules/undici/types/balanced-pool.d.ts","../../node_modules/undici/types/round-robin-pool.d.ts","../../node_modules/undici/types/h2c-client.d.ts","../../node_modules/undici/types/agent.d.ts","../../node_modules/undici/types/mock-interceptor.d.ts","../../node_modules/undici/types/mock-call-history.d.ts","../../node_modules/undici/types/mock-agent.d.ts","../../node_modules/undici/types/mock-client.d.ts","../../node_modules/undici/types/mock-pool.d.ts","../../node_modules/undici/types/snapshot-agent.d.ts","../../node_modules/undici/types/mock-errors.d.ts","../../node_modules/undici/types/proxy-agent.d.ts","../../node_modules/undici/types/socks5-proxy-agent.d.ts","../../node_modules/undici/types/env-http-proxy-agent.d.ts","../../node_modules/undici/types/retry-handler.d.ts","../../node_modules/undici/types/retry-agent.d.ts","../../node_modules/undici/types/api.d.ts","../../node_modules/undici/types/cache-interceptor.d.ts","../../node_modules/undici/types/interceptors.d.ts","../../node_modules/undici/types/util.d.ts","../../node_modules/undici/types/cookies.d.ts","../../node_modules/undici/types/patch.d.ts","../../node_modules/undici/types/websocket.d.ts","../../node_modules/undici/types/eventsource.d.ts","../../node_modules/undici/types/diagnostics-channel.d.ts","../../node_modules/undici/types/content-type.d.ts","../../node_modules/undici/types/cache.d.ts","../../node_modules/undici/types/index.d.ts","../../node_modules/undici/index.d.ts","./src/common/openai-client.ts","./src/index.ts"],"fileIdsList":[[309,373,381,385,388,390,391,392,405,434],[309,370,371,373,381,385,388,390,391,392,405,434],[309,372,373,381,385,388,390,391,392,405,434],[373,381,385,388,390,391,392,405,434],[309,373,381,385,388,390,391,392,405,414,434],[309,373,374,379,381,384,385,388,390,391,392,394,405,410,423,434],[309,373,374,375,381,384,385,388,390,391,392,405,434],[309,373,376,381,385,388,390,391,392,405,424,434],[309,373,377,378,381,385,388,390,391,392,396,405,434],[309,373,378,381,385,388,390,391,392,405,410,420,434],[309,373,379,381,384,385,388,390,391,392,394,405,434],[309,372,373,380,381,385,388,390,391,392,405,434],[309,373,381,382,385,388,390,391,392,405,434],[309,373,381,383,384,385,388,390,391,392,405,434],[309,372,373,381,384,385,388,390,391,392,405,434],[309,373,381,384,385,386,388,390,391,392,405,410,423,434],[309,373,381,384,385,386,388,390,391,392,405,410,412,414,434],[309,360,373,381,384,385,387,388,390,391,392,394,405,410,423,434],[309,373,381,384,385,387,388,390,391,392,394,405,410,420,423,434],[309,373,381,385,387,388,389,390,391,392,405,410,420,423,434],[307,308,309,310,311,312,313,314,315,316,317,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,434],[309,373,381,384,385,388,390,391,392,405,434],[309,373,381,385,388,390,392,405,434],[309,373,381,385,388,390,391,392,393,405,423,434],[309,373,381,384,385,388,390,391,392,394,405,410,434],[309,373,381,385,388,390,391,392,396,405,434],[309,373,381,385,388,390,391,392,397,405,434],[309,373,381,384,385,388,390,391,392,400,405,434],[309,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,434],[309,373,381,385,388,390,391,392,402,405,434],[309,373,381,385,388,390,391,392,403,405,434],[309,373,378,381,385,388,390,391,392,394,405,414,434],[309,373,381,384,385,388,390,391,392,405,406,434],[309,373,381,385,388,390,391,392,405,407,424,427,434],[309,373,381,384,385,388,390,391,392,405,410,413,414,434],[309,373,381,385,388,390,391,392,405,411,414,434],[309,373,381,385,388,390,391,392,405,412,434],[309,373,381,385,388,390,391,392,405,414,424,434],[309,373,381,385,388,390,391,392,405,415,434],[309,370,373,381,385,388,390,391,392,405,410,417,423,434],[309,373,381,385,388,390,391,392,405,410,416,434],[309,373,381,384,385,388,390,391,392,405,418,419,434],[309,373,381,385,388,390,391,392,405,418,419,434],[309,373,378,381,385,388,390,391,392,394,405,410,420,434],[309,373,381,385,388,390,391,392,405,421,434],[309,373,381,385,388,390,391,392,394,405,422,434],[309,373,381,385,387,388,390,391,392,403,405,423,434],[309,373,381,385,388,390,391,392,405,424,425,434],[309,373,378,381,385,388,390,391,392,405,425,434],[309,373,381,385,388,390,391,392,405,410,426,434],[309,373,381,385,388,390,391,392,393,405,427,434],[309,373,381,385,388,390,391,392,405,428,434],[309,373,376,381,385,388,390,391,392,405,434],[309,373,378,381,385,388,390,391,392,405,434],[309,373,381,385,388,390,391,392,405,424,434],[309,360,373,381,385,388,390,391,392,405,434],[309,373,381,385,388,390,391,392,405,423,434],[309,373,381,385,388,390,391,392,405,429,434],[309,373,381,385,388,390,391,392,400,405,434],[309,373,381,385,388,390,391,392,405,419,434],[309,360,373,381,384,385,386,388,390,391,392,400,405,410,414,423,426,427,429,434],[309,373,381,385,388,390,391,392,405,410,430,434],[309,373,381,385,388,390,391,392,405,412,431,434],[64,66,69,184,309,373,381,385,388,390,391,392,405,434],[66,69,184,309,373,381,385,388,390,391,392,405,434],[64,65,66,69,70,72,75,76,77,80,81,111,115,116,131,132,142,145,147,148,152,153,161,162,163,164,165,168,172,174,178,179,180,183,193,309,373,381,385,388,390,391,392,405,434],[65,74,184,309,373,381,385,388,390,391,392,405,434],[71,309,373,381,385,388,390,391,392,405,434],[69,74,75,184,309,373,381,385,388,390,391,392,405,434],[184,309,373,381,385,388,390,391,392,405,434],[67,184,309,373,381,385,388,390,391,392,405,434],[78,79,309,373,381,385,388,390,391,392,405,434],[72,309,373,381,385,388,390,391,392,405,434],[72,75,76,80,135,136,184,309,373,381,385,388,390,391,392,405,434],[69,73,184,309,373,381,385,388,390,391,392,405,434],[64,65,66,68,309,373,381,385,388,390,391,392,405,434],[64,309,373,381,385,388,390,391,392,405,434],[64,69,184,309,373,381,385,388,390,391,392,405,434],[69,184,309,373,381,385,388,390,391,392,405,434],[69,120,132,137,189,191,192,195,309,373,381,385,388,390,391,392,405,434],[67,69,117,118,120,122,123,124,309,373,381,385,388,390,391,392,405,434],[133,137,187,191,195,309,373,381,385,388,390,391,392,405,434],[67,69,137,187,193,195,309,373,381,385,388,390,391,392,405,434],[67,133,137,187,188,191,195,309,373,381,385,388,390,391,392,405,434],[119,309,373,381,385,388,390,391,392,405,434],[71,142,195,309,373,381,385,388,390,391,392,405,434],[142,309,373,381,385,388,390,391,392,405,434],[69,120,134,137,138,142,309,373,381,385,388,390,391,392,405,434],[133,142,195,309,373,381,385,388,390,391,392,405,434],[189,190,192,309,373,381,385,388,390,391,392,405,434],[76,309,373,381,385,388,390,391,392,405,434],[110,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,185,309,373,381,385,388,390,391,392,405,434],[69,76,185,309,373,381,385,388,390,391,392,405,434],[69,75,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,91,92,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,88,185,309,373,381,385,388,390,391,392,405,434],[83,84,85,86,87,88,89,90,93,106,109,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,103,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,94,95,96,97,98,99,100,101,102,104,108,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,88,106,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,107,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,105,185,309,373,381,385,388,390,391,392,405,434],[112,113,114,185,309,373,381,385,388,390,391,392,405,434],[68,69,75,80,113,115,185,309,373,381,385,388,390,391,392,405,434],[69,75,80,113,115,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,116,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,117,118,121,122,123,185,309,373,381,385,388,390,391,392,405,434],[123,124,127,130,185,309,373,381,385,388,390,391,392,405,434],[128,129,185,309,373,381,385,388,390,391,392,405,434],[69,75,128,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,130,185,309,373,381,385,388,390,391,392,405,434],[71,125,126,127,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,124,185,309,373,381,385,388,390,391,392,405,434],[68,69,71,75,76,117,118,121,122,123,124,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,118,185,309,373,381,385,388,390,391,392,405,434],[68,69,71,75,117,121,122,123,124,185,309,373,381,385,388,390,391,392,405,434],[71,185,193,309,373,381,385,388,390,391,392,405,434],[194,309,373,381,385,388,390,391,392,405,434],[68,69,71,75,76,132,133,185,186,187,188,189,191,192,193,309,373,381,385,388,390,391,392,405,434],[186,193,309,373,381,385,388,390,391,392,405,434],[69,76,185,193,309,373,381,385,388,390,391,392,405,434],[81,194,309,373,381,385,388,390,391,392,405,434],[68,69,75,132,185,193,309,373,381,385,388,390,391,392,405,434],[69,75,76,142,144,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,80,143,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,142,146,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,142,147,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,142,149,151,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,151,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,142,149,150,185,193,309,373,381,385,388,390,391,392,405,434],[69,75,76,80,185,309,373,381,385,388,390,391,392,405,434],[155,185,309,373,381,385,388,390,391,392,405,434],[69,75,149,185,309,373,381,385,388,390,391,392,405,434],[157,185,309,373,381,385,388,390,391,392,405,434],[154,156,158,160,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,154,159,185,309,373,381,385,388,390,391,392,405,434],[149,185,309,373,381,385,388,390,391,392,405,434],[71,142,149,185,309,373,381,385,388,390,391,392,405,434],[68,69,75,80,163,185,309,373,381,385,388,390,391,392,405,434],[71,82,111,115,116,131,132,142,145,147,148,152,153,161,162,163,164,165,168,172,174,178,179,182,309,373,381,385,388,390,391,392,405,434],[69,75,142,168,185,309,373,381,385,388,390,391,392,405,434],[69,75,142,167,168,185,309,373,381,385,388,390,391,392,405,434],[71,142,166,167,168,185,309,373,381,385,388,390,391,392,405,434],[69,76,142,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,142,185,309,373,381,385,388,390,391,392,405,434],[68,69,71,75,76,134,139,140,141,142,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,80,169,171,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,80,170,185,309,373,381,385,388,390,391,392,405,434],[69,75,80,185,309,373,381,385,388,390,391,392,405,434],[69,75,153,173,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,175,176,178,185,309,373,381,385,388,390,391,392,405,434],[69,75,76,175,178,185,309,373,381,385,388,390,391,392,405,434],[69,71,75,76,176,177,185,309,373,381,385,388,390,391,392,405,434],[181,309,373,381,385,388,390,391,392,405,434],[180,309,373,381,385,388,390,391,392,405,434],[66,185,309,373,381,385,388,390,391,392,405,434],[80,309,373,381,385,388,390,391,392,405,434],[309,324,327,330,331,373,381,385,388,390,391,392,405,423,434],[309,327,373,381,385,388,390,391,392,405,410,423,434],[309,327,331,373,381,385,388,390,391,392,405,423,434],[309,373,381,385,388,390,391,392,405,410,434],[309,321,373,381,385,388,390,391,392,405,434],[309,325,373,381,385,388,390,391,392,405,434],[309,323,324,327,373,381,385,388,390,391,392,405,423,434],[309,373,381,385,388,390,391,392,394,405,420,434],[309,373,381,385,388,390,391,392,405,432,434],[309,321,373,381,385,388,390,391,392,405,432,434],[309,323,327,373,381,385,388,390,391,392,394,405,423,434],[309,318,319,320,322,326,373,381,384,385,388,390,391,392,405,410,423,434],[309,327,336,344,373,381,385,388,390,391,392,405,434],[309,319,325,373,381,385,388,390,391,392,405,434],[309,327,354,355,373,381,385,388,390,391,392,405,434],[309,319,322,327,373,381,385,388,390,391,392,405,414,423,432,434],[309,327,373,381,385,388,390,391,392,405,434],[309,323,327,373,381,385,388,390,391,392,405,423,434],[309,318,373,381,385,388,390,391,392,405,434],[309,321,322,323,325,326,327,328,329,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,355,356,357,358,359,373,381,385,388,390,391,392,405,434],[309,327,347,350,373,381,385,388,390,391,392,405,434],[309,327,336,337,338,373,381,385,388,390,391,392,405,434],[309,325,327,337,339,373,381,385,388,390,391,392,405,434],[309,326,373,381,385,388,390,391,392,405,434],[309,319,321,327,373,381,385,388,390,391,392,405,434],[309,327,331,337,339,373,381,385,388,390,391,392,405,434],[309,331,373,381,385,388,390,391,392,405,434],[309,325,327,330,373,381,385,388,390,391,392,405,423,434],[309,319,323,327,336,373,381,385,388,390,391,392,405,434],[309,327,347,373,381,385,388,390,391,392,405,434],[309,339,373,381,385,388,390,391,392,405,434],[309,319,323,327,331,373,381,385,388,390,391,392,405,434],[309,321,327,354,373,381,385,388,390,391,392,405,414,429,432,434],[309,373,381,385,388,390,391,392,405,434,472],[309,373,381,385,388,390,391,392,405,423,434,436,439,442,443],[309,373,381,385,388,390,391,392,405,410,423,434,439],[309,373,381,385,388,390,391,392,405,423,434,439,443],[309,373,381,385,388,390,391,392,405,433,434],[309,373,381,385,388,390,391,392,405,434,437],[309,373,381,385,388,390,391,392,405,423,434,435,436,439],[309,373,381,385,388,390,391,392,405,432,433,434],[309,373,381,385,388,390,391,392,394,405,423,434,435,439],[304,305,306,309,373,381,384,385,388,390,391,392,405,410,423,434,438],[309,373,381,385,388,390,391,392,405,434,439,448,456],[305,309,373,381,385,388,390,391,392,405,434,437],[309,373,381,385,388,390,391,392,405,434,439,466,467],[305,309,373,381,385,388,390,391,392,405,414,423,432,434,439],[309,373,381,385,388,390,391,392,405,434,439],[309,373,381,385,388,390,391,392,405,423,434,435,439],[304,309,373,381,385,388,390,391,392,405,434],[309,373,381,385,388,390,391,392,405,433,434,435,437,438,439,440,441,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,467,468,469,470,471],[309,373,381,385,388,390,391,392,405,434,439,459,462],[309,373,381,385,388,390,391,392,405,434,439,448,449,450],[309,373,381,385,388,390,391,392,405,434,437,439,449,451],[309,373,381,385,388,390,391,392,405,434,438],[305,309,373,381,385,388,390,391,392,405,433,434,439],[309,373,381,385,388,390,391,392,405,434,439,443,449,451],[309,373,381,385,388,390,391,392,405,434,443],[309,373,381,385,388,390,391,392,405,423,434,437,439,442],[305,309,373,381,385,388,390,391,392,405,434,435,439,448],[309,373,381,385,388,390,391,392,405,434,439,459],[309,373,381,385,388,390,391,392,405,434,451],[305,309,373,381,385,388,390,391,392,405,434,435,439,443],[309,373,381,385,388,390,391,392,405,414,429,432,433,434,439,466],[284,309,373,381,385,388,390,391,392,405,434],[275,309,373,381,385,388,390,391,392,405,434],[275,278,309,373,381,385,388,390,391,392,405,434],[210,270,273,275,276,277,278,279,280,281,282,283,309,373,381,385,388,390,391,392,405,434],[206,208,278,309,373,381,385,388,390,391,392,405,434],[275,276,309,373,381,385,388,390,391,392,405,434],[207,275,277,309,373,381,385,388,390,391,392,405,434],[208,210,212,213,214,215,309,373,381,385,388,390,391,392,405,434],[210,212,214,215,309,373,381,385,388,390,391,392,405,434],[210,212,214,309,373,381,385,388,390,391,392,405,434],[207,210,212,213,215,309,373,381,385,388,390,391,392,405,434],[206,208,209,210,211,212,213,214,215,216,217,270,271,272,273,274,309,373,381,385,388,390,391,392,405,434],[206,208,209,212,309,373,381,385,388,390,391,392,405,434],[208,209,212,309,373,381,385,388,390,391,392,405,434],[212,215,309,373,381,385,388,390,391,392,405,434],[206,207,209,210,211,213,214,215,309,373,381,385,388,390,391,392,405,434],[206,207,208,212,275,309,373,381,385,388,390,391,392,405,434],[212,213,214,215,309,373,381,385,388,390,391,392,405,434],[214,309,373,381,385,388,390,391,392,405,434],[218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,309,373,381,385,388,390,391,392,405,434],[309,373,381,385,388,390,391,392,396,397,405,434],[309,373,374,378,381,385,388,390,391,392,397,405,434],[199,309,373,381,385,388,390,391,392,397,405,434],[309,373,374,381,385,388,390,391,392,405,434],[61,137,309,373,381,385,388,390,391,392,396,397,405,434,473],[60,195,303,309,373,381,385,388,390,391,392,405,434],[61,309,373,381,385,388,390,391,392,405,434],[61,199,309,373,381,385,388,390,391,392,397,405,434],[309,373,374,381,385,388,390,391,392,396,397,399,405,434],[198,200,309,373,381,385,388,390,391,392,397,405,434],[61,137,309,373,381,385,388,390,391,392,405,434],[285,286,309,373,381,385,388,390,391,392,405,434],[60,61,196,197,198,199,200,201,202,203,204,205,286,287,288,290,291,292,293,294,295,296,297,298,299,300,301,302,303,309,373,381,385,388,390,391,392,405,434,474],[204,309,373,374,381,385,388,390,391,392,397,405,434],[61,294,309,373,378,381,385,388,390,391,392,405,434],[60,62,63,198,303,309,373,374,381,385,388,390,391,392,396,397,405,423,434],[60,61,62,63,195,196,197,199,200,201,204,205,295,296,297,298,299,300,301,302,309,373,378,381,385,388,390,391,392,396,397,405,434],[60,309,373,381,385,388,390,391,392,396,397,405,434],[296,309,373,381,385,388,390,391,392,405,434],[198,203,204,296,309,373,374,378,381,385,388,390,391,392,396,397,405,434],[197,199,200,285,287,296,309,373,381,385,388,390,391,392,405,434],[202,205,286,288,290,291,292,293,295,309,373,381,385,388,390,391,392,405,434],[199,200,289,296,309,373,381,385,388,390,391,392,397,405,434],[285,287,296,309,373,381,385,388,390,391,392,405,434],[137,296,309,373,374,378,381,385,388,390,391,392,405,434],[199,200,285,287,296,309,373,381,385,388,390,391,392,405,434]],"fileInfos":[{"version":"bcd24271a113971ba9eb71ff8cb01bc6b0f872a85c23fdbe5d93065b375933cd","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f88bedbeb09c6f5a6645cb24c7c55f1aa22d19ae96c8e6959cbd8b85a707bc6","impliedFormat":1},{"version":"7fe93b39b810eadd916be8db880dd7f0f7012a5cc6ffb62de8f62a2117fa6f1f","impliedFormat":1},{"version":"bb0074cc08b84a2374af33d8bf044b80851ccc9e719a5e202eacf40db2c31600","impliedFormat":1},{"version":"1a7daebe4f45fb03d9ec53d60008fbf9ac45a697fdc89e4ce218bc94b94f94d6","impliedFormat":1},{"version":"f94b133a3cb14a288803be545ac2683e0d0ff6661bcd37e31aaaec54fc382aed","impliedFormat":1},{"version":"f59d0650799f8782fd74cf73c19223730c6d1b9198671b1c5b3a38e1188b5953","impliedFormat":1},{"version":"8a15b4607d9a499e2dbeed9ec0d3c0d7372c850b2d5f1fb259e8f6d41d468a84","impliedFormat":1},{"version":"26e0fe14baee4e127f4365d1ae0b276f400562e45e19e35fd2d4c296684715e6","impliedFormat":1},{"version":"eadcffda2aa84802c73938e589b9e58248d74c59cb7fcbca6474e3435ac15504","affectsGlobalScope":true,"impliedFormat":1},{"version":"105ba8ff7ba746404fe1a2e189d1d3d2e0eb29a08c18dded791af02f29fb4711","affectsGlobalScope":true,"impliedFormat":1},{"version":"00343ca5b2e3d48fa5df1db6e32ea2a59afab09590274a6cccb1dbae82e60c7c","affectsGlobalScope":true,"impliedFormat":1},{"version":"ebd9f816d4002697cb2864bea1f0b70a103124e18a8cd9645eeccc09bdf80ab4","affectsGlobalScope":true,"impliedFormat":1},{"version":"2c1afac30a01772cd2a9a298a7ce7706b5892e447bb46bdbeef720f7b5da77ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"7b0225f483e4fa685625ebe43dd584bb7973bbd84e66a6ba7bbe175ee1048b4f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0a4b8ac6ce74679c1da2b3795296f5896e31c38e888469a8e0f99dc3305de60","affectsGlobalScope":true,"impliedFormat":1},{"version":"3084a7b5f569088e0146533a00830e206565de65cae2239509168b11434cd84f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5079c53f0f141a0698faa903e76cb41cd664e3efb01cc17a5c46ec2eb0bef42","affectsGlobalScope":true,"impliedFormat":1},{"version":"32cafbc484dea6b0ab62cf8473182bbcb23020d70845b406f80b7526f38ae862","affectsGlobalScope":true,"impliedFormat":1},{"version":"fca4cdcb6d6c5ef18a869003d02c9f0fd95df8cfaf6eb431cd3376bc034cad36","affectsGlobalScope":true,"impliedFormat":1},{"version":"b93ec88115de9a9dc1b602291b85baf825c85666bf25985cc5f698073892b467","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5c06dcc3fe849fcb297c247865a161f995cc29de7aa823afdd75aaaddc1419b","affectsGlobalScope":true,"impliedFormat":1},{"version":"b77e16112127a4b169ef0b8c3a4d730edf459c5f25fe52d5e436a6919206c4d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"fbffd9337146eff822c7c00acbb78b01ea7ea23987f6c961eba689349e744f8c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a995c0e49b721312f74fdfb89e4ba29bd9824c770bbb4021d74d2bf560e4c6bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"c7b3542146734342e440a84b213384bfa188835537ddbda50d30766f0593aff9","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce6180fa19b1cccd07ee7f7dbb9a367ac19c0ed160573e4686425060b6df7f57","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f02e2476bccb9dbe21280d6090f0df17d2f66b74711489415a8aa4df73c9675","affectsGlobalScope":true,"impliedFormat":1},{"version":"45e3ab34c1c013c8ab2dc1ba4c80c780744b13b5676800ae2e3be27ae862c40c","affectsGlobalScope":true,"impliedFormat":1},{"version":"805c86f6cca8d7702a62a844856dbaa2a3fd2abef0536e65d48732441dde5b5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e42e397f1a5a77994f0185fd1466520691456c772d06bf843e5084ceb879a0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"f4c2b41f90c95b1c532ecc874bd3c111865793b23aebcc1c3cbbabcd5d76ffb0","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab26191cfad5b66afa11b8bf935ef1cd88fabfcb28d30b2dfa6fad877d050332","affectsGlobalScope":true,"impliedFormat":1},{"version":"2088bc26531e38fb05eedac2951480db5309f6be3fa4a08d2221abb0f5b4200d","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb9d366c425fea79716a8fb3af0d78e6b22ebbab3bd64d25063b42dc9f531c1e","affectsGlobalScope":true,"impliedFormat":1},{"version":"500934a8089c26d57ebdb688fc9757389bb6207a3c8f0674d68efa900d2abb34","affectsGlobalScope":true,"impliedFormat":1},{"version":"689da16f46e647cef0d64b0def88910e818a5877ca5379ede156ca3afb780ac3","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc21cc8b6fee4f4c2440d08035b7ea3c06b3511314c8bab6bef7a92de58a2593","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ca53d13d2957003abb47922a71866ba7cb2068f8d154877c596d63c359fed25","affectsGlobalScope":true,"impliedFormat":1},{"version":"54725f8c4df3d900cb4dac84b64689ce29548da0b4e9b7c2de61d41c79293611","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5594bc3076ac29e6c1ebda77939bc4c8833de72f654b6e376862c0473199323","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f3eb332c2d73e729f3364fcc0c2b375e72a121e8157d25a82d67a138c83a95c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f4427f9642ce8d500970e4e69d1397f64072ab73b97e476b4002a646ac743b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"48915f327cd1dea4d7bd358d9dc7732f58f9e1626a29cc0c05c8c692419d9bb7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7bf9377723203b5a6a4b920164df22d56a43f593269ba6ae1fdc97774b68855","affectsGlobalScope":true,"impliedFormat":1},{"version":"db9709688f82c9e5f65a119c64d835f906efe5f559d08b11642d56eb85b79357","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b25b8c874acd1a4cf8444c3617e037d444d19080ac9f634b405583fd10ce1f7","affectsGlobalScope":true,"impliedFormat":1},{"version":"37be57d7c90cf1f8112ee2636a068d8fd181289f82b744160ec56a7dc158a9f5","affectsGlobalScope":true,"impliedFormat":1},{"version":"a917a49ac94cd26b754ab84e113369a75d1a47a710661d7cd25e961cc797065f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d3261badeb7843d157ef3e6f5d1427d0eeb0af0cf9df84a62cfd29fd47ac86e","affectsGlobalScope":true,"impliedFormat":1},{"version":"195daca651dde22f2167ac0d0a05e215308119a3100f5e6268e8317d05a92526","affectsGlobalScope":true,"impliedFormat":1},{"version":"8b11e4285cd2bb164a4dc09248bdec69e9842517db4ca47c1ba913011e44ff2f","affectsGlobalScope":true,"impliedFormat":1},{"version":"0508571a52475e245b02bc50fa1394065a0a3d05277fbf5120c3784b85651799","affectsGlobalScope":true,"impliedFormat":1},{"version":"8f9af488f510c3015af3cc8c267a9e9d96c4dd38a1fdff0e11dc5a544711415b","affectsGlobalScope":true,"impliedFormat":1},{"version":"fc611fea8d30ea72c6bbfb599c9b4d393ce22e2f5bfef2172534781e7d138104","affectsGlobalScope":true,"impliedFormat":1},{"version":"f128dae7c44d8f35ee42e0a437000a57c9f06cc04f8b4fb42eebf44954d53dc8","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ecb8e347cb6b2a8927c09b86263663289418df375f5e68e11a0ae683776978f","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ce14b81c5cc821994aa8ec1d42b220dd41b27fcc06373bce3958af7421b77d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3a048b3e9302ef9a34ef4ebb9aecfb28b66abb3bce577206a79fee559c230da","affectsGlobalScope":true,"impliedFormat":1},{"version":"d5c693c7241b88f974795daf08b61244f552f065ec93344f0a87bb2ea8b9c23c","signature":"9033850caf9a677b88e949247cc7bb10baf88436c87597478bb6e23eed521742"},{"version":"4743a6dba8d31255325d84ef0d5687997755332b5fe042c908bf56d8b22535cc","signature":"427af1572cfe2b3dd93c53285141b662f6ca5c5b16ee9a10b7aaeb6f523de244"},{"version":"a52c5f687d788d283ea1fa38bdc2fabe0eac863135a7dfe175ec52b309f61892","impliedFormat":1},{"version":"f2a60d253f7206372203b736144906bf135762100a2b3d1b415776ebf6575d07","impliedFormat":1},{"version":"86d4ff8ba66b5ea1df375fe6092d2b167682ccd5dd0d9b003a7d30d95a0cda32","impliedFormat":99},{"version":"652071821de280fae0ba53f0abcdd7350b1bda286f8fcd39394f5d4250de44ce","impliedFormat":99},{"version":"2b5368217b57528a60433558585186a925d9842fe64c1262adde8eac5cb8de33","impliedFormat":99},{"version":"e22273698b7aad4352f0eb3c981d510b5cf6b17fde2eeaa5c018bb065d15558f","impliedFormat":99},{"version":"0249cc57fb4f04fcc725481b5f273fe4a18d943e108724b216c762aaf311c255","impliedFormat":99},{"version":"c674b1e72c7f6879711bb0e920319b2760dacb7125fac4653702a1aa37a8b283","impliedFormat":99},{"version":"91c093343733c2c2d40bee28dc793eff3071af0cb53897651f8459ad25ad01da","impliedFormat":99},{"version":"6cc2be65d508f5404dae184fbe1bc5fc6287f2af93195feba921e619721f56a0","impliedFormat":99},{"version":"17c51065e7822de999ed5ff702aead6057c172067e485e8ffe9721bfe5010f0a","impliedFormat":99},{"version":"5c9a2aec7cf29c39450fe23930e192bb58a90b36c3f169481c3ef25f2fcf79e2","impliedFormat":99},{"version":"f4fc36916b3eac2ea0180532b46283808604e4b6ff11e5031494d05aa6661cc6","impliedFormat":99},{"version":"82e23a5d9f36ccdac5322227cd970a545b8c23179f2035388a1524f82f96d8d0","impliedFormat":99},{"version":"45160eb8c4c54610c5f43c103ff539e204d12aeed21c6cbe74c0fdf63741b5db","impliedFormat":99},{"version":"67cce3d39642e38f36602ab04d683b8a0c5e3a943eb03ac288e3d68c31596014","impliedFormat":99},{"version":"bfce32506c0d081212ff9d27ec466fa6135a695ba61d5a02738abd2442566231","impliedFormat":99},{"version":"ddaf5d3ddc45282b19fb0fecec91c87fc9b4d1f45c2ee611677345c81383c5c5","impliedFormat":99},{"version":"5668033966c8247576fc316629df131d6175d24ccf22940324c19c159671e1c1","impliedFormat":99},{"version":"7630b6a1c0ebaec2ef8e8abff850e1d6c551c47d1c345340a8ab95667460fc95","impliedFormat":99},{"version":"597b0a9ef02a28f5b1195305ec9f20a4f9948bd90ec3291d0343d1e5c0b4bd16","impliedFormat":99},{"version":"5c4081cb959a116933350a69585eff8a3eeb8c98c9b8fb0b9659a0ab51ab0be5","impliedFormat":99},{"version":"eb06d1cb283278811a37f17dc35047db62bcfa69e75f752ae170e318e4704f55","impliedFormat":99},{"version":"9bda3cb21c5022c86d2325885672085a8282a08c9df21688f7d3c6eff58efd40","impliedFormat":99},{"version":"e600e54a07ac7bcf9f0fd67722865bda454f5325ca4742e08e7c321a848fc5b0","impliedFormat":99},{"version":"ddd904d24dff387d2484b69e0643541102a0e3a4f750bb2d517f46adabf84bd7","impliedFormat":99},{"version":"045b2cdfaf5cf84f5be6bde21862add9503e104b252c6dc91efae422d4e8f975","impliedFormat":99},{"version":"19f21a767c89a4f3d8721ae698ce2a61b31d0809c1633d43c89b5aad30027b95","impliedFormat":99},{"version":"d2c24000d0dadcba27d36e6b6fed7abc2c6a9b3ed6b4a8e069be303812e86bba","impliedFormat":99},{"version":"ceaaae220b5495a8fbc15cb3925107a2b1c6f5a7ca1f4de63c439d91e7726f71","impliedFormat":99},{"version":"6496e6e04c8719315d51cb1c98452f8fcbab340a46cc859e94f3b3a5e2368ea9","impliedFormat":99},{"version":"1c521e08d75a9f4ec24e0ed84c7e7d7dfee4ab5e51aa9a4dbae76283a66d0c49","impliedFormat":99},{"version":"dbcde4d0b3a3fa5b64aaf3dc80370e76b00e8e8935a9bf1f4381a2e6299cd388","impliedFormat":99},{"version":"9242750c276f71a51c8d1ca11e4bc2df24ce1c988537c9c914fdd8ec8bb9715a","impliedFormat":99},{"version":"c4bb4f8d6dfff722a008022b3157c8e921b114d6befd8651add3028df40a00e4","impliedFormat":99},{"version":"a6d7338f7fd9035f468bc64f071edbf8ad8c6363c3bfb875c3e1c0f4f5f36b5f","impliedFormat":99},{"version":"d479a5591022bf7b46d90d10e23cbf004b2e1a30ad9b675dbd96721aafb78441","impliedFormat":99},{"version":"c7af3aec3d4a4607a9e23c63d802b77235dfe6f066f912c1347e06ce5868d919","impliedFormat":99},{"version":"d2e351dc6d967923dc6ff200bfbb20dfa92f0c23331ccf34eef1ea7d4b1d8e9b","impliedFormat":99},{"version":"0c8e28a077e369f1c26e00a3c2f76824c0ac7f55cfada1a6ff42f40b5eec0c98","impliedFormat":99},{"version":"bb8194f799c99acb6c3dc6b40866ef69cc2ce063f63666c9d1a55f6b4bb6f352","impliedFormat":99},{"version":"242cda707d18d4bd715c1916eed6ef3ab3d3c107bce17c771c803ff898dabd8c","impliedFormat":99},{"version":"7116b824716ea8c11ab831cb599e27cccd1ea083689d7085ce26954d86f392d4","impliedFormat":99},{"version":"25123c80bcb4c0f874ad6d2facf40f7cfd5e27c08a3107b18302307b7a131016","impliedFormat":99},{"version":"5fb5756d1c11073dcf4b2c76eecc0e48f0331bcb43e02ecb35a7c80f53bcb677","impliedFormat":99},{"version":"121cf1f1c42afca44d5aeedb4469d525ffeb013b78031c4a9089d64acb7a1394","impliedFormat":99},{"version":"908cb76e7cace05e1622e08912e2978c9284444ebedcdf8cd341fa75e31f007e","impliedFormat":99},{"version":"f93fe279ba4ac525dcc682b54923999538090ae9eecfeb0001b8009c70c15295","impliedFormat":99},{"version":"7e5217864cf444cb86d59472a218f6781f402c60436d823541360caa64c02244","impliedFormat":99},{"version":"37f61ebbaac9cc1bee0e3c11bf9a9b5207f8e1aa066eedb2860f108961987a49","impliedFormat":99},{"version":"263a89f026d661b338a22517a0375a19af55abb09651e73e9d7940025e2402bc","impliedFormat":99},{"version":"f9bf95954745207c3a305a59f3a8f7e36290c742d006d1ce447a41dc772ba3c3","impliedFormat":99},{"version":"732e1c24c3f5a76e61b075bfee7d2b3e5714d4960f8587b0cf989e7e151dc1ea","impliedFormat":99},{"version":"4cc5c2fb807317de6f88edae5cc2b24b705cdce764bbc1cc23aeec15d91a7a49","impliedFormat":99},{"version":"53cae4e7f0a5716f296870e5eef84af8832d5700b23ff79f349c0d1b4aa40d25","impliedFormat":99},{"version":"775e97f58cc774218eb4e979ff7f73b2fb4d958521df4707ae382b32fce5f55b","impliedFormat":99},{"version":"d93588a85b0b0eef4e6ab906fa37caa21efa1d30647aef292567c078b2e3a0a9","impliedFormat":99},{"version":"2eaf0dcaaa03f1cce8c4069c98d198b4730d6e842d393031328aefd1ed7becb1","impliedFormat":99},{"version":"d62b09cb6f1ceb87ec6c26f3789bc38f8be9fb0ce3126fd0bf89b003d0cba371","impliedFormat":99},{"version":"4a5d9348012a3e46c03888e71b0d318cda7e7db25869731375f90edad8dcea02","impliedFormat":99},{"version":"61b3add3d48dfc79324531ede7da59203059a62986070f97645a83acd3f20aa0","impliedFormat":99},{"version":"6cd8356a92fd9f1edcbfbd3b891f50228738522e79bfdad16e7fb7cfd4a66932","impliedFormat":99},{"version":"347efb60859c806ef954a67ee7520c9aa33e1881eedd40d236298af775deef50","impliedFormat":99},{"version":"fc391876e409d362cc43a7468226a9eb83440de09873b284bf09fbfb261ec259","impliedFormat":99},{"version":"d06f5012d5ac1bc25c5033f7e916fe42cc0253d6b523b9747809b71676069370","impliedFormat":99},{"version":"5d35840bd540fad886e21ddaf9b078a44c21a827dec9abc08d2d2c1a3ff27d44","impliedFormat":99},{"version":"a02182b20bcb1966fc15eac80506f617b71fdd0e279ccff44b27f2ee366b2823","impliedFormat":99},{"version":"32563899782c456f03cadc7a9508b9b6468dd678404b093bd7557d6c6e143218","impliedFormat":99},{"version":"f613a93e0685802f7f7e248156ae93ff9088d45abeff0b21b656520699b79f06","impliedFormat":99},{"version":"5471b59fcb6ad04c41f6bf57075e88f3094d9d498e51595b4341d8bfcb729bf5","impliedFormat":99},{"version":"6aeb85043e6a5d2c3768c413a01885b0fc3dbfb4b3817fde5bb93601f5efb303","impliedFormat":99},{"version":"b6ff37737d006b86082f2f7176eb0a771001e9dde9152a26ef9ea8fd80e6eba0","impliedFormat":99},{"version":"491d5f012b1de793c45e75a930f5cdef1ff0e7875968e743fa6bd5dd7d31cb3b","impliedFormat":99},{"version":"1fd56873ada3f2bf6049ae741cf4efc1c90693015a6dc3467d6c995e5a6db03a","impliedFormat":99},{"version":"8074e5e85360339cc57e7a9b6db5f49af9ef8d6d0ee3c28a02d5e0ad5c21920b","impliedFormat":99},{"version":"43db9ade57eeeb241749f460e5eec4cc4eca8e8f3c35a0542a5a746eb2bcaf86","impliedFormat":99},{"version":"53c86b81daa463deacb0046fee490b6d589438ac71311050b74dcee99afca0f6","impliedFormat":99},{"version":"70587241a4cc2e08ffc30e60c20f3eb38bd5af7e3d99640568ffe2993f933485","impliedFormat":99},{"version":"dd01943d0fe191b3b2020438367709333ff08a69d285e2f715a60711dcf83b61","impliedFormat":99},{"version":"9c7188dc07bc5ce82bbe5b75495f44a7887b0a4945f63696661fffeddca0c0e9","impliedFormat":99},{"version":"93ea079d0b9af94efc1578a95aa0299ec4054f617fb31d243f66255e221276fd","impliedFormat":99},{"version":"4ecb0eb653de7093f2eb589cea5b35fdea6e2bbd62bc3d9fafdc5702850f7714","impliedFormat":99},{"version":"69ed52603ad6430aaffbc9dec25e0d01df733aaa32ab4d57d37987aedc94c349","impliedFormat":99},{"version":"6f8acb191da449d8dbec7a4e9c317bdb6b8af104a60a101950643ea52cfa3c85","impliedFormat":99},{"version":"4c01241847f841eddf3d727aac5686d8d1e06c92124002de9d9ed2ad3c590420","impliedFormat":99},{"version":"8bba80ef1e0e9ae8c061728626309824023e85eaafcd8c285a6fa89dc6881573","impliedFormat":99},{"version":"ada6bd808581a783390b1aabc2cc836136a5d214af0d924cc57d9f29b5733ce9","impliedFormat":99},{"version":"283336202f1a6a4e13271dc83b776718cf5d4a4137b28e2d013498e3020f7170","impliedFormat":99},{"version":"54a6a3e98b7ec00fec7bd7e42ad50c16014805576ccbe33bfee04f0aac9965da","impliedFormat":99},{"version":"7c90a7108c4319b0475d5419d52f2a2c9bf499234a2a15d5b8504983e141041b","impliedFormat":99},{"version":"67fc5d1b6877a799de1e3943ed2c3669b72a6ab3b17c7b0b0387bdd6e4c1a01f","impliedFormat":99},{"version":"8ac25d431d9b1bbe3ded6c578651cc43acbdbf19c435fbbe185b827ae74ba3df","impliedFormat":99},{"version":"953ee863def1b11f321dcb17a7a91686aa582e69dd4ec370e9e33fbad2adcfd3","impliedFormat":99},{"version":"392e72d77ae33ee322d5b0b907398f2200f72d36adaca1ca62dfa7e22f744ac3","impliedFormat":99},{"version":"e452b617664fc3d2db96f64ef3addadb8c1ef275eff7946373528b1d6c86a217","impliedFormat":99},{"version":"c6a811837fef3d4ba22e7e4adcb16f12caf30252047b133404d698bf8f0e883a","impliedFormat":99},{"version":"2f722a3a421baf9a7c175d8ae6a3118dfd14c5f36474e03f99e3df5800065030","impliedFormat":99},{"version":"f9511d2a891b0a017ae31674977b053f42ca7221dedd012f6de6f75e7cb9aa3e","impliedFormat":99},{"version":"d8f262b549f3ed95402297d10b84f0f86e3113d6d570b03364d2cfca1f75e5d8","impliedFormat":99},{"version":"f216cb46ebeff3f767183626f70d18242307b2c3aab203841ae1d309277aad6b","impliedFormat":99},{"version":"d6d95f96dd5b374484fd000228288cbcfb80aa47cb74ebd3e19ea94a36e8260a","impliedFormat":99},{"version":"9abda1f0836e696725c31ea63d36a6c7c54e0f762d5e387f52b27186dff81cab","impliedFormat":99},{"version":"92fb8aa5d61dca9ab2008d49397a639dbf71c7746da23c02245523cfec4a99ef","impliedFormat":99},{"version":"9e6cd6dc690d6e6c89b17b295cabf8a5a08011ae79a7a56578a429e5ae27b8dc","impliedFormat":99},{"version":"4c7eafc682ffbd45ac24d056c63a622993048ac272c76ba1721118dc601ab629","impliedFormat":99},{"version":"f72b0af7e81183c17d799cdea2ab0d81580dfe96a98343a21d746984c3b21933","impliedFormat":99},{"version":"3841ca1577c0927f59fac8faa7cd195485c5362d99ec2b16ff9b86ec4974a3e5","impliedFormat":99},{"version":"58c5a2a520ae555e0573873a5e6303b0f1a1e70f3b376e5ac9094eaad0623d8a","impliedFormat":99},{"version":"5f8217240c95e3f3007d9968104904616287f30d853bac73874759c1dfad4017","impliedFormat":99},{"version":"7ebc96af203f866e829b528e5cffb32111a1a1ff4662bc60c3b53696e89c67f4","impliedFormat":99},{"version":"9f5ee7c037b58964c1cee63c1849fa11757f693208444be0f2d9f08defe859cd","impliedFormat":99},{"version":"33a4085365aa21a995ea4721ffff814128b126e8e346e5f064d87bfcdd0ff7ce","impliedFormat":99},{"version":"3adf214b4b307152af85b77e441d36ede388dadba2bd9962671bf933738d2a25","impliedFormat":99},{"version":"9a2cc98a7884cb530a704f6cd16a83db9aa89360a2b391a49e498b5179443dc6","impliedFormat":99},{"version":"250998ae18ea49b8745d327e7739f56464a4318783129daab90b3299bf6f8a55","impliedFormat":99},{"version":"76b3afd1f2748ff725c277bd4701f442af697c0586e1b491e6a67383a246ffad","impliedFormat":99},{"version":"4df5fc6fc2438b8e3418cb25c8c0e863d1f92e4470297d6a8756394c597af844","impliedFormat":99},{"version":"92b5f0879161f1206e30a0c219dd8f23d736f2a74a4e015885e8e3f3b3c9a3e7","impliedFormat":99},{"version":"374d12016302e312ffccd3d38e6f3df1b412378bff6e6266f3e5844af450859c","impliedFormat":99},{"version":"18d0c2293aa57e33923fc1b10970650c6d6932dbfa711a3ffd67600b3caf924b","impliedFormat":99},{"version":"17758b72f880ed66754e3ff4aeade0b82417ec546b72bf3a326cadf4e56c1915","impliedFormat":99},{"version":"ffa547cbf7599d89b6ac4c2f038f99978e0dff46bb9850df46168ce6809a5b24","impliedFormat":99},{"version":"981240d6d3015e8de441325b90c07588a302f2d9c377bccfc61e4680b726f962","impliedFormat":99},{"version":"493c39c5f9e9c050c10930448fda1be8de10a0d9b34dcd24ff17a1713c282162","impliedFormat":99},{"version":"73e4673f2da8677556210e5a127b2637bf030ab73da222ea2a19979f89d9d40a","impliedFormat":99},{"version":"e9d27f2b7d5171f512053f153cadc303d1b84d00c98e917664ba68eca9b7af6a","impliedFormat":99},{"version":"4899d2cf406cd68748c5d536b736c90339a39f996945126d8a11355eba5f56f3","impliedFormat":99},{"version":"29c4e9ce50026f15c4e58637d8668ced90f82ce7605ca2fd7b521667caa4a12c","impliedFormat":99},{"version":"8575340c8560a52c3309956add745660ad319dbd67309fa268f5af9b1c7551f5","impliedFormat":99},{"version":"3b56bc74e48ec8704af54db1f6ecfee746297ee344b12e990ba5f406431014c1","impliedFormat":99},{"version":"9e4991da8b398fa3ee9b889b272b4fe3c21e898d873916b89c641c0717caed10","impliedFormat":99},{"version":"35290a0ba8d9287d4f3635948e7e84bcf14223239ad07902d111684dfafffaf4","impliedFormat":99},{"version":"dbf3d90c21c08217509df631336881a3105740033b0592dcc47036490f95e51c","impliedFormat":99},{"version":"e6ad9376e7d088ce1dc6d3183ba5f0b3fb67ee586aa824cc8519b52f2341307a","impliedFormat":99},{"version":"2391f2f7e3819f74e51039e431d4d68dd261e40e677810316008f08e778492e8","signature":"7446741158fcd0894addb90d6f00769719782745e713ad5b201eb0132cfb6551"},{"version":"0ca51b5dc00aa2c6a3551c5b511e7ca9a1a08e12d25422bd974c2ce1707ff959","signature":"399852f50bf374c4e4c8efb4274260a0b29c3ec863e71d6a754d69818276eb59"},{"version":"ad35da447be046219c92634332ceb694b52dbc37eed13536fd18bd802ff4ed53","signature":"16d5bdedef7ac1bafc90ef5edcb5a524f7a067285e3c68b742c3def1dc8a0909"},{"version":"5be00abdcbb4485dbe416d5301421f7086cca3689dadb5ece2a53676c1d17623","signature":"9693c11eef0516a468debb1a89eaa23472061a106a7586e3465fc840909e8f03"},{"version":"91243a5cf61d442103e43100007078aaf4634840971462b7df19faa687ece79a","signature":"4e01fdfcfa9d19e0f9522f61174233fad5db2988f030045fa80a73e32dfca9fd"},{"version":"750adbd023894fa6e7af9b6eddecf7de74b5e4b537ad46f220879eb937b8244a","signature":"f24da613e5429ab6caa9687e57745be0bd9e54d5760a66f3a116f2988a79f001"},{"version":"1e693a098c4d53ddd27d499ca4d8b3ee935663aa191e62d50eeff08b26146532","signature":"99662eb2cba010fdf1202a3e222c89b8492ff68e8e206a2296f6c6ec3ee6608c"},{"version":"fe8fcf43c4614dc877d3e56d518e95d69defa07f357b2af4c385b5fb1c591929","signature":"4c0b88ca9250fa0e0fa0ce791c837487fe6b100992833f19555048cb1b47eb18"},{"version":"324df572195e93def72d9867f75dc80446d6bbaf2c9a9f0f3a45fe5b5bd8af21","signature":"dc91ed21005509f86ef528d8c3bc026e5829206e558b30ac479c6109ff0ceee4"},{"version":"f2867aef276fc96e82476403721c7cc0725df14a4e47351b93be31a28da8a7c0","signature":"a8721a1ee15a172d5d0221d47f3f1746879713898dbd7f40f3ec95fdfd379f2c"},{"version":"c1a2e05eb6d7ca8d7e4a7f4c93ccf0c2857e842a64c98eaee4d85841ee9855e6","impliedFormat":1},{"version":"835fb2909ce458740fb4a49fc61709896c6864f5ce3db7f0a88f06c720d74d02","impliedFormat":1},{"version":"6e5857f38aa297a859cab4ec891408659218a5a2610cd317b6dcbef9979459cc","impliedFormat":1},{"version":"ead8e39c2e11891f286b06ae2aa71f208b1802661fcdb2425cffa4f494a68854","impliedFormat":1},{"version":"40ba6c32eb732a09e4446ade5cb6ad0c147f186f9c9dc6878b90b4418ad9f6ea","impliedFormat":1},{"version":"fdd814741843f85c98281522c58f5a646590ba9019fad2efaa95987655e0611b","impliedFormat":1},{"version":"c78aff4fb58b28b8f642d5095fc7eeb79f00e652a67caa19693af1adabb833c9","impliedFormat":1},{"version":"f80a08ced8818dc99359c0acd5b3f12762e1ce53758007759b0d4e503cbf4a5e","impliedFormat":1},{"version":"37935fa7564bcc6e0bc845b766a24391098d26f7c8245d6e8ab37bc016816e94","impliedFormat":1},{"version":"68add36d9632bc096d7245d24d6b0b8ad5f125183016102a3dad4c9c2438ccb0","impliedFormat":1},{"version":"3a819c2928ee06bbcc84e2797fd3558ae2ebb7e0ed8d87f71732fb2e2acc87b4","impliedFormat":1},{"version":"0f8a263f4c8595c8a07de52e3f3927640c44386c1aa2984de9eae50d75e613b2","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"e0bfe601a9fdf6defe94ed62dc60ac71597566001a1f86e705c95e431a9c816d","impliedFormat":1},{"version":"346fffde7c32da87c2196eb7494422449dc2ca82d3b4e6bf55be1d1a33ffc2b0","impliedFormat":1},{"version":"add0ce7b77ba5b308492fa68f77f24d1ed1d9148534bdf05ac17c30763fc1a79","impliedFormat":1},{"version":"8b5875e4958528042103fdd775e106a7f76bafc29709f0690df9a7d2241d52a7","impliedFormat":1},{"version":"2f67911e4bf4e0717dc2ded248ce2d5e4398d945ee13889a6852c1233ea41508","impliedFormat":1},{"version":"d8430c275b0f59417ea8e173cfb888a4477b430ec35b595bf734f3ec7a7d729f","impliedFormat":1},{"version":"69364df1c776372d7df1fb46a6cb3a6bf7f55e700f533a104e3f9d70a32bec18","impliedFormat":1},{"version":"6042774c61ece4ba77b3bf375f15942eb054675b7957882a00c22c0e4fe5865c","impliedFormat":1},{"version":"5a3bd57ed7a9d9afef74c75f77fce79ba3c786401af9810cdf45907c4e93f30e","impliedFormat":1},{"version":"aef26cf95593c8ace1c62c4724f9afac77bdfa756fb8a00613cd152117cb2f43","impliedFormat":1},{"version":"30db853bb2e60170ba11e39ab48bacecb32d06d4def89eedf17e58ebab762a65","impliedFormat":1},{"version":"e27451b24234dfed45f6cf22112a04955183a99c42a2691fb4936d63cfe42761","impliedFormat":1},{"version":"2316301dd223d31962d917999acf8e543e0119c5d24ec984c9f22cb23247160c","impliedFormat":1},{"version":"58d65a2803c3b6629b0e18c8bf1bc883a686fcf0333230dd0151ab6e85b74307","impliedFormat":1},{"version":"e818471014c77c103330aee11f00a7a00b37b35500b53ea6f337aefacd6174c9","impliedFormat":1},{"version":"268fd6d9f2e807a39a6c5aa654b00f949feb63d3faa7dd0f9bba7dde9172159c","impliedFormat":1},{"version":"29f823cbe0166e10e7176a94afe609a24b9e5af3858628c541ff8ce1727023cd","impliedFormat":1},{"version":"dc9cc4abaabd5cfd8d2749c9478d0abc7055e1b1fd922dff872e6e95a4175201","signature":"2651a6c04c20c6b829234047caa3db2f1b697af6365b3387872c3f5700dc28a4"},{"version":"12262a57c1c71f8d1bc50d5508ab3c53ad4afd89fd29d97e27ebf46035b3da3e","signature":"c4d6f8fba3839bb1e5ee491b43906b9183d7b8959baebd3ec5913fef4f40b635"},{"version":"decbb658d7b354b7fdc59db5ab541e6327b20ec00c96e891769e50f77d925523","signature":"be8b6bee4b407e0540537b69d6a4874eaf930d6a8b70ecc065c796fd1437c846"},{"version":"8b61608c154f87e13c88b21b5208a3acb906ddcee5e3001f3b27ef13703b61e8","impliedFormat":1},{"version":"f6b6e3d4ec6532a05ccad69c2605b792e7473039b9f16261a199b9dcf1c33084","signature":"c3196bfd12c96e513ae6baf5c945b3bfbaa2e8695693b3628414fc732cbe9fab"},{"version":"ab30e3e6030f247c9ead0b2e6928001e1be20907637719b3559c5da617002798","signature":"8fa424847eae1e9607dad437ba29f73de7ed8a64b60f26feddf422f3e9656655"},{"version":"b39529dc70f822883c8805eba3be4b896603b8be5c21fa9a5e8456853a9cac24","signature":"11b670ed51a4a4a6847d013b9dc50601581fa09816ba6d060c8f13a94df71c3e"},{"version":"7c45a0cff6182af8c36f68d2a3523c0d74c9019b32cd0aa071e236e774b67a71","signature":"fc6cb9ca05da11c96a920ca17e25d9aef74a7fe8e523b8046c5cea481255aeec"},{"version":"e8a7565fa8cc70df160ab9ffcab5098d0cf1b3e646ed266be197f0eacc857b34","signature":"8c4244dae03efb90eb6008beb0eec636d1d5bd8576d80a7c39a4c63e389e88ee"},{"version":"4e63aa0af8005027ec3e47a329ba2bce4ad30a7866f33fa3bc9f13a702022770","signature":"ee324efc620efe75b8389fb704c27a77e6dd246ef3cb238f1151f9768de30764"},{"version":"e6c8c2edceaf3627f7816caf15dcf6393e444ba776e8902e5f65b74d451b5cc6","signature":"d7e0473f2a6a61a3ecd75e7e79efac2edb2df3c3821a437b607d0757da48bd69"},{"version":"a23023a5093a3f8a871a80c958c0948b4bb98bf0a29972758b3c902f830457a2","signature":"9ebfe9eb079314c554dc22cec3fe0071c22226c5cffebfc4308ad406883466dc"},{"version":"952c21e8d1e308d08bf902e415daba0eeb927e60321d023e94c15cb2e211d043","signature":"afdb5288a1739d52d50c117da8b6caedb777042a5fa11f02ade7b4a5bf72d224"},{"version":"6e80e675b53df355531159abae68e983264ed2364f078e27edee37df7bd051da","signature":"a6afd1c9a3668eb51fc397e00dec8dc655aa4dc52479d5dfa95afd821e9b16f6"},{"version":"e2b671779a5c5304390d08a28d3f96338e05e418c4c18624ada291261c1a4d56","signature":"b985c9126287c3b7342fd7316a8a2899cf50d3996dff2cc901000965c9f19b8f"},{"version":"71ad1cc06270386d90b3c21b1bf1f99d65cb8a31851e8e912eb68193cf60e766","signature":"a3d4dd864c61c246a59b05bce5d84c3d219567f85f9a32e539c4a2be8dd58029"},{"version":"485e4b9a91ec3ec31512ee4d7b9aaa7aaac2886bb4770c8022f9f3e20a6e1a03","signature":"17f679537f92a306af086a40d952e8a3cf2c5f99e1fd05eb6674babe31b54ed5"},{"version":"4623d7cf72b29b7f5b223b97cb8618f9c11a6013f9e3ff6519889a423994519b","signature":"bd9508d745eb868afbc50c1a262379fd19b8c8e467c21612b246b8c3b84a4d7b"},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"156a859e21ef3244d13afeeba4e49760a6afa035c149dda52f0c45ea8903b338","impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"0ccdaa19852d25ecd84eec365c3bfa16e7859cadecf6e9ca6d0dbbbee439743f","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc2110f7decca6bfb9392e30421cfa1436479e4a6756e8fec6cbc22625d4f881","affectsGlobalScope":true,"impliedFormat":1},{"version":"096116f8fedc1765d5bd6ef360c257b4a9048e5415054b3bf3c41b07f8951b0b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5e01375c9e124a83b52ee4b3244ed1a4d214a6cfb54ac73e164a823a4a7860a","affectsGlobalScope":true,"impliedFormat":1},{"version":"f90ae2bbce1505e67f2f6502392e318f5714bae82d2d969185c4a6cecc8af2fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b58e207b93a8f1c88bbf2a95ddc686ac83962b13830fe8ad3f404ffc7051fb4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1fefabcb2b06736a66d2904074d56268753654805e829989a46a0161cd8412c5","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"c18a99f01eb788d849ad032b31cafd49de0b19e083fe775370834c5675d7df8e","affectsGlobalScope":true,"impliedFormat":1},{"version":"5247874c2a23b9a62d178ae84f2db6a1d54e6c9a2e7e057e178cc5eea13757fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"156a859e21ef3244d13afeeba4e49760a6afa035c149dda52f0c45ea8903b338","impliedFormat":1},{"version":"10ec5e82144dfac6f04fa5d1d6c11763b3e4dbbac6d99101427219ab3e2ae887","impliedFormat":1},{"version":"615754924717c0b1e293e083b83503c0a872717ad5aa60ed7f1a699eb1b4ea5c","impliedFormat":1},{"version":"14e9acf826baba0ef4b5665704084896e7bcc06f65a9ab13af7e93d27d6b7069","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"21adf13435b9b748529c8cedf80f884e5130b9684188120a686cd2b26a2059c7","impliedFormat":1},{"version":"eec76bf6b9346f3f95fa402621b889489e96930e72295b0369022f332e9b4a6a","impliedFormat":1},{"version":"0ecd58f413f9bc3b7d4383eae31b0c8fc576985cd7404d6f99f8c643543ade74","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"9c32412007b5662fd34a8eb04292fb5314ec370d7016d1c2fb8aa193c807fe22","impliedFormat":1},{"version":"7fd1b31fd35876b0aa650811c25ec2c97a3c6387e5473eb18004bed86cdd76b6","impliedFormat":1},{"version":"4d327f7d72ad0918275cea3eee49a6a8dc8114ae1d5b7f3f5d0774de75f7439a","impliedFormat":1},{"version":"6ebe8ebb8659aaa9d1acbf3710d7dae3e923e97610238b9511c25dc39023a166","impliedFormat":1},{"version":"e85d7f8068f6a26710bff0cc8c0fc5e47f71089c3780fbede05857331d2ddec9","impliedFormat":1},{"version":"7befaf0e76b5671be1d47b77fcc65f2b0aad91cc26529df1904f4a7c46d216e9","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"d33ce35e3f9cfcc1d94eca415bdd3bde94d5b153ffdd33e6c4455c029986c630","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"8aee8b6d4f9f62cf3776cda1305fb18763e2aade7e13cea5bbe699112df85214","impliedFormat":1},{"version":"98498b101803bb3dde9f76a56e65c14b75db1cc8bec5f4db72be541570f74fc5","impliedFormat":1},{"version":"4dc59f6e1dbf3d5f66660fceabe6c174d3261b37b696ae1854f0dbaf255fc753","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"436d7b4543b340b0f3eef4310d524242e41369b9652aa9c70428767c4dcac455","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"12950411eeab8563b349cb7959543d92d8d02c289ed893d78499a19becb5a8cc","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"114f493b30f364255290472111b5a4791d5902c308645670cd0401429cbc6930","impliedFormat":1},{"version":"c3f5289820990ab66b70c7fb5b63cb674001009ff84b13de40619619a9c8175f","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3275d55fac10b799c9546804126239baf020d220136163f763b55a74e50e750","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa68a0a3b7cb32c00e39ee3cd31f8f15b80cac97dce51b6ee7fc14a1e8deb30b","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"6c36e755bced82df7fb6ce8169265d0a7bb046ab4e2cb6d0da0cb72b22033e89","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7a93de4ff8a63bafe62ba86b89af1df0ccb5e40bb85b0c67d6bbcfdcf96bf3d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"90e85f9bc549dfe2b5749b45fe734144e96cd5d04b38eae244028794e142a77e","affectsGlobalScope":true,"impliedFormat":1},{"version":"e0a5deeb610b2a50a6350bd23df6490036a1773a8a71d70f2f9549ab009e67ee","affectsGlobalScope":true,"impliedFormat":1},{"version":"d2ae155afe8a01cc0ae612d99117cf8ef16692ba7c4366590156fdec1bcf2d8c","impliedFormat":1},{"version":"3f5e5d9be35913db9fea42a63f3df0b7e3c8703b97670a2125587b4dbbd56d7c","impliedFormat":1},{"version":"c8b8968311ec4e5e97b7b5fb8a65efaba455db9bdcfd7fff7fb15f6e317bfba0","impliedFormat":1},{"version":"57c23df0b5f7a8e26363a3849b0bc7763f6b241207157c8e40089d1df4116f35","affectsGlobalScope":true,"impliedFormat":1},{"version":"3b8bc0c17b54081b0878673989216229e575d67a10874e84566a21025a2461ee","impliedFormat":1},{"version":"5b0db5a58b73498792a29bfebc333438e61906fef75da898b410e24e52229e6f","impliedFormat":1},{"version":"dbe055b2b29a7bab2c1ca8f259436306adb43f469dca7e639a02cd3695d3f621","impliedFormat":1},{"version":"1678b04557dca52feab73cc67610918a7f5e25bfdba3e7fa081acd625d93106d","impliedFormat":1},{"version":"aecbf1d9e6a18dab7d92ef8a89a1444b47e1eb6134cb2bb776a26d55ff58c29a","impliedFormat":1},{"version":"2ea729503db9793f2691162fec3dd1118cab62e96d025f8eeb376d43ec293395","impliedFormat":1},{"version":"9ec87fea42b92894b0f209931a880789d43c3397d09dd99c631ae40a2f7071d1","impliedFormat":1},{"version":"c68e88cdfadfb6c8ba5fc38e58a3a166b0beae77b1f05b7d921150a32a5ffb8d","impliedFormat":1},{"version":"2bc7aa4fba46df0bd495425a7c8201437a7d465f83854fac859df2d67f664df3","impliedFormat":1},{"version":"41d17e1ad9a002feb11c8cdd2777e5bbc0cdb1e3f595d237e4dded0b6949983b","impliedFormat":1},{"version":"1fede9296beac11ce8e6b425396a1791f64341f2be85deebb6286faf6e16306e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce697b6a251d9cad53998c7fd3098072df883b525ec45d83530e434dc6d80dc6","impliedFormat":1},{"version":"719412f054e6ecc35489462c9a21bab0323d173a7d04e55b0ace4b5d86fbeb07","impliedFormat":1},{"version":"0eb5d0cbf09de5d34542b977fd6a933bb2e0817bffe8e1a541b2f1ad1b9af1ff","impliedFormat":1},{"version":"3db996ecdee7aabecc5385976cc07eb66216034a273c07b17d1a85292e9bab0c","impliedFormat":1},{"version":"2c2bdaa1d8ead9f68628d6d9d250e46ee8e81aa4898b4769a36956ae15e060fe","impliedFormat":1},{"version":"c32c840c62d8bd7aeb3147aa6754cd2d922b990a6b6634530cb2ebdce5adc8e9","impliedFormat":1},{"version":"5ff4433a2deae4f85ab1377e90a7554ce6b47ae51c69a84ca30a6e22fae85834","impliedFormat":1},{"version":"82b91e4e42e6c41bc7fc1b6c2dc5eba6a2ba98375eb1f210e6ff6bba2d54177e","impliedFormat":1},{"version":"c1fa52b3d014001e8662fa2669d90ea15373958a288e3b83a3b621733d25292a","affectsGlobalScope":true,"impliedFormat":1},{"version":"cbed824fec91efefc7bbdcb8b43d1a531fdbebd0e2ef19481501ff365a93cb70","impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"d0716593b3f2b0451bcf0c24cfa86dec2235c325c89f201934248b7c742715fc","impliedFormat":1},{"version":"ec501101c2a96133a6c695f934c8f6642149cc728571b29cbb7b770984c1088e","impliedFormat":1},{"version":"b214ebcf76c51b115453f69729ee8aa7b7f8eccdae2a922b568a45c2d7ff52f7","impliedFormat":1},{"version":"429c9cdfa7d126255779efd7e6d9057ced2d69c81859bbab32073bad52e9ba76","impliedFormat":1},{"version":"2991bca2cc0f0628a278df2a2ccdb8d6cbcb700f3761abbed62bba137d5b1790","impliedFormat":1},{"version":"5e66972e83eb4dc7123939bf816e6cbd9ad81af5552db1cab84e6bd9c64d2ecc","affectsGlobalScope":true,"impliedFormat":1},{"version":"230763250f20449fa7b3c9273e1967adb0023dc890d4be1553faca658ee65971","impliedFormat":1},{"version":"c3e9078b60cb329d1221f5878e88cecfa3e74460550e605a58fcfb41a66029ff","impliedFormat":1},{"version":"8413d0641f293aed551c7464615b770d34a02dedede889b9591172287d68e773","impliedFormat":1},{"version":"0ea59f7d3e51440baa64f429253759b106cfcbaf51e474cae606e02265b37cf8","impliedFormat":1},{"version":"bc18a1991ba681f03e13285fa1d7b99b03b67ee671b7bc936254467177543890","impliedFormat":1},{"version":"1b241e24f3227d078c06aeda6e050187ad59a4e591f4467abed44d92b084e08d","impliedFormat":1},{"version":"fa94bbf532b7af8f394b95fa310980d6e20bd2d4c871c6a6cb9f70f03750a44b","impliedFormat":1},{"version":"7fde0e1be5c8be204ffbf428abfcf01da2eb0f130e1bc3f539eb7275f4fd1f58","impliedFormat":1},{"version":"e284328553df5f425a5d33d36a0c3fa66b46af9d097cad6f4d2e8696dfdeb0f1","affectsGlobalScope":true,"impliedFormat":1},{"version":"7fa2214bb0d64701bc6f9ce8cde2fd2ff8c571e0b23065fa04a8a5a6beb91511","impliedFormat":1},{"version":"f36b3fbe2be150a9ca140da48593f21e6a8172004f92ddc549b43efec39f3e54","impliedFormat":1},{"version":"f1c93e046fb3d9b7f8249629f4b63dc068dd839b824dd0aa39a5e68476dc9420","impliedFormat":1},{"version":"016b29bf4926b80255a108c53a1451717350059da04fcae64d1075f5e93bbb39","impliedFormat":1},{"version":"841983e39bd4cbb463be385e92fda11057cab368bf27100a801c492f1d86cbaa","impliedFormat":1},{"version":"1c4f139ade4f6ebf45463505f8155173e5d7a5305e50e0aae0a5e712d6ff3b48","impliedFormat":1},{"version":"e16b319e5aca1031168de823c4946ff8e29629c4c8cc0ec0fcfe2a8ab2155043","impliedFormat":1},{"version":"e4156ddb25aa0e3b5303d372f26957b36778f0f6bbd4326359269873295e3058","affectsGlobalScope":true,"impliedFormat":1},{"version":"cc1b433a84cae05ddc5672d4823170af78606ad21ecef60dbc4570190cbf1357","impliedFormat":1},{"version":"9d3821bc75c59577e52643324cec92fc2145642e8d17cf7ee07a3181f21d985d","impliedFormat":1},{"version":"7f78cfb2b343838612c192cb251746e3a7c62ac7675726a47e130d9b213f6580","impliedFormat":1},{"version":"201db9cf1687fab1adf5282fcba861f382b32303dc4f67c89d59655e78a25461","impliedFormat":1},{"version":"2c3c5c0f54055e87640f5d233716fd889f3034fc7911d603b642369b0dbeb2a7","impliedFormat":1},{"version":"0a20eaf2e4b1e3c1e1f87f7bccb0c936375b23b022baeea750519b7c9bc6ce83","impliedFormat":1},{"version":"b484ec11ba00e3a2235562a41898d55372ccabe607986c6fa4f4aba72093749f","impliedFormat":1},{"version":"a16b91b27bd6b706c687c88cbc8a7d4ee98e5ed6043026d6b84bda923c0aed67","impliedFormat":1},{"version":"1c9e5b1a17b1fc9b3711fb36e0690421261ab2880f15b145155b5b2ba2ab6c2d","impliedFormat":1},{"version":"99ab6d0d660ce4d21efb52288a39fd35bb3f556980ec5463b1ae8f304a3bbc85","impliedFormat":1},{"version":"6eeded8c7e352be6e0efb83f4935ec752513c4d22043b52522b90849a49a3a11","impliedFormat":1},{"version":"6c1ad90050ffbb151cacc68e2d06ea1a26a945659391e32651f5d42b86fd7f2c","impliedFormat":1},{"version":"afa1c49f8e559e413d57343339db857d2a8159435cf9cf7d4deb41718fff1b88","impliedFormat":1},{"version":"6953d7597831d0860c7034cf4f0419687d263b6b98a4b32e37ce6d49615c36e2","impliedFormat":1},{"version":"3ac40516c33b87f751f7507346933081a26cdb8a3e11a6b3aa07d23f803c85db","impliedFormat":1},{"version":"4ac80270b6787c2b77a2d98a9714a71f4363c24b5890314f3ba582c94bfbe779","impliedFormat":1},{"version":"14e9acf826baba0ef4b5665704084896e7bcc06f65a9ab13af7e93d27d6b7069","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"21adf13435b9b748529c8cedf80f884e5130b9684188120a686cd2b26a2059c7","impliedFormat":1},{"version":"eec76bf6b9346f3f95fa402621b889489e96930e72295b0369022f332e9b4a6a","impliedFormat":1},{"version":"171b96f31e3fbdb55fe570f2a29a5ee47223fdca95a84ea2142e4cc4feaf9dfe","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"9c32412007b5662fd34a8eb04292fb5314ec370d7016d1c2fb8aa193c807fe22","impliedFormat":1},{"version":"d243db6b25788f439e7e2f03c05688e92f46764351673bb0e7b2f3631232e186","impliedFormat":1},{"version":"4d327f7d72ad0918275cea3eee49a6a8dc8114ae1d5b7f3f5d0774de75f7439a","impliedFormat":1},{"version":"6ebe8ebb8659aaa9d1acbf3710d7dae3e923e97610238b9511c25dc39023a166","impliedFormat":1},{"version":"e85d7f8068f6a26710bff0cc8c0fc5e47f71089c3780fbede05857331d2ddec9","impliedFormat":1},{"version":"7befaf0e76b5671be1d47b77fcc65f2b0aad91cc26529df1904f4a7c46d216e9","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"d33ce35e3f9cfcc1d94eca415bdd3bde94d5b153ffdd33e6c4455c029986c630","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"8aee8b6d4f9f62cf3776cda1305fb18763e2aade7e13cea5bbe699112df85214","impliedFormat":1},{"version":"98498b101803bb3dde9f76a56e65c14b75db1cc8bec5f4db72be541570f74fc5","impliedFormat":1},{"version":"4dc59f6e1dbf3d5f66660fceabe6c174d3261b37b696ae1854f0dbaf255fc753","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"436d7b4543b340b0f3eef4310d524242e41369b9652aa9c70428767c4dcac455","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"12950411eeab8563b349cb7959543d92d8d02c289ed893d78499a19becb5a8cc","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"114f493b30f364255290472111b5a4791d5902c308645670cd0401429cbc6930","impliedFormat":1},{"version":"b3fb72492a07a76f7bfa29ecadd029eea081df11512e4dfe6f930a5a9cb1fb75","impliedFormat":1},{"version":"cd6db591e858b53f23faad85346a4f43732bb33d6dff5f3f4dc47c4a448804ae","signature":"ad2664f941e8db7e19f9bae8100db326d4d1ed5701d56c4579331e575a43718e"},{"version":"328b1b71f3bedfca3331d6253b6f89aa207d876f1486a1017beebfa39fc8d418","signature":"47b10209e6f074245affea091a75da917d59c0e9bee84a78618c3a46359dc229"}],"root":[60,61,[196,205],[286,288],[290,303],474,475],"options":{"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"module":99,"outDir":"./dist","rootDir":"./src","skipLibCheck":true,"strict":true,"target":9},"referencedMap":[[63,1],[370,2],[371,2],[372,3],[309,4],[373,5],[374,6],[375,7],[307,1],[376,8],[377,9],[378,10],[379,11],[380,12],[381,13],[382,13],[383,14],[384,15],[385,16],[386,17],[310,1],[308,1],[387,18],[388,19],[389,20],[432,21],[390,22],[391,23],[392,22],[393,24],[394,25],[396,26],[397,27],[398,27],[399,27],[400,28],[401,29],[402,30],[403,31],[404,32],[405,33],[406,33],[407,34],[408,1],[409,1],[410,35],[411,36],[412,37],[413,35],[414,38],[415,39],[416,40],[417,41],[418,42],[419,43],[420,44],[421,45],[422,46],[423,47],[424,48],[425,49],[426,50],[427,51],[428,52],[311,22],[312,1],[313,53],[314,54],[315,1],[316,55],[317,1],[361,56],[362,57],[363,58],[364,58],[365,59],[366,1],[367,5],[368,60],[369,57],[429,61],[430,62],[431,63],[395,1],[62,1],[77,1],[135,64],[136,65],[184,66],[75,67],[72,68],[76,69],[185,70],[68,71],[80,72],[119,73],[137,74],[64,1],[66,1],[74,75],[69,76],[67,5],[79,77],[65,1],[78,78],[70,79],[187,80],[121,81],[192,82],[188,83],[189,84],[120,85],[190,1],[133,86],[138,87],[139,88],[134,89],[191,90],[73,91],[111,92],[83,93],[84,94],[85,93],[86,95],[93,96],[91,97],[92,93],[87,93],[110,98],[94,93],[95,94],[96,95],[104,99],[103,97],[97,95],[98,95],[109,100],[99,93],[100,97],[101,93],[102,93],[107,101],[108,102],[88,93],[89,93],[90,95],[105,101],[106,103],[115,104],[112,95],[113,105],[114,106],[116,107],[124,108],[131,109],[130,110],[129,111],[128,112],[127,113],[125,95],[126,95],[117,114],[122,115],[118,116],[123,117],[81,118],[195,119],[193,120],[194,121],[186,122],[82,123],[132,124],[145,125],[143,95],[144,126],[147,127],[146,128],[148,95],[152,129],[150,130],[151,131],[153,132],[156,133],[155,134],[158,135],[157,93],[161,136],[159,94],[160,137],[154,138],[149,139],[162,138],[163,140],[183,141],[164,93],[165,95],[166,142],[167,143],[168,144],[140,145],[141,146],[142,147],[71,1],[169,95],[172,148],[170,95],[171,149],[173,150],[174,151],[177,152],[176,153],[178,154],[179,132],[182,155],[181,156],[180,157],[175,158],[58,1],[59,1],[11,1],[10,1],[2,1],[12,1],[13,1],[14,1],[15,1],[16,1],[17,1],[18,1],[19,1],[3,1],[20,1],[21,1],[4,1],[22,1],[26,1],[23,1],[24,1],[25,1],[27,1],[28,1],[29,1],[5,1],[30,1],[31,1],[32,1],[33,1],[6,1],[37,1],[34,1],[35,1],[36,1],[38,1],[7,1],[39,1],[44,1],[45,1],[40,1],[41,1],[42,1],[43,1],[8,1],[49,1],[46,1],[47,1],[48,1],[50,1],[9,1],[51,1],[52,1],[53,1],[55,1],[54,1],[56,1],[1,1],[57,1],[336,159],[349,160],[333,161],[350,162],[359,163],[324,164],[325,165],[323,166],[358,167],[353,168],[357,169],[327,170],[346,171],[326,172],[356,173],[321,174],[322,168],[328,175],[329,1],[335,176],[332,175],[319,177],[360,178],[351,179],[339,180],[338,175],[340,181],[343,182],[337,183],[341,184],[354,167],[330,185],[331,186],[344,187],[320,162],[348,188],[347,175],[334,186],[342,189],[345,190],[352,1],[318,1],[355,191],[473,192],[448,193],[461,194],[445,195],[462,162],[471,196],[436,197],[437,198],[435,166],[470,167],[465,199],[469,200],[439,201],[458,202],[438,203],[468,204],[433,205],[434,199],[440,206],[441,1],[447,207],[444,206],[305,208],[472,209],[463,210],[451,211],[450,206],[452,212],[455,213],[449,214],[453,215],[466,167],[442,216],[443,217],[456,218],[306,162],[460,219],[459,206],[446,217],[454,220],[457,221],[464,1],[304,1],[467,222],[285,223],[279,224],[283,225],[280,225],[276,224],[284,226],[281,227],[282,225],[277,228],[278,229],[272,230],[213,231],[215,232],[271,1],[214,233],[275,234],[274,235],[273,236],[206,1],[216,231],[217,1],[208,237],[212,238],[207,1],[209,239],[210,240],[211,1],[218,241],[219,241],[220,241],[221,241],[222,241],[223,241],[224,241],[225,241],[226,241],[227,241],[228,241],[229,241],[230,241],[231,241],[233,241],[232,241],[234,241],[235,241],[236,241],[237,241],[238,241],[270,242],[239,241],[240,241],[241,241],[242,241],[243,241],[244,241],[245,241],[246,241],[247,241],[248,241],[249,241],[250,241],[251,241],[253,241],[252,241],[254,241],[255,241],[256,241],[257,241],[258,241],[259,241],[260,241],[261,241],[262,241],[263,241],[264,241],[265,241],[266,241],[269,241],[267,241],[268,241],[289,1],[203,1],[298,243],[297,243],[299,244],[200,245],[60,1],[196,246],[474,247],[302,248],[197,249],[300,250],[204,246],[198,251],[199,252],[301,1],[286,253],[287,254],[475,255],[294,256],[295,257],[201,258],[303,259],[61,260],[202,261],[205,262],[288,263],[296,264],[290,265],[291,266],[292,267],[293,268]],"latestChangedDtsFile":"./dist/tools/write-handler.d.ts","version":"6.0.3"} \ No newline at end of file From ca9d683b7903fe31b8036e5241614ef1dc571c08 Mon Sep 17 00:00:00 2001 From: hcyang Date: Wed, 17 Jun 2026 17:33:44 +0800 Subject: [PATCH 33/72] =?UTF-8?q?chore(git):=20=E6=9B=B4=E6=96=B0.gitignor?= =?UTF-8?q?e=E4=BB=A5=E5=BF=BD=E7=95=A5=E6=9B=B4=E5=A4=9A=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加了操作系统元数据文件的忽略规则(.DS_Store, Thumbs.db) - 新增对构建产物目录dist/和out/的忽略 - 添加了编辑器相关的忽略配置(.idea/, .vscode/) - 保留对node_modules/目录的忽略规则 - 移除了重复的.DS_Store忽略项 --- .gitignore | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index cceec9f7..c2546449 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,15 @@ +# OS metadata +.DS_Store +Thumbs.db + +# Dependency directory node_modules/ +# Ignore built ts files dist/ out/ -src/generated/ -.DS_Store + + +# Editors .idea/ .vscode/ *.tgz From a7949c325fac4fe59191731b9027ec8e10d9ef43 Mon Sep 17 00:00:00 2001 From: hcyang Date: Wed, 17 Jun 2026 17:35:15 +0800 Subject: [PATCH 34/72] =?UTF-8?q?chore(config):=20=E9=85=8D=E7=BD=AEnpm?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E8=A1=A8=E5=92=8CNode=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增.npmrc文件,指定npm注册表地址为https://registry.npmjs.org - 新增.nvmrc文件,指定Node.js版本为22 --- .npmrc | 1 + .nvmrc | 1 + 2 files changed, 2 insertions(+) create mode 100644 .npmrc create mode 100644 .nvmrc diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..38f11c64 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +registry=https://registry.npmjs.org diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..2bd5a0a9 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22 From 499081ababcfbe54ddab01e412e89a2bcc5cd8d3 Mon Sep 17 00:00:00 2001 From: hcyang Date: Thu, 18 Jun 2026 10:18:49 +0800 Subject: [PATCH 35/72] =?UTF-8?q?build(vscode-ide-companion):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=A8=A1=E6=9D=BF=E6=96=87=E4=BB=B6=E5=A4=8D=E5=88=B6?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=B9=B6=E6=9B=B4=E6=96=B0=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 build 脚本中新增复制 core 包 templates 到 vscode-ide-companion/templates - 修正 .gitignore,忽略 vscode-ide-companion 内的 templates 目录 - vscode-ide-companion package.json 中新增 templates 目录到文件列表 - 新增 scripts/prepare-package.js,实现构建、检查、发布、Git 提交与打 tag - 新增 scripts/version.js,实现 monorepo 中多个包版本统一更新与 lockfile 重生成 - package.json 新增 release:version 和 prepare:package 脚本命令 - 添加 RELEASE.md 及 RELEASE_en.md,详细说明版本发布和发布流程文档 --- .gitignore | 3 +- RELEASE.md | 235 ++++++++++++++++ RELEASE_en.md | 235 ++++++++++++++++ package.json | 4 +- packages/vscode-ide-companion/package.json | 1 + scripts/build-vscode-companion.js | 21 +- scripts/prepare-package.js | 302 +++++++++++++++++++++ scripts/version.js | 296 ++++++++++++++++++++ 8 files changed, 1092 insertions(+), 5 deletions(-) create mode 100644 RELEASE.md create mode 100644 RELEASE_en.md create mode 100644 scripts/prepare-package.js create mode 100644 scripts/version.js diff --git a/.gitignore b/.gitignore index c2546449..37f64ba0 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,5 @@ out/ # Generated files packages/cli/src/generated/ packages/core/src/generated/ -packages/vscode-ide-companion/*.vsix \ No newline at end of file +packages/vscode-ide-companion/*.vsix +packages/vscode-ide-companion/templates/ \ No newline at end of file diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..deca0fd7 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,235 @@ +# 版本发布 + +Deep Code 使用两个脚本管理 monorepo 的版本发布流程: + +| 脚本 | 命令 | 用途 | +|------|------|------| +| `scripts/version.js` | `npm run release:version` | 升级所有 workspace 包的版本号 + 重新生成 lockfile | +| `scripts/prepare-package.js` | `npm run prepare:package` | 构建 + 质量检查 + 发布到 npm + git commit & tag | + +两者配合使用,先升版本号,再发布。 + +--- + +## release:version — 版本号升级 + +用法与 `npm version` 一致,支持所有标准 bump 类型。 + +### 基本用法 + +```bash +npm run release:version -- [options] +``` + +> 注意:npm scripts 传参需要 `--` 分隔符。 + +### 支持的 bump 类型 + +| 类型 | 当前版本 | 结果 | 说明 | +|------|---------|------|------| +| `patch` | `0.1.31` | `0.1.32` | 补丁版本 +1 | +| `minor` | `0.1.31` | `0.2.0` | 次版本 +1,patch 归零 | +| `major` | `0.1.31` | `1.0.0` | 主版本 +1,minor/patch 归零 | +| `prepatch` | `0.1.31` | `0.1.32-0` | 预发布补丁 | +| `preminor` | `0.1.31` | `0.2.0-0` | 预发布次版本 | +| `premajor` | `0.1.31` | `1.0.0-0` | 预发布主版本 | +| `prerelease` | `0.1.31` | `0.1.32-0` | 递增预发布号 | +| `from-git` | — | 从最新 git tag 读取 | 适用于已有 tag 但未更新 package.json 的情况 | + +也可以直接指定版本号: + +```bash +npm run release:version -- 0.2.0 +``` + +### 预发布链 + +`prerelease` 支持链式递增: + +``` +0.1.31 + → prerelease → 0.1.32-beta.0 + → prerelease → 0.1.32-beta.1 + → prerelease → 0.1.32-beta.2 + → patch → 0.1.32 (去掉 prerelease 后缀) +``` + +### --preid 选项 + +预发布标识符,默认为 `"0"`,可自定义: + +```bash +npm run release:version -- prerelease --preid beta +# 0.1.31 → 0.1.32-beta.0 + +npm run release:version -- premajor --preid alpha +# 0.1.31 → 1.0.0-alpha.0 +``` + +### 实际执行的操作 + +1. 读取 `packages/core/package.json` 中的当前版本 +2. 根据 bump 类型计算目标版本 +3. 更新 **所有** `packages/*/package.json` 的 `version` 字段(core、cli、vscode-ide-companion) +4. 删除旧的 `package-lock.json`,执行 `npm install --package-lock-only` 重新生成 + +### 完整示例 + +```bash +# 升级 patch 版本 +npm run release:version -- patch + +# 升级 minor 版本 +npm run release:version -- minor + +# 发布 beta 预发布版 +npm run release:version -- prerelease --preid beta + +# 直接指定版本 +npm run release:version -- 0.2.0 + +# 从 git tag 获取版本 +npm run release:version -- from-git +``` + +升级后检查变更,确认无误后提交: + +```bash +git diff +git add -A +git commit -m "chore(release): v0.1.32" +git tag v0.1.32 +``` + +--- + +## prepare:package — 构建并发布到 npm + +完成质量检查、构建、发布两个 npm 包,并自动创建 git commit 和 tag。 + +### 基本用法 + +```bash +npm run prepare:package -- [options] +``` + +### 参数 + +| 参数 | 说明 | +|------|------| +| `` | **必填**,要发布的 semver 版本号 | +| `--tag ` | npm dist-tag,默认 `"latest`",常用于 `beta`、`next` | +| `--dry-run` | 预演模式,不实际执行任何写操作 | +| `--force` | 跳过 main 分支检查,允许从其他分支发布 | + +### 执行流程(9 步) + +| 步骤 | 操作 | 说明 | +|------|------|------| +| 1 | Git 检查 | 工作区必须 clean,必须在 main 分支(`--force` 可跳过分支检查) | +| 2 | npm 认证 | 检查 `npm whoami`,未登录则中止 | +| 3 | 更新版本号 | 同时更新 `packages/core` 和 `packages/cli` 的 version | +| 4 | 质量检查 | `npm run check`(typecheck + eslint + prettier) | +| 5 | 测试 | `npm run test --workspaces` | +| 6 | 构建 | `npm run build`(core tsc + cli esbuild bundle) | +| 7 | 发布 core | `npm publish --workspace=@vegamo/deepcode-core --access public` | +| 8 | 发布 cli | 将 cli 的 `@vegamo/deepcode-core` 依赖从 `file:../core` 临时改为 `^`,发布后恢复 | +| 9 | Git commit & tag | `chore(release): v` + `git tag v` | + +### 完整示例 + +```bash +# 发布正式版 +npm run prepare:package -- 0.1.32 + +# 发布 beta 版 +npm run prepare:package -- 0.1.32-beta.1 --tag beta + +# 预演(不实际发布,用于检查流程) +npm run prepare:package -- 0.1.32 --dry-run + +# 从非 main 分支发布 +npm run prepare:package -- 0.1.32 --force +``` + +### 关于 file:../core 依赖 + +CLI 包的 `@vegamo/deepcode-core` 依赖在开发时使用 `"file:../core"`(monorepo 本地链接)。发布到 npm 时,脚本会自动将其替换为 `"^"`,发布完成后恢复为 `file:../core`。这个过程对用户透明,无需手动处理。 + +### 发布后 + +脚本完成后会提示手动推送到 remote: + +```bash +git push && git push --tags +``` + +验证发布结果: + +```bash +npm view @vegamo/deepcode-cli version +npx @vegamo/deepcode-cli --version +``` + +--- + +## 典型发布流程 + +一个完整的版本发布通常按以下步骤进行: + +```bash +# 1. 确保工作区干净 +git status + +# 2. 升级版本号 +npm run release:version -- patch + +# 3. 检查变更 +git diff + +# 4. 提交版本变更 +git add -A +git commit -m "chore(release): v0.1.32" + +# 5. 构建 + 质量检查 + 发布 +npm run prepare:package -- 0.1.32 + +# 6. 推送到 remote +git push && git push --tags +``` + +也可以简化为两步(`prepare:package` 会自动 commit 和 tag): + +```bash +npm run release:version -- patch +npm run prepare:package -- 0.1.32 +git push && git push --tags +``` + +--- + +## 预发布版本流程 + +```bash +# 第一个 beta +npm run release:version -- prerelease --preid beta +# → 0.1.32-beta.0 + +git add -A && git commit -m "chore(release): v0.1.32-beta.0" +npm run prepare:package -- 0.1.32-beta.0 --tag beta + +# 后续 beta +npm run release:version -- prerelease --preid beta +# → 0.1.32-beta.1 + +git add -A && git commit -m "chore(release): v0.1.32-beta.1" +npm run prepare:package -- 0.1.32-beta.1 --tag beta + +# 正式发布 +npm run release:version -- patch +# → 0.1.32 + +git add -A && git commit -m "chore(release): v0.1.32" +npm run prepare:package -- 0.1.32 +git push && git push --tags +``` diff --git a/RELEASE_en.md b/RELEASE_en.md new file mode 100644 index 00000000..4844bf70 --- /dev/null +++ b/RELEASE_en.md @@ -0,0 +1,235 @@ +# Release + +Deep Code uses two scripts to manage version releases in the monorepo: + +| Script | Command | Purpose | +|--------|---------|---------| +| `scripts/version.js` | `npm run release:version` | Bump all workspace package versions + regenerate lockfile | +| `scripts/prepare-package.js` | `npm run prepare:package` | Build + quality checks + publish to npm + git commit & tag | + +Use them together: bump version first, then publish. + +--- + +## release:version — Version Bump + +Works like `npm version`, supporting all standard bump types. + +### Basic Usage + +```bash +npm run release:version -- [options] +``` + +> Note: npm scripts require the `--` separator to pass arguments. + +### Supported Bump Types + +| Type | Current | Result | Description | +|------|---------|--------|-------------| +| `patch` | `0.1.31` | `0.1.32` | Patch version +1 | +| `minor` | `0.1.31` | `0.2.0` | Minor version +1, patch reset | +| `major` | `0.1.31` | `1.0.0` | Major version +1, minor/patch reset | +| `prepatch` | `0.1.31` | `0.1.32-0` | Pre-release patch | +| `preminor` | `0.1.31` | `0.2.0-0` | Pre-release minor | +| `premajor` | `0.1.31` | `1.0.0-0` | Pre-release major | +| `prerelease` | `0.1.31` | `0.1.32-0` | Increment pre-release number | +| `from-git` | — | Read from latest git tag | For cases where tag exists but package.json not updated | + +You can also specify an exact version: + +```bash +npm run release:version -- 0.2.0 +``` + +### Pre-release Chain + +`prerelease` supports chained increments: + +``` +0.1.31 + → prerelease → 0.1.32-beta.0 + → prerelease → 0.1.32-beta.1 + → prerelease → 0.1.32-beta.2 + → patch → 0.1.32 (drops prerelease suffix) +``` + +### --preid Option + +Pre-release identifier, defaults to `"0"`, customizable: + +```bash +npm run release:version -- prerelease --preid beta +# 0.1.31 → 0.1.32-beta.0 + +npm run release:version -- premajor --preid alpha +# 0.1.31 → 1.0.0-alpha.0 +``` + +### What It Does + +1. Reads current version from `packages/core/package.json` +2. Calculates target version based on bump type +3. Updates `version` field in **all** `packages/*/package.json` (core, cli, vscode-ide-companion) +4. Deletes old `package-lock.json` and regenerates via `npm install --package-lock-only` + +### Examples + +```bash +# Bump patch +npm run release:version -- patch + +# Bump minor +npm run release:version -- minor + +# Beta pre-release +npm run release:version -- prerelease --preid beta + +# Exact version +npm run release:version -- 0.2.0 + +# From git tag +npm run release:version -- from-git +``` + +After bumping, review changes and commit: + +```bash +git diff +git add -A +git commit -m "chore(release): v0.1.32" +git tag v0.1.32 +``` + +--- + +## prepare:package — Build and Publish to npm + +Runs quality checks, builds, publishes both npm packages, and automatically creates a git commit with tag. + +### Basic Usage + +```bash +npm run prepare:package -- [options] +``` + +### Arguments + +| Argument | Description | +|----------|-------------| +| `` | **Required**. Semver version to publish | +| `--tag ` | npm dist-tag, default `"latest"`, commonly `beta` or `next` | +| `--dry-run` | Preview mode, no actual writes | +| `--force` | Skip main branch check, allow publishing from other branches | + +### Execution Flow (9 Steps) + +| Step | Action | Description | +|------|--------|-------------| +| 1 | Git check | Working tree must be clean, must be on main branch (`--force` skips branch check) | +| 2 | npm auth | Checks `npm whoami`, aborts if not logged in | +| 3 | Update versions | Updates `packages/core` and `packages/cli` version fields | +| 4 | Quality checks | `npm run check` (typecheck + eslint + prettier) | +| 5 | Tests | `npm run test --workspaces` | +| 6 | Build | `npm run build` (core tsc + cli esbuild bundle) | +| 7 | Publish core | `npm publish --workspace=@vegamo/deepcode-core --access public` | +| 8 | Publish cli | Temporarily changes cli's `@vegamo/deepcode-core` dep from `file:../core` to `^`, restores after publish | +| 9 | Git commit & tag | `chore(release): v` + `git tag v` | + +### Examples + +```bash +# Publish stable release +npm run prepare:package -- 0.1.32 + +# Publish beta +npm run prepare:package -- 0.1.32-beta.1 --tag beta + +# Dry run (no actual publish) +npm run prepare:package -- 0.1.32 --dry-run + +# Publish from non-main branch +npm run prepare:package -- 0.1.32 --force +``` + +### About the file:../core Dependency + +The CLI package uses `"file:../core"` for the `@vegamo/deepcode-core` dependency during development (monorepo local link). When publishing to npm, the script automatically replaces it with `"^"` and restores it after publishing. This is transparent — no manual handling required. + +### After Publishing + +The script prompts you to push to remote: + +```bash +git push && git push --tags +``` + +Verify the release: + +```bash +npm view @vegamo/deepcode-cli version +npx @vegamo/deepcode-cli --version +``` + +--- + +## Typical Release Flow + +A complete version release follows these steps: + +```bash +# 1. Ensure clean working tree +git status + +# 2. Bump version +npm run release:version -- patch + +# 3. Review changes +git diff + +# 4. Commit version change +git add -A +git commit -m "chore(release): v0.1.32" + +# 5. Build + quality check + publish +npm run prepare:package -- 0.1.32 + +# 6. Push to remote +git push && git push --tags +``` + +Or simplified to two steps (`prepare:package` auto-commits and tags): + +```bash +npm run release:version -- patch +npm run prepare:package -- 0.1.32 +git push && git push --tags +``` + +--- + +## Pre-release Flow + +```bash +# First beta +npm run release:version -- prerelease --preid beta +# → 0.1.32-beta.0 + +git add -A && git commit -m "chore(release): v0.1.32-beta.0" +npm run prepare:package -- 0.1.32-beta.0 --tag beta + +# Subsequent betas +npm run release:version -- prerelease --preid beta +# → 0.1.32-beta.1 + +git add -A && git commit -m "chore(release): v0.1.32-beta.1" +npm run prepare:package -- 0.1.32-beta.1 --tag beta + +# Stable release +npm run release:version -- patch +# → 0.1.32 + +git add -A && git commit -m "chore(release): v0.1.32" +npm run prepare:package -- 0.1.32 +git push && git push --tags +``` diff --git a/package.json b/package.json index e2a722c0..165ccfdb 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,9 @@ "start": "node scripts/start.js", "build-and-start": "npm run build && npm run start", "test": "npm run test --workspaces --if-present", - "prepare": "husky" + "release:version": "node scripts/version.js", + "prepare:package": "node scripts/prepare-package.js", + "prepare": "husky && npm run build && npm run bundle" }, "devDependencies": { "@eslint/js": "^9.39.4", diff --git a/packages/vscode-ide-companion/package.json b/packages/vscode-ide-companion/package.json index 5ad51fb7..fd4da3ac 100644 --- a/packages/vscode-ide-companion/package.json +++ b/packages/vscode-ide-companion/package.json @@ -31,6 +31,7 @@ "files": [ "out/extension.js", "resources/**", + "templates/**", "README.md", "README_cn.md", "README_en.md", diff --git a/scripts/build-vscode-companion.js b/scripts/build-vscode-companion.js index 7288c786..7fbb1c2a 100644 --- a/scripts/build-vscode-companion.js +++ b/scripts/build-vscode-companion.js @@ -1,4 +1,5 @@ import { spawnSync } from "node:child_process"; +import { cpSync, existsSync, rmSync } from "node:fs"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; @@ -16,8 +17,22 @@ console.log("========================================="); console.log(" Deep Code — Build VSCode Companion"); console.log("========================================="); -run("npm", ["run", "build", "--workspace=@vegamo/deepcode-core"], "1/3 Build core"); -run("node", ["scripts/esbuild-vscode.config.js"], "2/3 Bundle extension"); -run("npm", ["run", "package", "--workspace=deepcode-vscode"], "3/3 Package .vsix"); +run("npm", ["run", "build", "--workspace=@vegamo/deepcode-core"], "1/4 Build core"); +run("node", ["scripts/esbuild-vscode.config.js"], "2/4 Bundle extension"); + +// Copy templates from core so the extension can read them at runtime via fs +const templatesSrc = join(root, "packages", "core", "templates"); +const templatesDest = join(root, "packages", "vscode-ide-companion", "templates"); + +if (!existsSync(templatesSrc)) { + console.error(`\n❌ Templates not found at ${templatesSrc}`); + process.exit(1); +} + +rmSync(templatesDest, { recursive: true, force: true }); +cpSync(templatesSrc, templatesDest, { recursive: true, dereference: true }); +console.log("\n[3/4] Copied templates from core → vscode-ide-companion/templates/"); + +run("npm", ["run", "package", "--workspace=deepcode-vscode"], "4/4 Package .vsix"); console.log("\n✅ VSCode companion build complete.\n\n"); diff --git a/scripts/prepare-package.js b/scripts/prepare-package.js new file mode 100644 index 00000000..6049f082 --- /dev/null +++ b/scripts/prepare-package.js @@ -0,0 +1,302 @@ +import { spawnSync } from "node:child_process"; +import { readFileSync, writeFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); + +// ── Helpers ────────────────────────────────────────────────────────────────── + +function log(msg) { + console.log(msg); +} + +function step(n, total, msg) { + console.log(`\n[${n}/${total}] ${msg}`); +} + +function fail(msg) { + console.error(`\n❌ ${msg}`); + process.exit(1); +} + +function ok(msg) { + console.log(`✅ ${msg}`); +} + +function run(cmd, args, opts = {}) { + const label = opts.label ?? `${cmd} ${args.join(" ")}`; + if (opts.dryRun) { + log(` (dry-run) ${label}`); + return { status: 0, stdout: "" }; + } + const result = spawnSync(cmd, args, { + stdio: opts.stdio ?? "inherit", + cwd: opts.cwd ?? root, + shell: true, + env: { ...process.env, ...opts.env }, + }); + if (result.status !== 0) { + fail(`Command failed: ${label}`); + } + return result; +} + +function readJson(filePath) { + return JSON.parse(readFileSync(filePath, "utf-8")); +} + +function writeJson(filePath, data) { + writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8"); +} + +function isValidSemver(v) { + return /^\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$/.test(v); +} + +// ── Parse args ─────────────────────────────────────────────────────────────── + +const args = process.argv.slice(2); +let version = null; +let tag = "latest"; +let dryRun = false; +let force = false; + +for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (arg === "--dry-run") { + dryRun = true; + } else if (arg === "--force") { + force = true; + } else if (arg === "--tag") { + tag = args[++i]; + if (!tag) fail("--tag requires a value"); + } else if (!version) { + version = arg; + } else { + fail(`Unknown argument: ${arg}`); + } +} + +if (!version) { + log(` +Usage: node scripts/publish.js [options] + +Arguments: + Semver version to publish (e.g. 0.1.32, 0.2.0-beta.1) + +Options: + --tag npm dist-tag (default: "latest") + --dry-run Preview all steps without executing + --force Skip branch check (publish from non-main branch) + +Examples: + node scripts/publish.js 0.1.32 + node scripts/publish.js 0.1.32-beta.1 --tag beta + node scripts/publish.js 0.1.32 --dry-run +`); + process.exit(1); +} + +if (!isValidSemver(version)) { + fail(`Invalid semver version: ${version}`); +} + +const TOTAL_STEPS = 9; + +// ── Banner ─────────────────────────────────────────────────────────────────── + +log("========================================="); +log(` Deep Code CLI — Publish v${version}`); +log(` tag=${tag} dryRun=${dryRun} force=${force}`); +log("========================================="); + +// ── 1. Git checks ──────────────────────────────────────────────────────────── + +step(1, TOTAL_STEPS, "Checking git state..."); + +const gitStatus = spawnSync("git", ["status", "--porcelain"], { + cwd: root, + encoding: "utf-8", + shell: true, +}); +if (gitStatus.stdout.trim()) { + fail("Working tree is not clean. Commit or stash changes first."); +} +ok("Working tree is clean"); + +if (!force) { + const gitBranch = spawnSync("git", ["branch", "--show-current"], { + cwd: root, + encoding: "utf-8", + shell: true, + }); + const branch = gitBranch.stdout.trim(); + if (branch !== "main") { + fail(`Not on main branch (current: ${branch}). Use --force to publish from another branch.`); + } + ok("On main branch"); +} + +// ── 2. npm auth ────────────────────────────────────────────────────────────── + +step(2, TOTAL_STEPS, "Checking npm authentication..."); + +if (!dryRun) { + const whoami = spawnSync("npm", ["whoami"], { + cwd: root, + encoding: "utf-8", + shell: true, + }); + if (whoami.status !== 0) { + fail("Not logged in to npm. Run `npm login` first."); + } + ok(`Logged in as: ${whoami.stdout.trim()}`); +} else { + log(" (dry-run) skipping npm whoami"); +} + +// ── 3. Version bump ────────────────────────────────────────────────────────── + +step(3, TOTAL_STEPS, "Updating package versions..."); + +const corePkgPath = join(root, "packages", "core", "package.json"); +const cliPkgPath = join(root, "packages", "cli", "package.json"); + +const corePkg = readJson(corePkgPath); +const cliPkg = readJson(cliPkgPath); + +const oldVersion = corePkg.version; + +// Save originals for restore +const origCliPkg = JSON.stringify(cliPkg, null, 2) + "\n"; + +corePkg.version = version; +cliPkg.version = version; + +if (!dryRun) { + writeJson(corePkgPath, corePkg); + writeJson(cliPkgPath, cliPkg); + ok(`Updated packages/core: ${oldVersion} → ${version}`); + ok(`Updated packages/cli: ${oldVersion} → ${version}`); +} else { + log(` (dry-run) packages/core: ${oldVersion} → ${version}`); + log(` (dry-run) packages/cli: ${oldVersion} → ${version}`); +} + +// ── 4. Quality checks ──────────────────────────────────────────────────────── + +step(4, TOTAL_STEPS, "Running quality checks (typecheck + lint + format)..."); + +run("npm", ["run", "check"], { dryRun }); +ok("All checks passed"); + +step(5, TOTAL_STEPS, "Running tests..."); + +run("npm", ["run", "test", "--workspaces"], { dryRun }); +ok("All tests passed"); + +// ── 6. Build ───────────────────────────────────────────────────────────────── + +step(6, TOTAL_STEPS, "Building packages..."); + +run("npm", ["run", "build"], { dryRun }); +ok("Build complete"); + +// ── 7. Publish core ────────────────────────────────────────────────────────── + +step(7, TOTAL_STEPS, "Publishing @vegamo/deepcode-core..."); + +const corePublishArgs = [ + "publish", + "--workspace=@vegamo/deepcode-core", + "--access", + "public", + "--tag", + tag, + "--registry", + "https://registry.npmjs.org", +]; +if (dryRun) corePublishArgs.push("--dry-run"); + +run("npm", corePublishArgs, { dryRun, label: `npm ${corePublishArgs.join(" ")}` }); +ok(`Published @vegamo/deepcode-core@${version}`); + +// ── 8. Patch CLI deps & publish ────────────────────────────────────────────── + +step(8, TOTAL_STEPS, "Patching CLI dependencies and publishing @vegamo/deepcode-cli..."); + +// Replace file:../core with ^version for npm +const patchedCliPkg = readJson(cliPkgPath); +const coreDep = patchedCliPkg.dependencies["@vegamo/deepcode-core"]; +if (coreDep && coreDep.startsWith("file:")) { + patchedCliPkg.dependencies["@vegamo/deepcode-core"] = `^${version}`; + if (!dryRun) { + writeJson(cliPkgPath, patchedCliPkg); + } + log(` Patched @vegamo/deepcode-core dep: "${coreDep}" → "^${version}"`); +} + +const cliPublishArgs = [ + "publish", + "--workspace=@vegamo/deepcode-cli", + "--access", + "public", + "--tag", + tag, + "--registry", + "https://registry.npmjs.org", +]; +if (dryRun) cliPublishArgs.push("--dry-run"); + +run("npm", cliPublishArgs, { dryRun, label: `npm ${cliPublishArgs.join(" ")}` }); +ok(`Published @vegamo/deepcode-cli@${version}`); + +// Restore file:../core for local development +if (!dryRun) { + writeJson(cliPkgPath, JSON.parse(origCliPkg)); + // But keep the new version + const restoredCli = readJson(cliPkgPath); + restoredCli.version = version; + writeJson(cliPkgPath, restoredCli); + log(" Restored @vegamo/deepcode-core dep to file:../core"); +} + +// ── 9. Git commit + tag ────────────────────────────────────────────────────── + +step(9, TOTAL_STEPS, "Creating git commit and tag..."); + +if (!dryRun) { + run("git", ["add", "packages/core/package.json", "packages/cli/package.json"], { + label: "git add packages/*/package.json", + }); + run("git", ["commit", "-m", `chore(release): v${version}`], { + label: `git commit -m "chore(release): v${version}"`, + }); + run("git", ["tag", `v${version}`], { + label: `git tag v${version}`, + }); + ok(`Created commit and tag v${version}`); +} else { + log(` (dry-run) git add + commit "chore(release): v${version}"`); + log(` (dry-run) git tag v${version}`); +} + +// ── Done ───────────────────────────────────────────────────────────────────── + +console.log("\n========================================="); +console.log(` 🎉 Published v${version} successfully!`); +console.log("========================================="); +console.log(` + Packages published: + • @vegamo/deepcode-core@${version} + • @vegamo/deepcode-cli@${version} + + Verify: + npm view @vegamo/deepcode-cli version + npx @vegamo/deepcode-cli --version + + Push to remote: + git push && git push --tags +`); diff --git a/scripts/version.js b/scripts/version.js new file mode 100644 index 00000000..5d2fa4f1 --- /dev/null +++ b/scripts/version.js @@ -0,0 +1,296 @@ +import { spawnSync } from "node:child_process"; +import { readFileSync, writeFileSync, unlinkSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { globSync } from "glob"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); + +const BUMP_TYPES = ["major", "minor", "patch", "premajor", "preminor", "prepatch", "prerelease", "from-git"]; + +// ── Helpers ────────────────────────────────────────────────────────────────── + +function log(msg) { + console.log(msg); +} + +function fail(msg) { + console.error(`\n❌ ${msg}`); + process.exit(1); +} + +function ok(msg) { + console.log(`✅ ${msg}`); +} + +function readJson(filePath) { + return JSON.parse(readFileSync(filePath, "utf-8")); +} + +function writeJson(filePath, data) { + writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8"); +} + +function isValidSemver(v) { + return /^\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$/.test(v); +} + +function isBumpType(v) { + return BUMP_TYPES.includes(v); +} + +function run(cmd, args, opts = {}) { + const result = spawnSync(cmd, args, { + stdio: opts.stdio ?? "inherit", + cwd: opts.cwd ?? root, + shell: true, + }); + if (result.status !== 0) { + fail(`Command failed: ${cmd} ${args.join(" ")}`); + } + return result; +} + +function runSilent(cmd, args) { + const result = spawnSync(cmd, args, { + cwd: root, + encoding: "utf-8", + shell: true, + }); + if (result.status !== 0) { + return null; + } + return result.stdout.trim(); +} + +// ── Version bump logic ─────────────────────────────────────────────────────── + +function parseVersion(v) { + const match = v.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/); + if (!match) fail(`Cannot parse version: ${v}`); + return { + major: Number(match[1]), + minor: Number(match[2]), + patch: Number(match[3]), + prerelease: match[4] ?? null, + }; +} + +function formatVersion({ major, minor, patch, prerelease }) { + let v = `${major}.${minor}.${patch}`; + if (prerelease) v += `-${prerelease}`; + return v; +} + +function bumpVersion(current, type, preid) { + const v = parseVersion(current); + + switch (type) { + case "major": + return formatVersion({ major: v.major + 1, minor: 0, patch: 0, prerelease: null }); + + case "minor": + return formatVersion({ major: v.major, minor: v.minor + 1, patch: 0, prerelease: null }); + + case "patch": + if (v.prerelease) { + // 0.1.32-beta.1 → 0.1.32 (drop prerelease) + return formatVersion({ ...v, prerelease: null }); + } + return formatVersion({ ...v, patch: v.patch + 1 }); + + case "premajor": + return formatVersion({ + major: v.major + 1, + minor: 0, + patch: 0, + prerelease: `${preid}.0`, + }); + + case "preminor": + return formatVersion({ + major: v.major, + minor: v.minor + 1, + patch: 0, + prerelease: `${preid}.0`, + }); + + case "prepatch": + if (v.prerelease) { + // Already a prerelease — increment the prerelease number + const num = Number(v.prerelease.split(".").pop()); + const base = v.prerelease.split(".").slice(0, -1).join("."); + if (!isNaN(num)) { + return formatVersion({ ...v, prerelease: `${base}.${num + 1}` }); + } + } + return formatVersion({ + ...v, + patch: v.patch + 1, + prerelease: `${preid}.0`, + }); + + case "prerelease": + if (v.prerelease) { + // 0.1.32-beta.0 → 0.1.32-beta.1 + const num = Number(v.prerelease.split(".").pop()); + const base = v.prerelease.split(".").slice(0, -1).join("."); + if (!isNaN(num)) { + const newPre = base ? `${base}.${num + 1}` : `${num + 1}`; + return formatVersion({ ...v, prerelease: newPre }); + } + // Can't parse number, append .0 + return formatVersion({ ...v, prerelease: `${v.prerelease}.0` }); + } + // No prerelease yet — go to next patch prerelease + return formatVersion({ + ...v, + patch: v.patch + 1, + prerelease: `${preid}.0`, + }); + + default: + fail(`Unknown bump type: ${type}`); + } +} + +function resolveVersionFromGit() { + // Get latest tag matching v* + const tag = runSilent("git", ["describe", "--tags", "--abbrev=0"]); + if (!tag) { + fail("No git tags found. Cannot use 'from-git'."); + } + const v = tag.replace(/^v/, ""); + if (!isValidSemver(v)) { + fail(`Latest git tag is not a valid semver: ${tag}`); + } + return v; +} + +// ── Parse args ─────────────────────────────────────────────────────────────── + +const args = process.argv.slice(2); +let bumpArg = null; +let preid = "0"; + +for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (arg === "--help" || arg === "-h") { + log(` +Usage: npm run release:version -- [--preid ] + +Bumps all workspace package.json files and regenerates package-lock.json. +Works like npm version but for the entire monorepo. + +Bump types: + major 0.1.31 → 1.0.0 + minor 0.1.31 → 0.2.0 + patch 0.1.31 → 0.1.32 + premajor 0.1.31 → 1.0.0-0 + preminor 0.1.31 → 0.2.0-0 + prepatch 0.1.31 → 0.1.32-0 + prerelease 0.1.31 → 0.1.32-0 0.1.32-0 → 0.1.32-1 + from-git Use version from latest git tag + +Options: + --preid Prerelease identifier (default: "0", e.g. "beta", "alpha") + +Examples: + npm run release:version -- patch + npm run release:version -- minor + npm run release:version -- 0.2.0 + npm run release:version -- prerelease --preid beta + npm run release:version -- from-git +`); + process.exit(0); + } else if (arg === "--preid") { + preid = args[++i]; + if (!preid) fail("--preid requires a value"); + } else if (!bumpArg) { + bumpArg = arg; + } else { + fail(`Unknown argument: ${arg}`); + } +} + +if (!bumpArg) { + log(` +Usage: npm run release:version -- [--preid ] + Run with --help for details. +`); + process.exit(1); +} + +// ── Resolve target version ─────────────────────────────────────────────────── + +const corePkgPath = join(root, "packages", "core", "package.json"); +const currentVersion = readJson(corePkgPath).version; + +let version; + +if (bumpArg === "from-git") { + version = resolveVersionFromGit(); + log(`Resolved from git tag: v${version}`); +} else if (isBumpType(bumpArg)) { + version = bumpVersion(currentVersion, bumpArg, preid); +} else if (isValidSemver(bumpArg)) { + version = bumpArg; +} else { + fail(`Invalid argument: "${bumpArg}". Expected a bump type (${BUMP_TYPES.join(", ")}) or a semver version.`); +} + +// ── Banner ─────────────────────────────────────────────────────────────────── + +log("========================================="); +log(` Deep Code — Bump Version`); +log(` ${currentVersion} → ${version}`); +log("=========================================\n"); + +// ── Find all workspace package.json ────────────────────────────────────────── + +const pkgPaths = globSync("packages/*/package.json", { cwd: root, absolute: true }); + +if (pkgPaths.length === 0) { + fail("No workspace packages found under packages/"); +} + +// ── Update versions ────────────────────────────────────────────────────────── + +log("Updating package.json files:\n"); + +for (const pkgPath of pkgPaths) { + const pkg = readJson(pkgPath); + const oldVersion = pkg.version; + pkg.version = version; + writeJson(pkgPath, pkg); + const short = pkgPath.replace(root + "/", ""); + log(` ${short}: ${oldVersion} → ${version}`); +} + +// ── Regenerate lockfile ────────────────────────────────────────────────────── + +log("\nRegenerating package-lock.json...\n"); + +const lockPath = join(root, "package-lock.json"); +try { + unlinkSync(lockPath); + log(" Removed old package-lock.json"); +} catch { + // lockfile may not exist, that's fine +} + +run("npm", ["install", "--package-lock-only"]); +ok("package-lock.json regenerated"); + +// ── Done ───────────────────────────────────────────────────────────────────── + +console.log("\n========================================="); +log(` 🎉 Version bumped to v${version}`); +console.log("========================================="); +console.log(` + Updated ${pkgPaths.length} packages. Next steps: + git add -A && git commit -m "chore(release): v${version}" + git tag v${version} + git push && git push --tags +`); From 8fc6d696fdae44387cab561df18d331018783202 Mon Sep 17 00:00:00 2001 From: hcyang Date: Thu, 18 Jun 2026 11:22:26 +0800 Subject: [PATCH 36/72] =?UTF-8?q?refactor(scripts):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=B8=85=E7=90=86=E8=84=9A=E6=9C=AC=E4=BB=A5=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=9B=B4=E5=A4=9A=E6=9E=84=E5=BB=BA=E4=BA=A7=E7=89=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除根目录下的 node_modules 文件夹 - 增加按包删除每个包的 node_modules、dist、生成目录和 tsbuildinfo 文件 - 清理 vscode-ide-companion 包的 out 和 templates 目录 - 修正 vscode-ide-companion 的 vsix 文件清理路径 - 输出的日志信息更明确,显示具体删除路径 --- package-lock.json | 1515 ++++++++++++++++++++++----------------------- scripts/clean.js | 38 +- 2 files changed, 778 insertions(+), 775 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8bd4ca15..e36f1926 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,7 @@ }, "node_modules/@alcalzone/ansi-tokenize": { "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/@alcalzone/ansi-tokenize/-/ansi-tokenize-0.3.0.tgz", + "resolved": "https://registry.npmjs.org/@alcalzone/ansi-tokenize/-/ansi-tokenize-0.3.0.tgz", "integrity": "sha512-p+CMKJ93HFmLkjXKlXiVGlMQEuRb6H0MokBSwUsX+S6BRX8eV5naFZpQJFfJHjRZY0Hmnqy1/r6UWl3x+19zYA==", "license": "MIT", "dependencies": { @@ -42,7 +42,7 @@ }, "node_modules/@alcalzone/ansi-tokenize/node_modules/ansi-styles": { "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", "engines": { @@ -54,14 +54,14 @@ }, "node_modules/@azu/format-text": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/@azu/format-text/-/format-text-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/@azu/format-text/-/format-text-1.0.2.tgz", "integrity": "sha512-Swi4N7Edy1Eqq82GxgEECXSSLyn6GOb5htRFPzBDdUkECGXtlf12ynO5oJSpWKPwCaUssOu7NfhDcCWpIC6Ywg==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/@azu/style-format": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/@azu/style-format/-/style-format-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/@azu/style-format/-/style-format-1.0.1.tgz", "integrity": "sha512-AHcTojlNBdD/3/KxIKlg8sxIWHfOtQszLvOpagLTO+bjC3u7SAszu1lf//u7JJC50aUSH+BVWDD/KvaA6Gfn5g==", "dev": true, "license": "WTFPL", @@ -71,7 +71,7 @@ }, "node_modules/@azure/abort-controller": { "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", "dev": true, "license": "MIT", @@ -84,7 +84,7 @@ }, "node_modules/@azure/core-auth": { "version": "1.10.1", - "resolved": "https://registry.npmmirror.com/@azure/core-auth/-/core-auth-1.10.1.tgz", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz", "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", "dev": true, "license": "MIT", @@ -99,7 +99,7 @@ }, "node_modules/@azure/core-client": { "version": "1.10.2", - "resolved": "https://registry.npmmirror.com/@azure/core-client/-/core-client-1.10.2.tgz", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.2.tgz", "integrity": "sha512-1D2LpsU7y9xrqKjdIbsB7PlrRePw0xsVV8p+AKTlzITrWmscajryfJCdDJB/oGwvDI5HmRo04eMMADB67uwAwQ==", "dev": true, "license": "MIT", @@ -118,7 +118,7 @@ }, "node_modules/@azure/core-rest-pipeline": { "version": "1.24.0", - "resolved": "https://registry.npmmirror.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.24.0.tgz", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.24.0.tgz", "integrity": "sha512-PpLsoDQ3AMmKZ0VU+0GrmqMxgp/sExjlVm4R+nLWngeoEGAzOIPVifaxKGU5gMv+nWELUoHfvrolWD+ZS/nFJg==", "dev": true, "license": "MIT", @@ -137,7 +137,7 @@ }, "node_modules/@azure/core-tracing": { "version": "1.3.1", - "resolved": "https://registry.npmmirror.com/@azure/core-tracing/-/core-tracing-1.3.1.tgz", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz", "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", "dev": true, "license": "MIT", @@ -150,7 +150,7 @@ }, "node_modules/@azure/core-util": { "version": "1.13.1", - "resolved": "https://registry.npmmirror.com/@azure/core-util/-/core-util-1.13.1.tgz", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz", "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", "dev": true, "license": "MIT", @@ -165,7 +165,7 @@ }, "node_modules/@azure/identity": { "version": "4.13.1", - "resolved": "https://registry.npmmirror.com/@azure/identity/-/identity-4.13.1.tgz", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.1.tgz", "integrity": "sha512-5C/2WD5Vb1lHnZS16dNQRPMjN6oV/Upba+C9nBIs15PmOi6A3ZGs4Lr2u60zw4S04gi+u3cEXiqTVP7M4Pz3kw==", "dev": true, "license": "MIT", @@ -188,7 +188,7 @@ }, "node_modules/@azure/logger": { "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/@azure/logger/-/logger-1.3.0.tgz", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", "dev": true, "license": "MIT", @@ -201,22 +201,22 @@ } }, "node_modules/@azure/msal-browser": { - "version": "5.13.0", - "resolved": "https://registry.npmmirror.com/@azure/msal-browser/-/msal-browser-5.13.0.tgz", - "integrity": "sha512-Ea23x0U8XNFY+qJ9T44zO2BbY+AHdb+WdjmYnx36OhJ/KO+PGU5pmsNHf1DCElYX+6wyVRJz1HFeCPC/cHbRug==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.14.0.tgz", + "integrity": "sha512-Dfl7hPZe9/JJwRhFFXHq2z1oHYBuGubmff3kWXOsd1AGgyXlqjNYAWuN/1JL/ZrcZBs8TKMjGSil6Rcc7E8VPQ==", "dev": true, "license": "MIT", "dependencies": { - "@azure/msal-common": "16.8.0" + "@azure/msal-common": "16.9.0" }, "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-common": { - "version": "16.8.0", - "resolved": "https://registry.npmmirror.com/@azure/msal-common/-/msal-common-16.8.0.tgz", - "integrity": "sha512-5S4RHOcInL2Nu2U217tDZbWGI6StMfcWCrA7TWvWdJmXQ+cYrrIqr84AsN62fGh2MDBysiBJPt6CfWceJfloEA==", + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.9.0.tgz", + "integrity": "sha512-1MWGjqgUCRAYgLmVFZKp7fs3Rg1TFvIMgywY8ze2olNVvLlJoRThuoziWSDJuwwyJI5L4rnLb9Tyt5D9GvSLPw==", "dev": true, "license": "MIT", "engines": { @@ -224,13 +224,13 @@ } }, "node_modules/@azure/msal-node": { - "version": "5.2.4", - "resolved": "https://registry.npmmirror.com/@azure/msal-node/-/msal-node-5.2.4.tgz", - "integrity": "sha512-rpBUg9dA8UpC2WiFt3KeDKVQmmmVrfxdRnW+F1ebgou/jX/0tAvYuonaq5RUo8OaqzOrj4x/HaI8DmY56RXZ2Q==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-5.2.5.tgz", + "integrity": "sha512-RUuewWk9JvWJS5Yiy8/74Lm1rQAWlrU/qg/Bgtk1jIauVRtnb9XKwS5Xg0J+Whwjesq9EVrBIFgQEP8vHxgezA==", "dev": true, "license": "MIT", "dependencies": { - "@azure/msal-common": "16.8.0", + "@azure/msal-common": "16.9.0", "jsonwebtoken": "^9.0.0" }, "engines": { @@ -239,7 +239,7 @@ }, "node_modules/@babel/code-frame": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", @@ -254,7 +254,7 @@ }, "node_modules/@babel/compat-data": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", @@ -264,7 +264,7 @@ }, "node_modules/@babel/core": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", @@ -295,7 +295,7 @@ }, "node_modules/@babel/generator": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "license": "MIT", @@ -312,7 +312,7 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", @@ -329,7 +329,7 @@ }, "node_modules/@babel/helper-globals": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, "license": "MIT", @@ -339,7 +339,7 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, "license": "MIT", @@ -353,7 +353,7 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", @@ -371,7 +371,7 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", @@ -381,7 +381,7 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", @@ -391,7 +391,7 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", @@ -401,7 +401,7 @@ }, "node_modules/@babel/helpers": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", @@ -415,7 +415,7 @@ }, "node_modules/@babel/parser": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, "license": "MIT", @@ -431,7 +431,7 @@ }, "node_modules/@babel/template": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, "license": "MIT", @@ -446,7 +446,7 @@ }, "node_modules/@babel/traverse": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "license": "MIT", @@ -465,7 +465,7 @@ }, "node_modules/@babel/types": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.7.tgz", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "license": "MIT", @@ -479,7 +479,7 @@ }, "node_modules/@esbuild/aix-ppc64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" @@ -496,7 +496,7 @@ }, "node_modules/@esbuild/android-arm": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" @@ -513,7 +513,7 @@ }, "node_modules/@esbuild/android-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" @@ -530,7 +530,7 @@ }, "node_modules/@esbuild/android-x64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" @@ -547,7 +547,7 @@ }, "node_modules/@esbuild/darwin-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" @@ -564,7 +564,7 @@ }, "node_modules/@esbuild/darwin-x64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" @@ -581,7 +581,7 @@ }, "node_modules/@esbuild/freebsd-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" @@ -598,7 +598,7 @@ }, "node_modules/@esbuild/freebsd-x64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" @@ -615,7 +615,7 @@ }, "node_modules/@esbuild/linux-arm": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" @@ -632,7 +632,7 @@ }, "node_modules/@esbuild/linux-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" @@ -649,7 +649,7 @@ }, "node_modules/@esbuild/linux-ia32": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" @@ -666,7 +666,7 @@ }, "node_modules/@esbuild/linux-loong64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" @@ -683,7 +683,7 @@ }, "node_modules/@esbuild/linux-mips64el": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" @@ -700,7 +700,7 @@ }, "node_modules/@esbuild/linux-ppc64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" @@ -717,7 +717,7 @@ }, "node_modules/@esbuild/linux-riscv64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" @@ -734,7 +734,7 @@ }, "node_modules/@esbuild/linux-s390x": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" @@ -751,7 +751,7 @@ }, "node_modules/@esbuild/linux-x64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" @@ -768,7 +768,7 @@ }, "node_modules/@esbuild/netbsd-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" @@ -785,7 +785,7 @@ }, "node_modules/@esbuild/netbsd-x64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" @@ -802,7 +802,7 @@ }, "node_modules/@esbuild/openbsd-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" @@ -819,7 +819,7 @@ }, "node_modules/@esbuild/openbsd-x64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" @@ -836,7 +836,7 @@ }, "node_modules/@esbuild/openharmony-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "cpu": [ "arm64" @@ -853,7 +853,7 @@ }, "node_modules/@esbuild/sunos-x64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" @@ -870,7 +870,7 @@ }, "node_modules/@esbuild/win32-arm64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" @@ -887,7 +887,7 @@ }, "node_modules/@esbuild/win32-ia32": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" @@ -904,7 +904,7 @@ }, "node_modules/@esbuild/win32-x64": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" @@ -921,7 +921,7 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", - "resolved": "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", @@ -940,7 +940,7 @@ }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { "version": "3.4.3", - "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", @@ -953,7 +953,7 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.12.2", - "resolved": "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", @@ -963,7 +963,7 @@ }, "node_modules/@eslint/config-array": { "version": "0.21.2", - "resolved": "https://registry.npmmirror.com/@eslint/config-array/-/config-array-0.21.2.tgz", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, "license": "Apache-2.0", @@ -978,7 +978,7 @@ }, "node_modules/@eslint/config-helpers": { "version": "0.4.2", - "resolved": "https://registry.npmmirror.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, "license": "Apache-2.0", @@ -991,7 +991,7 @@ }, "node_modules/@eslint/core": { "version": "0.17.0", - "resolved": "https://registry.npmmirror.com/@eslint/core/-/core-0.17.0.tgz", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", @@ -1004,7 +1004,7 @@ }, "node_modules/@eslint/eslintrc": { "version": "3.3.5", - "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, "license": "MIT", @@ -1028,7 +1028,7 @@ }, "node_modules/@eslint/js": { "version": "9.39.4", - "resolved": "https://registry.npmmirror.com/@eslint/js/-/js-9.39.4.tgz", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", @@ -1041,7 +1041,7 @@ }, "node_modules/@eslint/object-schema": { "version": "2.1.7", - "resolved": "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", @@ -1051,7 +1051,7 @@ }, "node_modules/@eslint/plugin-kit": { "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", @@ -1065,7 +1065,7 @@ }, "node_modules/@humanfs/core": { "version": "0.19.2", - "resolved": "https://registry.npmmirror.com/@humanfs/core/-/core-0.19.2.tgz", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, "license": "Apache-2.0", @@ -1078,7 +1078,7 @@ }, "node_modules/@humanfs/node": { "version": "0.16.8", - "resolved": "https://registry.npmmirror.com/@humanfs/node/-/node-0.16.8.tgz", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, "license": "Apache-2.0", @@ -1093,7 +1093,7 @@ }, "node_modules/@humanfs/types": { "version": "0.15.0", - "resolved": "https://registry.npmmirror.com/@humanfs/types/-/types-0.15.0.tgz", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", "dev": true, "license": "Apache-2.0", @@ -1103,7 +1103,7 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", @@ -1117,7 +1117,7 @@ }, "node_modules/@humanwhocodes/retry": { "version": "0.4.3", - "resolved": "https://registry.npmmirror.com/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", @@ -1131,7 +1131,7 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", - "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", @@ -1142,7 +1142,7 @@ }, "node_modules/@jridgewell/remapping": { "version": "2.3.5", - "resolved": "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", @@ -1153,7 +1153,7 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", @@ -1163,14 +1163,14 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", - "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", - "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", @@ -1181,7 +1181,7 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", @@ -1195,7 +1195,7 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", @@ -1205,7 +1205,7 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", @@ -1219,7 +1219,7 @@ }, "node_modules/@secretlint/config-creator": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/config-creator/-/config-creator-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/config-creator/-/config-creator-10.2.2.tgz", "integrity": "sha512-BynOBe7Hn3LJjb3CqCHZjeNB09s/vgf0baBaHVw67w7gHF0d25c3ZsZ5+vv8TgwSchRdUCRrbbcq5i2B1fJ2QQ==", "dev": true, "license": "MIT", @@ -1232,7 +1232,7 @@ }, "node_modules/@secretlint/config-loader": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/config-loader/-/config-loader-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/config-loader/-/config-loader-10.2.2.tgz", "integrity": "sha512-ndjjQNgLg4DIcMJp4iaRD6xb9ijWQZVbd9694Ol2IszBIbGPPkwZHzJYKICbTBmh6AH/pLr0CiCaWdGJU7RbpQ==", "dev": true, "license": "MIT", @@ -1250,7 +1250,7 @@ }, "node_modules/@secretlint/config-loader/node_modules/ajv": { "version": "8.20.0", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.20.0.tgz", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", @@ -1267,14 +1267,14 @@ }, "node_modules/@secretlint/config-loader/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, "license": "MIT" }, "node_modules/@secretlint/core": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/core/-/core-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/core/-/core-10.2.2.tgz", "integrity": "sha512-6rdwBwLP9+TO3rRjMVW1tX+lQeo5gBbxl1I5F8nh8bgGtKwdlCMhMKsBWzWg1ostxx/tIG7OjZI0/BxsP8bUgw==", "dev": true, "license": "MIT", @@ -1290,7 +1290,7 @@ }, "node_modules/@secretlint/formatter": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/formatter/-/formatter-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/formatter/-/formatter-10.2.2.tgz", "integrity": "sha512-10f/eKV+8YdGKNQmoDUD1QnYL7TzhI2kzyx95vsJKbEa8akzLAR5ZrWIZ3LbcMmBLzxlSQMMccRmi05yDQ5YDA==", "dev": true, "license": "MIT", @@ -1313,7 +1313,7 @@ }, "node_modules/@secretlint/formatter/node_modules/chalk": { "version": "5.6.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", @@ -1326,7 +1326,7 @@ }, "node_modules/@secretlint/node": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/node/-/node-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/node/-/node-10.2.2.tgz", "integrity": "sha512-eZGJQgcg/3WRBwX1bRnss7RmHHK/YlP/l7zOQsrjexYt6l+JJa5YhUmHbuGXS94yW0++3YkEJp0kQGYhiw1DMQ==", "dev": true, "license": "MIT", @@ -1346,21 +1346,21 @@ }, "node_modules/@secretlint/profiler": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/profiler/-/profiler-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/profiler/-/profiler-10.2.2.tgz", "integrity": "sha512-qm9rWfkh/o8OvzMIfY8a5bCmgIniSpltbVlUVl983zDG1bUuQNd1/5lUEeWx5o/WJ99bXxS7yNI4/KIXfHexig==", "dev": true, "license": "MIT" }, "node_modules/@secretlint/resolver": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/resolver/-/resolver-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/resolver/-/resolver-10.2.2.tgz", "integrity": "sha512-3md0cp12e+Ae5V+crPQYGd6aaO7ahw95s28OlULGyclyyUtf861UoRGS2prnUrKh7MZb23kdDOyGCYb9br5e4w==", "dev": true, "license": "MIT" }, "node_modules/@secretlint/secretlint-formatter-sarif": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/secretlint-formatter-sarif/-/secretlint-formatter-sarif-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-formatter-sarif/-/secretlint-formatter-sarif-10.2.2.tgz", "integrity": "sha512-ojiF9TGRKJJw308DnYBucHxkpNovDNu1XvPh7IfUp0A12gzTtxuWDqdpuVezL7/IP8Ua7mp5/VkDMN9OLp1doQ==", "dev": true, "license": "MIT", @@ -1370,7 +1370,7 @@ }, "node_modules/@secretlint/secretlint-rule-no-dotenv": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/secretlint-rule-no-dotenv/-/secretlint-rule-no-dotenv-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-no-dotenv/-/secretlint-rule-no-dotenv-10.2.2.tgz", "integrity": "sha512-KJRbIShA9DVc5Va3yArtJ6QDzGjg3PRa1uYp9As4RsyKtKSSZjI64jVca57FZ8gbuk4em0/0Jq+uy6485wxIdg==", "dev": true, "license": "MIT", @@ -1383,7 +1383,7 @@ }, "node_modules/@secretlint/secretlint-rule-preset-recommend": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/secretlint-rule-preset-recommend/-/secretlint-rule-preset-recommend-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-preset-recommend/-/secretlint-rule-preset-recommend-10.2.2.tgz", "integrity": "sha512-K3jPqjva8bQndDKJqctnGfwuAxU2n9XNCPtbXVI5JvC7FnQiNg/yWlQPbMUlBXtBoBGFYp08A94m6fvtc9v+zA==", "dev": true, "license": "MIT", @@ -1393,7 +1393,7 @@ }, "node_modules/@secretlint/source-creator": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/source-creator/-/source-creator-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/source-creator/-/source-creator-10.2.2.tgz", "integrity": "sha512-h6I87xJfwfUTgQ7irWq7UTdq/Bm1RuQ/fYhA3dtTIAop5BwSFmZyrchph4WcoEvbN460BWKmk4RYSvPElIIvxw==", "dev": true, "license": "MIT", @@ -1407,7 +1407,7 @@ }, "node_modules/@secretlint/types": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/@secretlint/types/-/types-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/@secretlint/types/-/types-10.2.2.tgz", "integrity": "sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==", "dev": true, "license": "MIT", @@ -1417,7 +1417,7 @@ }, "node_modules/@sindresorhus/merge-streams": { "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", "dev": true, "license": "MIT", @@ -1430,14 +1430,14 @@ }, "node_modules/@textlint/ast-node-types": { "version": "15.7.1", - "resolved": "https://registry.npmmirror.com/@textlint/ast-node-types/-/ast-node-types-15.7.1.tgz", + "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-15.7.1.tgz", "integrity": "sha512-Wii5UgUKFEh9Uv6wbq1zr4/Kf+dtjiUuzPrrXzKp8H+ifkvKNzi23V4Nz+6wVyHQn5T28AFuc8VH8OtzvGYecA==", "dev": true, "license": "MIT" }, "node_modules/@textlint/linter-formatter": { "version": "15.7.1", - "resolved": "https://registry.npmmirror.com/@textlint/linter-formatter/-/linter-formatter-15.7.1.tgz", + "resolved": "https://registry.npmjs.org/@textlint/linter-formatter/-/linter-formatter-15.7.1.tgz", "integrity": "sha512-TdwZ/debWYFD05K3CcoHtwvnCrza29wZxD+BjDTk/V5N7iRqkK1dTTHSD4A8AIgROLiDkHJmIKQbasbmsg8AvA==", "dev": true, "license": "MIT", @@ -1460,7 +1460,7 @@ }, "node_modules/@textlint/linter-formatter/node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", @@ -1470,14 +1470,14 @@ }, "node_modules/@textlint/linter-formatter/node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, "node_modules/@textlint/linter-formatter/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", @@ -1487,14 +1487,14 @@ }, "node_modules/@textlint/linter-formatter/node_modules/pluralize": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/pluralize/-/pluralize-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-2.0.0.tgz", "integrity": "sha512-TqNZzQCD4S42De9IfnnBvILN7HAW7riLqsCyp8lgjXeysyPlX5HhqKAcJHHHb9XskE4/a+7VGC9zzx8Ls0jOAw==", "dev": true, "license": "MIT" }, "node_modules/@textlint/linter-formatter/node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", @@ -1509,7 +1509,7 @@ }, "node_modules/@textlint/linter-formatter/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", @@ -1522,21 +1522,21 @@ }, "node_modules/@textlint/module-interop": { "version": "15.7.1", - "resolved": "https://registry.npmmirror.com/@textlint/module-interop/-/module-interop-15.7.1.tgz", + "resolved": "https://registry.npmjs.org/@textlint/module-interop/-/module-interop-15.7.1.tgz", "integrity": "sha512-Jg+sQW2L/cRJypk59wtcMUVVpt8vmit5ZMT3gUnFwevP3A6Qp1HfOtUy9ObT4hBX3lOSGT/ekcCDxR1pL7uH1g==", "dev": true, "license": "MIT" }, "node_modules/@textlint/resolver": { "version": "15.7.1", - "resolved": "https://registry.npmmirror.com/@textlint/resolver/-/resolver-15.7.1.tgz", + "resolved": "https://registry.npmjs.org/@textlint/resolver/-/resolver-15.7.1.tgz", "integrity": "sha512-8XnO0pgF6mXnm41VvWmBbEIdGPhiCUt31uLZkOis1ECeg/1SoUcIT6Mx/F0e1rukq8l0UlOSeY9a31CsvRMK0g==", "dev": true, "license": "MIT" }, "node_modules/@textlint/types": { "version": "15.7.1", - "resolved": "https://registry.npmmirror.com/@textlint/types/-/types-15.7.1.tgz", + "resolved": "https://registry.npmjs.org/@textlint/types/-/types-15.7.1.tgz", "integrity": "sha512-Vye/GmFNBTgVzZFtIFJTmLB+s2A7oIADxNG6r9UhfPuY+Czv0z5G3xeyFZZudPlfxURsKUyPIU5XsjOFqVp33A==", "dev": true, "license": "MIT", @@ -1546,21 +1546,21 @@ }, "node_modules/@types/ejs": { "version": "3.1.5", - "resolved": "https://registry.npmmirror.com/@types/ejs/-/ejs-3.1.5.tgz", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==", "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.9", - "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, "node_modules/@types/gradient-string": { "version": "1.1.6", - "resolved": "https://registry.npmmirror.com/@types/gradient-string/-/gradient-string-1.1.6.tgz", + "resolved": "https://registry.npmjs.org/@types/gradient-string/-/gradient-string-1.1.6.tgz", "integrity": "sha512-LkaYxluY4G5wR1M4AKQUal2q61Di1yVVCw42ImFTuaIoQVgmV0WP1xUaLB8zwb47mp82vWTpePI9JmrjEnJ7nQ==", "license": "MIT", "dependencies": { @@ -1569,21 +1569,21 @@ }, "node_modules/@types/json-schema": { "version": "7.0.15", - "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, "license": "MIT" }, "node_modules/@types/linkify-it": { "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", "dev": true, "license": "MIT" }, "node_modules/@types/markdown-it": { "version": "14.1.2", - "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "dev": true, "license": "MIT", @@ -1594,14 +1594,14 @@ }, "node_modules/@types/mdurl": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@types/mdurl/-/mdurl-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { "version": "25.9.3", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-25.9.3.tgz", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.3.tgz", "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==", "dev": true, "license": "MIT", @@ -1611,14 +1611,14 @@ }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", - "resolved": "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true, "license": "MIT" }, "node_modules/@types/react": { "version": "19.2.17", - "resolved": "https://registry.npmmirror.com/@types/react/-/react-19.2.17.tgz", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "devOptional": true, "license": "MIT", @@ -1628,36 +1628,36 @@ }, "node_modules/@types/sarif": { "version": "2.1.7", - "resolved": "https://registry.npmmirror.com/@types/sarif/-/sarif-2.1.7.tgz", + "resolved": "https://registry.npmjs.org/@types/sarif/-/sarif-2.1.7.tgz", "integrity": "sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==", "dev": true, "license": "MIT" }, "node_modules/@types/tinycolor2": { "version": "1.4.6", - "resolved": "https://registry.npmmirror.com/@types/tinycolor2/-/tinycolor2-1.4.6.tgz", + "resolved": "https://registry.npmjs.org/@types/tinycolor2/-/tinycolor2-1.4.6.tgz", "integrity": "sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==", "license": "MIT" }, "node_modules/@types/vscode": { - "version": "1.120.0", - "resolved": "https://registry.npmmirror.com/@types/vscode/-/vscode-1.120.0.tgz", - "integrity": "sha512-feaT4Rst+FkTch5zz/ZbNCxoIvo55YU80Be2kiL7OJcod4+CUYf2lUBPdIJzozNnSEMq1VRTGrWEcCGFB3fBmA==", + "version": "1.125.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.125.0.tgz", + "integrity": "sha512-0icm/ZQAaism87P0ekHqi4/Ju9du+Tm0RUW+y7vqRsxY2cY0FNRX1nAnaW7nT6npPt2tfHiheZ55Zm9UhqonFA==", "dev": true, "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", - "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.1.tgz", + "integrity": "sha512-ZPlVl3PB3et/59Ne0fv/sci6ZXz4T4Hp4nTJ56i/Y0gR89ARb+KphojTq6j+56E5PIezmOIOOWyY+aWQFd+IkQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.61.0", - "@typescript-eslint/type-utils": "8.61.0", - "@typescript-eslint/utils": "8.61.0", - "@typescript-eslint/visitor-keys": "8.61.0", + "@typescript-eslint/scope-manager": "8.61.1", + "@typescript-eslint/type-utils": "8.61.1", + "@typescript-eslint/utils": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -1670,14 +1670,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.61.0", + "@typescript-eslint/parser": "^8.61.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { "version": "7.0.5", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", @@ -1686,16 +1686,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.61.0.tgz", - "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.1.tgz", + "integrity": "sha512-PJ5vePq5/ognBbrIcoC5+SHO5dfpeLPzP9FpLkzWrguoYQEeeSjlJpVwOpo1JRSTEi7dRcwNy4h4dzV70PqHcg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.61.0", - "@typescript-eslint/types": "8.61.0", - "@typescript-eslint/typescript-estree": "8.61.0", - "@typescript-eslint/visitor-keys": "8.61.0", + "@typescript-eslint/scope-manager": "8.61.1", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1", "debug": "^4.4.3" }, "engines": { @@ -1711,14 +1711,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", - "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.1.tgz", + "integrity": "sha512-PrC4JYGmR241lYnfhmKGTXkFqv8+ymbTFgSAY0fVXpY82/QkMw5TZPl+vGzuDDU2QYJk9fIDOBTntF+yDv9LEA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.61.0", - "@typescript-eslint/types": "^8.61.0", + "@typescript-eslint/tsconfig-utils": "^8.61.1", + "@typescript-eslint/types": "^8.61.1", "debug": "^4.4.3" }, "engines": { @@ -1733,14 +1733,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", - "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.1.tgz", + "integrity": "sha512-L2bdIeoQS8FlKAvONAr20w6OcLXeB+qiDKbAooS9A0Ben+iSIkBef0FxqwKWYqt5sa0i4KJtxVyVmhMylKzF5w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.61.0", - "@typescript-eslint/visitor-keys": "8.61.0" + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1751,9 +1751,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", - "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.1.tgz", + "integrity": "sha512-UN/H4di+OO7EWx2ovME+8t31YO+KVnK0RRKEHR3kOt21/Ay8BOq3M1OMvWs5vNiqcFCYGYoxK3MXPZzmMUE+yg==", "dev": true, "license": "MIT", "engines": { @@ -1768,15 +1768,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", - "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.1.tgz", + "integrity": "sha512-GYRicKmVK0C4fsKgaACaknOUAq9Oa2kwsjnpFhFcS/5p4Ht5IP9OVLbgIgcK4SRk92nVHFluurg1lumD9dBcLw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.61.0", - "@typescript-eslint/typescript-estree": "8.61.0", - "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1", + "@typescript-eslint/utils": "8.61.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -1793,9 +1793,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.61.0.tgz", - "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.1.tgz", + "integrity": "sha512-G+CRlPqLv7Bz1IZVs03x5K59F1veqL0EJUROAdGhKsEq8qOiRiZbI+HUojPq5l0fEGOKModD9br6lObhB8zkoA==", "dev": true, "license": "MIT", "engines": { @@ -1807,16 +1807,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", - "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.1.tgz", + "integrity": "sha512-u+oQD3BqYWPc8YV9Zab4vaJElJuwOLPRc10Jm1o/qS+6Qwen14HCWwx0Seo4LnSn2wxea2Ik8DxPt2/FHmuhrg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.61.0", - "@typescript-eslint/tsconfig-utils": "8.61.0", - "@typescript-eslint/types": "8.61.0", - "@typescript-eslint/visitor-keys": "8.61.0", + "@typescript-eslint/project-service": "8.61.1", + "@typescript-eslint/tsconfig-utils": "8.61.1", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -1836,7 +1836,7 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", @@ -1846,7 +1846,7 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "version": "5.0.6", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.6.tgz", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", @@ -1859,7 +1859,7 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "10.2.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.5.tgz", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", @@ -1875,7 +1875,7 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { "version": "7.8.4", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", @@ -1887,16 +1887,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.61.0.tgz", - "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.1.tgz", + "integrity": "sha512-1+P/3Dj6jvtybE1q0HQ6yBt/gq+oKJyLdEv4HdnqasaEXRSYCAsD59mXEVQnM/ULNdQxbX77tdG4jPRjIS6knA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.61.0", - "@typescript-eslint/types": "8.61.0", - "@typescript-eslint/typescript-estree": "8.61.0" + "@typescript-eslint/scope-manager": "8.61.1", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1911,13 +1911,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", - "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.1.tgz", + "integrity": "sha512-6fJ9MHWtK14C1DSkiMlHUSOmrVebL7150xZJBlJiL62jjhIA4JmOq6flwBgDxIdBKKdoiZRel+dfPD5MLfny3w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/types": "8.61.1", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -1930,7 +1930,7 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", @@ -1943,7 +1943,7 @@ }, "node_modules/@typespec/ts-http-runtime": { "version": "0.3.6", - "resolved": "https://registry.npmmirror.com/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.6.tgz", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.6.tgz", "integrity": "sha512-jIXhD0eWQ1JA6ln/5Dltyx22UxWNrw0hZmhy2rlv6m6KgF7kplHx3g0fzi09lNmTJQRR91OlemYp3xFnvDK9og==", "dev": true, "license": "MIT", @@ -1966,7 +1966,7 @@ }, "node_modules/@vscode/vsce": { "version": "3.9.2", - "resolved": "https://registry.npmmirror.com/@vscode/vsce/-/vsce-3.9.2.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.9.2.tgz", "integrity": "sha512-XSxMosEEDO6vLxELAHVkwmhC0qe0ijZni2jB9Rcs8kQsW4lhTDQ/wMzmwFs/buotAWSnpmUp/dRWD2ufG3UYKA==", "dev": true, "license": "MIT", @@ -2013,7 +2013,7 @@ }, "node_modules/@vscode/vsce-sign": { "version": "2.0.9", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign/-/vsce-sign-2.0.9.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.0.9.tgz", "integrity": "sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g==", "dev": true, "hasInstallScript": true, @@ -2032,7 +2032,7 @@ }, "node_modules/@vscode/vsce-sign-alpine-arm64": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz", "integrity": "sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==", "cpu": [ "arm64" @@ -2046,7 +2046,7 @@ }, "node_modules/@vscode/vsce-sign-alpine-x64": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz", "integrity": "sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w==", "cpu": [ "x64" @@ -2060,7 +2060,7 @@ }, "node_modules/@vscode/vsce-sign-darwin-arm64": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz", "integrity": "sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==", "cpu": [ "arm64" @@ -2074,7 +2074,7 @@ }, "node_modules/@vscode/vsce-sign-darwin-x64": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz", "integrity": "sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==", "cpu": [ "x64" @@ -2088,7 +2088,7 @@ }, "node_modules/@vscode/vsce-sign-linux-arm": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz", "integrity": "sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA==", "cpu": [ "arm" @@ -2102,7 +2102,7 @@ }, "node_modules/@vscode/vsce-sign-linux-arm64": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz", "integrity": "sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA==", "cpu": [ "arm64" @@ -2116,7 +2116,7 @@ }, "node_modules/@vscode/vsce-sign-linux-x64": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz", "integrity": "sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==", "cpu": [ "x64" @@ -2130,7 +2130,7 @@ }, "node_modules/@vscode/vsce-sign-win32-arm64": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz", "integrity": "sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg==", "cpu": [ "arm64" @@ -2144,7 +2144,7 @@ }, "node_modules/@vscode/vsce-sign-win32-x64": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz", "integrity": "sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ==", "cpu": [ "x64" @@ -2158,7 +2158,7 @@ }, "node_modules/@vscode/vsce/node_modules/balanced-match": { "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", @@ -2168,7 +2168,7 @@ }, "node_modules/@vscode/vsce/node_modules/brace-expansion": { "version": "5.0.6", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.6.tgz", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", @@ -2181,7 +2181,7 @@ }, "node_modules/@vscode/vsce/node_modules/minimatch": { "version": "10.2.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.5.tgz", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", @@ -2197,7 +2197,7 @@ }, "node_modules/@vscode/vsce/node_modules/semver": { "version": "7.8.4", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", @@ -2210,7 +2210,7 @@ }, "node_modules/acorn": { "version": "8.17.0", - "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.17.0.tgz", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "dev": true, "license": "MIT", @@ -2223,7 +2223,7 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", - "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", @@ -2233,7 +2233,7 @@ }, "node_modules/agent-base": { "version": "7.1.4", - "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-7.1.4.tgz", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", @@ -2243,7 +2243,7 @@ }, "node_modules/ajv": { "version": "6.15.0", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.15.0.tgz", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", @@ -2260,7 +2260,7 @@ }, "node_modules/ansi-escapes": { "version": "7.3.0", - "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", "license": "MIT", "dependencies": { @@ -2275,7 +2275,7 @@ }, "node_modules/ansi-regex": { "version": "6.2.2", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "engines": { @@ -2287,7 +2287,7 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", @@ -2303,13 +2303,13 @@ }, "node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, "node_modules/astral-regex": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, "license": "MIT", @@ -2319,14 +2319,14 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true, "license": "MIT" }, "node_modules/auto-bind": { "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/auto-bind/-/auto-bind-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-5.0.1.tgz", "integrity": "sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg==", "license": "MIT", "engines": { @@ -2338,7 +2338,7 @@ }, "node_modules/azure-devops-node-api": { "version": "12.5.0", - "resolved": "https://registry.npmmirror.com/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", + "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==", "dev": true, "license": "MIT", @@ -2349,14 +2349,14 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", - "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, "funding": [ @@ -2377,9 +2377,9 @@ "optional": true }, "node_modules/baseline-browser-mapping": { - "version": "2.10.37", - "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.37.tgz", - "integrity": "sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==", + "version": "2.10.38", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", + "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2391,7 +2391,7 @@ }, "node_modules/binaryextensions": { "version": "6.11.0", - "resolved": "https://registry.npmmirror.com/binaryextensions/-/binaryextensions-6.11.0.tgz", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", "dev": true, "license": "Artistic-2.0", @@ -2407,7 +2407,7 @@ }, "node_modules/bl": { "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, "license": "MIT", @@ -2420,21 +2420,21 @@ }, "node_modules/boolbase": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true, "license": "ISC" }, "node_modules/boundary": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/boundary/-/boundary-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/boundary/-/boundary-2.0.0.tgz", "integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==", "dev": true, "license": "BSD-2-Clause" }, "node_modules/brace-expansion": { "version": "1.1.15", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.15.tgz", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", "dev": true, "license": "MIT", @@ -2445,7 +2445,7 @@ }, "node_modules/braces": { "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", @@ -2458,7 +2458,7 @@ }, "node_modules/browserslist": { "version": "4.28.2", - "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.2.tgz", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", "dev": true, "funding": [ @@ -2492,7 +2492,7 @@ }, "node_modules/buffer": { "version": "5.7.1", - "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "funding": [ @@ -2518,7 +2518,7 @@ }, "node_modules/buffer-crc32": { "version": "0.2.13", - "resolved": "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, "license": "MIT", @@ -2528,14 +2528,14 @@ }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/bundle-name": { "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/bundle-name/-/bundle-name-4.1.0.tgz", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, "license": "MIT", @@ -2551,7 +2551,7 @@ }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", @@ -2565,7 +2565,7 @@ }, "node_modules/call-bound": { "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", @@ -2582,7 +2582,7 @@ }, "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", @@ -2592,7 +2592,7 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001799", - "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", "dev": true, "funding": [ @@ -2613,7 +2613,7 @@ }, "node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", @@ -2630,7 +2630,7 @@ }, "node_modules/cheerio": { "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/cheerio/-/cheerio-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", "dev": true, "license": "MIT", @@ -2656,7 +2656,7 @@ }, "node_modules/cheerio-select": { "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/cheerio-select/-/cheerio-select-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", "dev": true, "license": "BSD-2-Clause", @@ -2674,7 +2674,7 @@ }, "node_modules/chownr": { "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/chownr/-/chownr-1.1.4.tgz", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true, "license": "ISC", @@ -2682,7 +2682,7 @@ }, "node_modules/cli-boxes": { "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/cli-boxes/-/cli-boxes-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-4.0.1.tgz", "integrity": "sha512-5IOn+jcCEHEraYolBPs/sT4BxYCe2nHg374OPiItB1O96KZFseS2gthU4twyYzeDcFew4DaUM/xwc5BQf08JJw==", "license": "MIT", "engines": { @@ -2693,33 +2693,31 @@ } }, "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "license": "MIT", "dependencies": { - "restore-cursor": "^5.0.0" + "restore-cursor": "^4.0.0" }, "engines": { - "node": ">=18" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cli-truncate": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-5.2.0.tgz", - "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-6.0.0.tgz", + "integrity": "sha512-3+YKIUFsohD9MIoOFPFBldjAlnfCmCDcqe6aYGFqlDTRKg80p4wg35L+j83QQ63iOlKRccEkbn8IuM++HsgEjA==", "license": "MIT", "dependencies": { - "slice-ansi": "^8.0.0", + "slice-ansi": "^9.0.0", "string-width": "^8.2.0" }, "engines": { - "node": ">=20" + "node": ">=22" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2727,7 +2725,7 @@ }, "node_modules/cockatiel": { "version": "3.2.1", - "resolved": "https://registry.npmmirror.com/cockatiel/-/cockatiel-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", "dev": true, "license": "MIT", @@ -2737,7 +2735,7 @@ }, "node_modules/code-excerpt": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/code-excerpt/-/code-excerpt-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", "license": "MIT", "dependencies": { @@ -2749,7 +2747,7 @@ }, "node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", @@ -2762,14 +2760,14 @@ }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "license": "MIT", @@ -2782,7 +2780,7 @@ }, "node_modules/commander": { "version": "12.1.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-12.1.0.tgz", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "license": "MIT", @@ -2792,21 +2790,21 @@ }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, "node_modules/convert-source-map": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/convert-to-spaces": { "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", "license": "MIT", "engines": { @@ -2815,7 +2813,7 @@ }, "node_modules/cross-spawn": { "version": "7.0.6", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", @@ -2830,7 +2828,7 @@ }, "node_modules/css-select": { "version": "5.2.2", - "resolved": "https://registry.npmmirror.com/css-select/-/css-select-5.2.2.tgz", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", "dev": true, "license": "BSD-2-Clause", @@ -2847,7 +2845,7 @@ }, "node_modules/css-what": { "version": "6.2.2", - "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.2.2.tgz", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", "dev": true, "license": "BSD-2-Clause", @@ -2860,14 +2858,14 @@ }, "node_modules/csstype": { "version": "3.2.3", - "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "devOptional": true, "license": "MIT" }, "node_modules/debug": { "version": "4.4.3", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", @@ -2885,7 +2883,7 @@ }, "node_modules/decompress-response": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, "license": "MIT", @@ -2902,7 +2900,7 @@ }, "node_modules/deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmmirror.com/deep-extend/-/deep-extend-0.6.0.tgz", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "license": "MIT", @@ -2913,7 +2911,7 @@ }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" @@ -2924,7 +2922,7 @@ }, "node_modules/default-browser": { "version": "5.5.0", - "resolved": "https://registry.npmmirror.com/default-browser/-/default-browser-5.5.0.tgz", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", "dev": true, "license": "MIT", @@ -2941,7 +2939,7 @@ }, "node_modules/default-browser-id": { "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/default-browser-id/-/default-browser-id-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", "dev": true, "license": "MIT", @@ -2954,7 +2952,7 @@ }, "node_modules/define-lazy-prop": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "license": "MIT", @@ -2967,7 +2965,7 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, "license": "MIT", @@ -2977,7 +2975,7 @@ }, "node_modules/detect-libc": { "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", @@ -2988,7 +2986,7 @@ }, "node_modules/dom-serializer": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "license": "MIT", @@ -3003,7 +3001,7 @@ }, "node_modules/domelementtype": { "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true, "funding": [ @@ -3016,7 +3014,7 @@ }, "node_modules/domhandler": { "version": "5.0.3", - "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, "license": "BSD-2-Clause", @@ -3032,7 +3030,7 @@ }, "node_modules/domutils": { "version": "3.2.2", - "resolved": "https://registry.npmmirror.com/domutils/-/domutils-3.2.2.tgz", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, "license": "BSD-2-Clause", @@ -3047,7 +3045,7 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, "license": "MIT", @@ -3062,7 +3060,7 @@ }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "dev": true, "license": "Apache-2.0", @@ -3072,7 +3070,7 @@ }, "node_modules/editions": { "version": "6.22.0", - "resolved": "https://registry.npmmirror.com/editions/-/editions-6.22.0.tgz", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", "dev": true, "license": "Artistic-2.0", @@ -3089,7 +3087,7 @@ }, "node_modules/ejs": { "version": "5.0.2", - "resolved": "https://registry.npmmirror.com/ejs/-/ejs-5.0.2.tgz", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-5.0.2.tgz", "integrity": "sha512-IpbUaI/CAW86l3f+T8zN0iggSc0LmMZLcIW5eRVStLVNCoTXkE0YlncbbH50fp8Cl6zHIky0sW2uUbhBqGw0Jw==", "license": "Apache-2.0", "bin": { @@ -3100,22 +3098,22 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.372", - "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.372.tgz", - "integrity": "sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==", + "version": "1.5.375", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.375.tgz", + "integrity": "sha512-ZWP5eB4BVPW/ZYo9252hQZHZ5XavtsTgpbhcmMmRwymavC5AsLWQWBPaKMeNd2LW0KGby5HPXvj7+sr4ta5j/Q==", "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { "version": "10.6.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.6.0.tgz", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, "license": "MIT" }, "node_modules/encoding-sniffer": { "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", "dev": true, "license": "MIT", @@ -3129,7 +3127,7 @@ }, "node_modules/end-of-stream": { "version": "1.4.5", - "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "dev": true, "license": "MIT", @@ -3140,7 +3138,7 @@ }, "node_modules/entities": { "version": "4.5.0", - "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "license": "BSD-2-Clause", "engines": { @@ -3152,7 +3150,7 @@ }, "node_modules/environment": { "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/environment/-/environment-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "license": "MIT", "engines": { @@ -3164,7 +3162,7 @@ }, "node_modules/es-define-property": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", @@ -3174,7 +3172,7 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, "license": "MIT", @@ -3184,7 +3182,7 @@ }, "node_modules/es-object-atoms": { "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "dev": true, "license": "MIT", @@ -3197,7 +3195,7 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "license": "MIT", @@ -3213,7 +3211,7 @@ }, "node_modules/es-toolkit": { "version": "1.47.1", - "resolved": "https://registry.npmmirror.com/es-toolkit/-/es-toolkit-1.47.1.tgz", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.47.1.tgz", "integrity": "sha512-5RAqEwf4P4E17p+W75KLOWw/nOvKZzSQpxM32IpI2KZLaVonjTrZ0Ai5ghMaVI9eKC2p8eoQgcBdkEDgzFk6+Q==", "license": "MIT", "workspaces": [ @@ -3223,7 +3221,7 @@ }, "node_modules/esbuild": { "version": "0.28.1", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.1.tgz", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, "hasInstallScript": true, @@ -3265,7 +3263,7 @@ }, "node_modules/escalade": { "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", @@ -3275,7 +3273,7 @@ }, "node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", @@ -3288,7 +3286,7 @@ }, "node_modules/eslint": { "version": "9.39.4", - "resolved": "https://registry.npmmirror.com/eslint/-/eslint-9.39.4.tgz", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", @@ -3348,7 +3346,7 @@ }, "node_modules/eslint-config-prettier": { "version": "10.1.8", - "resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", @@ -3364,7 +3362,7 @@ }, "node_modules/eslint-plugin-react-hooks": { "version": "7.1.1", - "resolved": "https://registry.npmmirror.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", "dev": true, "license": "MIT", @@ -3384,7 +3382,7 @@ }, "node_modules/eslint-scope": { "version": "8.4.0", - "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-8.4.0.tgz", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", @@ -3401,7 +3399,7 @@ }, "node_modules/eslint-visitor-keys": { "version": "4.2.1", - "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", @@ -3414,7 +3412,7 @@ }, "node_modules/espree": { "version": "10.4.0", - "resolved": "https://registry.npmmirror.com/espree/-/espree-10.4.0.tgz", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", @@ -3432,7 +3430,7 @@ }, "node_modules/esprima": { "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "license": "BSD-2-Clause", "bin": { @@ -3445,7 +3443,7 @@ }, "node_modules/esquery": { "version": "1.7.0", - "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.7.0.tgz", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", @@ -3458,7 +3456,7 @@ }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", @@ -3471,7 +3469,7 @@ }, "node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", @@ -3481,7 +3479,7 @@ }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", @@ -3491,14 +3489,14 @@ }, "node_modules/eventemitter3": { "version": "5.0.4", - "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.4.tgz", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", "dev": true, "license": "MIT" }, "node_modules/expand-template": { "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/expand-template/-/expand-template-2.0.3.tgz", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "dev": true, "license": "(MIT OR WTFPL)", @@ -3509,7 +3507,7 @@ }, "node_modules/extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "license": "MIT", "dependencies": { @@ -3521,14 +3519,14 @@ }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", @@ -3545,7 +3543,7 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", @@ -3558,21 +3556,21 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT" }, "node_modules/fast-uri": { "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.2.tgz", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "dev": true, "funding": [ @@ -3589,7 +3587,7 @@ }, "node_modules/fastq": { "version": "1.20.1", - "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.20.1.tgz", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, "license": "ISC", @@ -3599,7 +3597,7 @@ }, "node_modules/fdir": { "version": "6.5.0", - "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", @@ -3617,7 +3615,7 @@ }, "node_modules/file-entry-cache": { "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", @@ -3630,7 +3628,7 @@ }, "node_modules/fill-range": { "version": "7.1.1", - "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", @@ -3643,7 +3641,7 @@ }, "node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", @@ -3660,7 +3658,7 @@ }, "node_modules/flat-cache": { "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", @@ -3674,14 +3672,14 @@ }, "node_modules/flatted": { "version": "3.4.2", - "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.4.2.tgz", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, "node_modules/form-data": { "version": "4.0.6", - "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.6.tgz", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "dev": true, "license": "MIT", @@ -3698,7 +3696,7 @@ }, "node_modules/fs-constants": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true, "license": "MIT", @@ -3706,7 +3704,7 @@ }, "node_modules/fs-extra": { "version": "11.3.5", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.5.tgz", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", "dev": true, "license": "MIT", @@ -3721,7 +3719,7 @@ }, "node_modules/fsevents": { "version": "2.3.3", - "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, @@ -3736,7 +3734,7 @@ }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, "license": "MIT", @@ -3746,7 +3744,7 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", @@ -3756,7 +3754,7 @@ }, "node_modules/get-east-asian-width": { "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", "license": "MIT", "engines": { @@ -3768,7 +3766,7 @@ }, "node_modules/get-intrinsic": { "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", @@ -3793,7 +3791,7 @@ }, "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, "license": "MIT", @@ -3807,7 +3805,7 @@ }, "node_modules/github-from-package": { "version": "0.0.0", - "resolved": "https://registry.npmmirror.com/github-from-package/-/github-from-package-0.0.0.tgz", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "dev": true, "license": "MIT", @@ -3815,7 +3813,7 @@ }, "node_modules/glob": { "version": "13.0.6", - "resolved": "https://registry.npmmirror.com/glob/-/glob-13.0.6.tgz", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", "dev": true, "license": "BlueOak-1.0.0", @@ -3833,7 +3831,7 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", @@ -3846,7 +3844,7 @@ }, "node_modules/glob/node_modules/balanced-match": { "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", @@ -3856,7 +3854,7 @@ }, "node_modules/glob/node_modules/brace-expansion": { "version": "5.0.6", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.6.tgz", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", @@ -3869,7 +3867,7 @@ }, "node_modules/glob/node_modules/minimatch": { "version": "10.2.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-10.2.5.tgz", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", @@ -3885,7 +3883,7 @@ }, "node_modules/globals": { "version": "14.0.0", - "resolved": "https://registry.npmmirror.com/globals/-/globals-14.0.0.tgz", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", @@ -3898,7 +3896,7 @@ }, "node_modules/globby": { "version": "14.1.0", - "resolved": "https://registry.npmmirror.com/globby/-/globby-14.1.0.tgz", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", "dev": true, "license": "MIT", @@ -3919,7 +3917,7 @@ }, "node_modules/globby/node_modules/ignore": { "version": "7.0.5", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", @@ -3929,7 +3927,7 @@ }, "node_modules/gopd": { "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", @@ -3942,14 +3940,14 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", - "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, "license": "ISC" }, "node_modules/gradient-string": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/gradient-string/-/gradient-string-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/gradient-string/-/gradient-string-3.0.0.tgz", "integrity": "sha512-frdKI4Qi8Ihp4C6wZNB565de/THpIaw3DjP5ku87M+N9rNSGmPTjfkq61SdRXB7eCaL8O1hkKDvf6CDMtOzIAg==", "license": "MIT", "dependencies": { @@ -3962,7 +3960,7 @@ }, "node_modules/gradient-string/node_modules/chalk": { "version": "5.6.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "license": "MIT", "engines": { @@ -3974,7 +3972,7 @@ }, "node_modules/gray-matter": { "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/gray-matter/-/gray-matter-4.0.3.tgz", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", "license": "MIT", "dependencies": { @@ -3989,7 +3987,7 @@ }, "node_modules/gray-matter/node_modules/argparse": { "version": "1.0.10", - "resolved": "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "license": "MIT", "dependencies": { @@ -3998,7 +3996,7 @@ }, "node_modules/gray-matter/node_modules/js-yaml": { "version": "3.14.2", - "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-3.14.2.tgz", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "license": "MIT", "dependencies": { @@ -4011,7 +4009,7 @@ }, "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", @@ -4021,7 +4019,7 @@ }, "node_modules/has-symbols": { "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", @@ -4034,7 +4032,7 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "license": "MIT", @@ -4050,7 +4048,7 @@ }, "node_modules/hasown": { "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.4.tgz", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "dev": true, "license": "MIT", @@ -4063,14 +4061,14 @@ }, "node_modules/hermes-estree": { "version": "0.25.1", - "resolved": "https://registry.npmmirror.com/hermes-estree/-/hermes-estree-0.25.1.tgz", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", "dev": true, "license": "MIT" }, "node_modules/hermes-parser": { "version": "0.25.1", - "resolved": "https://registry.npmmirror.com/hermes-parser/-/hermes-parser-0.25.1.tgz", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", "dev": true, "license": "MIT", @@ -4080,7 +4078,7 @@ }, "node_modules/hosted-git-info": { "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, "license": "ISC", @@ -4093,7 +4091,7 @@ }, "node_modules/hosted-git-info/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "license": "ISC", @@ -4106,14 +4104,14 @@ }, "node_modules/hosted-git-info/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, "node_modules/htmlparser2": { "version": "10.1.0", - "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-10.1.0.tgz", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", "dev": true, "funding": [ @@ -4133,7 +4131,7 @@ }, "node_modules/htmlparser2/node_modules/entities": { "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", "dev": true, "license": "BSD-2-Clause", @@ -4146,7 +4144,7 @@ }, "node_modules/http-proxy-agent": { "version": "7.0.2", - "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "license": "MIT", @@ -4160,7 +4158,7 @@ }, "node_modules/https-proxy-agent": { "version": "7.0.6", - "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", @@ -4174,7 +4172,7 @@ }, "node_modules/husky": { "version": "9.1.7", - "resolved": "https://registry.npmmirror.com/husky/-/husky-9.1.7.tgz", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "license": "MIT", @@ -4190,7 +4188,7 @@ }, "node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", @@ -4203,7 +4201,7 @@ }, "node_modules/ieee754": { "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, "funding": [ @@ -4225,7 +4223,7 @@ }, "node_modules/ignore": { "version": "5.3.2", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", @@ -4235,7 +4233,7 @@ }, "node_modules/import-fresh": { "version": "3.3.1", - "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", @@ -4252,7 +4250,7 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", @@ -4262,7 +4260,7 @@ }, "node_modules/indent-string": { "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "license": "MIT", "engines": { @@ -4274,7 +4272,7 @@ }, "node_modules/index-to-position": { "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/index-to-position/-/index-to-position-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", "dev": true, "license": "MIT", @@ -4287,7 +4285,7 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "license": "ISC", @@ -4295,16 +4293,16 @@ }, "node_modules/ini": { "version": "1.3.8", - "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, "license": "ISC", "optional": true }, "node_modules/ink": { - "version": "7.0.6", - "resolved": "https://registry.npmmirror.com/ink/-/ink-7.0.6.tgz", - "integrity": "sha512-/KG651f+LHln9gumb5ltieFqzNGJdhX1b/WwsCUd2Py7Htuk9KUzyFrk25ugmzjXyDneXSoXD3cm4ql4dWFGsQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/ink/-/ink-7.1.0.tgz", + "integrity": "sha512-VWE6/yeLtFCJBNLflyI2OSylyXK1Rc24LuXup8Qt+icwkmmycFNdbn8IkSp6Frc0h1iA0NOvvi1ajW44U/w3Qg==", "license": "MIT", "dependencies": { "@alcalzone/ansi-tokenize": "^0.3.0", @@ -4352,7 +4350,7 @@ }, "node_modules/ink-gradient": { "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/ink-gradient/-/ink-gradient-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/ink-gradient/-/ink-gradient-4.0.1.tgz", "integrity": "sha512-0ckdiM84zkfCdnTtcnq4BS3egIhUPPDoCqSx/7NUFsAVooBbdRuGnnWpk0fuaOTqU6rlZRh9F4LN1UI8fxd81Q==", "license": "MIT", "dependencies": { @@ -4373,7 +4371,7 @@ }, "node_modules/ink/node_modules/ansi-styles": { "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", "engines": { @@ -4385,7 +4383,7 @@ }, "node_modules/ink/node_modules/chalk": { "version": "5.6.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "license": "MIT", "engines": { @@ -4395,93 +4393,9 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ink/node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "license": "MIT", - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ink/node_modules/cli-truncate": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-6.0.0.tgz", - "integrity": "sha512-3+YKIUFsohD9MIoOFPFBldjAlnfCmCDcqe6aYGFqlDTRKg80p4wg35L+j83QQ63iOlKRccEkbn8IuM++HsgEjA==", - "license": "MIT", - "dependencies": { - "slice-ansi": "^9.0.0", - "string-width": "^8.2.0" - }, - "engines": { - "node": ">=22" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ink/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ink/node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ink/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, - "node_modules/ink/node_modules/slice-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-9.0.0.tgz", - "integrity": "sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.3", - "is-fullwidth-code-point": "^5.1.0" - }, - "engines": { - "node": ">=22" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/is-docker": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, "license": "MIT", @@ -4497,7 +4411,7 @@ }, "node_modules/is-extendable": { "version": "0.1.1", - "resolved": "https://registry.npmmirror.com/is-extendable/-/is-extendable-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", "license": "MIT", "engines": { @@ -4506,7 +4420,7 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", @@ -4516,7 +4430,7 @@ }, "node_modules/is-fullwidth-code-point": { "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", "license": "MIT", "dependencies": { @@ -4531,7 +4445,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", @@ -4544,7 +4458,7 @@ }, "node_modules/is-in-ci": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/is-in-ci/-/is-in-ci-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-2.0.0.tgz", "integrity": "sha512-cFeerHriAnhrQSbpAxL37W1wcJKUUX07HyLWZCW1URJT/ra3GyUTzBgUnh24TMVfNTV2Hij2HLxkPHFZfOZy5w==", "license": "MIT", "bin": { @@ -4559,7 +4473,7 @@ }, "node_modules/is-inside-container": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/is-inside-container/-/is-inside-container-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, "license": "MIT", @@ -4578,7 +4492,7 @@ }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", @@ -4588,7 +4502,7 @@ }, "node_modules/is-wsl": { "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-3.1.1.tgz", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", "dev": true, "license": "MIT", @@ -4604,14 +4518,14 @@ }, "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, "node_modules/istextorbinary": { "version": "9.5.0", - "resolved": "https://registry.npmmirror.com/istextorbinary/-/istextorbinary-9.5.0.tgz", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", "dev": true, "license": "Artistic-2.0", @@ -4629,14 +4543,14 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, "license": "MIT" }, "node_modules/js-yaml": { "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.2.0.tgz", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, "funding": [ @@ -4659,7 +4573,7 @@ }, "node_modules/jsesc": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", @@ -4672,28 +4586,28 @@ }, "node_modules/json-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", @@ -4706,14 +4620,14 @@ }, "node_modules/jsonc-parser": { "version": "3.3.1", - "resolved": "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", "dev": true, "license": "MIT" }, "node_modules/jsonfile": { "version": "6.2.1", - "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.2.1.tgz", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", "dev": true, "license": "MIT", @@ -4726,7 +4640,7 @@ }, "node_modules/jsonwebtoken": { "version": "9.0.3", - "resolved": "https://registry.npmmirror.com/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", "dev": true, "license": "MIT", @@ -4749,7 +4663,7 @@ }, "node_modules/jsonwebtoken/node_modules/semver": { "version": "7.8.4", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", @@ -4762,7 +4676,7 @@ }, "node_modules/jwa": { "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/jwa/-/jwa-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "dev": true, "license": "MIT", @@ -4774,7 +4688,7 @@ }, "node_modules/jws": { "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/jws/-/jws-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", "dev": true, "license": "MIT", @@ -4785,7 +4699,7 @@ }, "node_modules/keytar": { "version": "7.9.0", - "resolved": "https://registry.npmmirror.com/keytar/-/keytar-7.9.0.tgz", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", "dev": true, "hasInstallScript": true, @@ -4798,7 +4712,7 @@ }, "node_modules/keyv": { "version": "4.5.4", - "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", @@ -4808,7 +4722,7 @@ }, "node_modules/kind-of": { "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "license": "MIT", "engines": { @@ -4817,7 +4731,7 @@ }, "node_modules/leven": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, "license": "MIT", @@ -4827,7 +4741,7 @@ }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", @@ -4841,7 +4755,7 @@ }, "node_modules/linkify-it": { "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", "funding": [ { @@ -4860,7 +4774,7 @@ }, "node_modules/lint-staged": { "version": "17.0.7", - "resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-17.0.7.tgz", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-17.0.7.tgz", "integrity": "sha512-JrSobt+tW3rH8IOMi8tDZd3foorM5yPEkLD/V2NxobgHrFfHWGee4MOLVuZeScgxftEwbHrPHIFA/ZL+nUJeuA==", "dev": true, "license": "MIT", @@ -4885,7 +4799,7 @@ }, "node_modules/listr2": { "version": "10.2.1", - "resolved": "https://registry.npmmirror.com/listr2/-/listr2-10.2.1.tgz", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-10.2.1.tgz", "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", "dev": true, "license": "MIT", @@ -4900,9 +4814,56 @@ "node": ">=22.13.0" } }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/cli-truncate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, "node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", @@ -4918,77 +4879,77 @@ }, "node_modules/lodash": { "version": "4.18.1", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, "license": "MIT" }, "node_modules/lodash.includes": { "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", "dev": true, "license": "MIT" }, "node_modules/lodash.isboolean": { "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", "dev": true, "license": "MIT" }, "node_modules/lodash.isinteger": { "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", "dev": true, "license": "MIT" }, "node_modules/lodash.isnumber": { "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", "dev": true, "license": "MIT" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", - "resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "dev": true, "license": "MIT" }, "node_modules/lodash.isstring": { "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "dev": true, "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, "license": "MIT" }, "node_modules/lodash.once": { "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/lodash.once/-/lodash.once-4.1.1.tgz", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "dev": true, "license": "MIT" }, "node_modules/lodash.truncate": { "version": "4.4.2", - "resolved": "https://registry.npmmirror.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true, "license": "MIT" }, "node_modules/log-update": { "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/log-update/-/log-update-6.1.0.tgz", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "license": "MIT", @@ -5008,7 +4969,7 @@ }, "node_modules/log-update/node_modules/ansi-styles": { "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", @@ -5019,9 +4980,71 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/log-update/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/log-update/node_modules/slice-ansi": { "version": "7.1.2", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-7.1.2.tgz", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", "dev": true, "license": "MIT", @@ -5038,7 +5061,7 @@ }, "node_modules/log-update/node_modules/string-width": { "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-7.2.0.tgz", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", @@ -5056,7 +5079,7 @@ }, "node_modules/log-update/node_modules/wrap-ansi": { "version": "9.0.2", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dev": true, "license": "MIT", @@ -5074,7 +5097,7 @@ }, "node_modules/lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "license": "ISC", @@ -5084,7 +5107,7 @@ }, "node_modules/markdown-it": { "version": "14.2.0", - "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-14.2.0.tgz", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", "funding": [ { @@ -5111,7 +5134,7 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, "license": "MIT", @@ -5121,13 +5144,13 @@ }, "node_modules/mdurl": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", @@ -5137,7 +5160,7 @@ }, "node_modules/micromatch": { "version": "4.0.8", - "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", @@ -5151,7 +5174,7 @@ }, "node_modules/micromatch/node_modules/picomatch": { "version": "2.3.2", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.2.tgz", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", @@ -5164,7 +5187,7 @@ }, "node_modules/mime": { "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, "license": "MIT", @@ -5177,7 +5200,7 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", @@ -5187,7 +5210,7 @@ }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", @@ -5200,7 +5223,7 @@ }, "node_modules/mimic-fn": { "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "license": "MIT", "engines": { @@ -5209,7 +5232,7 @@ }, "node_modules/mimic-function": { "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/mimic-function/-/mimic-function-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, "license": "MIT", @@ -5222,7 +5245,7 @@ }, "node_modules/mimic-response": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, "license": "MIT", @@ -5236,7 +5259,7 @@ }, "node_modules/minimatch": { "version": "3.1.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", @@ -5249,7 +5272,7 @@ }, "node_modules/minimist": { "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "license": "MIT", @@ -5260,7 +5283,7 @@ }, "node_modules/minipass": { "version": "7.1.3", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.3.tgz", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, "license": "BlueOak-1.0.0", @@ -5270,7 +5293,7 @@ }, "node_modules/mkdirp-classic": { "version": "0.5.3", - "resolved": "https://registry.npmmirror.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "dev": true, "license": "MIT", @@ -5278,36 +5301,36 @@ }, "node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/mute-stream": { "version": "0.0.8", - "resolved": "https://registry.npmmirror.com/mute-stream/-/mute-stream-0.0.8.tgz", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true, "license": "ISC" }, "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", "dev": true, "license": "MIT", "optional": true }, "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, "node_modules/node-abi": { "version": "3.92.0", - "resolved": "https://registry.npmmirror.com/node-abi/-/node-abi-3.92.0.tgz", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", "dev": true, "license": "MIT", @@ -5321,7 +5344,7 @@ }, "node_modules/node-abi/node_modules/semver": { "version": "7.8.4", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", @@ -5335,7 +5358,7 @@ }, "node_modules/node-addon-api": { "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-4.3.0.tgz", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", "dev": true, "license": "MIT", @@ -5343,7 +5366,7 @@ }, "node_modules/node-releases": { "version": "2.0.47", - "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.47.tgz", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz", "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", "dev": true, "license": "MIT", @@ -5353,7 +5376,7 @@ }, "node_modules/node-sarif-builder": { "version": "3.4.0", - "resolved": "https://registry.npmmirror.com/node-sarif-builder/-/node-sarif-builder-3.4.0.tgz", + "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.4.0.tgz", "integrity": "sha512-tGnJW6OKRii9u/b2WiUViTJS+h7Apxx17qsMUjsUeNDiMMX5ZFf8F8Fcz7PAQ6omvOxHZtvDTmOYKJQwmfpjeg==", "dev": true, "license": "MIT", @@ -5367,7 +5390,7 @@ }, "node_modules/normalize-package-data": { "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", "dev": true, "license": "BSD-2-Clause", @@ -5382,7 +5405,7 @@ }, "node_modules/normalize-package-data/node_modules/hosted-git-info": { "version": "7.0.2", - "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, "license": "ISC", @@ -5395,14 +5418,14 @@ }, "node_modules/normalize-package-data/node_modules/lru-cache": { "version": "10.4.3", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, "license": "ISC" }, "node_modules/normalize-package-data/node_modules/semver": { "version": "7.8.4", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.8.4.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "dev": true, "license": "ISC", @@ -5415,7 +5438,7 @@ }, "node_modules/nth-check": { "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "license": "BSD-2-Clause", @@ -5428,7 +5451,7 @@ }, "node_modules/object-inspect": { "version": "1.13.4", - "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", @@ -5441,7 +5464,7 @@ }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", @@ -5451,16 +5474,15 @@ } }, "node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "license": "MIT", "dependencies": { - "mimic-function": "^5.0.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=18" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5468,7 +5490,7 @@ }, "node_modules/open": { "version": "10.2.0", - "resolved": "https://registry.npmmirror.com/open/-/open-10.2.0.tgz", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", "dev": true, "license": "MIT", @@ -5486,9 +5508,9 @@ } }, "node_modules/openai": { - "version": "6.42.0", - "resolved": "https://registry.npmmirror.com/openai/-/openai-6.42.0.tgz", - "integrity": "sha512-1WFEt/uXMXOLhYRNkgJWo08Y2YNvNwpVU72K7ibrWgWpNOXd4VojXLbe6SQ4bLiUQ3Y8jz4IiyVkylJCL1DtZg==", + "version": "6.44.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-6.44.0.tgz", + "integrity": "sha512-09/gH+8jH0RgUwsgWHAaxsKGRT5zVZ95IaJUnqAWj6XejIBmnFRwq2WUIF37VtDEsmGrtPmvCs5+yBSeZGWvkA==", "license": "Apache-2.0", "peerDependencies": { "ws": "^8.18.0", @@ -5505,7 +5527,7 @@ }, "node_modules/optionator": { "version": "0.9.4", - "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", @@ -5523,7 +5545,7 @@ }, "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", @@ -5539,7 +5561,7 @@ }, "node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", @@ -5555,7 +5577,7 @@ }, "node_modules/p-map": { "version": "7.0.4", - "resolved": "https://registry.npmmirror.com/p-map/-/p-map-7.0.4.tgz", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, "license": "MIT", @@ -5568,7 +5590,7 @@ }, "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", @@ -5581,7 +5603,7 @@ }, "node_modules/parse-json": { "version": "8.3.0", - "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-8.3.0.tgz", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", "dev": true, "license": "MIT", @@ -5599,7 +5621,7 @@ }, "node_modules/parse-json/node_modules/type-fest": { "version": "4.41.0", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-4.41.0.tgz", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, "license": "(MIT OR CC0-1.0)", @@ -5612,7 +5634,7 @@ }, "node_modules/parse-semver": { "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/parse-semver/-/parse-semver-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", "dev": true, "license": "MIT", @@ -5622,7 +5644,7 @@ }, "node_modules/parse-semver/node_modules/semver": { "version": "5.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "license": "ISC", @@ -5632,7 +5654,7 @@ }, "node_modules/parse5": { "version": "7.3.0", - "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.3.0.tgz", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "dev": true, "license": "MIT", @@ -5645,7 +5667,7 @@ }, "node_modules/parse5-htmlparser2-tree-adapter": { "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", "dev": true, "license": "MIT", @@ -5659,7 +5681,7 @@ }, "node_modules/parse5-parser-stream": { "version": "7.1.2", - "resolved": "https://registry.npmmirror.com/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", "dev": true, "license": "MIT", @@ -5672,7 +5694,7 @@ }, "node_modules/parse5/node_modules/entities": { "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/entities/-/entities-6.0.1.tgz", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", @@ -5685,7 +5707,7 @@ }, "node_modules/patch-console": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/patch-console/-/patch-console-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/patch-console/-/patch-console-2.0.0.tgz", "integrity": "sha512-0YNdUceMdaQwoKce1gatDScmMo5pu/tfABfnzEqeG0gtTmd7mh/WcwgUjtAeOU7N8nFFlbQBnFK2gXW5fGvmMA==", "license": "MIT", "engines": { @@ -5694,7 +5716,7 @@ }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", @@ -5704,7 +5726,7 @@ }, "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", @@ -5714,7 +5736,7 @@ }, "node_modules/path-scurry": { "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-2.0.2.tgz", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", "dev": true, "license": "BlueOak-1.0.0", @@ -5731,7 +5753,7 @@ }, "node_modules/path-scurry/node_modules/lru-cache": { "version": "11.5.1", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.5.1.tgz", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", "dev": true, "license": "BlueOak-1.0.0", @@ -5741,7 +5763,7 @@ }, "node_modules/path-type": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/path-type/-/path-type-6.0.0.tgz", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", "dev": true, "license": "MIT", @@ -5754,21 +5776,21 @@ }, "node_modules/pend": { "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true, "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", @@ -5781,7 +5803,7 @@ }, "node_modules/pluralize": { "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/pluralize/-/pluralize-8.0.0.tgz", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, "license": "MIT", @@ -5790,9 +5812,10 @@ } }, "node_modules/prebuild-install": { - "version": "7.1.2", - "resolved": "https://registry.npmmirror.com/prebuild-install/-/prebuild-install-7.1.2.tgz", - "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", "dev": true, "license": "MIT", "optional": true, @@ -5802,7 +5825,7 @@ "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", + "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", @@ -5819,7 +5842,7 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", @@ -5829,7 +5852,7 @@ }, "node_modules/prettier": { "version": "3.8.4", - "resolved": "https://registry.npmmirror.com/prettier/-/prettier-3.8.4.tgz", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.4.tgz", "integrity": "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==", "dev": true, "license": "MIT", @@ -5845,7 +5868,7 @@ }, "node_modules/pump": { "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.4.tgz", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", "dev": true, "license": "MIT", @@ -5857,7 +5880,7 @@ }, "node_modules/punycode": { "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", @@ -5867,7 +5890,7 @@ }, "node_modules/punycode.js": { "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/punycode.js/-/punycode.js-2.3.1.tgz", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "license": "MIT", "engines": { @@ -5876,7 +5899,7 @@ }, "node_modules/qs": { "version": "6.15.2", - "resolved": "https://registry.npmmirror.com/qs/-/qs-6.15.2.tgz", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "dev": true, "license": "BSD-3-Clause", @@ -5892,7 +5915,7 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ @@ -5913,7 +5936,7 @@ }, "node_modules/rc": { "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/rc/-/rc-1.2.8.tgz", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", @@ -5930,7 +5953,7 @@ }, "node_modules/rc-config-loader": { "version": "4.1.4", - "resolved": "https://registry.npmmirror.com/rc-config-loader/-/rc-config-loader-4.1.4.tgz", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.4.tgz", "integrity": "sha512-3GiwEzklkbXTDp52UR5nT8iXgYAx1V9ZG/kDZT7p60u2GCv2XTwQq4NzinMoMpNtXhmt3WkhYXcj6HH8HdwCEQ==", "dev": true, "license": "MIT", @@ -5943,7 +5966,7 @@ }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, "license": "MIT", @@ -5954,7 +5977,7 @@ }, "node_modules/react": { "version": "19.2.7", - "resolved": "https://registry.npmmirror.com/react/-/react-19.2.7.tgz", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", "engines": { @@ -5963,7 +5986,7 @@ }, "node_modules/react-reconciler": { "version": "0.33.0", - "resolved": "https://registry.npmmirror.com/react-reconciler/-/react-reconciler-0.33.0.tgz", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.33.0.tgz", "integrity": "sha512-KetWRytFv1epdpJc3J4G75I4WrplZE5jOL7Yq0p34+OVOKF4Se7WrdIdVC45XsSSmUTlht2FM/fM1FZb1mfQeA==", "license": "MIT", "dependencies": { @@ -5978,7 +6001,7 @@ }, "node_modules/read": { "version": "1.0.7", - "resolved": "https://registry.npmmirror.com/read/-/read-1.0.7.tgz", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", "dev": true, "license": "ISC", @@ -5991,7 +6014,7 @@ }, "node_modules/read-pkg": { "version": "9.0.1", - "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-9.0.1.tgz", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", "dev": true, "license": "MIT", @@ -6011,7 +6034,7 @@ }, "node_modules/read-pkg/node_modules/type-fest": { "version": "4.41.0", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-4.41.0.tgz", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, "license": "(MIT OR CC0-1.0)", @@ -6024,7 +6047,7 @@ }, "node_modules/read-pkg/node_modules/unicorn-magic": { "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", "dev": true, "license": "MIT", @@ -6037,7 +6060,7 @@ }, "node_modules/readable-stream": { "version": "3.6.2", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", @@ -6053,7 +6076,7 @@ }, "node_modules/require-from-string": { "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "license": "MIT", @@ -6063,7 +6086,7 @@ }, "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", @@ -6072,17 +6095,16 @@ } }, "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "license": "MIT", "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=18" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6090,7 +6112,7 @@ }, "node_modules/reusify": { "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", @@ -6101,14 +6123,14 @@ }, "node_modules/rfdc": { "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true, "license": "MIT" }, "node_modules/run-applescript": { "version": "7.1.0", - "resolved": "https://registry.npmmirror.com/run-applescript/-/run-applescript-7.1.0.tgz", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", "dev": true, "license": "MIT", @@ -6121,7 +6143,7 @@ }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ @@ -6145,7 +6167,7 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ @@ -6166,14 +6188,14 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT" }, "node_modules/sax": { "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/sax/-/sax-1.6.0.tgz", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", "dev": true, "license": "BlueOak-1.0.0", @@ -6183,13 +6205,13 @@ }, "node_modules/scheduler": { "version": "0.27.0", - "resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.27.0.tgz", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, "node_modules/secretlint": { "version": "10.2.2", - "resolved": "https://registry.npmmirror.com/secretlint/-/secretlint-10.2.2.tgz", + "resolved": "https://registry.npmjs.org/secretlint/-/secretlint-10.2.2.tgz", "integrity": "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==", "dev": true, "license": "MIT", @@ -6211,7 +6233,7 @@ }, "node_modules/section-matter": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/section-matter/-/section-matter-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", "license": "MIT", "dependencies": { @@ -6224,7 +6246,7 @@ }, "node_modules/semver": { "version": "6.3.1", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", @@ -6234,7 +6256,7 @@ }, "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", @@ -6247,7 +6269,7 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", @@ -6257,7 +6279,7 @@ }, "node_modules/side-channel": { "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "license": "MIT", @@ -6277,7 +6299,7 @@ }, "node_modules/side-channel-list": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "dev": true, "license": "MIT", @@ -6294,7 +6316,7 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", @@ -6313,7 +6335,7 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", @@ -6332,21 +6354,14 @@ } }, "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" }, "node_modules/simple-concat": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "dev": true, "funding": [ @@ -6368,7 +6383,7 @@ }, "node_modules/simple-get": { "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "dev": true, "funding": [ @@ -6395,7 +6410,7 @@ }, "node_modules/slash": { "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/slash/-/slash-5.1.0.tgz", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "license": "MIT", @@ -6407,17 +6422,16 @@ } }, "node_modules/slice-ansi": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-8.0.0.tgz", - "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", - "dev": true, + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-9.0.0.tgz", + "integrity": "sha512-SO/3iYL5S3W57LLEniscOGPZgOqZUPCx6d3dB+52B80yJ0XstzsC/eV8gnA4tM3MHDrKz+OCFSLNjswdSC+/bA==", "license": "MIT", "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" }, "engines": { - "node": ">=20" + "node": ">=22" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" @@ -6425,9 +6439,8 @@ }, "node_modules/slice-ansi/node_modules/ansi-styles": { "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -6438,7 +6451,7 @@ }, "node_modules/spdx-correct": { "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "license": "Apache-2.0", @@ -6449,14 +6462,14 @@ }, "node_modules/spdx-exceptions": { "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true, "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "license": "MIT", @@ -6467,20 +6480,20 @@ }, "node_modules/spdx-license-ids": { "version": "3.0.23", - "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", "dev": true, "license": "CC0-1.0" }, "node_modules/sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "license": "BSD-3-Clause" }, "node_modules/stack-utils": { "version": "2.0.6", - "resolved": "https://registry.npmmirror.com/stack-utils/-/stack-utils-2.0.6.tgz", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "license": "MIT", "dependencies": { @@ -6492,7 +6505,7 @@ }, "node_modules/stack-utils/node_modules/escape-string-regexp": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "license": "MIT", "engines": { @@ -6501,7 +6514,7 @@ }, "node_modules/string_decoder": { "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "license": "MIT", @@ -6512,7 +6525,7 @@ }, "node_modules/string-argv": { "version": "0.3.2", - "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, "license": "MIT", @@ -6522,7 +6535,7 @@ }, "node_modules/string-width": { "version": "8.2.1", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-8.2.1.tgz", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", "license": "MIT", "dependencies": { @@ -6538,7 +6551,7 @@ }, "node_modules/strip-ansi": { "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "license": "MIT", "dependencies": { @@ -6553,7 +6566,7 @@ }, "node_modules/strip-bom-string": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", "license": "MIT", "engines": { @@ -6562,7 +6575,7 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", @@ -6575,7 +6588,7 @@ }, "node_modules/structured-source": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/structured-source/-/structured-source-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", "dev": true, "license": "BSD-2-Clause", @@ -6585,7 +6598,7 @@ }, "node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", @@ -6598,7 +6611,7 @@ }, "node_modules/supports-hyperlinks": { "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", "dev": true, "license": "MIT", @@ -6615,7 +6628,7 @@ }, "node_modules/table": { "version": "6.9.0", - "resolved": "https://registry.npmmirror.com/table/-/table-6.9.0.tgz", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", "dev": true, "license": "BSD-3-Clause", @@ -6632,7 +6645,7 @@ }, "node_modules/table/node_modules/ajv": { "version": "8.20.0", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.20.0.tgz", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", @@ -6649,7 +6662,7 @@ }, "node_modules/table/node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", @@ -6659,14 +6672,14 @@ }, "node_modules/table/node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", @@ -6676,14 +6689,14 @@ }, "node_modules/table/node_modules/json-schema-traverse": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, "license": "MIT" }, "node_modules/table/node_modules/slice-ansi": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "license": "MIT", @@ -6701,7 +6714,7 @@ }, "node_modules/table/node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", @@ -6716,7 +6729,7 @@ }, "node_modules/table/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", @@ -6729,7 +6742,7 @@ }, "node_modules/tagged-tag": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/tagged-tag/-/tagged-tag-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", "license": "MIT", "engines": { @@ -6741,7 +6754,7 @@ }, "node_modules/tar-fs": { "version": "2.1.4", - "resolved": "https://registry.npmmirror.com/tar-fs/-/tar-fs-2.1.4.tgz", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "dev": true, "license": "MIT", @@ -6755,7 +6768,7 @@ }, "node_modules/tar-stream": { "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, "license": "MIT", @@ -6773,7 +6786,7 @@ }, "node_modules/terminal-link": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/terminal-link/-/terminal-link-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", "integrity": "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==", "dev": true, "license": "MIT", @@ -6790,7 +6803,7 @@ }, "node_modules/terminal-size": { "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/terminal-size/-/terminal-size-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/terminal-size/-/terminal-size-4.0.1.tgz", "integrity": "sha512-avMLDQpUI9I5XFrklECw1ZEUPJhqzcwSWsyyI8blhRLT+8N1jLJWLWWYQpB2q2xthq8xDvjZPISVh53T/+CLYQ==", "license": "MIT", "engines": { @@ -6802,14 +6815,14 @@ }, "node_modules/text-table": { "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, "license": "MIT" }, "node_modules/textextensions": { "version": "6.11.0", - "resolved": "https://registry.npmmirror.com/textextensions/-/textextensions-6.11.0.tgz", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", "dev": true, "license": "Artistic-2.0", @@ -6825,13 +6838,13 @@ }, "node_modules/tinycolor2": { "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", "license": "MIT" }, "node_modules/tinyexec": { "version": "1.2.4", - "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.2.4.tgz", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, "license": "MIT", @@ -6841,7 +6854,7 @@ }, "node_modules/tinyglobby": { "version": "0.2.17", - "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", @@ -6858,7 +6871,7 @@ }, "node_modules/tinygradient": { "version": "1.1.5", - "resolved": "https://registry.npmmirror.com/tinygradient/-/tinygradient-1.1.5.tgz", + "resolved": "https://registry.npmjs.org/tinygradient/-/tinygradient-1.1.5.tgz", "integrity": "sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==", "license": "MIT", "dependencies": { @@ -6868,7 +6881,7 @@ }, "node_modules/tmp": { "version": "0.2.7", - "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.2.7.tgz", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true, "license": "MIT", @@ -6878,7 +6891,7 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", @@ -6891,7 +6904,7 @@ }, "node_modules/ts-api-utils": { "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", @@ -6904,14 +6917,14 @@ }, "node_modules/tslib": { "version": "2.8.1", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, "node_modules/tsx": { "version": "4.22.4", - "resolved": "https://registry.npmmirror.com/tsx/-/tsx-4.22.4.tgz", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz", "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==", "dev": true, "license": "MIT", @@ -6930,7 +6943,7 @@ }, "node_modules/tunnel": { "version": "0.0.6", - "resolved": "https://registry.npmmirror.com/tunnel/-/tunnel-0.0.6.tgz", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", "dev": true, "license": "MIT", @@ -6940,7 +6953,7 @@ }, "node_modules/tunnel-agent": { "version": "0.6.0", - "resolved": "https://registry.npmmirror.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, "license": "Apache-2.0", @@ -6954,7 +6967,7 @@ }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", @@ -6967,7 +6980,7 @@ }, "node_modules/type-fest": { "version": "5.7.0", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-5.7.0.tgz", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.7.0.tgz", "integrity": "sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==", "license": "(MIT OR CC0-1.0)", "dependencies": { @@ -6982,7 +6995,7 @@ }, "node_modules/typed-rest-client": { "version": "1.8.11", - "resolved": "https://registry.npmmirror.com/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", "dev": true, "license": "MIT", @@ -6994,7 +7007,7 @@ }, "node_modules/typescript": { "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/typescript/-/typescript-6.0.3.tgz", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, "license": "Apache-2.0", @@ -7007,16 +7020,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.61.0", - "resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.61.0.tgz", - "integrity": "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.1.tgz", + "integrity": "sha512-V7PayAfJokV3pEHgN7/v03D1SpujhRfQtYLbLIiBfDDncdg4PAiRBfoS4cnCANK4jmAPncczi59QO3afiXUlNw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.61.0", - "@typescript-eslint/parser": "8.61.0", - "@typescript-eslint/typescript-estree": "8.61.0", - "@typescript-eslint/utils": "8.61.0" + "@typescript-eslint/eslint-plugin": "8.61.1", + "@typescript-eslint/parser": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1", + "@typescript-eslint/utils": "8.61.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7032,21 +7045,21 @@ }, "node_modules/uc.micro": { "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "license": "MIT" }, "node_modules/underscore": { "version": "1.13.8", - "resolved": "https://registry.npmmirror.com/underscore/-/underscore-1.13.8.tgz", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", "dev": true, "license": "MIT" }, "node_modules/undici": { - "version": "7.27.2", - "resolved": "https://registry.npmmirror.com/undici/-/undici-7.27.2.tgz", - "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -7054,14 +7067,14 @@ }, "node_modules/undici-types": { "version": "7.24.6", - "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.24.6.tgz", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", "dev": true, "license": "MIT" }, "node_modules/unicorn-magic": { "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", "dev": true, "license": "MIT", @@ -7074,7 +7087,7 @@ }, "node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", @@ -7084,7 +7097,7 @@ }, "node_modules/update-browserslist-db": { "version": "1.2.3", - "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ @@ -7115,7 +7128,7 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", @@ -7125,14 +7138,14 @@ }, "node_modules/url-join": { "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/url-join/-/url-join-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true, "license": "MIT" }, "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, "license": "MIT", @@ -7140,7 +7153,7 @@ }, "node_modules/validate-npm-package-license": { "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "license": "Apache-2.0", @@ -7151,7 +7164,7 @@ }, "node_modules/version-range": { "version": "4.15.0", - "resolved": "https://registry.npmmirror.com/version-range/-/version-range-4.15.0.tgz", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", "dev": true, "license": "Artistic-2.0", @@ -7164,7 +7177,7 @@ }, "node_modules/whatwg-encoding": { "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", "dev": true, @@ -7178,7 +7191,7 @@ }, "node_modules/whatwg-mimetype": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, "license": "MIT", @@ -7188,7 +7201,7 @@ }, "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", @@ -7204,7 +7217,7 @@ }, "node_modules/widest-line": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/widest-line/-/widest-line-6.0.0.tgz", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-6.0.0.tgz", "integrity": "sha512-U89AsyEeAsyoF0zVJBkG9zBgekjgjK7yk9sje3F4IQpXBJ10TF6ByLlIfjMhcmHMJgHZI4KHt4rdNfktzxIAMA==", "license": "MIT", "dependencies": { @@ -7219,7 +7232,7 @@ }, "node_modules/word-wrap": { "version": "1.2.5", - "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", @@ -7229,7 +7242,7 @@ }, "node_modules/wrap-ansi": { "version": "10.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-10.0.0.tgz", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.0.tgz", "integrity": "sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==", "license": "MIT", "dependencies": { @@ -7246,7 +7259,7 @@ }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", "engines": { @@ -7258,7 +7271,7 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "license": "ISC", @@ -7266,7 +7279,7 @@ }, "node_modules/ws": { "version": "8.21.0", - "resolved": "https://registry.npmmirror.com/ws/-/ws-8.21.0.tgz", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "license": "MIT", "engines": { @@ -7287,7 +7300,7 @@ }, "node_modules/wsl-utils": { "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/wsl-utils/-/wsl-utils-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", "dev": true, "license": "MIT", @@ -7303,7 +7316,7 @@ }, "node_modules/xml2js": { "version": "0.5.0", - "resolved": "https://registry.npmmirror.com/xml2js/-/xml2js-0.5.0.tgz", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "dev": true, "license": "MIT", @@ -7317,7 +7330,7 @@ }, "node_modules/xmlbuilder": { "version": "11.0.1", - "resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "dev": true, "license": "MIT", @@ -7327,14 +7340,14 @@ }, "node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" }, "node_modules/yaml": { "version": "2.9.0", - "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.9.0.tgz", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "dev": true, "license": "ISC", @@ -7351,7 +7364,7 @@ }, "node_modules/yauzl": { "version": "3.4.0", - "resolved": "https://registry.npmmirror.com/yauzl/-/yauzl-3.4.0.tgz", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz", "integrity": "sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==", "dev": true, "license": "MIT", @@ -7364,7 +7377,7 @@ }, "node_modules/yazl": { "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/yazl/-/yazl-2.5.1.tgz", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", "dev": true, "license": "MIT", @@ -7374,7 +7387,7 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", @@ -7387,13 +7400,13 @@ }, "node_modules/yoga-layout": { "version": "3.2.1", - "resolved": "https://registry.npmmirror.com/yoga-layout/-/yoga-layout-3.2.1.tgz", + "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz", "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==", "license": "MIT" }, "node_modules/zod": { "version": "4.4.3", - "resolved": "https://registry.npmmirror.com/zod/-/zod-4.4.3.tgz", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "license": "MIT", "funding": { @@ -7402,7 +7415,7 @@ }, "node_modules/zod-validation-error": { "version": "4.0.2", - "resolved": "https://registry.npmmirror.com/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", "dev": true, "license": "MIT", @@ -7435,7 +7448,7 @@ }, "packages/cli/node_modules/chalk": { "version": "5.6.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "license": "MIT", "engines": { @@ -7447,7 +7460,7 @@ }, "packages/cli/node_modules/ignore": { "version": "7.0.5", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "license": "MIT", "engines": { @@ -7470,7 +7483,7 @@ }, "packages/core/node_modules/chalk": { "version": "5.6.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "license": "MIT", "engines": { @@ -7482,31 +7495,13 @@ }, "packages/core/node_modules/ignore": { "version": "7.0.5", - "resolved": "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "license": "MIT", "engines": { "node": ">= 4" } }, - "packages/vscode": { - "name": "@vegamo/deepcode-vscode", - "version": "0.1.22", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@vegamo/deepcode-core": "*", - "markdown-it": "^14.1.1", - "openai": "^6.35.0" - }, - "devDependencies": { - "@types/markdown-it": "^14.1.1", - "@types/vscode": "^1.85.0" - }, - "engines": { - "vscode": "^1.85.0" - } - }, "packages/vscode-ide-companion": { "name": "deepcode-vscode", "version": "0.1.22", diff --git a/scripts/clean.js b/scripts/clean.js index db532c3b..4fd4c7e6 100644 --- a/scripts/clean.js +++ b/scripts/clean.js @@ -9,31 +9,39 @@ const RMRF = { recursive: true, force: true }; console.log("Cleaning build artifacts...\n"); -// Root artifacts +// Root node_modules rmSync(join(root, "node_modules"), RMRF); console.log(" rm node_modules/"); -// Generated version files -for (const pkg of ["cli", "core", "vscode-ide-companion"]) { - rmSync(join(root, "packages", pkg, "src", "generated"), RMRF); - console.log(` rm packages/${pkg}/src/generated/`); -} - -// All workspace dist/ and tsbuildinfo +// Per-package node_modules, dist, generated, tsbuildinfo const packageDirs = globSync("packages/*", { cwd: root, absolute: true }); for (const pkgDir of packageDirs) { + const short = pkgDir.replace(root + "/", ""); + + rmSync(join(pkgDir, "node_modules"), RMRF); + console.log(` rm ${short}/node_modules/`); + rmSync(join(pkgDir, "dist"), RMRF); - console.log(` rm ${join(pkgDir, "dist")}`); + console.log(` rm ${short}/dist/`); + + rmSync(join(pkgDir, "src", "generated"), RMRF); + console.log(` rm ${short}/src/generated/`); + rmSync(join(pkgDir, "tsconfig.tsbuildinfo"), { force: true }); } -// Clean up vscode-ide-companion package -rmSync(join(root, "packages/vscode-ide-companion/node_modules"), RMRF); -// VSCode .vsix files -const vsixFiles = globSync("packages/vscode-ide-companion/*.vsix", { cwd: root }); +// VSCode companion specific artifacts +const vscodeDir = join(root, "packages", "vscode-ide-companion"); +rmSync(join(vscodeDir, "out"), RMRF); +console.log(" rm packages/vscode-ide-companion/out/"); + +rmSync(join(vscodeDir, "templates"), RMRF); +console.log(" rm packages/vscode-ide-companion/templates/"); + +const vsixFiles = globSync("*.vsix", { cwd: vscodeDir }); for (const vsixFile of vsixFiles) { - rmSync(join(root, vsixFile), RMRF); - console.log(` rm ${vsixFile}`); + rmSync(join(vscodeDir, vsixFile), RMRF); + console.log(` rm packages/vscode-ide-companion/${vsixFile}`); } console.log("\n✅ Clean complete.\n\n"); From d83c348912fb9f6e6d14ede960ab4eecd20287c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 20 Jun 2026 11:24:40 +0000 Subject: [PATCH 37/72] chore(deps): bump undici from 7.25.0 to 7.28.0 Bumps [undici](https://github.com/nodejs/undici) from 7.25.0 to 7.28.0. - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v7.25.0...v7.28.0) --- updated-dependencies: - dependency-name: undici dependency-version: 7.28.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8db59638..a65e91ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3591,9 +3591,9 @@ } }, "node_modules/undici": { - "version": "7.25.0", - "resolved": "https://registry.npmmirror.com/undici/-/undici-7.25.0.tgz", - "integrity": "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", "license": "MIT", "engines": { "node": ">=20.18.1" From efdacc23190c4d95ce99c6994c73d3774e3bc3f2 Mon Sep 17 00:00:00 2001 From: hcyang Date: Mon, 22 Jun 2026 15:34:28 +0800 Subject: [PATCH 38/72] =?UTF-8?q?build(core):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=90=8E=E6=9E=84=E5=BB=BA=E7=9A=84=20ESM=20=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E5=90=8D=E9=87=8D=E5=86=99=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在构建流程中新增运行 rewrite-esm-imports.js 脚本步骤 - 该脚本修正 core 包 dist 目录下无扩展名的相对导入为显式 .js 扩展名 - 更新 esbuild 配置,将 @vegamo/deepcode-core 标记为外部依赖 - 保证 Node.js ESM 可以正确解析导入路径,避免运行时错误 --- scripts/build.js | 5 +++-- scripts/esbuild.config.js | 1 + scripts/rewrite-esm-imports.js | 40 ++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 scripts/rewrite-esm-imports.js diff --git a/scripts/build.js b/scripts/build.js index 080e2e54..7710968b 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -17,7 +17,8 @@ console.log("========================================="); console.log(" Deep Code CLI — Build"); console.log("========================================="); -run("npm", ["run", "build", "--workspace=@vegamo/deepcode-core"], "1/2"); -run("npm", ["run", "bundle"], "2/2"); +run("npm", ["run", "build", "--workspace=@vegamo/deepcode-core"], "1/3"); +run("node", ["scripts/rewrite-esm-imports.js"], "2/3"); +run("npm", ["run", "bundle"], "3/3"); console.log("\n✅ Build complete.\n\n"); diff --git a/scripts/esbuild.config.js b/scripts/esbuild.config.js index bf814a32..36c174dc 100644 --- a/scripts/esbuild.config.js +++ b/scripts/esbuild.config.js @@ -20,6 +20,7 @@ await build({ jsx: "automatic", jsxImportSource: "react", packages: "external", + external: ["@vegamo/deepcode-core"], logOverride: { "empty-import-meta": "silent", }, diff --git a/scripts/rewrite-esm-imports.js b/scripts/rewrite-esm-imports.js new file mode 100644 index 00000000..715e5c3b --- /dev/null +++ b/scripts/rewrite-esm-imports.js @@ -0,0 +1,40 @@ +/** + * Post-build script: rewrites extensionless relative imports in the core + * package's dist/ output to include explicit ".js" extensions. + * + * tsc with moduleResolution:"bundler" emits `from "./foo"` (no extension). + * Node.js ESM requires `from "./foo.js"`. This script bridges the gap. + */ +import { readFileSync, writeFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { globSync } from "glob"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); +const distDir = join(root, "packages", "core", "dist"); + +const files = globSync("**/*.js", { cwd: distDir, absolute: true }); + +// Match: from "./anything" or from "../anything" +// Negative lookahead: skip if already ends with .js, .json, .node, or is a bare specifier +const IMPORT_RE = /(from\s+["'])(\.\.?\/[^"']+?)(? { + rewrites++; + return `${prefix}${specifier}.js${quote}`; + }); + + if (rewrites > 0) { + writeFileSync(filePath, updated, "utf8"); + totalRewrites += rewrites; + } +} + +console.log(`\n✅ Rewrote ${totalRewrites} imports across ${files.length} files in core/dist/\n`); From 93ebf7cc241ffd21d01bafd2f9d4d267f9bf3ba2 Mon Sep 17 00:00:00 2001 From: hcyang Date: Mon, 22 Jun 2026 20:48:38 +0800 Subject: [PATCH 39/72] =?UTF-8?q?build(cli):=20=E9=87=8D=E6=9E=84=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E6=B5=81=E7=A8=8B=E5=B9=B6=E5=86=85=E8=81=94=E6=A0=B8?= =?UTF-8?q?=E5=BF=83=E5=8F=8A=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 CLI 构建改为使用 esbuild 的拆分和代码分块,适配 Node 22 环境 - esbuild 配置中内联 core 包及所有依赖,实现零运行时依赖 - 引入自定义 shims 支持 Node 内置模块和空 shim 替代浏览器专用包 - 修改 copy 脚本,复制 core/templates 至 dist/templates 及 legacy bundled 目录 - 发布脚本重构:只发布单个打包的 CLI 包,不再单独发布 core 包 - 发布时在 dist 写入无依赖的 package.json 并从 dist 目录发布 - 简化发布流程,减少步骤数并更新发布文档说明 - package.json 添加对 react-devtools-core 的开发依赖用于本地开发支持 --- .deepcode/AGENTS.md | 4 +- RELEASE.md | 15 ++-- RELEASE_en.md | 15 ++-- package-lock.json | 47 +++++++++++ package.json | 1 + scripts/copy-bundle-assets.js | 34 ++++++-- scripts/empty-shim.js | 2 + scripts/esbuild-shims.js | 22 +++++ scripts/esbuild.config.js | 24 ++++-- scripts/prepare-package.js | 150 ++++++++++++++++++---------------- 10 files changed, 213 insertions(+), 101 deletions(-) create mode 100644 scripts/empty-shim.js create mode 100644 scripts/esbuild-shims.js diff --git a/.deepcode/AGENTS.md b/.deepcode/AGENTS.md index 167d5a68..9d827b0e 100644 --- a/.deepcode/AGENTS.md +++ b/.deepcode/AGENTS.md @@ -68,8 +68,8 @@ dist/ # Bundled CLI output (gitignored) | `npm run format` | Prettier on all `src/**/*.{ts,tsx}` | | `npm run format:check` | Prettier in check-only mode | | `npm run check` | Runs typecheck + lint + format:check together | -| `npm run bundle` | esbuild bundles `src/cli.tsx` → `dist/cli.js` (ESM, Node 18) | -| `npm run build` | `check` + `bundle` + chmod 755 — full CI gate before publish | +| `npm run bundle` | esbuild bundles cli + core + all deps → `dist/cli.js` (ESM, Node 22) | +| `npm run build` | build core (tsc) + rewrite ESM imports + bundle CLI (esbuild) | | `npm test` | Runs all tests via `node src/tests/run-tests.mjs` | | `npm run test:single -- ` | Run a single test file via `tsx --test` (e.g., `npm run test:single -- src/tests/session.test.ts`) | diff --git a/RELEASE.md b/RELEASE.md index deca0fd7..19229167 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -105,7 +105,7 @@ git tag v0.1.32 ## prepare:package — 构建并发布到 npm -完成质量检查、构建、发布两个 npm 包,并自动创建 git commit 和 tag。 +完成质量检查、构建、发布 CLI 到 npm,并自动创建 git commit 和 tag。 ### 基本用法 @@ -122,7 +122,7 @@ npm run prepare:package -- [options] | `--dry-run` | 预演模式,不实际执行任何写操作 | | `--force` | 跳过 main 分支检查,允许从其他分支发布 | -### 执行流程(9 步) +### 执行流程(8 步) | 步骤 | 操作 | 说明 | |------|------|------| @@ -131,10 +131,9 @@ npm run prepare:package -- [options] | 3 | 更新版本号 | 同时更新 `packages/core` 和 `packages/cli` 的 version | | 4 | 质量检查 | `npm run check`(typecheck + eslint + prettier) | | 5 | 测试 | `npm run test --workspaces` | -| 6 | 构建 | `npm run build`(core tsc + cli esbuild bundle) | -| 7 | 发布 core | `npm publish --workspace=@vegamo/deepcode-core --access public` | -| 8 | 发布 cli | 将 cli 的 `@vegamo/deepcode-core` 依赖从 `file:../core` 临时改为 `^`,发布后恢复 | -| 9 | Git commit & tag | `chore(release): v` + `git tag v` | +| 6 | 构建 | `npm run build`(core tsc + esbuild 将 core 及所有依赖内联到 `dist/cli.js`) | +| 7 | 发布 CLI | 往 `dist/` 写入 `dependencies: {}` 的 package.json,从 `dist/` 目录执行 `npm publish` | +| 8 | Git commit & tag | `chore(release): v` + `git tag v` | ### 完整示例 @@ -152,9 +151,9 @@ npm run prepare:package -- 0.1.32 --dry-run npm run prepare:package -- 0.1.32 --force ``` -### 关于 file:../core 依赖 +### 关于 Core 打包策略 -CLI 包的 `@vegamo/deepcode-core` 依赖在开发时使用 `"file:../core"`(monorepo 本地链接)。发布到 npm 时,脚本会自动将其替换为 `"^"`,发布完成后恢复为 `file:../core`。这个过程对用户透明,无需手动处理。 +CLI 的 `package.json` 中保留 `"@vegamo/deepcode-core": "file:../core"` 用于本地开发(IDE 类型检查、monorepo 工作区解析)。构建时 esbuild 使用 `packages: "bundle"` 将 core 的全部代码及其运行时依赖(`openai`、`ejs`、`zod` 等)内联到单个 `dist/cli.js` 文件中。发布时脚本往 `dist/` 写入 `dependencies: {}` 的 `package.json`,从 `dist/` 目录发布,因此发布的 CLI 包零运行时依赖。`@vegamo/deepcode-core` 不再作为独立 npm 包发布。 ### 发布后 diff --git a/RELEASE_en.md b/RELEASE_en.md index 4844bf70..e6cd7013 100644 --- a/RELEASE_en.md +++ b/RELEASE_en.md @@ -105,7 +105,7 @@ git tag v0.1.32 ## prepare:package — Build and Publish to npm -Runs quality checks, builds, publishes both npm packages, and automatically creates a git commit with tag. +Runs quality checks, builds, publishes the CLI to npm, and automatically creates a git commit with tag. ### Basic Usage @@ -122,7 +122,7 @@ npm run prepare:package -- [options] | `--dry-run` | Preview mode, no actual writes | | `--force` | Skip main branch check, allow publishing from other branches | -### Execution Flow (9 Steps) +### Execution Flow (8 Steps) | Step | Action | Description | |------|--------|-------------| @@ -131,10 +131,9 @@ npm run prepare:package -- [options] | 3 | Update versions | Updates `packages/core` and `packages/cli` version fields | | 4 | Quality checks | `npm run check` (typecheck + eslint + prettier) | | 5 | Tests | `npm run test --workspaces` | -| 6 | Build | `npm run build` (core tsc + cli esbuild bundle) | -| 7 | Publish core | `npm publish --workspace=@vegamo/deepcode-core --access public` | -| 8 | Publish cli | Temporarily changes cli's `@vegamo/deepcode-core` dep from `file:../core` to `^`, restores after publish | -| 9 | Git commit & tag | `chore(release): v` + `git tag v` | +| 6 | Build | `npm run build` (core tsc + esbuild inlines core and all deps into `dist/cli.js`) | +| 7 | Publish CLI | Writes `dist/package.json` with `dependencies: {}`, runs `npm publish` from `dist/` | +| 8 | Git commit & tag | `chore(release): v` + `git tag v` | ### Examples @@ -152,9 +151,9 @@ npm run prepare:package -- 0.1.32 --dry-run npm run prepare:package -- 0.1.32 --force ``` -### About the file:../core Dependency +### About the Core Bundling Strategy -The CLI package uses `"file:../core"` for the `@vegamo/deepcode-core` dependency during development (monorepo local link). When publishing to npm, the script automatically replaces it with `"^"` and restores it after publishing. This is transparent — no manual handling required. +The CLI's `package.json` keeps `"@vegamo/deepcode-core": "file:../core"` for local development (IDE type checking, monorepo workspace resolution). At build time, esbuild uses `packages: "bundle"` to inline all of core's code and its runtime dependencies (`openai`, `ejs`, `zod`, etc.) into a single `dist/cli.js` file. At publish time, the script writes a `dist/package.json` with `dependencies: {}` and publishes from the `dist/` directory, so the published CLI package has zero runtime dependencies. `@vegamo/deepcode-core` is no longer published as a separate npm package. ### After Publishing diff --git a/package-lock.json b/package-lock.json index e36f1926..0e4b47f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "husky": "^9.1.7", "lint-staged": "^17.0.4", "prettier": "^3.8.3", + "react-devtools-core": "^7.0.1", "tsx": "^4.21.0", "typescript": "^6.0.3", "typescript-eslint": "^8.59.2" @@ -5984,6 +5985,39 @@ "node": ">=0.10.0" } }, + "node_modules/react-devtools-core": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-7.0.1.tgz", + "integrity": "sha512-C3yNvRHaizlpiASzy7b9vbnBGLrhvdhl1CbdU6EnZgxPNbai60szdLtl+VL76UNOt5bOoVTOz5rNWZxgGt+Gsw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-devtools-core/node_modules/ws": { + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz", + "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/react-reconciler": { "version": "0.33.0", "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.33.0.tgz", @@ -6277,6 +6311,19 @@ "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz", + "integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/side-channel": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", diff --git a/package.json b/package.json index 165ccfdb..c9a0e723 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "husky": "^9.1.7", "lint-staged": "^17.0.4", "prettier": "^3.8.3", + "react-devtools-core": "^7.0.1", "tsx": "^4.21.0", "typescript": "^6.0.3", "typescript-eslint": "^8.59.2" diff --git a/scripts/copy-bundle-assets.js b/scripts/copy-bundle-assets.js index 88315484..a5b261aa 100644 --- a/scripts/copy-bundle-assets.js +++ b/scripts/copy-bundle-assets.js @@ -6,22 +6,42 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); const root = join(__dirname, ".."); const cliRoot = join(root, "packages", "cli"); const distDir = join(cliRoot, "dist"); -const bundledSkillsSrc = join(root, "packages", "core", "templates", "skills", "bundled"); -const bundledSkillsDest = join(distDir, "bundled"); + +// 1. Copy core/templates/ → dist/templates/ +// Core's getExtensionRoot() resolves to dist/ in the bundle (because +// __dirname is dist/chunks/ and ".." goes up to dist/). The runtime code +// loads templates from extensionRoot + "/templates/...", so they must +// exist at dist/templates/. +const templatesSrc = join(root, "packages", "core", "templates"); +const templatesDest = join(distDir, "templates"); if (!existsSync(distDir)) { mkdirSync(distDir, { recursive: true }); } -if (!existsSync(bundledSkillsSrc)) { - console.error(`Bundled skills directory not found at ${bundledSkillsSrc}`); +if (!existsSync(templatesSrc)) { + console.error(`Templates directory not found at ${templatesSrc}`); process.exit(1); } -rmSync(bundledSkillsDest, { recursive: true, force: true }); -cpSync(bundledSkillsSrc, bundledSkillsDest, { +rmSync(templatesDest, { recursive: true, force: true }); +cpSync(templatesSrc, templatesDest, { recursive: true, dereference: true, }); +console.log("\n✅ Copied core/templates/ → dist/templates/"); + +// 2. Copy bundled skills to dist/bundled/ (legacy path used by getBundledSkillsRoot fallback) +const bundledSkillsSrc = join(templatesSrc, "skills", "bundled"); +const bundledSkillsDest = join(distDir, "bundled"); + +if (existsSync(bundledSkillsSrc)) { + rmSync(bundledSkillsDest, { recursive: true, force: true }); + cpSync(bundledSkillsSrc, bundledSkillsDest, { + recursive: true, + dereference: true, + }); + console.log("✅ Copied bundled skills → dist/bundled/"); +} -console.log("\n✅ All bundle assets copied to dist/bundled/"); +console.log("\n✅ All bundle assets copied.\n"); diff --git a/scripts/empty-shim.js b/scripts/empty-shim.js new file mode 100644 index 00000000..76f9cbf5 --- /dev/null +++ b/scripts/empty-shim.js @@ -0,0 +1,2 @@ +// Empty shim for react-devtools-core (browser-only, not needed in CLI bundle) +export default {}; diff --git a/scripts/esbuild-shims.js b/scripts/esbuild-shims.js new file mode 100644 index 00000000..f38ee0c1 --- /dev/null +++ b/scripts/esbuild-shims.js @@ -0,0 +1,22 @@ +/** + * Shims for esbuild ESM bundles. + * + * When esbuild bundles CJS modules into ESM output, it replaces require() + * calls with a __require shim that throws for non-bundled modules. This + * file provides a real require() via createRequire() so Node.js built-in + * modules (assert, events, zlib, etc.) resolve correctly at runtime. + */ + +import { createRequire } from "node:module"; +import { fileURLToPath } from "node:url"; +import { dirname } from "node:path"; + +const _require = createRequire(import.meta.url); + +if (typeof globalThis.require === "undefined") { + globalThis.require = _require; +} + +export const require = _require; +export const __filename = fileURLToPath(import.meta.url); +export const __dirname = dirname(__filename); diff --git a/scripts/esbuild.config.js b/scripts/esbuild.config.js index 36c174dc..3236c5ee 100644 --- a/scripts/esbuild.config.js +++ b/scripts/esbuild.config.js @@ -7,23 +7,37 @@ const root = join(__dirname, ".."); const cliRoot = join(root, "packages", "cli"); const entry = join(cliRoot, "src", "cli.tsx"); -const outfile = join(cliRoot, "dist", "cli.js"); await build({ entryPoints: [entry], bundle: true, + outdir: join(cliRoot, "dist"), + entryNames: "[name]", + chunkNames: "chunks/[name]-[hash]", + splitting: true, platform: "node", format: "esm", target: "node22", - outfile, banner: { js: "#!/usr/bin/env node" }, jsx: "automatic", jsxImportSource: "react", - packages: "external", - external: ["@vegamo/deepcode-core"], + packages: "bundle", + inject: [join(__dirname, "esbuild-shims.js")], + alias: { + // react-devtools-core is a browser-only package pulled in by ink's + // devtools support. It cannot run in a Node.js CLI, so we replace it + // with an empty shim so esbuild doesn't bundle the real (broken) code. + "react-devtools-core": join(__dirname, "empty-shim.js"), + }, + define: { + "process.env.NODE_ENV": JSON.stringify("production"), + }, logOverride: { "empty-import-meta": "silent", }, + metafile: true, + write: true, + keepNames: true, }); -console.log(`\n✅ ${outfile} built successfully\n\n`); +console.log(`\n✅ ${join(cliRoot, "dist", "cli.js")} built successfully\n\n`); diff --git a/scripts/prepare-package.js b/scripts/prepare-package.js index 6049f082..02481c50 100644 --- a/scripts/prepare-package.js +++ b/scripts/prepare-package.js @@ -1,5 +1,5 @@ import { spawnSync } from "node:child_process"; -import { readFileSync, writeFileSync } from "node:fs"; +import { readFileSync, writeFileSync, existsSync, copyFileSync } from "node:fs"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; @@ -81,7 +81,7 @@ for (let i = 0; i < args.length; i++) { if (!version) { log(` -Usage: node scripts/publish.js [options] +Usage: node scripts/prepare-package.js [options] Arguments: Semver version to publish (e.g. 0.1.32, 0.2.0-beta.1) @@ -92,9 +92,9 @@ Options: --force Skip branch check (publish from non-main branch) Examples: - node scripts/publish.js 0.1.32 - node scripts/publish.js 0.1.32-beta.1 --tag beta - node scripts/publish.js 0.1.32 --dry-run + node scripts/prepare-package.js 0.1.32 + node scripts/prepare-package.js 0.1.32-beta.1 --tag beta + node scripts/prepare-package.js 0.1.32 --dry-run `); process.exit(1); } @@ -103,7 +103,7 @@ if (!isValidSemver(version)) { fail(`Invalid semver version: ${version}`); } -const TOTAL_STEPS = 9; +const TOTAL_STEPS = 8; // ── Banner ─────────────────────────────────────────────────────────────────── @@ -169,9 +169,6 @@ const cliPkg = readJson(cliPkgPath); const oldVersion = corePkg.version; -// Save originals for restore -const origCliPkg = JSON.stringify(cliPkg, null, 2) + "\n"; - corePkg.version = version; cliPkg.version = version; @@ -199,75 +196,88 @@ ok("All tests passed"); // ── 6. Build ───────────────────────────────────────────────────────────────── -step(6, TOTAL_STEPS, "Building packages..."); +step(6, TOTAL_STEPS, "Building and bundling packages..."); run("npm", ["run", "build"], { dryRun }); -ok("Build complete"); - -// ── 7. Publish core ────────────────────────────────────────────────────────── - -step(7, TOTAL_STEPS, "Publishing @vegamo/deepcode-core..."); - -const corePublishArgs = [ - "publish", - "--workspace=@vegamo/deepcode-core", - "--access", - "public", - "--tag", - tag, - "--registry", - "https://registry.npmjs.org", -]; -if (dryRun) corePublishArgs.push("--dry-run"); - -run("npm", corePublishArgs, { dryRun, label: `npm ${corePublishArgs.join(" ")}` }); -ok(`Published @vegamo/deepcode-core@${version}`); - -// ── 8. Patch CLI deps & publish ────────────────────────────────────────────── - -step(8, TOTAL_STEPS, "Patching CLI dependencies and publishing @vegamo/deepcode-cli..."); - -// Replace file:../core with ^version for npm -const patchedCliPkg = readJson(cliPkgPath); -const coreDep = patchedCliPkg.dependencies["@vegamo/deepcode-core"]; -if (coreDep && coreDep.startsWith("file:")) { - patchedCliPkg.dependencies["@vegamo/deepcode-core"] = `^${version}`; - if (!dryRun) { - writeJson(cliPkgPath, patchedCliPkg); +ok("Build and bundle complete"); + +// ── 7. Prepare dist/ for publishing ────────────────────────────────────────── + +step(7, TOTAL_STEPS, "Preparing dist/ for publishing..."); + +const cliRoot = join(root, "packages", "cli"); +const distDir = join(cliRoot, "dist"); +const distCliJs = join(distDir, "cli.js"); +const distChunks = join(distDir, "chunks"); +const distBundled = join(distDir, "bundled"); + +if (!existsSync(distCliJs)) { + fail(`Bundle artifact not found: ${distCliJs}. Run "npm run build" first.`); +} +if (!existsSync(distChunks)) { + fail(`Chunks directory not found: ${distChunks}. Run "npm run build" first.`); +} +if (!existsSync(distBundled)) { + fail(`Bundled assets not found: ${distBundled}. Run "npm run build" first.`); +} + +// Copy README.md and LICENSE into dist/ +for (const file of ["README.md", "LICENSE"]) { + const src = join(root, file); + const dest = join(distDir, file); + if (existsSync(src)) { + if (!dryRun) { + copyFileSync(src, dest); + } + log(` Copied ${file} → dist/`); + } else { + log(` Warning: ${file} not found at ${src}`); } - log(` Patched @vegamo/deepcode-core dep: "${coreDep}" → "^${version}"`); } -const cliPublishArgs = [ - "publish", - "--workspace=@vegamo/deepcode-cli", - "--access", - "public", - "--tag", - tag, - "--registry", - "https://registry.npmjs.org", -]; -if (dryRun) cliPublishArgs.push("--dry-run"); - -run("npm", cliPublishArgs, { dryRun, label: `npm ${cliPublishArgs.join(" ")}` }); -ok(`Published @vegamo/deepcode-cli@${version}`); +// Write a new package.json for publishing with empty dependencies. +// All runtime code (including @vegamo/deepcode-core and its deps) is already +// bundled into dist/cli.js by esbuild with packages: "bundle". +const distPackageJson = { + name: cliPkg.name, + version: version, + description: cliPkg.description, + license: cliPkg.license, + type: "module", + main: "cli.js", + bin: { + deepcode: "cli.js", + }, + files: ["cli.js", "chunks/**", "templates/**", "bundled/**", "README.md", "LICENSE"], + engines: cliPkg.engines, + dependencies: {}, +}; -// Restore file:../core for local development if (!dryRun) { - writeJson(cliPkgPath, JSON.parse(origCliPkg)); - // But keep the new version - const restoredCli = readJson(cliPkgPath); - restoredCli.version = version; - writeJson(cliPkgPath, restoredCli); - log(" Restored @vegamo/deepcode-core dep to file:../core"); + writeJson(join(distDir, "package.json"), distPackageJson); } +log(" Written dist/package.json with dependencies: {}"); + +ok("dist/ prepared for publishing"); + +// ── 7. Publish from dist/ ──────────────────────────────────────────────────── -// ── 9. Git commit + tag ────────────────────────────────────────────────────── +step(8, TOTAL_STEPS, "Publishing @vegamo/deepcode-cli from dist/..."); + +const publishArgs = ["publish", "--access", "public", "--tag", tag, "--registry", "https://registry.npmjs.org"]; +if (dryRun) publishArgs.push("--dry-run"); + +run("npm", publishArgs, { + dryRun, + cwd: distDir, + label: `cd dist && npm ${publishArgs.join(" ")}`, +}); +ok(`Published @vegamo/deepcode-cli@${version}`); -step(9, TOTAL_STEPS, "Creating git commit and tag..."); +// ── Git commit + tag ───────────────────────────────────────────────────────── if (!dryRun) { + log("\nCreating git commit and tag..."); run("git", ["add", "packages/core/package.json", "packages/cli/package.json"], { label: "git add packages/*/package.json", }); @@ -279,8 +289,7 @@ if (!dryRun) { }); ok(`Created commit and tag v${version}`); } else { - log(` (dry-run) git add + commit "chore(release): v${version}"`); - log(` (dry-run) git tag v${version}`); + log("\n (dry-run) git add + commit + tag"); } // ── Done ───────────────────────────────────────────────────────────────────── @@ -289,9 +298,8 @@ console.log("\n========================================="); console.log(` 🎉 Published v${version} successfully!`); console.log("========================================="); console.log(` - Packages published: - • @vegamo/deepcode-core@${version} - • @vegamo/deepcode-cli@${version} + Package published: + • @vegamo/deepcode-cli@${version} (core bundled, zero runtime dependencies) Verify: npm view @vegamo/deepcode-cli version From 78d9ec6cc5e9be2139b43a550434d7162694d33f Mon Sep 17 00:00:00 2001 From: hcyang Date: Mon, 22 Jun 2026 21:11:05 +0800 Subject: [PATCH 40/72] =?UTF-8?q?fix(cli):=20=E8=B0=83=E6=95=B4=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=A4=8D=E5=88=B6=E9=80=BB=E8=BE=91=E4=BB=A5=E6=8E=92?= =?UTF-8?q?=E9=99=A4=E5=B9=B6=E5=8D=95=E7=8B=AC=E5=A4=84=E7=90=86=20skills?= =?UTF-8?q?/bundled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在复制 core/templates 到 dist/templates 时排除 skills/bundled 目录 - 将 skills/bundled 资源单独复制到 dist/bundled 目录 - 更新 getBundledSkillsRoot 方法以匹配新的 bundled 资源路径 - 添加路径存在性检查,确保模板目录存在 - 优化日志信息,明确排除的目录范围 --- packages/core/src/session.ts | 5 ++++- scripts/copy-bundle-assets.js | 27 +++++++++++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/core/src/session.ts b/packages/core/src/session.ts index 3460cea5..4483c67f 100644 --- a/packages/core/src/session.ts +++ b/packages/core/src/session.ts @@ -818,12 +818,15 @@ ${agentInstructions} private getBundledSkillsRoot(): string { const extensionRoot = getExtensionRoot(); const sourceRoot = path.join(extensionRoot, "templates", "skills", "bundled"); - const distRoot = path.join(extensionRoot, "dist", "bundled"); // Source check keeps local development/tests on the checked-in templates. if (fs.existsSync(path.join(extensionRoot, "src", "session.ts")) && fs.existsSync(sourceRoot)) { return sourceRoot; } + + // In the published bundle, getExtensionRoot() resolves to dist/ and + // bundled skills are copied to dist/bundled/ (not dist/templates/skills/bundled/). + const distRoot = path.join(extensionRoot, "bundled"); return fs.existsSync(distRoot) ? distRoot : sourceRoot; } diff --git a/scripts/copy-bundle-assets.js b/scripts/copy-bundle-assets.js index a5b261aa..c1905c79 100644 --- a/scripts/copy-bundle-assets.js +++ b/scripts/copy-bundle-assets.js @@ -1,5 +1,5 @@ -import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs"; -import { dirname, join } from "node:path"; +import { cpSync, existsSync, mkdirSync, rmSync, statSync } from "node:fs"; +import { dirname, join, relative } from "node:path"; import { fileURLToPath } from "node:url"; const __dirname = dirname(fileURLToPath(import.meta.url)); @@ -7,31 +7,34 @@ const root = join(__dirname, ".."); const cliRoot = join(root, "packages", "cli"); const distDir = join(cliRoot, "dist"); -// 1. Copy core/templates/ → dist/templates/ -// Core's getExtensionRoot() resolves to dist/ in the bundle (because -// __dirname is dist/chunks/ and ".." goes up to dist/). The runtime code -// loads templates from extensionRoot + "/templates/...", so they must -// exist at dist/templates/. -const templatesSrc = join(root, "packages", "core", "templates"); -const templatesDest = join(distDir, "templates"); - if (!existsSync(distDir)) { mkdirSync(distDir, { recursive: true }); } +const templatesSrc = join(root, "packages", "core", "templates"); +const templatesDest = join(distDir, "templates"); + if (!existsSync(templatesSrc)) { console.error(`Templates directory not found at ${templatesSrc}`); process.exit(1); } +// 1. Copy core/templates/ → dist/templates/, excluding skills/bundled/. +// Bundled skills are copied separately to dist/bundled/ (see step 2) and +// getBundledSkillsRoot() resolves them from there at runtime. rmSync(templatesDest, { recursive: true, force: true }); cpSync(templatesSrc, templatesDest, { recursive: true, dereference: true, + filter: (src) => { + const rel = relative(templatesSrc, src); + // Exclude skills/bundled and everything under it + return !(rel === join("skills", "bundled") || rel.startsWith(join("skills", "bundled") + "/")); + }, }); -console.log("\n✅ Copied core/templates/ → dist/templates/"); +console.log("\n✅ Copied core/templates/ → dist/templates/ (excluding skills/bundled/)"); -// 2. Copy bundled skills to dist/bundled/ (legacy path used by getBundledSkillsRoot fallback) +// 2. Copy bundled skills to dist/bundled/ const bundledSkillsSrc = join(templatesSrc, "skills", "bundled"); const bundledSkillsDest = join(distDir, "bundled"); From 2f33293b2cd6861703f3c8d84362d8458d778956 Mon Sep 17 00:00:00 2001 From: dengmik-commits <270912164+dengmik-commits@users.noreply.github.com> Date: Tue, 23 Jun 2026 09:50:49 +0800 Subject: [PATCH 41/72] =?UTF-8?q?feat(cli):=20=E6=B7=BB=E5=8A=A0=E5=8F=AF?= =?UTF-8?q?=E6=8F=92=E6=8B=94=E7=8A=B6=E6=80=81=E6=A0=8F=20(statusline)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在输入框下方渲染由用户配置的状态栏,通过 settings.json#statusline 声明 command/module 两类 provider,无需改动 CLI 源码即可扩展。 - core: 新增 StatusLineProviderConfig/Settings 类型与 normalize/merge 逻辑, resolveSettings 返回 ResolvedStatusLineSettings - cli: 新增 statusline manager、command-provider、module-provider、sanitize; useStatusLine hook;App.tsx 组装 SessionInfo(含 model/thinking/context/ toolUsage);PromptInput.tsx 末尾渲染分段 - docs: 新增 statusline.md / statusline_en.md,configuration 表格补字段 - .deepcode/plugins: 提供 model-info / cwd / git-branch / session-stats / tool-usage 五个示例 mjs - eslint: 为 .deepcode/plugins/**/*.mjs 添加 Node 环境 globals - tests: 新增 statusline.test.ts,覆盖 normalize / merge / manager --- .deepcode/plugins/cwd.mjs | 7 + .deepcode/plugins/git-branch.mjs | 16 ++ .deepcode/plugins/model-info.mjs | 13 + .deepcode/plugins/session-stats.mjs | 22 ++ .deepcode/plugins/tool-usage.mjs | 23 ++ docs/configuration.md | 1 + docs/configuration_en.md | 1 + docs/statusline.md | 149 +++++++++++ docs/statusline_en.md | 149 +++++++++++ eslint.config.mjs | 10 + packages/cli/src/tests/statusline.test.ts | 249 ++++++++++++++++++ packages/cli/src/ui/hooks/index.ts | 2 + packages/cli/src/ui/hooks/useStatusLine.ts | 47 ++++ .../cli/src/ui/statusline/command-provider.ts | 94 +++++++ packages/cli/src/ui/statusline/index.ts | 4 + packages/cli/src/ui/statusline/manager.ts | 169 ++++++++++++ .../cli/src/ui/statusline/module-provider.ts | 91 +++++++ packages/cli/src/ui/statusline/sanitize.ts | 21 ++ packages/cli/src/ui/statusline/types.ts | 39 +++ packages/cli/src/ui/views/App.tsx | 60 +++++ packages/cli/src/ui/views/PromptInput.tsx | 17 ++ packages/core/src/index.ts | 3 + packages/core/src/settings.ts | 146 ++++++++++ 23 files changed, 1333 insertions(+) create mode 100644 .deepcode/plugins/cwd.mjs create mode 100644 .deepcode/plugins/git-branch.mjs create mode 100644 .deepcode/plugins/model-info.mjs create mode 100644 .deepcode/plugins/session-stats.mjs create mode 100644 .deepcode/plugins/tool-usage.mjs create mode 100644 docs/statusline.md create mode 100644 docs/statusline_en.md create mode 100644 packages/cli/src/tests/statusline.test.ts create mode 100644 packages/cli/src/ui/hooks/useStatusLine.ts create mode 100644 packages/cli/src/ui/statusline/command-provider.ts create mode 100644 packages/cli/src/ui/statusline/index.ts create mode 100644 packages/cli/src/ui/statusline/manager.ts create mode 100644 packages/cli/src/ui/statusline/module-provider.ts create mode 100644 packages/cli/src/ui/statusline/sanitize.ts create mode 100644 packages/cli/src/ui/statusline/types.ts diff --git a/.deepcode/plugins/cwd.mjs b/.deepcode/plugins/cwd.mjs new file mode 100644 index 00000000..d36099b4 --- /dev/null +++ b/.deepcode/plugins/cwd.mjs @@ -0,0 +1,7 @@ +export default function cwdProvider({ projectRoot }) { + const cwd = process.cwd() || projectRoot || ""; + if (!cwd) return ""; + const home = process.env.HOME || process.env.USERPROFILE || ""; + const display = home && cwd.startsWith(home) ? "~" + cwd.slice(home.length) : cwd; + return display; +} diff --git a/.deepcode/plugins/git-branch.mjs b/.deepcode/plugins/git-branch.mjs new file mode 100644 index 00000000..b5096073 --- /dev/null +++ b/.deepcode/plugins/git-branch.mjs @@ -0,0 +1,16 @@ +import { execFileSync } from "node:child_process"; + +export default function gitBranchProvider({ projectRoot }) { + try { + const out = execFileSync("git", ["branch", "--show-current"], { + cwd: projectRoot || process.cwd(), + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"], + timeout: 1500, + }).trim(); + if (!out) return ""; + return `git:${out}`; + } catch { + return ""; + } +} diff --git a/.deepcode/plugins/model-info.mjs b/.deepcode/plugins/model-info.mjs new file mode 100644 index 00000000..71a4ec09 --- /dev/null +++ b/.deepcode/plugins/model-info.mjs @@ -0,0 +1,13 @@ +export default function modelInfoProvider({ session }) { + if (!session) return ""; + const parts = []; + if (session.model) { + parts.push(session.model); + } + if (session.thinkingEnabled && session.reasoningEffort) { + parts.push(`thinking:${session.reasoningEffort}`); + } else if (session.thinkingEnabled) { + parts.push("thinking"); + } + return parts.join(" "); +} diff --git a/.deepcode/plugins/session-stats.mjs b/.deepcode/plugins/session-stats.mjs new file mode 100644 index 00000000..79aca645 --- /dev/null +++ b/.deepcode/plugins/session-stats.mjs @@ -0,0 +1,22 @@ +function formatTokens(n) { + if (n >= 1000) return (n / 1000).toFixed(1).replace(/\.0$/, "") + "k"; + return String(n); +} + +export default function sessionStatsProvider({ session }) { + if (!session || !session.activeSessionId) { + return "no session"; + } + const parts = []; + parts.push(`msgs:${session.messageCount}`); + if (session.requestCount > 0) { + parts.push(`reqs:${session.requestCount}`); + } + if (session.activeTokens > 0 && session.maxContextTokens > 0) { + const pct = Math.round((session.activeTokens / session.maxContextTokens) * 100); + parts.push(`ctx:${formatTokens(session.activeTokens)}/${formatTokens(session.maxContextTokens)} ${pct}%`); + } else if (session.totalTokens > 0) { + parts.push(`tokens:${formatTokens(session.totalTokens)}`); + } + return parts.join(" "); +} diff --git a/.deepcode/plugins/tool-usage.mjs b/.deepcode/plugins/tool-usage.mjs new file mode 100644 index 00000000..212fe45e --- /dev/null +++ b/.deepcode/plugins/tool-usage.mjs @@ -0,0 +1,23 @@ +const TOOL_ORDER = ["bash", "edit", "read", "write", "AskUserQuestion", "UpdatePlan", "WebSearch"]; + +export default function toolUsageProvider({ session }) { + if (!session || !session.activeSessionId) { + return ""; + } + const usage = session.toolUsage; + if (!usage || Object.keys(usage).length === 0) { + return ""; + } + // Sort: preferred order first, then by count desc + const sorted = Object.entries(usage).sort((a, b) => { + const ai = TOOL_ORDER.indexOf(a[0]); + const bi = TOOL_ORDER.indexOf(b[0]); + if (ai !== -1 && bi !== -1) return ai - bi; + if (ai !== -1) return -1; + if (bi !== -1) return 1; + return b[1] - a[1]; + }); + + const shortNames = sorted.slice(0, 6); + return shortNames.map(([name, count]) => `${name}×${count}`).join(" "); +} diff --git a/docs/configuration.md b/docs/configuration.md index 2f198b10..d942dc04 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -37,6 +37,7 @@ Deep Code 使用 `settings.json` 设置文件进行持久化配置,支持两 | `mcpServers` | object | MCP 服务器配置(键为服务名,值为 McpServerConfig 对象) | | `temperature` | number | 模型采样温度,范围 `0` 到 `2` | | `enabledSkills` | object | 按 skill 名称启用或禁用 skill 的配置 | +| `statusline` | object | 状态栏插件配置(参见 [statusline.md](./statusline.md)) | #### `env` 子字段 diff --git a/docs/configuration_en.md b/docs/configuration_en.md index fac8c349..a078c428 100644 --- a/docs/configuration_en.md +++ b/docs/configuration_en.md @@ -37,6 +37,7 @@ The following are all the top-level fields supported in `settings.json`, along w | `mcpServers` | object | MCP server configurations (keys are service names, values are McpServerConfig objects) | | `temperature` | number | Sampling temperature for LLM, from `0` to `2` | | `enabledSkills` | object | Per-skill enable/disable map, keyed by skill name | +| `statusline` | object | Status line plugins (see [statusline_en.md](./statusline_en.md)) | #### `env` Sub-fields diff --git a/docs/statusline.md b/docs/statusline.md new file mode 100644 index 00000000..4ab8a11d --- /dev/null +++ b/docs/statusline.md @@ -0,0 +1,149 @@ +# 状态栏插件 + +Deep Code CLI 支持通过插件向终端底部状态栏注入自定义信息(Git 分支、当前时间、token 用量等),无需修改 CLI 源码。状态栏行展示在输入框下方的快捷键提示行下方,所有 provider 的输出会用分隔符拼接后渲染。 + +## 配置 + +在 `~/.deepcode/settings.json`(或项目级 `.deepcode/settings.json`)中添加 `statusline` 字段: + +```jsonc +{ + "statusline": { + "enabled": true, + "refreshMs": 2000, + "separator": " · ", + "providers": [ + { + "type": "command", + "id": "git", + "command": "git branch --show-current", + "color": "cyan" + }, + { + "type": "module", + "id": "tokens", + "path": "./.deepcode/plugins/tokens.mjs", + "color": "yellow" + } + ] + } +} +``` + +### 字段 + +| 字段 | 类型 | 说明 | +| ------------- | --------- | ------------------------------------------------------------------- | +| `enabled` | boolean | 是否启用。省略时,只要存在至少一个 provider 即视为启用 | +| `refreshMs` | number | 拉取间隔毫秒。最小 500,默认 2000 | +| `separator` | string | 多个 provider 输出之间的分隔符,默认 `" · "` | +| `providers` | array | provider 列表,按声明顺序渲染 | + +## Provider 类型 + +### `command` —— 执行外部命令 + +每隔 `refreshMs` 在 shell 中执行一次命令,取 stdout 第一行作为状态栏 segment。 + +| 字段 | 类型 | 必填 | 说明 | +| ----------- | ------- | ---- | ----------------------------------------------------------------- | +| `type` | string | 是 | 固定为 `"command"` | +| `command` | string | 是 | shell 命令(支持管道、重定向等) | +| `id` | string | 否 | 唯一标识。省略时按下标自动生成 | +| `cwd` | string | 否 | 执行目录。相对路径相对于项目根目录,省略时使用项目根目录 | +| `timeoutMs` | number | 否 | 超时毫秒,默认 1500。超时返回空串 | +| `color` | string | 否 | ink 支持的颜色名(如 `"red"`、`"#229ac3"`) | + +示例: + +```json +{ "type": "command", "id": "git", "command": "git status -sb | head -1" } +{ "type": "command", "id": "time", "command": "date +%H:%M" } +{ "type": "command", "id": "node", "command": "node -v", "color": "green" } +``` + +### `module` —— 加载 JS 模块 + +加载本地 JS/MJS 模块,调用其默认导出函数,把返回值作为 segment 文本。 + +| 字段 | 类型 | 必填 | 说明 | +| ----------- | ------- | ---- | ----------------------------------------------------------------------------------- | +| `type` | string | 是 | 固定为 `"module"` | +| `path` | string | 是 | 模块路径。相对路径相对于项目根目录 | +| `id` | string | 否 | 唯一标识 | +| `timeoutMs` | number | 否 | 超时毫秒,默认 2000 | +| `color` | string | 否 | ink 支持的颜色 | + +模块需导出一个 `default` 函数(或具名 `provider`): + +```js +// .deepcode/plugins/tokens.mjs +export default function tokensProvider({ projectRoot, session }) { + // 返回字符串(同步或异步) + if (session?.activeSessionId) { + return `msgs:${session.messageCount} reqs:${session.requestCount} tokens:${session.totalTokens}`; + } + return `tokens: 1.2k`; +} +``` + +函数接收一个对象 `{ projectRoot: string, session: SessionInfo | null }`,返回 `string` 或 `Promise`。 + +`SessionInfo` 结构: + +| 字段 | 类型 | 说明 | +| ----------------- | ------------------ | --------------------------------------------------- | +| `activeSessionId` | `string \| null` | 当前活跃会话的 ID,无会话时为 `null` | +| `messageCount` | `number` | 当前会话中的消息总数 | +| `requestCount` | `number` | 当前会话中的 LLM API 请求次数 | +| `totalTokens` | `number` | 当前会话中消耗的 token 总数 | + +## 安全限制 + +- **module provider 路径必须位于项目根目录或用户家目录之下**,绝对路径在这两个范围之外会被拒绝加载(防止从任意位置执行代码)。 +- 单个 segment 文本被自动: + - 取第一个非空行 + - 去除 ANSI 转义序列 + - 折叠空白字符 + - 截断到 40 个字符(超出加 `…`) +- command provider 的 stdout 最多读取 4 KB。 +- 任何 provider 抛错、超时、或返回空字符串,**只跳过该 segment**,不影响其它 provider。 + +## 行为 + +- 启动 CLI 后立即触发一次拉取,之后按 `refreshMs` 周期刷新。 +- 用户级与项目级配置的 `providers` 数组会**合并**(用户先、项目后);其他字段以项目级为优先。 +- 状态栏行在任何场景下都显示(包括 busy、permission prompt 等),不影响 busy 提示。 +- 修改配置文件后需重启 CLI 生效(不会热加载)。 + +## 完整示例 + +```json +{ + "statusline": { + "enabled": true, + "refreshMs": 3000, + "providers": [ + { + "type": "command", + "id": "branch", + "command": "git branch --show-current", + "color": "cyan" + }, + { + "type": "command", + "id": "dirty", + "command": "git status --porcelain | wc -l | xargs -I{} echo '{} files changed'", + "color": "yellow" + }, + { + "type": "module", + "id": "ts-errors", + "path": "./.deepcode/plugins/ts-errors.mjs", + "color": "red", + "timeoutMs": 5000 + } + ] + } +} +``` diff --git a/docs/statusline_en.md b/docs/statusline_en.md new file mode 100644 index 00000000..bd14d91a --- /dev/null +++ b/docs/statusline_en.md @@ -0,0 +1,149 @@ +# Status Line Plugins + +Deep Code CLI lets you inject custom information into the status line at the bottom of the terminal (Git branch, current time, token usage, etc.) through plugins, without modifying the CLI source. The status line renders below the keyboard hint line under the prompt input, and all provider outputs are concatenated with a separator. + +## Configuration + +Add a `statusline` field to `~/.deepcode/settings.json` (or the project-level `.deepcode/settings.json`): + +```jsonc +{ + "statusline": { + "enabled": true, + "refreshMs": 2000, + "separator": " · ", + "providers": [ + { + "type": "command", + "id": "git", + "command": "git branch --show-current", + "color": "cyan" + }, + { + "type": "module", + "id": "tokens", + "path": "./.deepcode/plugins/tokens.mjs", + "color": "yellow" + } + ] + } +} +``` + +### Fields + +| Field | Type | Description | +| ------------- | --------- | ---------------------------------------------------------------------------- | +| `enabled` | boolean | Whether the status line is enabled. If omitted, defaults to true when at least one provider is configured. | +| `refreshMs` | number | Refresh interval in milliseconds. Minimum 500, default 2000. | +| `separator` | string | Separator between provider outputs. Default `" · "`. | +| `providers` | array | List of providers, rendered in declaration order. | + +## Provider Types + +### `command` — Run an External Command + +Executes a shell command every `refreshMs` and uses the first line of stdout as the status segment. + +| Field | Type | Required | Description | +| ----------- | ------- | -------- | ------------------------------------------------------------------------ | +| `type` | string | Yes | Must be `"command"`. | +| `command` | string | Yes | Shell command (supports pipes, redirection, etc.). | +| `id` | string | No | Unique identifier. Auto-generated from index if omitted. | +| `cwd` | string | No | Working directory. Relative paths resolved against the project root. | +| `timeoutMs` | number | No | Timeout in milliseconds. Default 1500. Empty string on timeout. | +| `color` | string | No | Ink-supported color (e.g. `"red"`, `"#229ac3"`). | + +Examples: + +```json +{ "type": "command", "id": "git", "command": "git status -sb | head -1" } +{ "type": "command", "id": "time", "command": "date +%H:%M" } +{ "type": "command", "id": "node", "command": "node -v", "color": "green" } +``` + +### `module` — Load a JS Module + +Loads a local JS/MJS module and calls its default-exported function. The return value becomes the segment text. + +| Field | Type | Required | Description | +| ----------- | ------- | -------- | ------------------------------------------------------------------------------------ | +| `type` | string | Yes | Must be `"module"`. | +| `path` | string | Yes | Module path. Relative paths resolved against the project root. | +| `id` | string | No | Unique identifier. | +| `timeoutMs` | number | No | Timeout in milliseconds. Default 2000. | +| `color` | string | No | Ink-supported color. | + +The module must export a `default` function (or a named `provider`): + +```js +// .deepcode/plugins/tokens.mjs +export default function tokensProvider({ projectRoot, session }) { + // Return a string (sync or async). + if (session?.activeSessionId) { + return `msgs:${session.messageCount} reqs:${session.requestCount} tokens:${session.totalTokens}`; + } + return `tokens: 1.2k`; +} +``` + +The function receives `{ projectRoot: string, session: SessionInfo | null }` and returns `string` or `Promise`. + +`SessionInfo` shape: + +| Field | Type | Description | +| ----------------- | ------------------- | ---------------------------------------------------------- | +| `activeSessionId` | `string \| null` | ID of the currently active session, or `null` if none. | +| `messageCount` | `number` | Total messages in the active session. | +| `requestCount` | `number` | Total LLM API requests made in the active session. | +| `totalTokens` | `number` | Total tokens consumed in the active session. | + +## Safety Constraints + +- **Module provider paths must reside within the project root or the user's home directory**; absolute paths outside both are rejected (to prevent loading arbitrary code). +- Each segment's text is automatically: + - Reduced to the first non-empty line + - Stripped of ANSI escape sequences + - Whitespace-collapsed + - Truncated to 40 characters (with `…` for overflow) +- Command provider stdout is capped at 4 KB. +- If any provider throws, times out, or returns an empty string, **only that segment is skipped**; the rest are unaffected. + +## Behavior + +- The first refresh fires immediately after CLI startup, then on the configured interval. +- The `providers` arrays from user-level and project-level configs are **merged** (user first, project second); other fields prefer the project-level value. +- The status line is shown in every state (including busy and permission prompts) without interfering with busy indicators. +- Changes to config require a CLI restart (no hot reload). + +## Full Example + +```json +{ + "statusline": { + "enabled": true, + "refreshMs": 3000, + "providers": [ + { + "type": "command", + "id": "branch", + "command": "git branch --show-current", + "color": "cyan" + }, + { + "type": "command", + "id": "dirty", + "command": "git status --porcelain | wc -l | xargs -I{} echo '{} files changed'", + "color": "yellow" + }, + { + "type": "module", + "id": "ts-errors", + "path": "./.deepcode/plugins/ts-errors.mjs", + "color": "red", + "timeoutMs": 5000 + } + ] + } +} +``` diff --git a/eslint.config.mjs b/eslint.config.mjs index b9ec5dc1..abeb8390 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -65,6 +65,16 @@ export default tseslint.config( }, }, }, + // Statusline plugins: Node.js environment + { + files: [".deepcode/plugins/**/*.mjs", ".deepcode/plugins/**/*.js"], + languageOptions: { + globals: { + process: "readonly", + console: "readonly", + }, + }, + }, // Browser resources: VSCode webview scripts { files: ["packages/*/resources/**/*.js"], diff --git a/packages/cli/src/tests/statusline.test.ts b/packages/cli/src/tests/statusline.test.ts new file mode 100644 index 00000000..fffc15a1 --- /dev/null +++ b/packages/cli/src/tests/statusline.test.ts @@ -0,0 +1,249 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import * as fs from "node:fs"; +import * as os from "node:os"; +import * as path from "node:path"; +import { sanitizeStatusText, STATUS_SEGMENT_MAX_LENGTH } from "../ui/statusline/sanitize"; +import { validateModulePath, loadModuleProvider } from "../ui/statusline/module-provider"; +import { createCommandStatusProvider } from "../ui/statusline/command-provider"; +import { StatusLineManager } from "../ui/statusline/manager"; +import { resolveSettings } from "@vegamo/deepcode-core"; +import type { ResolvedStatusLineSettings } from "@vegamo/deepcode-core"; + +test("sanitizeStatusText returns empty for null/undefined/empty", () => { + assert.equal(sanitizeStatusText(undefined), ""); + assert.equal(sanitizeStatusText(null), ""); + assert.equal(sanitizeStatusText(""), ""); +}); + +test("sanitizeStatusText keeps first non-empty line and strips ANSI", () => { + assert.equal(sanitizeStatusText("\n\nfirst\nsecond"), "first"); + assert.equal(sanitizeStatusText("red text"), "red text"); + assert.equal(sanitizeStatusText("multiple spaces\t\there"), "multiple spaces here"); +}); + +test("sanitizeStatusText truncates to max length with ellipsis", () => { + const long = "x".repeat(STATUS_SEGMENT_MAX_LENGTH + 20); + const result = sanitizeStatusText(long); + assert.equal(result.length, STATUS_SEGMENT_MAX_LENGTH); + assert.ok(result.endsWith("…")); +}); + +test("sanitizeStatusText respects custom max length", () => { + assert.equal(sanitizeStatusText("hello world", 5), "hell…"); + assert.equal(sanitizeStatusText("hi", 5), "hi"); +}); + +test("validateModulePath accepts paths under project root", () => { + const projectRoot = path.resolve(os.tmpdir(), "deepcode-test-project"); + const inside = path.join(projectRoot, "plugins", "status.js"); + const result = validateModulePath(inside, projectRoot); + assert.equal(result, path.normalize(inside)); +}); + +test("validateModulePath accepts relative paths resolved under project root", () => { + const projectRoot = path.resolve(os.tmpdir(), "deepcode-test-project"); + const result = validateModulePath("plugins/status.js", projectRoot); + assert.equal(result, path.normalize(path.join(projectRoot, "plugins", "status.js"))); +}); + +test("validateModulePath rejects paths outside project root and home", () => { + const projectRoot = path.resolve(os.tmpdir(), "deepcode-isolated-test"); + // Use a path guaranteed to be outside both projectRoot and HOME. + const outside = path.resolve("/totally-not-in-any-allowed-base/status.js"); + const result = validateModulePath(outside, projectRoot); + assert.equal(result, null); +}); + +test("resolveSettings produces a default statusline with no providers", () => { + const resolved = resolveSettings({}, { model: "default-model", baseURL: "https://default.example.com" }, {}); + assert.equal(resolved.statusline.enabled, false); + assert.equal(resolved.statusline.refreshMs, 2000); + assert.deepEqual(resolved.statusline.providers, []); +}); + +test("resolveSettings normalizes statusline providers and filters invalid entries", () => { + const resolved = resolveSettings( + { + statusline: { + enabled: true, + refreshMs: 3000, + providers: [ + { type: "command", id: "git", command: "git status -sb" }, + { type: "command", command: "" } as never, // invalid: empty command + { type: "module", path: "./plugins/x.js" }, + { type: "module" } as never, // invalid: missing path + { type: "unknown" } as never, // invalid: bad type + ], + }, + }, + { model: "default-model", baseURL: "https://default.example.com" }, + {} + ); + assert.equal(resolved.statusline.enabled, true); + assert.equal(resolved.statusline.refreshMs, 3000); + assert.equal(resolved.statusline.providers.length, 2); + assert.equal(resolved.statusline.providers[0]?.type, "command"); + assert.equal(resolved.statusline.providers[1]?.type, "module"); +}); + +test("resolveSettings clamps refreshMs to minimum and ignores invalid values", () => { + const tooSmall = resolveSettings({ statusline: { refreshMs: 100 } }, { model: "m", baseURL: "https://e" }, {}); + assert.equal(tooSmall.statusline.refreshMs, 2000); // falls back to default +}); + +test("createCommandStatusProvider returns stdout from short commands", async () => { + const provider = createCommandStatusProvider( + { type: "command", command: process.platform === "win32" ? "echo hello" : "printf hello" }, + process.cwd(), + "test-cmd" + ); + const ac = new AbortController(); + const result = await provider.fetch({ projectRoot: process.cwd(), signal: ac.signal }); + assert.ok(result.includes("hello")); +}); + +test("createCommandStatusProvider times out long-running commands", async () => { + const sleepCmd = process.platform === "win32" ? "ping -n 5 127.0.0.1 > nul" : "sleep 3"; + const provider = createCommandStatusProvider( + { type: "command", command: sleepCmd, timeoutMs: 200 }, + process.cwd(), + "slow" + ); + const ac = new AbortController(); + const start = Date.now(); + const result = await provider.fetch({ projectRoot: process.cwd(), signal: ac.signal }); + const elapsed = Date.now() - start; + assert.ok(elapsed < 1500, `expected timeout within ~1.5s, got ${elapsed}ms`); + assert.equal(result, ""); +}); + +test("createCommandStatusProvider returns empty on non-existent command", async () => { + const provider = createCommandStatusProvider( + { type: "command", command: "this-command-definitely-does-not-exist-xyz-abc-12345" }, + process.cwd(), + "missing" + ); + const ac = new AbortController(); + const result = await provider.fetch({ projectRoot: process.cwd(), signal: ac.signal }); + // Either empty (failure) or shell error message — both fine, just must not hang/throw. + assert.equal(typeof result, "string"); +}); + +test("loadModuleProvider returns null when the path does not exist", async () => { + const provider = await loadModuleProvider( + path.join(os.tmpdir(), "does-not-exist-xyz.mjs"), + undefined, + "missing", + 1000 + ); + assert.equal(provider, null); +}); + +test("loadModuleProvider isolates errors thrown by the user function", async () => { + // Create a temporary module that throws. + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "deepcode-statusline-")); + const modPath = path.join(dir, "bad.mjs"); + fs.writeFileSync(modPath, "export default () => { throw new Error('boom'); }", "utf8"); + try { + const provider = await loadModuleProvider(modPath, undefined, "bad", 1000); + assert.ok(provider, "provider should load even if its fn throws on invocation"); + const ac = new AbortController(); + await assert.rejects(provider!.fetch({ projectRoot: process.cwd(), signal: ac.signal })); + } finally { + fs.rmSync(dir, { recursive: true, force: true }); + } +}); + +test("loadModuleProvider succeeds for a well-formed module", async () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "deepcode-statusline-")); + const modPath = path.join(dir, "good.mjs"); + fs.writeFileSync(modPath, "export default ({ projectRoot }) => `root=${projectRoot}`;", "utf8"); + try { + const provider = await loadModuleProvider(modPath, "yellow", "good", 1000); + assert.ok(provider); + assert.equal(provider!.color, "yellow"); + const ac = new AbortController(); + const result = await provider!.fetch({ projectRoot: "/some/root", signal: ac.signal }); + assert.equal(result, "root=/some/root"); + } finally { + fs.rmSync(dir, { recursive: true, force: true }); + } +}); + +test("StatusLineManager emits segments after fetch and stops cleanly", async () => { + const config: ResolvedStatusLineSettings = { + enabled: true, + refreshMs: 60_000, + separator: " · ", + providers: [ + { + type: "command", + id: "echo", + command: process.platform === "win32" ? "echo hello" : "printf hello", + }, + ], + }; + const manager = new StatusLineManager(); + const updates: Array> = []; + const unsub = manager.subscribe((segments) => updates.push(segments.map((s) => ({ id: s.id, text: s.text })))); + await manager.start(config, process.cwd()); + + // Wait for the initial fetch to settle. + await new Promise((resolve) => setTimeout(resolve, 400)); + + unsub(); + manager.stop(); + + const populated = updates.find((u) => u.length > 0 && u[0]?.text.includes("hello")); + assert.ok(populated, `expected an update with 'hello' segment; got ${JSON.stringify(updates)}`); +}); + +test("StatusLineManager skips fetch when disabled", async () => { + const config: ResolvedStatusLineSettings = { + enabled: false, + refreshMs: 60_000, + separator: " · ", + providers: [{ type: "command", command: "echo whatever" }], + }; + const manager = new StatusLineManager(); + const updates: Array<{ id: string; text: string }[]> = []; + manager.subscribe((segs) => updates.push(segs.map((s) => ({ id: s.id, text: s.text })))); + await manager.start(config, process.cwd()); + await new Promise((resolve) => setTimeout(resolve, 100)); + manager.stop(); + assert.equal(updates.length, 0); +}); + +test("StatusLineManager isolates a failing provider from succeeding ones", async () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "deepcode-statusline-")); + const badMod = path.join(dir, "bad.mjs"); + const goodMod = path.join(dir, "good.mjs"); + fs.writeFileSync(badMod, "export default () => { throw new Error('boom'); }", "utf8"); + fs.writeFileSync(goodMod, "export default () => 'ok';", "utf8"); + + try { + const config: ResolvedStatusLineSettings = { + enabled: true, + refreshMs: 60_000, + separator: " · ", + providers: [ + { type: "module", id: "bad", path: badMod }, + { type: "module", id: "good", path: goodMod }, + ], + }; + const manager = new StatusLineManager(); + let lastSegments: Array<{ id: string; text: string }> = []; + manager.subscribe((segs) => { + lastSegments = segs.map((s) => ({ id: s.id, text: s.text })); + }); + await manager.start(config, dir); + await new Promise((resolve) => setTimeout(resolve, 400)); + manager.stop(); + assert.equal(lastSegments.length, 1); + assert.equal(lastSegments[0]?.id, "good"); + assert.equal(lastSegments[0]?.text, "ok"); + } finally { + fs.rmSync(dir, { recursive: true, force: true }); + } +}); diff --git a/packages/cli/src/ui/hooks/index.ts b/packages/cli/src/ui/hooks/index.ts index 226a6e98..4e6bda52 100644 --- a/packages/cli/src/ui/hooks/index.ts +++ b/packages/cli/src/ui/hooks/index.ts @@ -17,3 +17,5 @@ export type { PasteRegion, PasteHandlingState, PasteHandlingActions } from "./us export { useHistoryNavigation } from "./useHistoryNavigation"; export type { HistoryNavigationState, HistoryNavigationActions } from "./useHistoryNavigation"; + +export { useStatusLine } from "./useStatusLine"; diff --git a/packages/cli/src/ui/hooks/useStatusLine.ts b/packages/cli/src/ui/hooks/useStatusLine.ts new file mode 100644 index 00000000..f84534ec --- /dev/null +++ b/packages/cli/src/ui/hooks/useStatusLine.ts @@ -0,0 +1,47 @@ +import { useEffect, useMemo, useRef, useState } from "react"; +import type { ResolvedStatusLineSettings } from "@vegamo/deepcode-core"; +import { StatusLineManager } from "../statusline"; +import type { SessionInfo, StatusSegment } from "../statusline"; + +/** + * Manages a StatusLineManager lifecycle and returns the current segments. + * Starts polling when the config is enabled, stops on unmount or config change. + */ +export function useStatusLine( + config: ResolvedStatusLineSettings, + projectRoot: string, + getSessionInfo?: () => SessionInfo | null +): StatusSegment[] { + const [segments, setSegments] = useState([]); + const managerRef = useRef(null); + const getSessionInfoRef = useRef(getSessionInfo); + getSessionInfoRef.current = getSessionInfo; + + const configKey = useMemo( + () => + JSON.stringify({ + enabled: config.enabled, + refreshMs: config.refreshMs, + separator: config.separator, + providers: config.providers, + }), + [config] + ); + + useEffect(() => { + const manager = new StatusLineManager(); + managerRef.current = manager; + + const unsub = manager.subscribe(setSegments); + void manager.start(config, projectRoot, () => (getSessionInfoRef.current ? getSessionInfoRef.current() : null)); + + return () => { + unsub(); + manager.stop(); + managerRef.current = null; + }; + // eslint-disable-next-line react-hooks/exhaustive-deps -- config tracked via configKey + }, [configKey, projectRoot]); + + return segments; +} diff --git a/packages/cli/src/ui/statusline/command-provider.ts b/packages/cli/src/ui/statusline/command-provider.ts new file mode 100644 index 00000000..fb6327d0 --- /dev/null +++ b/packages/cli/src/ui/statusline/command-provider.ts @@ -0,0 +1,94 @@ +import { spawn } from "child_process"; +import * as path from "path"; +import type { StatusLineProviderConfig } from "@vegamo/deepcode-core"; +import type { StatusProvider, StatusProviderContext } from "./types"; + +const DEFAULT_TIMEOUT_MS = 1500; +const MIN_TIMEOUT_MS = 100; +const MAX_OUTPUT_BYTES = 4096; + +function resolveTimeout(value: number | undefined): number { + if (typeof value !== "number" || !Number.isFinite(value) || value < MIN_TIMEOUT_MS) { + return DEFAULT_TIMEOUT_MS; + } + return Math.floor(value); +} + +function resolveCwd(configCwd: string | undefined, projectRoot: string): string { + if (!configCwd) { + return projectRoot; + } + return path.isAbsolute(configCwd) ? configCwd : path.resolve(projectRoot, configCwd); +} + +export function createCommandStatusProvider( + config: Extract, + projectRoot: string, + id: string +): StatusProvider { + const timeoutMs = resolveTimeout(config.timeoutMs); + const cwd = resolveCwd(config.cwd, projectRoot); + + return { + id, + color: config.color, + maxLength: config.maxLength, + fetch: ({ signal }: StatusProviderContext) => + new Promise((resolve) => { + if (signal.aborted) { + resolve(""); + return; + } + const isWindows = process.platform === "win32"; + const child = spawn(config.command, { + cwd, + shell: isWindows ? true : "/bin/sh", + windowsHide: true, + stdio: ["ignore", "pipe", "pipe"], + }); + + let stdout = ""; + let stdoutBytes = 0; + let settled = false; + const finish = (value: string): void => { + if (settled) { + return; + } + settled = true; + cleanup(); + if (!child.killed) { + child.kill(); + } + resolve(value); + }; + + const onAbort = (): void => finish(""); + signal.addEventListener("abort", onAbort, { once: true }); + + const timer = setTimeout(() => finish(""), timeoutMs); + + const cleanup = (): void => { + clearTimeout(timer); + signal.removeEventListener("abort", onAbort); + }; + + child.stdout?.on("data", (chunk: Buffer | string) => { + if (settled) { + return; + } + const text = typeof chunk === "string" ? chunk : chunk.toString("utf8"); + if (stdoutBytes >= MAX_OUTPUT_BYTES) { + return; + } + const remaining = MAX_OUTPUT_BYTES - stdoutBytes; + const slice = text.length > remaining ? text.slice(0, remaining) : text; + stdout += slice; + stdoutBytes += slice.length; + }); + // Drain stderr to avoid blocking, but ignore content. + child.stderr?.on("data", () => undefined); + child.on("error", () => finish("")); + child.on("close", () => finish(stdout)); + }), + }; +} diff --git a/packages/cli/src/ui/statusline/index.ts b/packages/cli/src/ui/statusline/index.ts new file mode 100644 index 00000000..1299c8ec --- /dev/null +++ b/packages/cli/src/ui/statusline/index.ts @@ -0,0 +1,4 @@ +export { StatusLineManager } from "./manager"; +export { sanitizeStatusText, STATUS_SEGMENT_MAX_LENGTH } from "./sanitize"; +export { validateModulePath } from "./module-provider"; +export type { StatusSegment, StatusProvider, StatusProviderContext, SessionInfo } from "./types"; diff --git a/packages/cli/src/ui/statusline/manager.ts b/packages/cli/src/ui/statusline/manager.ts new file mode 100644 index 00000000..4ebd8888 --- /dev/null +++ b/packages/cli/src/ui/statusline/manager.ts @@ -0,0 +1,169 @@ +import type { ResolvedStatusLineSettings, StatusLineProviderConfig } from "@vegamo/deepcode-core"; +import { sanitizeStatusText } from "./sanitize"; +import { createCommandStatusProvider } from "./command-provider"; +import { loadModuleProvider, validateModulePath } from "./module-provider"; +import type { SessionInfo, StatusProvider, StatusSegment } from "./types"; + +type SegmentsListener = (segments: StatusSegment[]) => void; + +function segmentsEqual(a: StatusSegment[], b: StatusSegment[]): boolean { + if (a.length !== b.length) { + return false; + } + for (let i = 0; i < a.length; i++) { + if (a[i]?.id !== b[i]?.id || a[i]?.text !== b[i]?.text || a[i]?.color !== b[i]?.color) { + return false; + } + } + return true; +} + +export class StatusLineManager { + private providers: StatusProvider[] = []; + private ac: AbortController | null = null; + private timer: ReturnType | null = null; + private subscribers = new Set(); + private segments: StatusSegment[] = []; + private running = false; + private projectRoot = ""; + private getSessionInfo: (() => SessionInfo | null) | undefined; + + get currentSegments(): StatusSegment[] { + return this.segments; + } + + subscribe(fn: SegmentsListener): () => void { + this.subscribers.add(fn); + return () => { + this.subscribers.delete(fn); + }; + } + + private emit(segments: StatusSegment[]): void { + if (segmentsEqual(this.segments, segments)) { + return; + } + this.segments = segments; + for (const fn of this.subscribers) { + try { + fn(segments); + } catch { + // ignore subscriber errors + } + } + } + + async start( + config: ResolvedStatusLineSettings, + projectRoot: string, + getSessionInfo?: () => SessionInfo | null + ): Promise { + if (this.running) { + this.stop(); + } + if (!config.enabled || config.providers.length === 0) { + return; + } + + this.projectRoot = projectRoot; + this.getSessionInfo = getSessionInfo; + const { providers, refreshMs } = config; + this.ac = new AbortController(); + const { signal } = this.ac; + + // Build providers + const built: StatusProvider[] = []; + let nextId = 0; + for (const entry of providers) { + const providerId = entry.id || `${entry.type}-${nextId}`; + const provider = await this.buildProvider(entry, projectRoot, providerId); + if (provider) { + built.push(provider); + } + nextId += 1; + } + + if (built.length === 0) { + return; + } + + this.providers = built; + this.running = true; + + // Fetch immediately, then on interval. + void this.fetchAll(); + this.timer = setInterval(() => { + if (signal.aborted) { + return; + } + void this.fetchAll(); + }, refreshMs); + } + + stop(): void { + this.running = false; + if (this.timer !== null) { + clearInterval(this.timer); + this.timer = null; + } + if (this.ac) { + this.ac.abort(); + this.ac = null; + } + for (const provider of this.providers) { + provider.dispose?.(); + } + this.providers = []; + this.getSessionInfo = undefined; + } + + private async buildProvider( + config: StatusLineProviderConfig, + projectRoot: string, + providerId: string + ): Promise { + if (config.type === "command") { + return createCommandStatusProvider(config, projectRoot, providerId); + } + if (config.type === "module") { + const resolvedPath = validateModulePath(config.path, projectRoot); + if (!resolvedPath) { + return null; + } + return loadModuleProvider(resolvedPath, config.color, providerId, config.timeoutMs, config.maxLength); + } + return null; + } + + private async fetchAll(): Promise { + if (!this.ac || this.ac.signal.aborted) { + return; + } + + const results = await Promise.all( + this.providers.map(async (provider) => { + try { + const text = await provider.fetch({ + projectRoot: this.projectRoot, + signal: this.ac!.signal, + getSessionInfo: this.getSessionInfo, + }); + const sanitized = sanitizeStatusText(text, provider.maxLength); + if (!sanitized) { + return null; + } + const segment: StatusSegment = { id: provider.id, text: sanitized }; + if (provider.color) { + segment.color = provider.color; + } + return segment; + } catch { + return null; + } + }) + ); + + const segments = results.filter((s): s is StatusSegment => s !== null); + this.emit(segments); + } +} diff --git a/packages/cli/src/ui/statusline/module-provider.ts b/packages/cli/src/ui/statusline/module-provider.ts new file mode 100644 index 00000000..0222bb6c --- /dev/null +++ b/packages/cli/src/ui/statusline/module-provider.ts @@ -0,0 +1,91 @@ +import * as path from "path"; +import type { StatusProvider, StatusProviderContext } from "./types"; + +const DEFAULT_TIMEOUT_MS = 2000; + +/** + * Validate that the module path is within the allowed base directory. + * Only paths under or relative to the project root or home directory are allowed. + */ +export function validateModulePath(modulePath: string, projectRoot: string): string | null { + // Resolve relative to project root first. + const resolved = path.isAbsolute(modulePath) ? modulePath : path.resolve(projectRoot, modulePath); + const normalized = path.normalize(resolved); + + const homeDir = process.env.HOME || process.env.USERPROFILE || ""; + const allowedBases = [projectRoot]; + if (homeDir) { + allowedBases.push(homeDir); + } + + for (const base of allowedBases) { + const normalizedBase = path.normalize(base); + // Check if the resolved path is under the allowed base. + if (normalized.startsWith(normalizedBase + path.sep) || normalized === normalizedBase) { + return normalized; + } + } + return null; +} + +export async function loadModuleProvider( + resolvedPath: string, + color: string | undefined, + id: string, + timeoutMs: number | undefined, + maxLength?: number +): Promise { + try { + const timeout = + typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs >= 100 + ? Math.floor(timeoutMs) + : DEFAULT_TIMEOUT_MS; + + let mod: unknown; + try { + mod = await import(resolvedPath); + } catch { + // Try with file:// protocol + const fileUrl = path.isAbsolute(resolvedPath) ? `file://${resolvedPath}` : resolvedPath; + mod = await import(fileUrl); + } + + const providerFn = (mod as Record).default ?? (mod as Record).provider; + if (typeof providerFn !== "function") { + return null; + } + + return { + id, + color, + maxLength, + fetch: async (ctx: StatusProviderContext): Promise => { + if (ctx.signal.aborted) { + return ""; + } + const result = await Promise.race([ + Promise.resolve().then(() => + providerFn({ + projectRoot: ctx.projectRoot, + session: ctx.getSessionInfo ? ctx.getSessionInfo() : null, + }) + ), + new Promise((_, reject) => { + const timer = setTimeout(() => reject(new Error("timeout")), timeout); + ctx.signal.addEventListener( + "abort", + () => { + clearTimeout(timer); + reject(new Error("aborted")); + }, + { once: true } + ); + }), + ]); + return typeof result === "string" ? result : ""; + }, + }; + } catch { + return null; + } +} diff --git a/packages/cli/src/ui/statusline/sanitize.ts b/packages/cli/src/ui/statusline/sanitize.ts new file mode 100644 index 00000000..3beb5f7b --- /dev/null +++ b/packages/cli/src/ui/statusline/sanitize.ts @@ -0,0 +1,21 @@ +export const STATUS_SEGMENT_MAX_LENGTH = 40; + +const ANSI_PATTERN = /\x1B\[[0-?]*[ -/]*[@-~]/g; + +export function sanitizeStatusText(value: unknown, maxLength: number = STATUS_SEGMENT_MAX_LENGTH): string { + if (value === null || value === undefined) { + return ""; + } + const text = typeof value === "string" ? value : String(value); + if (!text) { + return ""; + } + // Take only first non-empty line, strip ANSI escapes, collapse whitespace. + const firstLine = text.split(/\r?\n/).find((line) => line.trim().length > 0) ?? ""; + const stripped = firstLine.replace(ANSI_PATTERN, ""); + const collapsed = stripped.replace(/\s+/g, " ").trim(); + if (collapsed.length <= maxLength) { + return collapsed; + } + return collapsed.slice(0, Math.max(1, maxLength - 1)) + "…"; +} diff --git a/packages/cli/src/ui/statusline/types.ts b/packages/cli/src/ui/statusline/types.ts new file mode 100644 index 00000000..5639138c --- /dev/null +++ b/packages/cli/src/ui/statusline/types.ts @@ -0,0 +1,39 @@ +import type { StatusLineProviderConfig } from "@vegamo/deepcode-core"; + +export type StatusSegment = { + id: string; + text: string; + color?: string; +}; + +export type SessionInfo = { + activeSessionId: string | null; + messageCount: number; + requestCount: number; + totalTokens: number; + activeTokens: number; + maxContextTokens: number; + model: string; + thinkingEnabled: boolean; + reasoningEffort: string; + toolUsage: Record; +}; + +export type StatusProviderContext = { + projectRoot: string; + signal: AbortSignal; + getSessionInfo?: () => SessionInfo | null; +}; + +export type StatusProvider = { + id: string; + color?: string; + maxLength?: number; + fetch: (ctx: StatusProviderContext) => Promise; + dispose?: () => void; +}; + +export type StatusProviderFactory = ( + config: StatusLineProviderConfig, + projectRoot: string +) => Promise; diff --git a/packages/cli/src/ui/views/App.tsx b/packages/cli/src/ui/views/App.tsx index fe1f81cf..e3cf54a2 100644 --- a/packages/cli/src/ui/views/App.tsx +++ b/packages/cli/src/ui/views/App.tsx @@ -32,6 +32,8 @@ import { renderRawModeMessages, } from "../utils"; import { resolveCurrentSettings, writeModelConfigSelection } from "@vegamo/deepcode-core"; +import { useStatusLine } from "../hooks"; +import type { SessionInfo } from "../statusline"; import { isCollapsedThinking } from "../core/thinking-state"; import { ANSI_CLEAR_SCREEN } from "../constants"; import type { @@ -45,6 +47,7 @@ import type { UserPromptContent, } from "@vegamo/deepcode-core"; import { SessionManager } from "@vegamo/deepcode-core"; +import { getCompactPromptTokenThreshold } from "@vegamo/deepcode-core"; type View = "chat" | "session-list" | "undo" | "mcp-status"; @@ -637,6 +640,61 @@ function App({ projectRoot, initialPrompt, onRestart }: AppProps): React.ReactEl const screenWidth = useMemo(() => columns ?? stdout?.columns ?? 80, [columns, stdout]); const screenHeight = useMemo(() => rows ?? stdout?.rows ?? 24, [rows, stdout]); + const getSessionInfo = useCallback((): SessionInfo | null => { + const activeSessionId = sessionManager.getActiveSessionId(); + const settings = resolveCurrentSettings(projectRoot); + const model = settings.model || ""; + const thinkingEnabled = settings.thinkingEnabled; + const reasoningEffort = settings.reasoningEffort; + const maxContextTokens = getCompactPromptTokenThreshold(model); + if (!activeSessionId) { + return { + activeSessionId: null, + messageCount: 0, + requestCount: 0, + totalTokens: 0, + activeTokens: 0, + maxContextTokens, + model, + thinkingEnabled, + reasoningEffort, + toolUsage: {}, + }; + } + const session = sessionManager.getSession(activeSessionId); + const messages = sessionManager.listSessionMessages(activeSessionId); + const usage = session?.usage; + const totalTokens = + usage && typeof (usage as { total_tokens?: unknown }).total_tokens === "number" + ? ((usage as { total_tokens: number }).total_tokens ?? 0) + : 0; + const requestCount = + usage && typeof (usage as { total_reqs?: unknown }).total_reqs === "number" + ? ((usage as { total_reqs: number }).total_reqs ?? 0) + : 0; + const toolUsage: Record = {}; + for (const msg of messages) { + if (msg.role === "tool" && msg.meta?.function) { + const fn = msg.meta.function as { name?: string }; + if (fn.name) { + toolUsage[fn.name] = (toolUsage[fn.name] || 0) + 1; + } + } + } + return { + activeSessionId, + messageCount: messages.length, + requestCount, + totalTokens, + activeTokens: session?.activeTokens ?? 0, + maxContextTokens, + model, + thinkingEnabled, + reasoningEffort, + toolUsage, + }; + }, [sessionManager, projectRoot]); + const statusLineSegments = useStatusLine(resolvedSettings.statusline, projectRoot, getSessionInfo); const promptHistory = useMemo(() => { return messages .filter((message) => message.role === "user" && typeof message.content === "string") @@ -872,6 +930,8 @@ function App({ projectRoot, initialPrompt, onRestart }: AppProps): React.ReactEl onInterrupt={handleInterrupt} onToggleProcessStdout={handleToggleProcessStdout} placeholder="Type your message..." + statusLineSegments={statusLineSegments} + statusLineSeparator={resolvedSettings.statusline.separator} /> )}
diff --git a/packages/cli/src/ui/views/PromptInput.tsx b/packages/cli/src/ui/views/PromptInput.tsx index 8124d7aa..9a24abe0 100644 --- a/packages/cli/src/ui/views/PromptInput.tsx +++ b/packages/cli/src/ui/views/PromptInput.tsx @@ -64,6 +64,7 @@ import type { ModelConfigSelection, PermissionScope } from "@vegamo/deepcode-cor import { FileMentionMenu, ModelsDropdown, RawModelDropdown, SkillsDropdown } from "../components"; import type { SessionEntry, SkillInfo } from "@vegamo/deepcode-core"; import type { UserToolPermission } from "@vegamo/deepcode-core"; +import type { StatusSegment } from "../statusline"; export type PromptSubmission = { text: string; @@ -93,6 +94,8 @@ type Props = { placeholder?: string; runningProcesses?: SessionEntry["processes"]; promptDraft?: PromptDraft | null; + statusLineSegments?: StatusSegment[]; + statusLineSeparator?: string; onSubmit: (submission: PromptSubmission) => void; onModelConfigChange: (selection: ModelConfigSelection) => string | Promise; onRawModeChange?: (mode: string) => void; @@ -123,6 +126,8 @@ export const PromptInput = React.memo(function PromptInput({ placeholder, runningProcesses, promptDraft, + statusLineSegments, + statusLineSeparator, onSubmit, onModelConfigChange, onInterrupt, @@ -839,6 +844,18 @@ export const PromptInput = React.memo(function PromptInput({ {footerText}
)} + {statusLineSegments && statusLineSegments.length > 0 && ( + + {statusLineSegments.map((segment, index) => ( + + {index > 0 && {statusLineSeparator ?? " · "}} + + {segment.text} + + + ))} + + )}
); }); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 8ad813a7..832d2444 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -26,6 +26,9 @@ export type { PermissionDefaultMode, McpServerConfig, ReasoningEffort, + StatusLineSettings, + ResolvedStatusLineSettings, + StatusLineProviderConfig, } from "./settings"; // Session diff --git a/packages/core/src/settings.ts b/packages/core/src/settings.ts index c91f0306..f7c9f51f 100644 --- a/packages/core/src/settings.ts +++ b/packages/core/src/settings.ts @@ -45,6 +45,39 @@ export type PermissionSettings = { export type EnabledSkillsSettings = Record; +export type StatusLineProviderConfig = + | { + type: "command"; + id?: string; + command: string; + cwd?: string; + timeoutMs?: number; + color?: string; + maxLength?: number; + } + | { + type: "module"; + id?: string; + path: string; + timeoutMs?: number; + color?: string; + maxLength?: number; + }; + +export type StatusLineSettings = { + enabled?: boolean; + refreshMs?: number; + separator?: string; + providers?: StatusLineProviderConfig[]; +}; + +export type ResolvedStatusLineSettings = { + enabled: boolean; + refreshMs: number; + separator: string; + providers: StatusLineProviderConfig[]; +}; + export type DeepcodingSettings = { env?: DeepcodingEnv; model?: string; @@ -58,6 +91,7 @@ export type DeepcodingSettings = { mcpServers?: Record; permissions?: PermissionSettings; enabledSkills?: EnabledSkillsSettings; + statusline?: StatusLineSettings; }; export type ResolvedDeepcodingSettings = { @@ -75,6 +109,7 @@ export type ResolvedDeepcodingSettings = { mcpServers?: Record; permissions: Required; enabledSkills: EnabledSkillsSettings; + statusline: ResolvedStatusLineSettings; }; export type ModelConfigSelection = { @@ -216,6 +251,116 @@ function mergeEnabledSkills( }; } +const DEFAULT_STATUSLINE_REFRESH_MS = 2000; +const MIN_STATUSLINE_REFRESH_MS = 500; +const DEFAULT_STATUSLINE_SEPARATOR = " · "; + +function isPlainObject(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function normalizeStatusLineProvider(value: unknown): StatusLineProviderConfig | null { + if (!isPlainObject(value)) { + return null; + } + const type = value["type"]; + const idRaw = trimString(value["id"]); + const id = idRaw || undefined; + const timeoutRaw = value["timeoutMs"]; + const timeoutMs = + typeof timeoutRaw === "number" && Number.isFinite(timeoutRaw) && timeoutRaw > 0 + ? Math.floor(timeoutRaw) + : undefined; + const colorRaw = trimString(value["color"]); + const color = colorRaw || undefined; + const maxLengthRaw = value["maxLength"]; + const maxLength = + typeof maxLengthRaw === "number" && Number.isFinite(maxLengthRaw) && maxLengthRaw > 0 + ? Math.floor(maxLengthRaw) + : undefined; + + if (type === "command") { + const command = trimString(value["command"]); + if (!command) { + return null; + } + const cwdRaw = trimString(value["cwd"]); + return { + type: "command", + id, + command, + cwd: cwdRaw || undefined, + timeoutMs, + color, + maxLength, + }; + } + if (type === "module") { + const modulePath = trimString(value["path"]); + if (!modulePath) { + return null; + } + return { + type: "module", + id, + path: modulePath, + timeoutMs, + color, + maxLength, + }; + } + return null; +} + +function normalizeStatusLine(value: unknown): StatusLineSettings | null { + if (!isPlainObject(value)) { + return null; + } + const result: StatusLineSettings = {}; + const enabled = parseBoolean(value["enabled"]); + if (enabled !== undefined) { + result.enabled = enabled; + } + const refreshRaw = value["refreshMs"]; + if (typeof refreshRaw === "number" && Number.isFinite(refreshRaw) && refreshRaw >= MIN_STATUSLINE_REFRESH_MS) { + result.refreshMs = Math.floor(refreshRaw); + } + const separator = value["separator"]; + if (typeof separator === "string") { + result.separator = separator; + } + const providers = value["providers"]; + if (Array.isArray(providers)) { + const normalized: StatusLineProviderConfig[] = []; + for (const entry of providers) { + const provider = normalizeStatusLineProvider(entry); + if (provider) { + normalized.push(provider); + } + } + result.providers = normalized; + } + return result; +} + +function mergeStatusLine( + userSettings: DeepcodingSettings | null | undefined, + projectSettings: DeepcodingSettings | null | undefined +): ResolvedStatusLineSettings { + const userConfig = normalizeStatusLine(userSettings?.statusline) ?? {}; + const projectConfig = normalizeStatusLine(projectSettings?.statusline) ?? {}; + const providers = [...(userConfig.providers ?? []), ...(projectConfig.providers ?? [])]; + const enabled = projectConfig.enabled ?? userConfig.enabled ?? providers.length > 0; + const refreshMs = projectConfig.refreshMs ?? userConfig.refreshMs ?? DEFAULT_STATUSLINE_REFRESH_MS; + const separator = projectConfig.separator ?? userConfig.separator ?? DEFAULT_STATUSLINE_SEPARATOR; + return { + enabled, + refreshMs, + separator, + providers, + }; +} + function normalizeEnv(env: DeepcodingSettings["env"]): Record { const result: Record = {}; if (!env) { @@ -393,6 +538,7 @@ export function resolveSettingsSources( mcpServers: mergeMcpServers(userSettings, projectSettings, userEnv, projectEnv, systemEnv), permissions: mergePermissions(userSettings, projectSettings), enabledSkills: mergeEnabledSkills(userSettings, projectSettings), + statusline: mergeStatusLine(userSettings, projectSettings), }; } From f291919df6a2a07b464c7e7b0d602706bf233ada Mon Sep 17 00:00:00 2001 From: hcyang Date: Tue, 23 Jun 2026 10:52:57 +0800 Subject: [PATCH 42/72] =?UTF-8?q?chore(release):=20=E6=96=B0=E5=A2=9E=20VS?= =?UTF-8?q?Code=20=E6=89=A9=E5=B1=95=E5=8F=91=E5=B8=83=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E5=8F=8A=E6=B5=81=E7=A8=8B=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 scripts/prepare-vscode.js,实现 VSCode 扩展构建发布自动化 - 在 package.json 中新增 prepare:vscode 脚本命令 - 更新 .gitignore,忽略环境变量文件 .env 和 .env.local - 新增 .env.example,说明 VSCE_PAT 环境变量用法 - 在 RELEASE.md 和 RELEASE_en.md 中添加 prepare:vscode 使用说明及发布流程 - 增加发布流程示例,支持单独发布 CLI 和 VSCode 扩展 - 脚本支持版本号参数、dry-run 和 force 分支跳过检查选项 - 业务逻辑包括版本更新、质量检查、测试、构建、发布、Git 提交和打标签 --- .env.example | 4 + .gitignore | 4 + RELEASE.md | 69 +++++++++- RELEASE_en.md | 69 +++++++++- package.json | 1 + scripts/prepare-vscode.js | 260 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 395 insertions(+), 12 deletions(-) create mode 100644 .env.example create mode 100644 scripts/prepare-vscode.js diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..aab21d64 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# VS Code Marketplace publish token +# Generate at: https://dev.azure.com/vegamo/_usersSettings/tokens +# Permission required: Marketplace → Publish +VSCE_PAT= diff --git a/.gitignore b/.gitignore index 37f64ba0..634aea11 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,10 @@ out/ # TypeScript build info files *.tsbuildinfo +# Environment variables +.env +.env.local + # Generated files packages/cli/src/generated/ packages/core/src/generated/ diff --git a/RELEASE.md b/RELEASE.md index 19229167..b6479f30 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,13 +1,14 @@ # 版本发布 -Deep Code 使用两个脚本管理 monorepo 的版本发布流程: +Deep Code 使用三个脚本管理 monorepo 的版本发布流程: | 脚本 | 命令 | 用途 | |------|------|------| | `scripts/version.js` | `npm run release:version` | 升级所有 workspace 包的版本号 + 重新生成 lockfile | -| `scripts/prepare-package.js` | `npm run prepare:package` | 构建 + 质量检查 + 发布到 npm + git commit & tag | +| `scripts/prepare-package.js` | `npm run prepare:package` | 构建 CLI + 质量检查 + 发布到 npm + git commit & tag | +| `scripts/prepare-vscode.js` | `npm run prepare:vscode` | 构建 VSCode 扩展 + 质量检查 + 发布到 VS Code 市场 + git commit & tag | -两者配合使用,先升版本号,再发布。 +发布流程:先升版本号,再分别发布 CLI 和 VSCode 扩展。 --- @@ -172,6 +173,58 @@ npx @vegamo/deepcode-cli --version --- +## prepare:vscode — 构建并发布 VSCode 扩展到市场 + +完成质量检查、构建、发布 VSCode 扩展到 VS Code Marketplace,并自动创建 git commit 和 tag。 + +### 前置条件 + +需要 Azure DevOps Personal Access Token(PAT)用于市场认证: + +1. 访问 https://dev.azure.com/vegamo/_usersSettings/tokens 生成 token +2. 设置环境变量 `VSCE_PAT=` + +### 基本用法 + +```bash +VSCE_PAT= npm run prepare:vscode -- [options] +``` + +### 参数 + +| 参数 | 说明 | +|------|------| +| `` | **必填**,要发布的 semver 版本号 | +| `--dry-run` | 预演模式,不实际执行任何写操作 | +| `--force` | 跳过 main 分支检查,允许从其他分支发布 | + +### 执行流程(7 步) + +| 步骤 | 操作 | 说明 | +|------|------|------| +| 1 | Git 检查 | 工作区必须 clean,必须在 main 分支 | +| 2 | VSCE_PAT 检查 | 环境变量必须已设置 | +| 3 | 更新版本号 | 同时更新 `packages/core`、`packages/cli`、`packages/vscode-ide-companion` 的 version | +| 4 | 质量检查 | `npm run check`(typecheck + eslint + prettier) | +| 5 | 测试 | `npm run test --workspaces` | +| 6 | 构建 | `npm run build:vscode`(core tsc + esbuild 打包扩展 + 拷贝模板 + vsce package) | +| 7 | 发布 | `vsce publish --no-dependencies` 发布到 VS Code Marketplace | + +### 完整示例 + +```bash +# 发布正式版 +VSCE_PAT=xxx npm run prepare:vscode -- 0.1.32 + +# 发布预发布版 +VSCE_PAT=xxx npm run prepare:vscode -- 0.1.32-beta.1 + +# 预演(不实际发布) +npm run prepare:vscode -- 0.1.32 --dry-run +``` + +--- + ## 典型发布流程 一个完整的版本发布通常按以下步骤进行: @@ -190,18 +243,22 @@ git diff git add -A git commit -m "chore(release): v0.1.32" -# 5. 构建 + 质量检查 + 发布 +# 5. 构建 + 质量检查 + 发布 CLI npm run prepare:package -- 0.1.32 -# 6. 推送到 remote +# 6. 发布 VSCode 扩展 +VSCE_PAT=xxx npm run prepare:vscode -- 0.1.32 + +# 7. 推送到 remote git push && git push --tags ``` -也可以简化为两步(`prepare:package` 会自动 commit 和 tag): +也可以简化为三步(`prepare:package` 和 `prepare:vscode` 各自自动 commit 和 tag): ```bash npm run release:version -- patch npm run prepare:package -- 0.1.32 +VSCE_PAT=xxx npm run prepare:vscode -- 0.1.32 git push && git push --tags ``` diff --git a/RELEASE_en.md b/RELEASE_en.md index e6cd7013..2f0fbcca 100644 --- a/RELEASE_en.md +++ b/RELEASE_en.md @@ -1,13 +1,14 @@ # Release -Deep Code uses two scripts to manage version releases in the monorepo: +Deep Code uses three scripts to manage version releases in the monorepo: | Script | Command | Purpose | |--------|---------|---------| | `scripts/version.js` | `npm run release:version` | Bump all workspace package versions + regenerate lockfile | -| `scripts/prepare-package.js` | `npm run prepare:package` | Build + quality checks + publish to npm + git commit & tag | +| `scripts/prepare-package.js` | `npm run prepare:package` | Build CLI + quality checks + publish to npm + git commit & tag | +| `scripts/prepare-vscode.js` | `npm run prepare:vscode` | Build VSCode extension + quality checks + publish to VS Code Marketplace + git commit & tag | -Use them together: bump version first, then publish. +Release flow: bump version first, then publish CLI and VSCode extension separately. --- @@ -172,6 +173,58 @@ npx @vegamo/deepcode-cli --version --- +## prepare:vscode — Build and Publish VSCode Extension to Marketplace + +Runs quality checks, builds, publishes the VSCode extension to the VS Code Marketplace, and automatically creates a git commit with tag. + +### Prerequisites + +Requires an Azure DevOps Personal Access Token (PAT) for marketplace authentication: + +1. Generate a token at https://dev.azure.com/vegamo/_usersSettings/tokens +2. Set the environment variable `VSCE_PAT=` + +### Basic Usage + +```bash +VSCE_PAT= npm run prepare:vscode -- [options] +``` + +### Arguments + +| Argument | Description | +|----------|-------------| +| `` | **Required**. Semver version to publish | +| `--dry-run` | Preview mode, no actual writes | +| `--force` | Skip main branch check, allow publishing from other branches | + +### Execution Flow (7 Steps) + +| Step | Action | Description | +|------|--------|-------------| +| 1 | Git check | Working tree must be clean, must be on main branch | +| 2 | VSCE_PAT check | Environment variable must be set | +| 3 | Update versions | Updates `packages/core`, `packages/cli`, and `packages/vscode-ide-companion` version fields | +| 4 | Quality checks | `npm run check` (typecheck + eslint + prettier) | +| 5 | Tests | `npm run test --workspaces` | +| 6 | Build | `npm run build:vscode` (core tsc + esbuild bundle extension + copy templates + vsce package) | +| 7 | Publish | `vsce publish --no-dependencies` to VS Code Marketplace | + +### Examples + +```bash +# Publish stable release +VSCE_PAT=xxx npm run prepare:vscode -- 0.1.32 + +# Publish pre-release +VSCE_PAT=xxx npm run prepare:vscode -- 0.1.32-beta.1 + +# Dry run (no actual publish) +npm run prepare:vscode -- 0.1.32 --dry-run +``` + +--- + ## Typical Release Flow A complete version release follows these steps: @@ -190,18 +243,22 @@ git diff git add -A git commit -m "chore(release): v0.1.32" -# 5. Build + quality check + publish +# 5. Build + quality check + publish CLI npm run prepare:package -- 0.1.32 -# 6. Push to remote +# 6. Publish VSCode extension +VSCE_PAT=xxx npm run prepare:vscode -- 0.1.32 + +# 7. Push to remote git push && git push --tags ``` -Or simplified to two steps (`prepare:package` auto-commits and tags): +Or simplified to three steps (`prepare:package` and `prepare:vscode` each auto-commit and tag): ```bash npm run release:version -- patch npm run prepare:package -- 0.1.32 +VSCE_PAT=xxx npm run prepare:vscode -- 0.1.32 git push && git push --tags ``` diff --git a/package.json b/package.json index c9a0e723..d4f502b4 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "test": "npm run test --workspaces --if-present", "release:version": "node scripts/version.js", "prepare:package": "node scripts/prepare-package.js", + "prepare:vscode": "node scripts/prepare-vscode.js", "prepare": "husky && npm run build && npm run bundle" }, "devDependencies": { diff --git a/scripts/prepare-vscode.js b/scripts/prepare-vscode.js new file mode 100644 index 00000000..a9e0cb83 --- /dev/null +++ b/scripts/prepare-vscode.js @@ -0,0 +1,260 @@ +import { spawnSync } from "node:child_process"; +import { readFileSync, writeFileSync, existsSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const root = join(__dirname, ".."); + +// Load .env file if VSCE_PAT is not already set +if (!process.env.VSCE_PAT) { + const envPath = join(root, ".env"); + if (existsSync(envPath)) { + const lines = readFileSync(envPath, "utf-8").split("\n"); + for (const line of lines) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith("#")) continue; + const eqIdx = trimmed.indexOf("="); + if (eqIdx === -1) continue; + const key = trimmed.slice(0, eqIdx).trim(); + const value = trimmed.slice(eqIdx + 1).trim(); + if (key && !process.env[key]) { + process.env[key] = value; + } + } + } +} + +// ── Helpers ────────────────────────────────────────────────────────────────── + +function log(msg) { + console.log(msg); +} + +function step(n, total, msg) { + console.log(`\n[${n}/${total}] ${msg}`); +} + +function fail(msg) { + console.error(`\n❌ ${msg}`); + process.exit(1); +} + +function ok(msg) { + console.log(`✅ ${msg}`); +} + +function run(cmd, args, opts = {}) { + const label = opts.label ?? `${cmd} ${args.join(" ")}`; + if (opts.dryRun) { + log(` (dry-run) ${label}`); + return { status: 0, stdout: "" }; + } + const result = spawnSync(cmd, args, { + stdio: opts.stdio ?? "inherit", + cwd: opts.cwd ?? root, + shell: true, + env: { ...process.env, ...opts.env }, + }); + if (result.status !== 0) { + fail(`Command failed: ${label}`); + } + return result; +} + +function readJson(filePath) { + return JSON.parse(readFileSync(filePath, "utf-8")); +} + +function writeJson(filePath, data) { + writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8"); +} + +function isValidSemver(v) { + return /^\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$/.test(v); +} + +// ── Parse args ─────────────────────────────────────────────────────────────── + +const args = process.argv.slice(2); +let version = null; +let dryRun = false; +let force = false; + +for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (arg === "--dry-run") { + dryRun = true; + } else if (arg === "--force") { + force = true; + } else if (!version) { + version = arg; + } else { + fail(`Unknown argument: ${arg}`); + } +} + +if (!version) { + log(` +Usage: node scripts/prepare-vscode.js [options] + +Arguments: + Semver version to publish (e.g. 0.1.32, 0.2.0-beta.1) + +Options: + --dry-run Preview all steps without executing + --force Skip branch check (publish from non-main branch) + +Environment: + VSCE_PAT Required. Azure DevOps Personal Access Token for marketplace auth. + Generate at: https://dev.azure.com/vegamo/_usersSettings/tokens + Can also be set in .env file (auto-loaded). + +Examples: + VSCE_PAT=xxx node scripts/prepare-vscode.js 0.1.32 + node scripts/prepare-vscode.js 0.1.32-beta.1 + node scripts/prepare-vscode.js 0.1.32 --dry-run +`); + process.exit(1); +} + +if (!isValidSemver(version)) { + fail(`Invalid semver version: ${version}`); +} + +const TOTAL_STEPS = 7; + +// ── Banner ─────────────────────────────────────────────────────────────────── + +log("========================================="); +log(` Deep Code VSCode — Publish v${version}`); +log(` dryRun=${dryRun} force=${force}`); +log("========================================="); + +// ── 1. Git checks ──────────────────────────────────────────────────────────── + +step(1, TOTAL_STEPS, "Checking git state..."); + +const gitStatus = spawnSync("git", ["status", "--porcelain"], { + cwd: root, + encoding: "utf-8", + shell: true, +}); +if (gitStatus.stdout.trim()) { + fail("Working tree is not clean. Commit or stash changes first."); +} +ok("Working tree is clean"); + +if (!force) { + const gitBranch = spawnSync("git", ["branch", "--show-current"], { + cwd: root, + encoding: "utf-8", + shell: true, + }); + const branch = gitBranch.stdout.trim(); + if (branch !== "main") { + fail(`Not on main branch (current: ${branch}). Use --force to publish from another branch.`); + } + ok("On main branch"); +} + +// ── 2. VSCE_PAT check ──────────────────────────────────────────────────────── + +step(2, TOTAL_STEPS, "Checking VSCE_PAT..."); + +if (!dryRun) { + if (!process.env.VSCE_PAT) { + fail( + "VSCE_PAT environment variable is not set.\n Generate a Personal Access Token at:\n https://dev.azure.com/vegamo/_usersSettings/tokens\n Then: VSCE_PAT= node scripts/prepare-vscode.js " + ); + } + ok("VSCE_PAT is set"); +} else { + log(" (dry-run) skipping VSCE_PAT check"); +} + +// ── 3. Version bump ────────────────────────────────────────────────────────── + +step(3, TOTAL_STEPS, "Updating package version..."); + +const vscodePkgPath = join(root, "packages", "vscode-ide-companion", "package.json"); + +const vscodePkg = readJson(vscodePkgPath); + +const oldVersion = vscodePkg.version; + +vscodePkg.version = version; + +if (!dryRun) { + writeJson(vscodePkgPath, vscodePkg); + ok(`Updated packages/vscode-ide-companion: ${oldVersion} → ${version}`); +} else { + log(` (dry-run) packages/vscode-ide-companion: ${oldVersion} → ${version}`); +} + +// ── 4. Quality checks ──────────────────────────────────────────────────────── + +step(4, TOTAL_STEPS, "Running quality checks (typecheck + lint + format)..."); + +run("npm", ["run", "check"], { dryRun }); +ok("All checks passed"); + +// ── 5. Tests ────────────────────────────────────────────────────────────────── + +step(5, TOTAL_STEPS, "Running tests..."); + +run("npm", ["run", "test", "--workspaces"], { dryRun }); +ok("All tests passed"); + +// ── 6. Build ────────────────────────────────────────────────────────────────── + +step(6, TOTAL_STEPS, "Building VSCode extension..."); + +run("npm", ["run", "build:vscode"], { dryRun }); +ok("VSCode extension built"); + +// ── 7. Publish to marketplace ───────────────────────────────────────────────── + +step(7, TOTAL_STEPS, "Publishing deepcode-vscode to marketplace..."); + +const vscodeRoot = join(root, "packages", "vscode-ide-companion"); +const vsceArgs = ["vsce", "publish", version, "--no-dependencies"]; +if (dryRun) vsceArgs.splice(2, 0, "--dry-run"); + +run("npx", vsceArgs, { + cwd: vscodeRoot, + env: { VSCE_PAT: process.env.VSCE_PAT }, + label: `npx ${vsceArgs.join(" ")}`, +}); +ok(`Published deepcode-vscode@${version} to marketplace`); + +// ── Git commit + tag ───────────────────────────────────────────────────────── + +if (!dryRun) { + log("\nCreating git commit and tag..."); + run("git", ["add", "packages/vscode-ide-companion/package.json"], { + label: "git add packages/vscode-ide-companion/package.json", + }); + run("git", ["commit", "-m", `chore(release): vscode v${version}`], { + label: `git commit -m "chore(release): vscode v${version}"`, + }); + run("git", ["tag", `vscode-v${version}`], { + label: `git tag vscode-v${version}`, + }); + ok(`Created commit and tag vscode-v${version}`); +} else { + log("\n (dry-run) git add + commit + tag"); +} + +// ── Done ───────────────────────────────────────────────────────────────────── + +console.log("\n========================================="); +console.log(` 🎉 Published deepcode-vscode@${version} successfully!`); +console.log("========================================="); +console.log(` + Verify: + https://marketplace.visualstudio.com/items?itemName=vegamo.deepcode-vscode + + Push to remote: + git push && git push --tags +`); From 01b68053838ef43f6ed1a4d1374865676941f247 Mon Sep 17 00:00:00 2001 From: hcyang Date: Tue, 23 Jun 2026 14:42:59 +0800 Subject: [PATCH 43/72] =?UTF-8?q?chore(vscode-ide-companion):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20package.json=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 preview 字段,标记为预览版本 - 修正 repository URL 结构,添加目录字段 - 扩展 categories,新增 Chat 分类 - 格式化部分字段列表,使结构更清晰 --- packages/vscode-ide-companion/package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/vscode-ide-companion/package.json b/packages/vscode-ide-companion/package.json index fd4da3ac..6369f37b 100644 --- a/packages/vscode-ide-companion/package.json +++ b/packages/vscode-ide-companion/package.json @@ -7,15 +7,18 @@ "license": "MIT", "type": "commonjs", "main": "./out/extension.js", + "preview": true, "repository": { "type": "git", - "url": "git+https://github.com/lessweb/deepcode-cli.git" + "url": "https://github.com/lessweb/deepcode-cli.git", + "directory": "packages/vscode-ide-companion" }, "engines": { "vscode": "^1.85.0" }, "categories": [ - "AI" + "AI", + "Chat" ], "keywords": [ "deep-code", From bac49377cfd0c74c8ccab4b473c247fb2ead5713 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Tue, 23 Jun 2026 15:25:09 +0800 Subject: [PATCH 44/72] docs: update .deepcode/AGENTS.md --- .deepcode/AGENTS.md | 144 ++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 79 deletions(-) diff --git a/.deepcode/AGENTS.md b/.deepcode/AGENTS.md index 9d827b0e..a1611307 100644 --- a/.deepcode/AGENTS.md +++ b/.deepcode/AGENTS.md @@ -2,78 +2,61 @@ ## Project Structure & Module Organization +This is an **npm workspaces monorepo**. Packages live under `packages/`. + ``` -src/ -├── cli.tsx # Entry point — parses args (-p, -v), renders Ink App -├── session.ts # SessionManager — LLM loop, compaction, tool orchestration -├── settings.ts # Settings resolution from ~/.deepcode/settings.json -├── prompt.ts # System prompt builder, tool definitions, built-in skills -├── common/ -│ ├── bash-timeout.ts # Bash command timeout enforcement -│ ├── debug-logger.ts # Debug logging for OpenAI API calls -│ ├── error-logger.ts # API error logging -│ ├── file-history.ts # GitFileHistory — checkpoint/undo via Git branches -│ ├── file-utils.ts # File read/write with encoding and diff preview -│ ├── model-capabilities.ts # Model detection and thinking-mode defaults -│ ├── notify.ts # Desktop notification after LLM turn completion -│ ├── openai-client.ts # OpenAI client singleton with keep-alive agent -│ ├── openai-thinking.ts # OpenAI thinking request options builder -│ ├── permissions.ts # Permission scoping, decisions, and tool-call tracking -│ ├── process-tree.ts # Process tree construction and orphan detection -│ ├── shell-utils.ts # Shell path resolution (Git Bash, zsh, bash) -│ ├── state.ts # In-memory file state and snippet tracking -│ ├── telemetry.ts # Usage telemetry collection and reporting -│ ├── update-check.ts # Latest-version check against npm registry -│ └── validate.ts # Tool validation runtime helpers (was runtime.ts) -├── mcp/ -│ ├── mcp-client.ts # MCP client — JSON-RPC communication with MCP servers -│ └── mcp-manager.ts # MCP manager — lifecycle, tool registration, execution, status -├── tools/ -│ ├── executor.ts # ToolExecutor — dispatches tool calls to handlers (7 built-in) -│ ├── bash-handler.ts # Executes shell commands with live stdout streaming -│ ├── read-handler.ts # Reads files, images, PDFs, and notebooks -│ ├── write-handler.ts # Creates/overwrites files -│ ├── edit-handler.ts # Scoped string replacements with snippet tracking -│ ├── update-plan-handler.ts # Updates the task plan progress display -│ ├── web-search-handler.ts # Web search via natural language queries -│ └── ask-user-question-handler.ts # Interactive user prompts with options -├── ui/ -│ ├── components/ # Reusable Ink components (MessageView, DropdownMenu, ModelsDropdown, SkillsDropdown, FileMentionMenu, RawModelDropdown, etc.) -│ ├── contexts/ # React contexts (AppContext, RawModeContext) -│ ├── hooks/ # Custom hooks (cursor, useHistoryNavigation, usePasteHandling, useTerminalInput) -│ ├── views/ # Top-level screen components (App, PromptInput, SessionList, PermissionPrompt, ProcessStdoutView, WelcomeScreen, UndoSelector, etc.) -│ ├── core/ # Core UI logic (file-mentions, slash-commands, prompt-buffer, thinking-state, clipboard, prompt-undo-redo, etc.) -│ ├── utils/ # Shared utility helpers -│ ├── ascii-art.ts # ASCII art banner for welcome screen -│ ├── exit-summary.ts # Session exit summary and cost reporting -│ ├── index.ts # UI module barrel exports -│ └── constants.ts # UI-wide constants -├── tests/ # Test files per source module, plus run-tests.mjs -templates/ -├── tools/ # Tool descriptions fed to the LLM -├── skills/ # Built-in skill definitions (agent-drift-guard, plan-and-execute, karpathy-guidelines) -└── prompts/ # EJS templates (e.g., init_command.md.ejs) -docs/ # User-facing documentation (configuration, MCP, notify, permissions) -resources/ # Static assets (intro screenshots) -dist/ # Bundled CLI output (gitignored) +packages/ +├── core/src/ # LLM session, tool execution, shared utilities +│ ├── common/ # File I/O, permissions, telemetry, OpenAI client, shell utils, etc. +│ ├── tools/ # 7 built-in handlers (bash, read, write, edit, web-search, ask-user-question, update-plan) +│ ├── mcp/ # MCP client & manager (JSON-RPC lifecycle) +│ ├── session.ts # SessionManager — LLM loop, compaction, tool orchestration +│ ├── prompt.ts # System prompt builder & tool definitions +│ └── settings.ts # Settings resolution from ~/.deepcode/settings.json +├── cli/src/ # Terminal UI (Ink/React) +│ ├── cli.tsx # Entry point — parses args (-p, -v), renders AppContainer +│ ├── ui/views/ # Top-level screens (App, PromptInput, SessionList, PermissionPrompt, etc.) +│ ├── ui/components/ # Reusable Ink components (MessageView, DropdownMenu, ModelsDropdown, etc.) +│ ├── ui/core/ # Prompt buffer, slash commands, file mentions, clipboard, undo/redo +│ ├── ui/hooks/ # Custom hooks (cursor, history navigation, paste handling, terminal input) +│ ├── ui/contexts/ # React contexts (AppContext, RawModeContext) +│ └── tests/ # UI-focused tests with run-tests.mjs runner +├── vscode-ide-companion/ # VSCode extension companion +│ └── src/ # extension.ts, provider.ts, utils.ts +docs/ # User-facing documentation (configuration, MCP, notify, permissions) +scripts/ # Build, release, and packaging scripts +dist/ # Bundled CLI output — single-file dist/cli.js (gitignored) +dist/bundled/ # Bundled skills & references shipped with the CLI ``` +Templates for tool descriptions and prompts are at `packages/cli/dist/templates/` (copied during build from `packages/core/templates/`). Built-in skills are under `packages/cli/dist/bundled/`. + ## Build, Test, and Development Commands -| Command | Purpose | +All commands run from the repo root. + +| Command | What it does | |---|---| -| `npm run typecheck` | TypeScript type checking (`tsc --noEmit`) | -| `npm run lint` | ESLint across `src/` | +| `npm run typecheck` | TypeScript type checking across all workspaces | +| `npm run lint` | ESLint across `packages/*/src/**/*.{ts,tsx}` + `scripts/*.js` | | `npm run lint:fix` | ESLint with auto-fix | -| `npm run format` | Prettier on all `src/**/*.{ts,tsx}` | +| `npm run format` | Prettier on all source files | | `npm run format:check` | Prettier in check-only mode | | `npm run check` | Runs typecheck + lint + format:check together | -| `npm run bundle` | esbuild bundles cli + core + all deps → `dist/cli.js` (ESM, Node 22) | -| `npm run build` | build core (tsc) + rewrite ESM imports + bundle CLI (esbuild) | -| `npm test` | Runs all tests via `node src/tests/run-tests.mjs` | -| `npm run test:single -- ` | Run a single test file via `tsx --test` (e.g., `npm run test:single -- src/tests/session.test.ts`) | +| `npm run build` | Orchestrates full build (scripts/build.js) — compiles core + bundles CLI + copies assets | +| `npm run bundle` | Generates git commit info + esbuild bundle + copies bundled assets | +| `npm test` | Runs all workspace tests (`npm run test --workspaces --if-present`) | +| `npm run start` | Runs the locally built CLI (`scripts/start.js`) | +| `npm run build-and-start` | Builds then starts the CLI | +| `npm run clean` | Removes generated files and dist directories | + +To run a **single test file** within a package: +``` +node packages/core/src/tests/run-tests.mjs packages/core/src/tests/session.test.ts +node packages/cli/src/tests/run-tests.mjs packages/cli/src/tests/slash-commands.test.ts +``` -Run the CLI locally for manual testing: `node dist/cli.js` (after `npm run bundle`). +Run the CLI locally for manual testing: `node packages/cli/dist/cli.js` (after `npm run bundle`). ## Coding Style & Naming Conventions @@ -84,9 +67,9 @@ Run the CLI locally for manual testing: `node dist/cli.js` (after `npm run bundl - **Line width**: 120 characters max - **Line endings**: LF only -**TypeScript**: Strict mode enabled. Use `import type` for type-only imports (enforced by `@typescript-eslint/consistent-type-imports`). Unused variables prefixed with `_` are allowed. +**TypeScript**: Strict mode enabled (`strict: true`). Use `import type` for type-only imports (`@typescript-eslint/consistent-type-imports`). Unused variables prefixed with `_` are allowed (`argsIgnorePattern: "^_"`). Target ES2022, module ESNext with bundler resolution. JSX is `react-jsx`. -**Formatting/Linting**: Prettier + ESLint (typescript-eslint, react-hooks). Run `npm run check` before pushing. On commit, Husky + lint-staged auto-formats staged `*.{ts,tsx,js,mjs,cjs,ejs,jsx}` and `*.json` files. +**Formatting/Linting**: Prettier (double quotes, 2-space indent, semicolons) + ESLint (typescript-eslint, react-hooks). Run `npm run check` before pushing. On commit, Husky + lint-staged auto-formats staged `*.{ts,tsx,js,mjs,cjs,jsx}` and `*.json` files. **File naming**: `kebab-case.ts` for modules, `kebab-case.tsx` for React/Ink components. Test files: `*.test.ts` (always kebab-case). @@ -94,22 +77,24 @@ Run the CLI locally for manual testing: `node dist/cli.js` (after `npm run bundl - **Framework**: Node.js native test runner (`node:test`) with `tsx` for TypeScript - **Assertions**: `node:assert/strict` -- **Coverage**: Target meaningful unit tests for core logic (session management, tool handlers, settings resolution, prompt buffer, permissions, MCP client, telemetry). Test files are in `src/tests/` matching the source module name. +- **Coverage**: Target meaningful unit tests for core logic (session management, tool handlers, settings resolution, prompt buffer, permissions, MCP client, telemetry). Test files are in `packages/*/src/tests/` matching the source module name. - **Test naming**: `describe`/`test` blocks with descriptive names. Example: `test("SessionManager preserves structured system content when building OpenAI messages", ...)` - **Relaxed lint rules**: Test files allow `any` and unused vars. -- Run all tests with `npm test` before submitting a PR. A cross-platform test runner is available at `src/tests/run-tests.mjs`. +- Run all tests with `npm test` before submitting a PR. Each package has its own `run-tests.mjs` cross-platform runner. ## Commit & Pull Request Guidelines -**Commit messages** follow conventional commits. From the project history: +**Commit messages** follow conventional commits: - `feat:` — new feature (e.g., `feat: add /model command`) -- `fix:` — bug fix (e.g., `fix(ui): redraw cleanly after terminal resize`) +- `fix:` — bug fix (e.g., `fix(mcp): fix Windows MCP spawn double-quoting`) - `chore:` — tooling, deps, hooks (e.g., `chore: add husky + lint-staged`) - `refactor:` — code restructuring (e.g., `refactor(ui): optimize App hooks`) -- `style:` — formatting-only changes (e.g., `style: adjust the tree structure symbols`) -- `test:` — adding or updating tests (e.g., `test: add telemetry module unit tests`) -- `docs:` — documentation (e.g., `docs: add MCP configuration guide`) +- `style:` — formatting-only changes +- `test:` — adding or updating tests +- `docs:` — documentation changes +- `perf:` — performance improvements +- `build:` — build system changes **Pull requests** should include: - A clear description of what changed and why @@ -120,22 +105,23 @@ Run the CLI locally for manual testing: `node dist/cli.js` (after `npm run bundl ## Architecture Overview -The CLI (`@vegamo/deepcode-cli`) renders a terminal UI using [Ink](https://github.com/vadimdemedes/ink) (React for terminals). `SessionManager` drives the LLM interaction loop: it builds system prompts, sends user messages with optional skills/images, streams responses, executes tool calls via `ToolExecutor`, and compacts context when token thresholds are exceeded (512K for DeepSeek V4 models, 128K for others). OpenAI client connectivity is managed by `createOpenAIClient()` in `src/common/openai-client.ts`, which caches the client singleton and applies a 180-second keep-alive timeout. +The CLI (`@vegamo/deepcode-cli`) renders a terminal UI using [Ink](https://github.com/vadimdemedes/ink) (React for terminals). `SessionManager` (in `@vegamo/deepcode-core`) drives the LLM interaction loop: it builds system prompts, sends user messages with optional skills/images, streams responses, executes tool calls via `ToolExecutor`, and compacts context when token thresholds are exceeded (512K for DeepSeek V4 models, 128K for others). OpenAI client connectivity is managed by `createOpenAIClient()` with a 180-second keep-alive timeout. -Seven built-in tools are available to the LLM: `bash`, `read`, `write`, `edit`, `AskUserQuestion`, `UpdatePlan`, and `WebSearch`. Tool definitions are registered in `src/tools/executor.ts` and described to the LLM via `src/prompt.ts` and `templates/tools/`. The `UpdatePlan` tool enables the LLM to display and update a structured task list in the terminal. +Seven built-in tools are available to the LLM: `bash`, `read`, `write`, `edit`, `AskUserQuestion`, `UpdatePlan`, and `WebSearch`. Tool definitions are registered in `packages/core/src/tools/executor.ts` and described to the LLM via `packages/core/src/prompt.ts`. -A **permission system** (`src/common/permissions.ts`) controls tool execution scopes (read/write/delete/network/git-log, etc.) with configurable allow/deny/ask decisions. The `PermissionPrompt` view presents interactive prompts when a tool requires user approval. +A **permission system** (`packages/core/src/common/permissions.ts`) controls tool execution scopes (read/write/delete/network/git-log, etc.) with configurable allow/deny/ask decisions. -A **file history system** (`src/common/file-history.ts`) provides undo/checkpoint support by creating lightweight Git branches per session. The `GitFileHistory` class manages blob storage and branch references via a `.deepcode-file-history.json` manifest. +A **file history system** (`packages/core/src/common/file-history.ts`) provides undo/checkpoint support via lightweight Git branches. -**Slash commands**: `/model`, `/new`, `/init`, `/resume`, `/continue`, `/mcp`, `/exit`, plus dynamic `/skill-name` for each loaded skill. +**Slash commands**: `/skills`, `/model`, `/new`, `/init`, `/resume`, `/continue`, `/undo`, `/mcp`, `/raw`, `/exit`, plus dynamic `/skill-name` for each loaded skill. -**Key UI features**: `@` file mentions in the prompt input (scans project files), `Ctrl+O` to view live process stdout in fullscreen, `Ctrl+V` to paste images, MCP server status display, undo selector, and permission prompts. +**Key UI features**: `@` file mentions in the prompt input, `Ctrl+O` to view live process stdout, `Ctrl+V` to paste images, Shift+Enter for newlines, MCP server status display, undo selector, and permission prompts. **CLI flags**: `-p ` / `--prompt` to auto-submit a prompt on launch, `-v` / `--version`, `-h` / `--help`. ## Agent-Specific Instructions -- **AGENTS.md loading**: The CLI loads agent instructions from `./AGENTS.md`, `./.deepcode/AGENTS.md`, or `~/.deepcode/AGENTS.md` (first found wins). Write project-specific guidance for the LLM in any of these. +- **AGENTS.md loading**: The CLI loads agent instructions from `./AGENTS.md`, `./.deepcode/AGENTS.md`, or `~/.deepcode/AGENTS.md` (first found wins). - **Skills**: Place skill definitions in `~/.agents/skills//SKILL.md` (user-level) or `./.agents/skills//SKILL.md` (project-level). Legacy path `./.deepcode/skills/` is also supported. Each SKILL.md uses YAML frontmatter with `name` and `description` fields. -- **Built-in skills**: `agent-drift-guard` (detects and corrects execution drift), `plan-and-execute` (structured task planning with progress tracking), and `karpathy-guidelines` (behavioral guidelines to reduce common LLM coding mistakes). All three are defined in `templates/skills/` and always injected into every session. +- **Built-in skills**: Four bundled skills ship with the CLI — `plan` (task planning workflow), `deepcode-self-refer` (Deep Code CLI documentation), `skill-digester` (digest & install skills), `skill-writer` (create & debug skills). Additionally, `karpathy-guidelines` (behavioral guidelines to reduce LLM coding mistakes) is injected as a default skill template. +- **Prompt file references**: Use `@path/to/file` syntax in prompts to load file contents through the read tool. From ad11d9af15bb7114d32c4da02c78394adb5a60a7 Mon Sep 17 00:00:00 2001 From: hcyang Date: Tue, 23 Jun 2026 16:08:24 +0800 Subject: [PATCH 45/72] =?UTF-8?q?feat(cli):=20=E6=94=AF=E6=8C=81=E9=80=9A?= =?UTF-8?q?=E8=BF=87=20--resume=20=E5=8F=82=E6=95=B0=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 App 组件中新增 resumeSessionId 属性以支持恢复会话功能 - 在 AppContainer 中传递 resumeSessionId 以贯穿组件树 - 在 cli.tsx 中解析并传递 --resume 参数,支持无 ID 列出会话选择 - 新增构建退出摘要时显示 resume 会话提示的逻辑 - 添加对应单元测试覆盖 resumeSessionId 解析及退出摘要展示 - 抽离 cli 参数解析函数,支持提取初始提示和恢复会话 ID - 修复退出摘要文本,添加 resume 使用提示,提升用户体验 --- packages/cli/src/cli-args.ts | 31 +++++++++ packages/cli/src/cli.tsx | 12 ++-- packages/cli/src/tests/cli-args.test.ts | 76 +++++++++++++++++++++ packages/cli/src/tests/exit-summary.test.ts | 38 +++++++++++ packages/cli/src/ui/exit-summary.ts | 9 ++- packages/cli/src/ui/views/App.tsx | 21 +++++- packages/cli/src/ui/views/AppContainer.tsx | 10 ++- 7 files changed, 184 insertions(+), 13 deletions(-) create mode 100644 packages/cli/src/cli-args.ts create mode 100644 packages/cli/src/tests/cli-args.test.ts diff --git a/packages/cli/src/cli-args.ts b/packages/cli/src/cli-args.ts new file mode 100644 index 00000000..5ae0325e --- /dev/null +++ b/packages/cli/src/cli-args.ts @@ -0,0 +1,31 @@ +/** + * CLI argument parsing helpers. + * Extracted from cli.tsx for testability. + */ + +export function extractInitialPrompt(args: string[]): string | undefined { + const promptIndex = args.findIndex((arg) => arg === "-p" || arg === "--prompt"); + if (promptIndex !== -1 && promptIndex + 1 < args.length) { + return args[promptIndex + 1]; + } + return undefined; +} + +/** + * Extract the --resume flag value. + * + * Returns: + * - `undefined` — `--resume` was not used + * - `true` — `--resume` was used without a session ID (show session picker) + * - `string` — `--resume ` was used (resume specific session) + */ +export function extractResumeSessionId(args: string[]): string | true | undefined { + const idx = args.findIndex((arg) => arg === "--resume"); + if (idx === -1) { + return undefined; + } + if (idx + 1 < args.length && !args[idx + 1].startsWith("-")) { + return args[idx + 1]; + } + return true; +} diff --git a/packages/cli/src/cli.tsx b/packages/cli/src/cli.tsx index c595916b..4812f9eb 100644 --- a/packages/cli/src/cli.tsx +++ b/packages/cli/src/cli.tsx @@ -3,6 +3,7 @@ import { render } from "ink"; import { setShellIfWindows } from "@vegamo/deepcode-core"; import { checkForNpmUpdate, promptForPendingUpdate, type PackageInfo } from "./common/update-check"; import { AppContainer } from "./ui"; +import { extractInitialPrompt, extractResumeSessionId } from "./cli-args"; const args = process.argv.slice(2); const packageInfo = readPackageInfo(); @@ -21,6 +22,7 @@ if (args.includes("--help") || args.includes("-h")) { " deepcode Launch the interactive TUI in the current directory", " deepcode -p Launch with a pre-filled prompt", " deepcode --prompt Same as -p", + " deepcode --resume [sessionId] Resume a specific session by its ID. Use without an ID to show session picker", " deepcode --version Print the version", " deepcode --help Show this help", "", @@ -58,15 +60,8 @@ if (args.includes("--help") || args.includes("-h")) { process.exit(0); } -function extractInitialPrompt(args: string[]): string | undefined { - const promptIndex = args.findIndex((arg) => arg === "-p" || arg === "--prompt"); - if (promptIndex !== -1 && promptIndex + 1 < args.length) { - return args[promptIndex + 1]; - } - return undefined; -} - let initialPrompt = extractInitialPrompt(args); +const resumeSessionId = extractResumeSessionId(args); const projectRoot = process.cwd(); configureWindowsShell(); @@ -94,6 +89,7 @@ async function main(): Promise { projectRoot={projectRoot} version={packageInfo.version} initialPrompt={appInitialPrompt} + resumeSessionId={resumeSessionId} onRestart={() => restartRef.current?.()} />, { exitOnCtrlC: false } diff --git a/packages/cli/src/tests/cli-args.test.ts b/packages/cli/src/tests/cli-args.test.ts new file mode 100644 index 00000000..e42a4b00 --- /dev/null +++ b/packages/cli/src/tests/cli-args.test.ts @@ -0,0 +1,76 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { extractInitialPrompt, extractResumeSessionId } from "../cli-args"; + +// ── extractInitialPrompt ───────────────────────────────────────────────────── + +test("extractInitialPrompt returns prompt after -p", () => { + assert.equal(extractInitialPrompt(["-p", "hello world"]), "hello world"); +}); + +test("extractInitialPrompt returns prompt after --prompt", () => { + assert.equal(extractInitialPrompt(["--prompt", "hello world"]), "hello world"); +}); + +test("extractInitialPrompt returns undefined when -p is not present", () => { + assert.equal(extractInitialPrompt(["--version"]), undefined); +}); + +test("extractInitialPrompt returns undefined when -p has no value", () => { + assert.equal(extractInitialPrompt(["-p"]), undefined); +}); + +test("extractInitialPrompt returns undefined for empty args", () => { + assert.equal(extractInitialPrompt([]), undefined); +}); + +test("extractInitialPrompt ignores -p in non-flag position", () => { + assert.equal(extractInitialPrompt(["--resume", "-p", "hello"]), "hello"); +}); + +// ── extractResumeSessionId ─────────────────────────────────────────────────── + +test("extractResumeSessionId returns session ID after --resume", () => { + assert.equal( + extractResumeSessionId(["--resume", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"]), + "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6" + ); +}); + +test("extractResumeSessionId returns true when --resume has no value (show picker)", () => { + assert.equal(extractResumeSessionId(["--resume"]), true); +}); + +test("extractResumeSessionId returns true when --resume is followed by another flag", () => { + assert.equal(extractResumeSessionId(["--resume", "--force"]), true); +}); + +test("extractResumeSessionId returns undefined when --resume is not present", () => { + assert.equal(extractResumeSessionId(["--version"]), undefined); +}); + +test("extractResumeSessionId returns undefined for empty args", () => { + assert.equal(extractResumeSessionId([]), undefined); +}); + +test("extractResumeSessionId works with other flags after sessionId", () => { + assert.equal(extractResumeSessionId(["--resume", "abc-123", "--force"]), "abc-123"); +}); + +test("extractResumeSessionId does not confuse --resume with other args", () => { + assert.equal(extractResumeSessionId(["-p", "test"]), undefined); +}); + +// ── combined usage ─────────────────────────────────────────────────────────── + +test("extractInitialPrompt and extractResumeSessionId work independently", () => { + const args = ["--resume", "session-123", "-p", "hello"]; + assert.equal(extractResumeSessionId(args), "session-123"); + assert.equal(extractInitialPrompt(args), "hello"); +}); + +test("extractResumeSessionId with --resume and -p but no sessionId", () => { + const args = ["--resume", "-p", "hello"]; + assert.equal(extractResumeSessionId(args), true); + assert.equal(extractInitialPrompt(args), "hello"); +}); diff --git a/packages/cli/src/tests/exit-summary.test.ts b/packages/cli/src/tests/exit-summary.test.ts index e0d481db..d768c165 100644 --- a/packages/cli/src/tests/exit-summary.test.ts +++ b/packages/cli/src/tests/exit-summary.test.ts @@ -90,6 +90,44 @@ test("buildExitSummaryText does not derive usage rows from legacy aggregate usag assert.doesNotMatch(summary, /11,966/); }); +test("buildExitSummaryText shows resume hint when sessionId is provided", () => { + const sessionId = "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"; + const summary = stripAnsi( + buildExitSummaryText({ + session: buildSession(null), + sessionId, + }) + ); + + assert.match(summary, /Goodbye!/); + assert.match(summary, /deepcode --resume 0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6/); + assert.match(summary, /To continue this session/); +}); + +test("buildExitSummaryText does not show resume hint when sessionId is omitted", () => { + const summary = stripAnsi( + buildExitSummaryText({ + session: buildSession(null), + }) + ); + + assert.match(summary, /Goodbye!/); + assert.doesNotMatch(summary, /deepcode --resume/); + assert.doesNotMatch(summary, /To continue this session/); +}); + +test("buildExitSummaryText shows resume hint with null session", () => { + const summary = stripAnsi( + buildExitSummaryText({ + session: null, + sessionId: "test-session-id", + }) + ); + + assert.match(summary, /Goodbye!/); + assert.match(summary, /deepcode --resume test-session-id/); +}); + function buildSession(usage: ModelUsage | null, usagePerModel: Record | null = null): SessionEntry { return { id: "session-1", diff --git a/packages/cli/src/ui/exit-summary.ts b/packages/cli/src/ui/exit-summary.ts index 25e09b48..baef723a 100644 --- a/packages/cli/src/ui/exit-summary.ts +++ b/packages/cli/src/ui/exit-summary.ts @@ -4,6 +4,7 @@ import type { ModelUsage, SessionEntry } from "@vegamo/deepcode-core"; type ExitSummaryInput = { session: SessionEntry | null; + sessionId?: string; }; const ANSI_RE = /\u001b\[[0-9;]*[a-zA-Z]/g; @@ -67,7 +68,7 @@ function extractUsageFields(usage: ModelUsage | null): UsageFields { } export function buildExitSummaryText(input: ExitSummaryInput): string { - const { session } = input; + const { session, sessionId } = input; const innerWidth = 98; const contentWidth = innerWidth - 4; // "│ " prefix + " │" suffix → 4 chars padding @@ -134,6 +135,12 @@ export function buildExitSummaryText(input: ExitSummaryInput): string { rows.push(""); + if (sessionId) { + const resumeHint = chalk.dim(`To continue this session, run deepcode --resume ${sessionId}`); + rows.push(resumeHint); + rows.push(""); + } + const border = borderColor("─".repeat(innerWidth)); const top = `${borderColor("╭")}${border}${borderColor("╮")}`; const bottom = `${borderColor("╰")}${border}${borderColor("╯")}`; diff --git a/packages/cli/src/ui/views/App.tsx b/packages/cli/src/ui/views/App.tsx index fe1f81cf..afcaa26c 100644 --- a/packages/cli/src/ui/views/App.tsx +++ b/packages/cli/src/ui/views/App.tsx @@ -53,6 +53,7 @@ const STATUS_SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", type AppProps = { projectRoot: string; initialPrompt?: string; + resumeSessionId?: string | true; onRestart?: () => void; }; @@ -89,12 +90,13 @@ const StatusLine = React.memo(function StatusLine({ ); }); -function App({ projectRoot, initialPrompt, onRestart }: AppProps): React.ReactElement { +function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProps): React.ReactElement { const { exit } = useApp(); const { stdout, write } = useStdout(); const { columns, rows } = useWindowSize(); const { mode, setMode } = useRawModeContext(); const initialPromptSubmittedRef = useRef(false); + const resumeSessionIdRef = useRef(false); const processStdoutRef = useRef>(new Map()); const rawModeRef = useRef(mode); const writeRef = useRef(write); @@ -288,7 +290,7 @@ function App({ projectRoot, initialPrompt, onRestart }: AppProps): React.ReactEl setTimeout(() => { const activeSessionId = sessionManager.getActiveSessionId(); const session = activeSessionId ? sessionManager.getSession(activeSessionId) : null; - const summary = buildExitSummaryText({ session }); + const summary = buildExitSummaryText({ session, sessionId: activeSessionId ?? undefined }); process.stdout.write("\n"); process.stdout.write(chalk.rgb(34, 154, 195)("> /exit ")); process.stdout.write("\n\n"); @@ -506,6 +508,21 @@ function App({ projectRoot, initialPrompt, onRestart }: AppProps): React.ReactEl [sessionManager, resetStaticView, pendingPermissionReply, refreshSkills] ); + useEffect(() => { + if (resumeSessionIdRef.current || !resumeSessionId) { + return; + } + + resumeSessionIdRef.current = true; + if (resumeSessionId === true) { + // No session ID — show the session picker (same as /resume) + refreshSessionsList(); + navigateToSubView("session-list"); + } else { + handleSelectSession(resumeSessionId); + } + }, [handleSelectSession, navigateToSubView, refreshSessionsList, resumeSessionId]); + const handleDeleteSession = useCallback( async (id: string): Promise => { const isActiveSession = sessionManager.getActiveSessionId() === id; diff --git a/packages/cli/src/ui/views/AppContainer.tsx b/packages/cli/src/ui/views/AppContainer.tsx index d5f6363a..555588f1 100644 --- a/packages/cli/src/ui/views/AppContainer.tsx +++ b/packages/cli/src/ui/views/AppContainer.tsx @@ -7,12 +7,18 @@ const AppContainer: React.FC<{ projectRoot: string; version: string; initialPrompt: string | undefined; + resumeSessionId: string | true | undefined; onRestart: () => void; -}> = ({ version, projectRoot, initialPrompt, onRestart }) => { +}> = ({ version, projectRoot, initialPrompt, resumeSessionId, onRestart }) => { return ( - + ); From 361f2b171fe72efd4d588b5730105b22626a1394 Mon Sep 17 00:00:00 2001 From: hcyang Date: Tue, 23 Jun 2026 16:31:37 +0800 Subject: [PATCH 46/72] =?UTF-8?q?fix(cli):=20=E9=AA=8C=E8=AF=81=20--resume?= =?UTF-8?q?=20=E5=8F=82=E6=95=B0=E4=B8=AD=E7=9A=84=E4=BC=9A=E8=AF=9DID?= =?UTF-8?q?=E6=9C=89=E6=95=88=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在启动 TUI 之前校验传入的 resumeSessionId 是否在本地会话索引中存在 - 读取用户主目录下的 sessions-index.json 文件进行会话ID验证 - 未找到匹配会话时输出错误信息并退出进程 - 在 App 组件中移除对会话ID重复验证的注释补充说明 - 确保 resumeSessionId 已经校验通过后才调用 handleSelectSession --- packages/cli/src/cli.tsx | 22 +++++++++++++++++++++- packages/cli/src/ui/views/App.tsx | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/cli.tsx b/packages/cli/src/cli.tsx index 4812f9eb..80513f78 100644 --- a/packages/cli/src/cli.tsx +++ b/packages/cli/src/cli.tsx @@ -1,6 +1,9 @@ import React from "react"; import { render } from "ink"; -import { setShellIfWindows } from "@vegamo/deepcode-core"; +import { readFileSync, existsSync } from "node:fs"; +import { join } from "node:path"; +import { homedir } from "node:os"; +import { setShellIfWindows, getProjectCode } from "@vegamo/deepcode-core"; import { checkForNpmUpdate, promptForPendingUpdate, type PackageInfo } from "./common/update-check"; import { AppContainer } from "./ui"; import { extractInitialPrompt, extractResumeSessionId } from "./cli-args"; @@ -65,6 +68,23 @@ const resumeSessionId = extractResumeSessionId(args); const projectRoot = process.cwd(); configureWindowsShell(); +// Validate --resume before entering TUI +if (typeof resumeSessionId === "string") { + const projectCode = getProjectCode(projectRoot); + const indexPath = join(homedir(), ".deepcode", "projects", projectCode, "sessions-index.json"); + try { + const index = JSON.parse(readFileSync(indexPath, "utf-8")); + const found = Array.isArray(index?.entries) && index.entries.some((e: { id: string }) => e.id === resumeSessionId); + if (!found) { + process.stderr.write(`No saved session found with ID "${resumeSessionId}".\n`); + process.exit(1); + } + } catch { + process.stderr.write(`No saved session found with ID "${resumeSessionId}".\n`); + process.exit(1); + } +} + if (!process.stdin.isTTY) { process.stderr.write("deepcode requires an interactive terminal (TTY). " + "Re-run from a real terminal session.\n"); process.exit(1); diff --git a/packages/cli/src/ui/views/App.tsx b/packages/cli/src/ui/views/App.tsx index afcaa26c..4175b49d 100644 --- a/packages/cli/src/ui/views/App.tsx +++ b/packages/cli/src/ui/views/App.tsx @@ -519,6 +519,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp refreshSessionsList(); navigateToSubView("session-list"); } else { + // Session ID already validated in cli.tsx — guaranteed to exist handleSelectSession(resumeSessionId); } }, [handleSelectSession, navigateToSubView, refreshSessionsList, resumeSessionId]); From c47b1166d767b80979dd3043103aba653889a03b Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Tue, 23 Jun 2026 16:58:14 +0800 Subject: [PATCH 47/72] feat: when defaultMode is set to allowAll, "unknown" scope permissions should be allowed by default. --- packages/core/src/common/permissions.ts | 6 ++- packages/core/src/tests/permissions.test.ts | 42 +++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/packages/core/src/common/permissions.ts b/packages/core/src/common/permissions.ts index 822fcca4..f50d485c 100644 --- a/packages/core/src/common/permissions.ts +++ b/packages/core/src/common/permissions.ts @@ -273,7 +273,7 @@ export function evaluatePermissionScopes( defaultMode: "allowAll", } ): PermissionDecision { - if (scopes.includes("unknown")) { + if (scopes.includes("unknown") && settings.defaultMode !== "allowAll") { return "ask"; } if (scopes.length === 0) { @@ -304,7 +304,9 @@ export function getPermissionScopesRequiringAsk( const result: AskPermissionScope[] = []; for (const scope of scopes) { if (scope === "unknown") { - result.push(scope); + if (settings.defaultMode !== "allowAll") { + result.push(scope); + } continue; } if (settings.deny.includes(scope)) { diff --git a/packages/core/src/tests/permissions.test.ts b/packages/core/src/tests/permissions.test.ts index 5e8bf1e8..d7ca2c5e 100644 --- a/packages/core/src/tests/permissions.test.ts +++ b/packages/core/src/tests/permissions.test.ts @@ -7,6 +7,7 @@ import { appendProjectPermissionAllows, computeToolCallPermissions, evaluatePermissionScopes, + getPermissionScopesRequiringAsk, hasUserPermissionReplies, isPathInAnyDirectory, parseBashSideEffects, @@ -46,6 +47,47 @@ test("evaluatePermissionScopes applies deny, ask, allow, and default mode preced assert.equal(evaluatePermissionScopes(["unknown"], settings), "ask"); }); +test("evaluatePermissionScopes allows unknown when defaultMode is allowAll", () => { + const allowAllSettings = { + allow: [] as const, + deny: [] as const, + ask: [] as const, + defaultMode: "allowAll" as const, + }; + assert.equal(evaluatePermissionScopes(["unknown"], allowAllSettings), "allow"); + + // unknown + other scopes that would otherwise trigger ask should still ask for those scopes + const askNetworkSettings = { + allow: [] as const, + deny: [] as const, + ask: ["network" as const], + defaultMode: "allowAll" as const, + }; + assert.equal(evaluatePermissionScopes(["unknown", "network"], askNetworkSettings), "ask"); +}); + +test("getPermissionScopesRequiringAsk excludes unknown when defaultMode is allowAll", () => { + const allowAllSettings = { + allow: [] as const, + deny: [] as const, + ask: ["network" as const], + defaultMode: "allowAll" as const, + }; + const result = getPermissionScopesRequiringAsk(["unknown", "network"], allowAllSettings); + assert.deepEqual(result, ["network"]); +}); + +test("getPermissionScopesRequiringAsk includes unknown when defaultMode is askAll", () => { + const askAllSettings = { + allow: [] as const, + deny: [] as const, + ask: ["network" as const], + defaultMode: "askAll" as const, + }; + const result = getPermissionScopesRequiringAsk(["unknown", "network"], askAllSettings); + assert.deepEqual(result, ["unknown", "network"]); +}); + test("computeToolCallPermissions maps tool calls to permission requests", () => { const projectRoot = createTempDir("deepcode-permissions-workspace-"); const plan = computeToolCallPermissions({ From dc068a6935b3e14d01970a9775e6b7207397ded5 Mon Sep 17 00:00:00 2001 From: dengmik-commits <270912164+dengmik-commits@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:49:17 +0800 Subject: [PATCH 48/72] fix: prevent duplicate statusline when user/project settings are the same file When the CLI is launched from ~ (home directory), user-level and project-level settings.json resolve to the same file. This caused resolveSettingsSources to merge the same content twice, resulting in duplicate statusline segments and React non-unique key warnings. Fix: detect same-file early in resolveCurrentSettings and pass null for project settings when paths are identical. --- packages/core/src/settings.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/core/src/settings.ts b/packages/core/src/settings.ts index f7c9f51f..019b7f38 100644 --- a/packages/core/src/settings.ts +++ b/packages/core/src/settings.ts @@ -654,9 +654,12 @@ export function writeModelConfigSelection( } export function resolveCurrentSettings(projectRoot: string = process.cwd()): ResolvedDeepcodingSettings { + const userPath = path.resolve(getUserSettingsPath()); + const projectPath = path.resolve(getProjectSettingsPath(projectRoot)); + const sameFile = userPath === projectPath; return resolveSettingsSources( readSettings(), - readProjectSettings(projectRoot), + sameFile ? null : readProjectSettings(projectRoot), { model: DEFAULT_MODEL, baseURL: DEFAULT_BASE_URL, From a2c74df41679301089c089890f24d0d05586460c Mon Sep 17 00:00:00 2001 From: dengmik-commits <270912164+dengmik-commits@users.noreply.github.com> Date: Tue, 23 Jun 2026 19:05:24 +0800 Subject: [PATCH 49/72] fix: statusline provider id dedup, newLine support, and CI type errors - Project-level providers override user-level by id instead of appending - Add newLine option to break statusline into multiple rows - Remove external deepcode-core from esbuild (bundle inline) - Fix permissions.test.ts readonly array type errors --- packages/cli/src/tests/statusline.test.ts | 29 ++++++++++++++- .../cli/src/ui/statusline/command-provider.ts | 1 + packages/cli/src/ui/statusline/manager.ts | 22 ++++++++++-- packages/cli/src/ui/statusline/types.ts | 2 ++ packages/cli/src/ui/views/PromptInput.tsx | 36 ++++++++++++++----- packages/core/src/settings.ts | 10 +++++- packages/core/src/tests/permissions.test.ts | 25 ++++++------- scripts/esbuild.config.js | 1 - 8 files changed, 100 insertions(+), 26 deletions(-) diff --git a/packages/cli/src/tests/statusline.test.ts b/packages/cli/src/tests/statusline.test.ts index fffc15a1..4417cca1 100644 --- a/packages/cli/src/tests/statusline.test.ts +++ b/packages/cli/src/tests/statusline.test.ts @@ -7,7 +7,7 @@ import { sanitizeStatusText, STATUS_SEGMENT_MAX_LENGTH } from "../ui/statusline/ import { validateModulePath, loadModuleProvider } from "../ui/statusline/module-provider"; import { createCommandStatusProvider } from "../ui/statusline/command-provider"; import { StatusLineManager } from "../ui/statusline/manager"; -import { resolveSettings } from "@vegamo/deepcode-core"; +import { resolveSettings, resolveSettingsSources } from "@vegamo/deepcode-core"; import type { ResolvedStatusLineSettings } from "@vegamo/deepcode-core"; test("sanitizeStatusText returns empty for null/undefined/empty", () => { @@ -171,6 +171,33 @@ test("loadModuleProvider succeeds for a well-formed module", async () => { } }); +test("resolveSettingsSources lets project-level providers override user-level by id", () => { + const resolved = resolveSettingsSources( + { + statusline: { + enabled: true, + providers: [ + { type: "command", id: "model", command: "echo user-model" }, + { type: "command", id: "branch", command: "echo user-branch" }, + ], + }, + }, + { + statusline: { + providers: [ + { type: "command", id: "model", command: "echo project-model" }, + { type: "command", id: "cwd", command: "echo project-cwd" }, + ], + }, + }, + { model: "default-model", baseURL: "https://default.example.com" } + ); + const ids = resolved.statusline.providers.map((p) => p.id); + assert.deepEqual(ids, ["branch", "model", "cwd"]); + const modelProvider = resolved.statusline.providers.find((p) => p.id === "model"); + assert.equal(modelProvider?.type === "command" && modelProvider.command, "echo project-model"); +}); + test("StatusLineManager emits segments after fetch and stops cleanly", async () => { const config: ResolvedStatusLineSettings = { enabled: true, diff --git a/packages/cli/src/ui/statusline/command-provider.ts b/packages/cli/src/ui/statusline/command-provider.ts index fb6327d0..c89545a4 100644 --- a/packages/cli/src/ui/statusline/command-provider.ts +++ b/packages/cli/src/ui/statusline/command-provider.ts @@ -32,6 +32,7 @@ export function createCommandStatusProvider( return { id, color: config.color, + newLine: config.newLine, maxLength: config.maxLength, fetch: ({ signal }: StatusProviderContext) => new Promise((resolve) => { diff --git a/packages/cli/src/ui/statusline/manager.ts b/packages/cli/src/ui/statusline/manager.ts index 4ebd8888..9f4015ff 100644 --- a/packages/cli/src/ui/statusline/manager.ts +++ b/packages/cli/src/ui/statusline/manager.ts @@ -11,7 +11,12 @@ function segmentsEqual(a: StatusSegment[], b: StatusSegment[]): boolean { return false; } for (let i = 0; i < a.length; i++) { - if (a[i]?.id !== b[i]?.id || a[i]?.text !== b[i]?.text || a[i]?.color !== b[i]?.color) { + if ( + a[i]?.id !== b[i]?.id || + a[i]?.text !== b[i]?.text || + a[i]?.color !== b[i]?.color || + a[i]?.newLine !== b[i]?.newLine + ) { return false; } } @@ -130,7 +135,17 @@ export class StatusLineManager { if (!resolvedPath) { return null; } - return loadModuleProvider(resolvedPath, config.color, providerId, config.timeoutMs, config.maxLength); + const provider = await loadModuleProvider( + resolvedPath, + config.color, + providerId, + config.timeoutMs, + config.maxLength + ); + if (provider && config.newLine) { + provider.newLine = true; + } + return provider; } return null; } @@ -156,6 +171,9 @@ export class StatusLineManager { if (provider.color) { segment.color = provider.color; } + if (provider.newLine) { + segment.newLine = true; + } return segment; } catch { return null; diff --git a/packages/cli/src/ui/statusline/types.ts b/packages/cli/src/ui/statusline/types.ts index 5639138c..6f687e61 100644 --- a/packages/cli/src/ui/statusline/types.ts +++ b/packages/cli/src/ui/statusline/types.ts @@ -4,6 +4,7 @@ export type StatusSegment = { id: string; text: string; color?: string; + newLine?: boolean; }; export type SessionInfo = { @@ -29,6 +30,7 @@ export type StatusProvider = { id: string; color?: string; maxLength?: number; + newLine?: boolean; fetch: (ctx: StatusProviderContext) => Promise; dispose?: () => void; }; diff --git a/packages/cli/src/ui/views/PromptInput.tsx b/packages/cli/src/ui/views/PromptInput.tsx index 9a24abe0..2bf720b1 100644 --- a/packages/cli/src/ui/views/PromptInput.tsx +++ b/packages/cli/src/ui/views/PromptInput.tsx @@ -845,15 +845,33 @@ export const PromptInput = React.memo(function PromptInput({ )} {statusLineSegments && statusLineSegments.length > 0 && ( - - {statusLineSegments.map((segment, index) => ( - - {index > 0 && {statusLineSeparator ?? " · "}} - - {segment.text} - - - ))} + + {(() => { + const lines: StatusSegment[][] = []; + let currentLine: StatusSegment[] = []; + for (const segment of statusLineSegments) { + if (segment.newLine && currentLine.length > 0) { + lines.push(currentLine); + currentLine = []; + } + currentLine.push(segment); + } + if (currentLine.length > 0) { + lines.push(currentLine); + } + return lines.map((line, lineIndex) => ( + + {line.map((segment, index) => ( + + {index > 0 && {statusLineSeparator ?? " · "}} + + {segment.text} + + + ))} + + )); + })()} )} diff --git a/packages/core/src/settings.ts b/packages/core/src/settings.ts index 019b7f38..5dab3b5a 100644 --- a/packages/core/src/settings.ts +++ b/packages/core/src/settings.ts @@ -53,6 +53,7 @@ export type StatusLineProviderConfig = cwd?: string; timeoutMs?: number; color?: string; + newLine?: boolean; maxLength?: number; } | { @@ -61,6 +62,7 @@ export type StatusLineProviderConfig = path: string; timeoutMs?: number; color?: string; + newLine?: boolean; maxLength?: number; }; @@ -278,6 +280,7 @@ function normalizeStatusLineProvider(value: unknown): StatusLineProviderConfig | typeof maxLengthRaw === "number" && Number.isFinite(maxLengthRaw) && maxLengthRaw > 0 ? Math.floor(maxLengthRaw) : undefined; + const newLine = value["newLine"] === true ? true : undefined; if (type === "command") { const command = trimString(value["command"]); @@ -292,6 +295,7 @@ function normalizeStatusLineProvider(value: unknown): StatusLineProviderConfig | cwd: cwdRaw || undefined, timeoutMs, color, + newLine, maxLength, }; } @@ -306,6 +310,7 @@ function normalizeStatusLineProvider(value: unknown): StatusLineProviderConfig | path: modulePath, timeoutMs, color, + newLine, maxLength, }; } @@ -349,7 +354,10 @@ function mergeStatusLine( ): ResolvedStatusLineSettings { const userConfig = normalizeStatusLine(userSettings?.statusline) ?? {}; const projectConfig = normalizeStatusLine(projectSettings?.statusline) ?? {}; - const providers = [...(userConfig.providers ?? []), ...(projectConfig.providers ?? [])]; + const userProviders = userConfig.providers ?? []; + const projectProviders = projectConfig.providers ?? []; + const projectIds = new Set(projectProviders.map((p) => p.id)); + const providers = [...userProviders.filter((p) => !projectIds.has(p.id)), ...projectProviders]; const enabled = projectConfig.enabled ?? userConfig.enabled ?? providers.length > 0; const refreshMs = projectConfig.refreshMs ?? userConfig.refreshMs ?? DEFAULT_STATUSLINE_REFRESH_MS; const separator = projectConfig.separator ?? userConfig.separator ?? DEFAULT_STATUSLINE_SEPARATOR; diff --git a/packages/core/src/tests/permissions.test.ts b/packages/core/src/tests/permissions.test.ts index 5e8bf1e8..bc7393c7 100644 --- a/packages/core/src/tests/permissions.test.ts +++ b/packages/core/src/tests/permissions.test.ts @@ -11,6 +11,7 @@ import { isPathInAnyDirectory, parseBashSideEffects, } from "../common/permissions"; +import type { PermissionScope } from "../settings"; const tempDirs: string[] = []; @@ -52,10 +53,10 @@ test("computeToolCallPermissions maps tool calls to permission requests", () => sessionId: "session-1", projectRoot, settings: { - allow: [], - deny: [], - ask: ["write-out-cwd", "network"], - defaultMode: "allowAll", + allow: [] as PermissionScope[], + deny: [] as PermissionScope[], + ask: ["write-out-cwd", "network"] as PermissionScope[], + defaultMode: "allowAll" as const, }, resolveSnippetPath: () => path.join(projectRoot, "src", "file.ts"), toolCalls: [ @@ -100,10 +101,10 @@ test("computeToolCallPermissions only asks for scopes not already allowed", () = sessionId: "session-1", projectRoot, settings: { - allow: ["read-in-cwd"], - deny: [], - ask: [], - defaultMode: "askAll", + allow: ["read-in-cwd"] as PermissionScope[], + deny: [] as PermissionScope[], + ask: [] as PermissionScope[], + defaultMode: "askAll" as const, }, toolCalls: [ { @@ -138,10 +139,10 @@ test("computeToolCallPermissions allows read tool calls under skill scan paths", projectRoot, readPermissionExemptPaths: [skillRoot], settings: { - allow: [], - deny: [], - ask: [], - defaultMode: "askAll", + allow: [] as PermissionScope[], + deny: [] as PermissionScope[], + ask: [] as PermissionScope[], + defaultMode: "askAll" as const, }, toolCalls: [ { diff --git a/scripts/esbuild.config.js b/scripts/esbuild.config.js index 36c174dc..bf814a32 100644 --- a/scripts/esbuild.config.js +++ b/scripts/esbuild.config.js @@ -20,7 +20,6 @@ await build({ jsx: "automatic", jsxImportSource: "react", packages: "external", - external: ["@vegamo/deepcode-core"], logOverride: { "empty-import-meta": "silent", }, From afc5ca82921c4abcba5284acaa0574676dbb7379 Mon Sep 17 00:00:00 2001 From: dengmik-commits <270912164+dengmik-commits@users.noreply.github.com> Date: Tue, 23 Jun 2026 19:18:26 +0800 Subject: [PATCH 50/72] fix: resolve permissions.test.ts type errors from upstream merge Add PermissionSettings import and use explicit type annotations for settings objects with empty arrays (as const produces readonly never[] which is incompatible with Required). --- packages/core/src/tests/permissions.test.ts | 52 ++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/packages/core/src/tests/permissions.test.ts b/packages/core/src/tests/permissions.test.ts index 26baecad..fd3b676a 100644 --- a/packages/core/src/tests/permissions.test.ts +++ b/packages/core/src/tests/permissions.test.ts @@ -12,7 +12,7 @@ import { isPathInAnyDirectory, parseBashSideEffects, } from "../common/permissions"; -import type { PermissionScope } from "../settings"; +import type { PermissionScope, PermissionSettings } from "../settings"; const tempDirs: string[] = []; @@ -33,11 +33,11 @@ test("parseBashSideEffects accepts valid scopes and normalizes unsafe values to }); test("evaluatePermissionScopes applies deny, ask, allow, and default mode precedence", () => { - const settings = { - allow: ["read-in-cwd" as const], - deny: ["write-out-cwd" as const], - ask: ["network" as const], - defaultMode: "askAll" as const, + const settings: Required = { + allow: ["read-in-cwd"] as PermissionScope[], + deny: ["write-out-cwd"] as PermissionScope[], + ask: ["network"] as PermissionScope[], + defaultMode: "askAll", }; assert.equal(evaluatePermissionScopes(["write-out-cwd"], settings), "deny"); @@ -49,41 +49,41 @@ test("evaluatePermissionScopes applies deny, ask, allow, and default mode preced }); test("evaluatePermissionScopes allows unknown when defaultMode is allowAll", () => { - const allowAllSettings = { - allow: [] as const, - deny: [] as const, - ask: [] as const, - defaultMode: "allowAll" as const, + const allowAllSettings: Required = { + allow: [] as PermissionScope[], + deny: [] as PermissionScope[], + ask: [] as PermissionScope[], + defaultMode: "allowAll", }; assert.equal(evaluatePermissionScopes(["unknown"], allowAllSettings), "allow"); // unknown + other scopes that would otherwise trigger ask should still ask for those scopes - const askNetworkSettings = { - allow: [] as const, - deny: [] as const, - ask: ["network" as const], - defaultMode: "allowAll" as const, + const askNetworkSettings: Required = { + allow: [] as PermissionScope[], + deny: [] as PermissionScope[], + ask: ["network"] as PermissionScope[], + defaultMode: "allowAll", }; assert.equal(evaluatePermissionScopes(["unknown", "network"], askNetworkSettings), "ask"); }); test("getPermissionScopesRequiringAsk excludes unknown when defaultMode is allowAll", () => { - const allowAllSettings = { - allow: [] as const, - deny: [] as const, - ask: ["network" as const], - defaultMode: "allowAll" as const, + const allowAllSettings: Required = { + allow: [] as PermissionScope[], + deny: [] as PermissionScope[], + ask: ["network"] as PermissionScope[], + defaultMode: "allowAll", }; const result = getPermissionScopesRequiringAsk(["unknown", "network"], allowAllSettings); assert.deepEqual(result, ["network"]); }); test("getPermissionScopesRequiringAsk includes unknown when defaultMode is askAll", () => { - const askAllSettings = { - allow: [] as const, - deny: [] as const, - ask: ["network" as const], - defaultMode: "askAll" as const, + const askAllSettings: Required = { + allow: [] as PermissionScope[], + deny: [] as PermissionScope[], + ask: ["network"] as PermissionScope[], + defaultMode: "askAll", }; const result = getPermissionScopesRequiringAsk(["unknown", "network"], askAllSettings); assert.deepEqual(result, ["unknown", "network"]); From a3952e11115236dbd0bd31dee89f954a7c1a3b08 Mon Sep 17 00:00:00 2001 From: hcyang Date: Wed, 24 Jun 2026 09:24:54 +0800 Subject: [PATCH 51/72] =?UTF-8?q?refactor(cli):=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=9C=AA=E4=BD=BF=E7=94=A8=E7=9A=84=20existsSync=20=E5=AF=BC?= =?UTF-8?q?=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 node:fs 模块中未使用的 existsSync 导入 - 保持代码整洁,避免冗余依赖 - 优化代码可读性和维护性 --- packages/cli/src/cli.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/cli.tsx b/packages/cli/src/cli.tsx index 80513f78..6ac5372d 100644 --- a/packages/cli/src/cli.tsx +++ b/packages/cli/src/cli.tsx @@ -1,6 +1,6 @@ import React from "react"; import { render } from "ink"; -import { readFileSync, existsSync } from "node:fs"; +import { readFileSync } from "node:fs"; import { join } from "node:path"; import { homedir } from "node:os"; import { setShellIfWindows, getProjectCode } from "@vegamo/deepcode-core"; From c8d8fa815b9a10f7fda36cff4c061ac216c48295 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Wed, 24 Jun 2026 09:59:01 +0800 Subject: [PATCH 52/72] fix: the CLI typecheck error --- packages/core/src/tests/permissions.test.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/core/src/tests/permissions.test.ts b/packages/core/src/tests/permissions.test.ts index d7ca2c5e..a0d1f17b 100644 --- a/packages/core/src/tests/permissions.test.ts +++ b/packages/core/src/tests/permissions.test.ts @@ -49,17 +49,17 @@ test("evaluatePermissionScopes applies deny, ask, allow, and default mode preced test("evaluatePermissionScopes allows unknown when defaultMode is allowAll", () => { const allowAllSettings = { - allow: [] as const, - deny: [] as const, - ask: [] as const, + allow: [], + deny: [], + ask: [], defaultMode: "allowAll" as const, }; assert.equal(evaluatePermissionScopes(["unknown"], allowAllSettings), "allow"); // unknown + other scopes that would otherwise trigger ask should still ask for those scopes const askNetworkSettings = { - allow: [] as const, - deny: [] as const, + allow: [], + deny: [], ask: ["network" as const], defaultMode: "allowAll" as const, }; @@ -68,8 +68,8 @@ test("evaluatePermissionScopes allows unknown when defaultMode is allowAll", () test("getPermissionScopesRequiringAsk excludes unknown when defaultMode is allowAll", () => { const allowAllSettings = { - allow: [] as const, - deny: [] as const, + allow: [], + deny: [], ask: ["network" as const], defaultMode: "allowAll" as const, }; @@ -79,8 +79,8 @@ test("getPermissionScopesRequiringAsk excludes unknown when defaultMode is allow test("getPermissionScopesRequiringAsk includes unknown when defaultMode is askAll", () => { const askAllSettings = { - allow: [] as const, - deny: [] as const, + allow: [], + deny: [], ask: ["network" as const], defaultMode: "askAll" as const, }; From f4ded9a866c157169ad6fc16b70b700283c46ac6 Mon Sep 17 00:00:00 2001 From: hcyang Date: Wed, 24 Jun 2026 10:04:33 +0800 Subject: [PATCH 53/72] =?UTF-8?q?feat(cli):=20=E5=A2=9E=E5=8A=A0Git?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BF=A1=E6=81=AF=E5=92=8C=E6=94=B9=E8=BF=9B?= =?UTF-8?q?=E7=95=8C=E9=9D=A2=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入并展示CLI版本及Git提交信息 - 优化退出摘要界面颜色,提升可读性 - 在会话恢复提示中添加高亮命令显示 - 在PackageInfo类型中添加gitCommit字段支持 --- packages/cli/src/cli.tsx | 6 ++++-- packages/cli/src/common/update-check.ts | 1 + packages/cli/src/ui/exit-summary.ts | 7 ++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/cli.tsx b/packages/cli/src/cli.tsx index 6ac5372d..48152d0b 100644 --- a/packages/cli/src/cli.tsx +++ b/packages/cli/src/cli.tsx @@ -7,6 +7,7 @@ import { setShellIfWindows, getProjectCode } from "@vegamo/deepcode-core"; import { checkForNpmUpdate, promptForPendingUpdate, type PackageInfo } from "./common/update-check"; import { AppContainer } from "./ui"; import { extractInitialPrompt, extractResumeSessionId } from "./cli-args"; +import { CLI_VERSION, GIT_COMMIT_INFO } from "./generated/git-commit"; const args = process.argv.slice(2); const packageInfo = readPackageInfo(); @@ -151,9 +152,10 @@ function readPackageInfo(): PackageInfo { const pkg = require("../package.json") as { name?: unknown; version?: unknown }; return { name: typeof pkg.name === "string" ? pkg.name : "@vegamo/deepcode-cli", - version: typeof pkg.version === "string" ? pkg.version : "", + version: typeof pkg.version === "string" ? pkg.version : (CLI_VERSION ?? ""), + gitCommit: GIT_COMMIT_INFO ?? "", }; } catch { - return { name: "@vegamo/deepcode-cli", version: "" }; + return { name: "@vegamo/deepcode-cli", version: CLI_VERSION ?? "", gitCommit: GIT_COMMIT_INFO ?? "" }; } } diff --git a/packages/cli/src/common/update-check.ts b/packages/cli/src/common/update-check.ts index 7a4710be..3b82e51a 100644 --- a/packages/cli/src/common/update-check.ts +++ b/packages/cli/src/common/update-check.ts @@ -10,6 +10,7 @@ import { killProcessTree } from "@vegamo/deepcode-core"; export type PackageInfo = { name: string; version: string; + gitCommit?: string; }; type UpdateState = { diff --git a/packages/cli/src/ui/exit-summary.ts b/packages/cli/src/ui/exit-summary.ts index baef723a..1a28ab8f 100644 --- a/packages/cli/src/ui/exit-summary.ts +++ b/packages/cli/src/ui/exit-summary.ts @@ -73,7 +73,7 @@ export function buildExitSummaryText(input: ExitSummaryInput): string { const innerWidth = 98; const contentWidth = innerWidth - 4; // "│ " prefix + " │" suffix → 4 chars padding - const borderColor = chalk.hex("#229ac3e6"); + const borderColor = chalk.dim; const titleColor = gradientString("#229ac3e6", "rgb(125 51 247 / 0.7)"); const line = (text: string) => `${borderColor("│")} ${padRight(text, contentWidth)} ${borderColor("│")}`; @@ -114,7 +114,7 @@ export function buildExitSummaryText(input: ExitSummaryInput): string { padLeft("Output Tokens", colOutput) + padLeft("Cached Tokens", colCached); rows.push(chalk.bold(headerRow)); - rows.push(divider); + rows.push(chalk.gray(divider)); for (const { modelName, usage } of usageRows) { const reqsStr = formatNumber(usage.totalReqs).padStart(colReqs); @@ -136,7 +136,8 @@ export function buildExitSummaryText(input: ExitSummaryInput): string { rows.push(""); if (sessionId) { - const resumeHint = chalk.dim(`To continue this session, run deepcode --resume ${sessionId}`); + const resumeHint = + chalk.dim(`To continue this session, run `) + chalk.hex("#229ac3")(`deepcode --resume ${sessionId}`); rows.push(resumeHint); rows.push(""); } From 346ecee0c988eb6e62d7e4aadf7261d03453a4f5 Mon Sep 17 00:00:00 2001 From: hcyang Date: Thu, 25 Jun 2026 09:00:13 +0800 Subject: [PATCH 54/72] =?UTF-8?q?refactor(cli):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E8=A1=8C=E5=8F=82=E6=95=B0=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E5=90=AF=E5=8A=A8=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 yargs 库替代原有手写解析,增强参数解析的健壮性和可维护性 - 添加严格参数校验,提升错误提示的清晰度 - 统一处理 --resume 和 --prompt 参数的组合逻辑,避免冲突使用 - 改进启动流程,确保先恢复会话再提交初始提示 - 将 resetStaticView 方法修改为异步以支持启动流程等待 - 替换部分异步调用为 await 确保顺序执行,避免竞态问题 - 更新 CLI 帮助文案,优化用户体验和信息表达 - 调整欢迎界面文本样式,增加标题加粗显示 - 添加相关单元测试 covering 新的参数解析和校验逻辑 - 引入 yargs 及其类型依赖,更新 package.json 和锁文件依赖清单 --- package-lock.json | 146 +++++++++++++++- packages/cli/package.json | 6 +- packages/cli/src/cli-args.ts | 111 ++++++++++--- packages/cli/src/cli.tsx | 124 +++++++------- packages/cli/src/tests/cli-args.test.ts | 174 +++++++++++++++----- packages/cli/src/tests/exit-summary.test.ts | 2 +- packages/cli/src/ui/views/App.tsx | 72 ++++---- packages/cli/src/ui/views/WelcomeScreen.tsx | 4 +- 8 files changed, 487 insertions(+), 152 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0e4b47f0..954b83b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1647,6 +1647,23 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.61.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.1.tgz", @@ -2724,6 +2741,66 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "license": "ISC", + "dependencies": { + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/cockatiel": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", @@ -3109,7 +3186,6 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, "license": "MIT" }, "node_modules/encoding-sniffer": { @@ -3266,7 +3342,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -3753,6 +3828,15 @@ "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-east-asian-width": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", @@ -7385,6 +7469,15 @@ "node": ">=4.0" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -7409,6 +7502,49 @@ "url": "https://github.com/sponsors/eemeli" } }, + "node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "license": "MIT", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/yauzl": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz", @@ -7484,11 +7620,15 @@ "ignore": "^7.0.5", "ink": "^7.0.4", "ink-gradient": "^4.0.1", - "react": "^19.2.5" + "react": "^19.2.5", + "yargs": "^18.0.0" }, "bin": { "deepcode": "dist/cli.js" }, + "devDependencies": { + "@types/yargs": "^17.0.35" + }, "engines": { "node": ">=22" } diff --git a/packages/cli/package.json b/packages/cli/package.json index 654038ee..977bad59 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -37,6 +37,10 @@ "ignore": "^7.0.5", "ink": "^7.0.4", "ink-gradient": "^4.0.1", - "react": "^19.2.5" + "react": "^19.2.5", + "yargs": "^18.0.0" + }, + "devDependencies": { + "@types/yargs": "^17.0.35" } } diff --git a/packages/cli/src/cli-args.ts b/packages/cli/src/cli-args.ts index 5ae0325e..3851ac00 100644 --- a/packages/cli/src/cli-args.ts +++ b/packages/cli/src/cli-args.ts @@ -1,31 +1,102 @@ /** * CLI argument parsing helpers. - * Extracted from cli.tsx for testability. + * Uses yargs for robust argument parsing and validation. */ -export function extractInitialPrompt(args: string[]): string | undefined { - const promptIndex = args.findIndex((arg) => arg === "-p" || arg === "--prompt"); - if (promptIndex !== -1 && promptIndex + 1 < args.length) { - return args[promptIndex + 1]; - } - return undefined; +import Yargs from "yargs"; + +export interface ParsedCliArgs { + /** Prompt text from -p / --prompt */ + prompt: string | undefined; + /** + * Resume session identifier: + * - `undefined` — --resume was not used + * - `true` — --resume was used without a session ID (show picker) + * - `string` — --resume was used + */ + resume: string | true | undefined; + /** True when --version / -v was passed */ + version: boolean; + /** True when --help / -h was passed */ + help: boolean; +} + +export interface CliParseError { + message: string; } /** - * Extract the --resume flag value. - * - * Returns: - * - `undefined` — `--resume` was not used - * - `true` — `--resume` was used without a session ID (show session picker) - * - `string` — `--resume ` was used (resume specific session) + * Parse CLI arguments with validation. + * Returns parsed args on success, or an error object if the arguments are invalid. */ -export function extractResumeSessionId(args: string[]): string | true | undefined { - const idx = args.findIndex((arg) => arg === "--resume"); - if (idx === -1) { - return undefined; +export function parseCliArgs(argv: string[]): ParsedCliArgs | CliParseError { + let validationError: string | null = null; + + const y = Yargs(argv) + .locale("en") + .scriptName("deepcode") + .version(false) + .help(false) + .option("version", { + alias: "v", + type: "boolean", + describe: "Print the version", + }) + .option("help", { + alias: "h", + type: "boolean", + describe: "Show this help", + }) + .option("resume", { + alias: "r", + type: "string", + describe: "Resume a specific session by its ID. Use without an ID to show session picker.", + }) + .option("prompt", { + alias: "p", + type: "string", + describe: "Submit a prompt on launch", + }) + .strict() + .exitProcess(false) + .fail((msg) => { + validationError = msg; + }) + .check((parsed) => { + // bare --resume conflicts with --prompt + if (parsed.resume === "" && parsed.prompt) { + throw new Error( + "Cannot use --resume without a session ID together with --prompt.\n" + + "Use --resume -p to resume a session and send a prompt." + ); + } + // empty prompt is meaningless + if (parsed.prompt === "") { + throw new Error("--prompt / -p requires a non-empty value."); + } + return true; + }); + + const parsed = y.parseSync() as Record; + + if (validationError) { + return { message: validationError }; } - if (idx + 1 < args.length && !args[idx + 1].startsWith("-")) { - return args[idx + 1]; + + const resumeRaw = parsed.resume as string | undefined; + let resume: ParsedCliArgs["resume"]; + if (resumeRaw === undefined) { + resume = undefined; + } else if (resumeRaw === "") { + resume = true; + } else { + resume = resumeRaw; } - return true; + + return { + prompt: parsed.prompt as string | undefined, + resume, + version: parsed.version === true, + help: parsed.help === true, + }; } diff --git a/packages/cli/src/cli.tsx b/packages/cli/src/cli.tsx index 48152d0b..1ea702bc 100644 --- a/packages/cli/src/cli.tsx +++ b/packages/cli/src/cli.tsx @@ -6,69 +6,86 @@ import { homedir } from "node:os"; import { setShellIfWindows, getProjectCode } from "@vegamo/deepcode-core"; import { checkForNpmUpdate, promptForPendingUpdate, type PackageInfo } from "./common/update-check"; import { AppContainer } from "./ui"; -import { extractInitialPrompt, extractResumeSessionId } from "./cli-args"; +import { hideBin } from "yargs/helpers"; +import { parseCliArgs } from "./cli-args"; import { CLI_VERSION, GIT_COMMIT_INFO } from "./generated/git-commit"; -const args = process.argv.slice(2); +const args = hideBin(process.argv); const packageInfo = readPackageInfo(); -if (args.includes("--version") || args.includes("-v")) { +const HELP_TEXT = + [ + "", + "Usage: deepcode [options] [command]\n\nDeep Code - Launch an interactive CLI, use -p/--prompt for non-interactive mode", + "", + "Commands:", + " deepcode Launch the interactive TUI in the current directory", + "", + "Options:", + " -p, --prompt Launch with a pre-filled prompt", + " -r, --resume [sessionId] Resume a specific session by its ID. Use without an ID to show session picker", + " -v, --version Show version number", + " -h, --help Show help", + "", + "Configuration:", + " ~/.deepcode/settings.json User-level API key, model, base URL", + " ./.deepcode/settings.json Project-level settings", + " ./.deepcode/skills/*/SKILL.md Project-level native skills", + " ./.agents/skills/*/SKILL.md Project-level interoperable skills", + " ~/.deepcode/skills/*/SKILL.md User-level native skills", + " ~/.agents/skills/*/SKILL.md User-level interoperable skills", + "", + "Inside the TUI:", + " enter Send the prompt", + " shift+enter Insert a newline", + " home/end Move within the current line", + " alt+left/right Move by word", + " ctrl+w Delete the previous word", + " ctrl+v Paste an image from the clipboard", + " ctrl+x Clear pasted images", + " esc Interrupt the current model turn", + " / Open the skills/commands menu", + " /skills List available skills", + " /model Select model, thinking mode and effort control", + " /new Start a fresh conversation", + " /init Initialize an AGENTS.md file with instructions for LLM", + " /resume Pick a previous conversation to continue", + " /continue Continue the active conversation, or resume one if empty", + " /undo Restore code and/or conversation to a previous point", + " /mcp Show MCP server status and available tools", + " /raw Toggle display mode for viewing or collapsing reasoning content", + " /exit Quit", + " ctrl+d twice Quit", + ].join("\n") + "\n"; + +const parsed = parseCliArgs(args); + +if ("message" in parsed) { + process.stderr.write(parsed.message + "\n\n"); + process.stdout.write(HELP_TEXT); + process.exit(1); +} + +if (parsed.version) { process.stdout.write(`${packageInfo.version || "unknown"}\n`); process.exit(0); } -if (args.includes("--help") || args.includes("-h")) { - process.stdout.write( - [ - "deepcode - Deep Code CLI", - "", - "Usage:", - " deepcode Launch the interactive TUI in the current directory", - " deepcode -p Launch with a pre-filled prompt", - " deepcode --prompt Same as -p", - " deepcode --resume [sessionId] Resume a specific session by its ID. Use without an ID to show session picker", - " deepcode --version Print the version", - " deepcode --help Show this help", - "", - "Configuration:", - " ~/.deepcode/settings.json User-level API key, model, base URL", - " ./.deepcode/settings.json Project-level settings", - " ./.deepcode/skills/*/SKILL.md Project-level native skills", - " ./.agents/skills/*/SKILL.md Project-level interoperable skills", - " ~/.deepcode/skills/*/SKILL.md User-level native skills", - " ~/.agents/skills/*/SKILL.md User-level interoperable skills", - "", - "Inside the TUI:", - " enter Send the prompt", - " shift+enter Insert a newline", - " home/end Move within the current line", - " alt+left/right Move by word", - " ctrl+w Delete the previous word", - " ctrl+v Paste an image from the clipboard", - " ctrl+x Clear pasted images", - " esc Interrupt the current model turn", - " / Open the skills/commands menu", - " /skills List available skills", - " /model Select model, thinking mode and effort control", - " /new Start a fresh conversation", - " /init Initialize an AGENTS.md file with instructions for LLM", - " /resume Pick a previous conversation to continue", - " /continue Continue the active conversation, or resume one if empty", - " /undo Restore code and/or conversation to a previous point", - " /mcp Show MCP server status and available tools", - " /raw Toggle display mode for viewing or collapsing reasoning content", - " /exit Quit", - " ctrl+d twice Quit", - ].join("\n") + "\n" - ); +if (parsed.help) { + process.stdout.write(HELP_TEXT); process.exit(0); } -let initialPrompt = extractInitialPrompt(args); -const resumeSessionId = extractResumeSessionId(args); +let initialPrompt = parsed.prompt; +let resumeSessionId = parsed.resume; const projectRoot = process.cwd(); configureWindowsShell(); +if (!process.stdin.isTTY) { + process.stderr.write("deepcode requires an interactive terminal (TTY). " + "Re-run from a real terminal session.\n"); + process.exit(1); +} + // Validate --resume before entering TUI if (typeof resumeSessionId === "string") { const projectCode = getProjectCode(projectRoot); @@ -86,11 +103,6 @@ if (typeof resumeSessionId === "string") { } } -if (!process.stdin.isTTY) { - process.stderr.write("deepcode requires an interactive terminal (TTY). " + "Re-run from a real terminal session.\n"); - process.exit(1); -} - void main(); async function main(): Promise { @@ -105,12 +117,14 @@ async function main(): Promise { let restarting = false; const appInitialPrompt = initialPrompt; initialPrompt = undefined; + const appResumeSessionId = resumeSessionId; + resumeSessionId = undefined; const inkInstance = render( restartRef.current?.()} />, { exitOnCtrlC: false } diff --git a/packages/cli/src/tests/cli-args.test.ts b/packages/cli/src/tests/cli-args.test.ts index e42a4b00..fd97de76 100644 --- a/packages/cli/src/tests/cli-args.test.ts +++ b/packages/cli/src/tests/cli-args.test.ts @@ -1,76 +1,168 @@ import { test } from "node:test"; import assert from "node:assert/strict"; -import { extractInitialPrompt, extractResumeSessionId } from "../cli-args"; +import { parseCliArgs } from "../cli-args"; -// ── extractInitialPrompt ───────────────────────────────────────────────────── +// ── parseCliArgs: basic parsing ────────────────────────────────────────────── -test("extractInitialPrompt returns prompt after -p", () => { - assert.equal(extractInitialPrompt(["-p", "hello world"]), "hello world"); +test("parseCliArgs returns prompt after -p", () => { + const r = parseCliArgs(["-p", "hello world"]); + assert.ok(!("message" in r)); + assert.equal(r.prompt, "hello world"); }); -test("extractInitialPrompt returns prompt after --prompt", () => { - assert.equal(extractInitialPrompt(["--prompt", "hello world"]), "hello world"); +test("parseCliArgs returns prompt after --prompt", () => { + const r = parseCliArgs(["--prompt", "hello world"]); + assert.ok(!("message" in r)); + assert.equal(r.prompt, "hello world"); }); -test("extractInitialPrompt returns undefined when -p is not present", () => { - assert.equal(extractInitialPrompt(["--version"]), undefined); +test("parseCliArgs returns undefined prompt when -p is not present", () => { + const r = parseCliArgs(["--resume"]); + assert.ok(!("message" in r)); + assert.equal(r.prompt, undefined); }); -test("extractInitialPrompt returns undefined when -p has no value", () => { - assert.equal(extractInitialPrompt(["-p"]), undefined); +test("parseCliArgs returns session ID after --resume", () => { + const r = parseCliArgs(["--resume", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"]); + assert.ok(!("message" in r)); + assert.equal(r.resume, "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"); }); -test("extractInitialPrompt returns undefined for empty args", () => { - assert.equal(extractInitialPrompt([]), undefined); +test("parseCliArgs returns true when --resume has no value", () => { + const r = parseCliArgs(["--resume"]); + assert.ok(!("message" in r)); + assert.equal(r.resume, true); }); -test("extractInitialPrompt ignores -p in non-flag position", () => { - assert.equal(extractInitialPrompt(["--resume", "-p", "hello"]), "hello"); +test("parseCliArgs returns undefined resume when not present", () => { + const r = parseCliArgs(["-p", "test"]); + assert.ok(!("message" in r)); + assert.equal(r.resume, undefined); }); -// ── extractResumeSessionId ─────────────────────────────────────────────────── +test("parseCliArgs returns defaults for empty args", () => { + const r = parseCliArgs([]); + assert.ok(!("message" in r)); + assert.equal(r.prompt, undefined); + assert.equal(r.resume, undefined); + assert.equal(r.version, false); + assert.equal(r.help, false); +}); + +// ── parseCliArgs: -r alias ─────────────────────────────────────────────────── + +test("parseCliArgs returns session ID after -r", () => { + const r = parseCliArgs(["-r", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"]); + assert.ok(!("message" in r)); + assert.equal(r.resume, "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"); +}); + +test("parseCliArgs returns true when -r has no value", () => { + const r = parseCliArgs(["-r"]); + assert.ok(!("message" in r)); + assert.equal(r.resume, true); +}); + +test("parseCliArgs handles -r combined with -p", () => { + const r = parseCliArgs(["-r", "session-123", "-p", "hello"]); + assert.ok(!("message" in r)); + assert.equal(r.resume, "session-123"); + assert.equal(r.prompt, "hello"); +}); + +test("parseCliArgs rejects bare -r with -p", () => { + const r = parseCliArgs(["-r", "-p", "hello"]); + assert.ok("message" in r); + assert.match(r.message, /Cannot use --resume/); +}); -test("extractResumeSessionId returns session ID after --resume", () => { - assert.equal( - extractResumeSessionId(["--resume", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"]), - "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6" - ); +// ── parseCliArgs: --version / --help ───────────────────────────────────────── + +test("parseCliArgs detects --version", () => { + const r = parseCliArgs(["--version"]); + assert.ok(!("message" in r)); + assert.equal(r.version, true); + assert.equal(r.help, false); +}); + +test("parseCliArgs detects -v", () => { + const r = parseCliArgs(["-v"]); + assert.ok(!("message" in r)); + assert.equal(r.version, true); +}); + +test("parseCliArgs detects --help", () => { + const r = parseCliArgs(["--help"]); + assert.ok(!("message" in r)); + assert.equal(r.help, true); + assert.equal(r.version, false); }); -test("extractResumeSessionId returns true when --resume has no value (show picker)", () => { - assert.equal(extractResumeSessionId(["--resume"]), true); +test("parseCliArgs detects -h", () => { + const r = parseCliArgs(["-h"]); + assert.ok(!("message" in r)); + assert.equal(r.help, true); }); -test("extractResumeSessionId returns true when --resume is followed by another flag", () => { - assert.equal(extractResumeSessionId(["--resume", "--force"]), true); +test("parseCliArgs version and help are false when not passed", () => { + const r = parseCliArgs(["-p", "hello"]); + assert.ok(!("message" in r)); + assert.equal(r.version, false); + assert.equal(r.help, false); }); -test("extractResumeSessionId returns undefined when --resume is not present", () => { - assert.equal(extractResumeSessionId(["--version"]), undefined); +test("parseCliArgs handles -v combined with -r (both flags set)", () => { + const r = parseCliArgs(["-v", "-r", "abc"]); + assert.ok(!("message" in r)); + assert.equal(r.version, true); + assert.equal(r.resume, "abc"); }); -test("extractResumeSessionId returns undefined for empty args", () => { - assert.equal(extractResumeSessionId([]), undefined); +// ── parseCliArgs: combined usage ───────────────────────────────────────────── + +test("parseCliArgs handles --resume combined with -p", () => { + const r = parseCliArgs(["--resume", "session-123", "-p", "hello"]); + assert.ok(!("message" in r)); + assert.equal(r.resume, "session-123"); + assert.equal(r.prompt, "hello"); }); -test("extractResumeSessionId works with other flags after sessionId", () => { - assert.equal(extractResumeSessionId(["--resume", "abc-123", "--force"]), "abc-123"); +test("parseCliArgs handles -p before --resume ", () => { + const r = parseCliArgs(["-p", "hello", "--resume", "session-123"]); + assert.ok(!("message" in r)); + assert.equal(r.resume, "session-123"); + assert.equal(r.prompt, "hello"); }); -test("extractResumeSessionId does not confuse --resume with other args", () => { - assert.equal(extractResumeSessionId(["-p", "test"]), undefined); +// ── parseCliArgs: validation ───────────────────────────────────────────────── + +test("parseCliArgs rejects bare --resume with -p", () => { + const r = parseCliArgs(["--resume", "-p", "hello"]); + assert.ok("message" in r); + assert.match(r.message, /Cannot use --resume/); }); -// ── combined usage ─────────────────────────────────────────────────────────── +test("parseCliArgs rejects -p with bare --resume (reversed order)", () => { + const r = parseCliArgs(["-p", "hello", "--resume"]); + assert.ok("message" in r); + assert.match(r.message, /Cannot use --resume/); +}); + +test("parseCliArgs rejects unknown flags in strict mode", () => { + const r = parseCliArgs(["--unknown-flag"]); + assert.ok("message" in r); + assert.match(r.message, /Unknown argument/); +}); -test("extractInitialPrompt and extractResumeSessionId work independently", () => { - const args = ["--resume", "session-123", "-p", "hello"]; - assert.equal(extractResumeSessionId(args), "session-123"); - assert.equal(extractInitialPrompt(args), "hello"); +test("parseCliArgs rejects empty -p value", () => { + const r = parseCliArgs(["-p", ""]); + assert.ok("message" in r); + assert.match(r.message, /non-empty/); }); -test("extractResumeSessionId with --resume and -p but no sessionId", () => { - const args = ["--resume", "-p", "hello"]; - assert.equal(extractResumeSessionId(args), true); - assert.equal(extractInitialPrompt(args), "hello"); +test("parseCliArgs --version takes precedence over --help", () => { + const r = parseCliArgs(["--version", "--help"]); + assert.ok(!("message" in r)); + assert.equal(r.version, true); + assert.equal(r.help, true); }); diff --git a/packages/cli/src/tests/exit-summary.test.ts b/packages/cli/src/tests/exit-summary.test.ts index d768c165..fd6b8ad0 100644 --- a/packages/cli/src/tests/exit-summary.test.ts +++ b/packages/cli/src/tests/exit-summary.test.ts @@ -3,7 +3,7 @@ import assert from "node:assert/strict"; import { buildExitSummaryText } from "../ui"; import type { ModelUsage, SessionEntry } from "@vegamo/deepcode-core"; -const stripAnsi = (text: string): string => text.replace(/\u001b\[[0-9;]*m/g, ""); +const stripAnsi = (text: string): string => text.replace(/\u001b\[[0-9;]*[a-zA-Z]/g, ""); test("buildExitSummaryText only shows Goodbye and model usage with cached tokens", () => { const summary = stripAnsi( diff --git a/packages/cli/src/ui/views/App.tsx b/packages/cli/src/ui/views/App.tsx index 4175b49d..5e345802 100644 --- a/packages/cli/src/ui/views/App.tsx +++ b/packages/cli/src/ui/views/App.tsx @@ -97,6 +97,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp const { mode, setMode } = useRawModeContext(); const initialPromptSubmittedRef = useRef(false); const resumeSessionIdRef = useRef(false); + const startupDoneRef = useRef(false); const processStdoutRef = useRef>(new Map()); const rawModeRef = useRef(mode); const writeRef = useRef(write); @@ -190,17 +191,20 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp * Reset the static view to the welcome screen. */ const resetStaticView = useCallback( - (loadedMessages: SessionMessage[], options?: { clearScreen?: boolean }) => { + (loadedMessages: SessionMessage[], options?: { clearScreen?: boolean }): Promise => { if (options?.clearScreen) { process.stdout.write(ANSI_CLEAR_SCREEN); } setMessages([]); setWelcomeNonce((n) => n + 1); navigateToSubView("chat"); - setTimeout(() => { - setMessages(loadedMessages); - setShowWelcome(true); - }, 0); + return new Promise((resolve) => { + setTimeout(() => { + setMessages(loadedMessages); + setShowWelcome(true); + resolve(); + }, 0); + }); }, [navigateToSubView] ); @@ -246,7 +250,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp setActiveAskPermissions(undefined); setPendingPermissionReply(null); setDismissedQuestionIds(new Set()); - resetStaticView([]); + await resetStaticView([]); await refreshSkills(); }, [sessionManager, resetStaticView, refreshSkills]); @@ -477,24 +481,11 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp [resetStaticView, sessionManager] ); - useEffect(() => { - if (initialPromptSubmittedRef.current || !initialPrompt || !initialPrompt.trim()) { - return; - } - - initialPromptSubmittedRef.current = true; - handleSubmit({ - text: initialPrompt, - imageUrls: [], - selectedSkills: undefined, - }); - }, [handleSubmit, initialPrompt]); - const handleSelectSession = useCallback( async (sessionId: string) => { sessionManager.setActiveSessionId(sessionId); // Clear first so resets its index to 0. - resetStaticView(loadVisibleMessages(sessionManager, sessionId), { clearScreen: true }); + await resetStaticView(loadVisibleMessages(sessionManager, sessionId), { clearScreen: true }); const session = sessionManager.getSession(sessionId); setStatusLine(session ? buildStatusLine(session) : ""); setRunningProcesses(session?.processes ?? null); @@ -508,21 +499,42 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp [sessionManager, resetStaticView, pendingPermissionReply, refreshSkills] ); + /** + * Coordinated startup effect: handle --resume and --prompt together. + * When both are present, resume the session first, then submit the prompt. + */ useEffect(() => { - if (resumeSessionIdRef.current || !resumeSessionId) { + if (startupDoneRef.current) { return; } + startupDoneRef.current = true; + + async function run() { + // Step 1: Resume session if requested + if (resumeSessionId) { + resumeSessionIdRef.current = true; + if (resumeSessionId === true) { + // Bare --resume — show session picker; prompt makes no sense here + refreshSessionsList(); + navigateToSubView("session-list"); + return; + } + await handleSelectSession(resumeSessionId); + } - resumeSessionIdRef.current = true; - if (resumeSessionId === true) { - // No session ID — show the session picker (same as /resume) - refreshSessionsList(); - navigateToSubView("session-list"); - } else { - // Session ID already validated in cli.tsx — guaranteed to exist - handleSelectSession(resumeSessionId); + // Step 2: Submit prompt if provided + if (initialPrompt && initialPrompt.trim()) { + initialPromptSubmittedRef.current = true; + handleSubmit({ + text: initialPrompt, + imageUrls: [], + selectedSkills: undefined, + }); + } } - }, [handleSelectSession, navigateToSubView, refreshSessionsList, resumeSessionId]); + + void run(); + }, [handleSubmit, handleSelectSession, initialPrompt, navigateToSubView, refreshSessionsList, resumeSessionId]); const handleDeleteSession = useCallback( async (id: string): Promise => { diff --git a/packages/cli/src/ui/views/WelcomeScreen.tsx b/packages/cli/src/ui/views/WelcomeScreen.tsx index fdcf9211..e465a2f6 100644 --- a/packages/cli/src/ui/views/WelcomeScreen.tsx +++ b/packages/cli/src/ui/views/WelcomeScreen.tsx @@ -58,7 +58,9 @@ export function WelcomeScreen({ projectRoot, settings, skills, width }: WelcomeS paddingX={1} > - {">"}_ Deep Code + + {">"}_ Deep Code{" "} + (v{version || "unknown"}) {!compact ? : null} From 24a2ad934e2d59caf74a5a0515432603d618dc04 Mon Sep 17 00:00:00 2001 From: hcyang Date: Thu, 25 Jun 2026 14:37:41 +0800 Subject: [PATCH 55/72] =?UTF-8?q?refactor(cli):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E8=A1=8C=E5=8F=82=E6=95=B0=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E5=92=8C=E4=B8=BB=E5=85=A5=E5=8F=A3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用异步方式获取包信息,替代同步读取package.json - 用yargs重构参数解析,加入严格校验和格式验证 - 新增UUID格式验证函数,确保会话ID合法性 - 改善错误输出,统一通过writeStderrLine打印错误信息 - 移除过时的手工参数解析逻辑,改用parseArguments异步解析 - 统一并简化应用启动流程,支持终端交互性检查 - 替换process.stdout.write为writeStdoutLine,增强代码一致性 - 增加对版本号、帮助信息参数的自动处理和退出 - 使用read-package-up获取package.json,保证包信息准确 - 测试覆盖parseArguments及isValidSessionId的多种场景和错误处理 - 修改构建脚本为异步导入fs模块的chmodSync操作,兼容现代Node版本 --- package-lock.json | 121 ++++++++++++-- packages/cli/package.json | 3 +- packages/cli/src/cli-args.ts | 166 +++++++++++++------- packages/cli/src/cli.tsx | 146 +++++------------ packages/cli/src/common/update-check.ts | 9 +- packages/cli/src/tests/cli-args.test.ts | 199 ++++++++++++++---------- packages/cli/src/utils/package.ts | 29 ++++ packages/cli/src/utils/stdioHelpers.ts | 25 +++ packages/cli/src/utils/version.ts | 6 + 9 files changed, 447 insertions(+), 257 deletions(-) create mode 100644 packages/cli/src/utils/package.ts create mode 100644 packages/cli/src/utils/stdioHelpers.ts create mode 100644 packages/cli/src/utils/version.ts diff --git a/package-lock.json b/package-lock.json index 954b83b3..66cf2bce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -242,7 +242,6 @@ "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", @@ -384,7 +383,6 @@ "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1614,7 +1612,6 @@ "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true, "license": "MIT" }, "node_modules/@types/react": { @@ -3732,6 +3729,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", @@ -4359,7 +4368,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -4630,7 +4638,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -5690,7 +5697,6 @@ "version": "8.3.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", @@ -5708,7 +5714,6 @@ "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=16" @@ -5870,7 +5875,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -6130,6 +6134,101 @@ "node": ">=0.8" } }, + "node_modules/read-package-up": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-12.0.0.tgz", + "integrity": "sha512-Q5hMVBYur/eQNWDdbF4/Wqqr9Bjvtrw2kjGxxBbKLbx8bVCL8gcArjTy8zDUuLGQicftpMuU0riQNcAsbtOVsw==", + "license": "MIT", + "dependencies": { + "find-up-simple": "^1.0.1", + "read-pkg": "^10.0.0", + "type-fest": "^5.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-package-up/node_modules/hosted-git-info": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz", + "integrity": "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==", + "license": "ISC", + "dependencies": { + "lru-cache": "^11.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/read-package-up/node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/read-package-up/node_modules/normalize-package-data": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-8.0.0.tgz", + "integrity": "sha512-RWk+PI433eESQ7ounYxIp67CYuVsS1uYSonX3kA6ps/3LWfjVQa/ptEg6Y3T6uAMq1mWpX9PQ+qx+QaHpsc7gQ==", + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^9.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/read-package-up/node_modules/read-pkg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-10.1.0.tgz", + "integrity": "sha512-I8g2lArQiP78ll51UeMZojewtYgIRCKCWqZEgOO8c/uefTI+XDXvCSXu3+YNUaTNvZzobrL5+SqHjBrByRRTdg==", + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.4", + "normalize-package-data": "^8.0.0", + "parse-json": "^8.3.0", + "type-fest": "^5.4.4", + "unicorn-magic": "^0.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-package-up/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-package-up/node_modules/unicorn-magic": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz", + "integrity": "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/read-pkg": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", @@ -6584,7 +6683,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -6595,14 +6693,12 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", @@ -6613,7 +6709,6 @@ "version": "3.0.23", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", - "dev": true, "license": "CC0-1.0" }, "node_modules/sprintf-js": { @@ -7286,7 +7381,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", @@ -7621,6 +7715,7 @@ "ink": "^7.0.4", "ink-gradient": "^4.0.1", "react": "^19.2.5", + "read-package-up": "^12.0.0", "yargs": "^18.0.0" }, "bin": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 977bad59..1f657304 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -25,7 +25,7 @@ "scripts": { "typecheck": "tsc -p ./ --noEmit", "bundle": "node ../../scripts/esbuild.config.js", - "build": "npm run typecheck && npm run bundle && node ../../scripts/copy-bundle-assets.js && node -e \"require('fs').chmodSync('dist/cli.js', 0o755)\"", + "build": "npm run typecheck && npm run bundle && node ../../scripts/copy-bundle-assets.js && node -e \"import('node:fs').then(f => f.chmodSync('dist/cli.js', 0o755))\"", "prepublishOnly": "npm run build", "format": "prettier --write .", "test": "node src/tests/run-tests.mjs" @@ -38,6 +38,7 @@ "ink": "^7.0.4", "ink-gradient": "^4.0.1", "react": "^19.2.5", + "read-package-up": "^12.0.0", "yargs": "^18.0.0" }, "devDependencies": { diff --git a/packages/cli/src/cli-args.ts b/packages/cli/src/cli-args.ts index 3851ac00..780869c0 100644 --- a/packages/cli/src/cli-args.ts +++ b/packages/cli/src/cli-args.ts @@ -3,7 +3,21 @@ * Uses yargs for robust argument parsing and validation. */ +import type { Argv } from "yargs"; import Yargs from "yargs"; +import { getCliVersion } from "./utils/version"; +import { writeStderrLine } from "./utils/stdioHelpers"; +import { hideBin } from "yargs/helpers"; + +// UUID v4 regex pattern for validation +const SESSION_ID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; + +/** + * Validates if a string is a valid session ID format. + */ +export function isValidSessionId(value: string): boolean { + return SESSION_ID_REGEX.test(value); +} export interface ParsedCliArgs { /** Prompt text from -p / --prompt */ @@ -21,68 +35,112 @@ export interface ParsedCliArgs { help: boolean; } -export interface CliParseError { - message: string; +const EPILOG = [ + "Configuration:", + " ~/.deepcode/settings.json User-level API key, model, base URL", + " ./.deepcode/settings.json Project-level settings", + " ./.deepcode/skills/*/SKILL.md Project-level native skills", + " ./.agents/skills/*/SKILL.md Project-level interoperable skills", + " ~/.deepcode/skills/*/SKILL.md User-level native skills", + " ~/.agents/skills/*/SKILL.md User-level interoperable skills", + "", + "Inside the TUI:", + " enter Send the prompt", + " shift+enter Insert a newline", + " home/end Move within the current line", + " alt+left/right Move by word", + " ctrl+w Delete the previous word", + " ctrl+v Paste an image from the clipboard", + " ctrl+x Clear pasted images", + " esc Interrupt the current model turn", + " / Open the skills/commands menu", + " /skills List available skills", + " /model Select model, thinking mode and effort control", + " /new Start a fresh conversation", + " /init Initialize an AGENTS.md file with instructions for LLM", + " /resume Pick a previous conversation to continue", + " /continue Continue the active conversation, or resume one if empty", + " /undo Restore code and/or conversation to a previous point", + " /mcp Show MCP server status and available tools", + " /raw Toggle display mode for viewing or collapsing reasoning content", + " /exit Quit", + " ctrl+d twice Quit", +].join("\n"); + +async function configureYargs(argv?: string[]) { + const rawArgv = argv ?? hideBin(process.argv); + const yargsInstance = Yargs(rawArgv) + .locale("en") + .scriptName("deepcode") + .usage( + "Usage: $0 [options] [command]\n\nDeep Code - Launch an interactive CLI, use -p/--prompt for non-interactive mode" + ) + .command("$0 [query..]", "Launch Deep Code CLI", (yargsInstance: Argv) => + yargsInstance + .option("prompt", { + alias: "p", + type: "string", + describe: "Submit a prompt on launch", + }) + .option("resume", { + alias: "r", + type: "string", + describe: "Resume a specific session by its ID. Use without an ID to show session picker.", + }) + .check((argv: { [x: string]: unknown }) => { + const query = argv["query"] as string | string[] | undefined; + const hasPositionalQuery = Array.isArray(query) ? query.length > 0 : !!query; + + if (argv["prompt"] && hasPositionalQuery) { + return "Cannot use both a positional prompt and the --prompt (-p) flag together"; + } + // bare --resume conflicts with --prompt + if (argv["resume"] === "" && argv["prompt"]) { + return "Cannot use --resume without a session ID together with --prompt.\nUse --resume -p to resume a session and send a prompt."; + } + // validate --resume format if provided + if (argv["resume"] && argv["resume"] !== "" && !isValidSessionId(argv["resume"] as string)) { + return `Invalid session ID: "${argv["resume"]}". Must be a valid UUID (e.g., "123e4567-e89b-12d3-a456-426614174000").`; + } + // empty prompt is meaningless + if (argv["prompt"] === "") { + return "--prompt / -p requires a non-empty value."; + } + return true; + }) + ) + .example("deepcode", "Launch the interactive TUI in the current directory") + .example("deepcode -p ", "Launch with a pre-filled prompt") + .example("deepcode -r, --resume [sessionId]", "Resume a session or show session picker") + .epilog(EPILOG) + .strict() + .demandCommand(0, 0) + .wrap(Math.min(process.stdout.columns || 80, 120)); + yargsInstance + .version(await getCliVersion()) + .alias("v", "version") + .help() + .alias("h", "help"); + yargsInstance.wrap(yargsInstance.terminalWidth()); + return yargsInstance; } /** * Parse CLI arguments with validation. - * Returns parsed args on success, or an error object if the arguments are invalid. + * + * On validation failure the `.fail()` handler prints the error, shows help, + * and calls `process.exit(1)`, so this function always either returns a + * valid `ParsedCliArgs` or terminates the process. */ -export function parseCliArgs(argv: string[]): ParsedCliArgs | CliParseError { - let validationError: string | null = null; - - const y = Yargs(argv) - .locale("en") - .scriptName("deepcode") - .version(false) - .help(false) - .option("version", { - alias: "v", - type: "boolean", - describe: "Print the version", - }) - .option("help", { - alias: "h", - type: "boolean", - describe: "Show this help", - }) - .option("resume", { - alias: "r", - type: "string", - describe: "Resume a specific session by its ID. Use without an ID to show session picker.", - }) - .option("prompt", { - alias: "p", - type: "string", - describe: "Submit a prompt on launch", - }) - .strict() - .exitProcess(false) - .fail((msg) => { - validationError = msg; - }) - .check((parsed) => { - // bare --resume conflicts with --prompt - if (parsed.resume === "" && parsed.prompt) { - throw new Error( - "Cannot use --resume without a session ID together with --prompt.\n" + - "Use --resume -p to resume a session and send a prompt." - ); - } - // empty prompt is meaningless - if (parsed.prompt === "") { - throw new Error("--prompt / -p requires a non-empty value."); - } - return true; - }); +export async function parseArguments(argv?: string[]): Promise { + const y = (await configureYargs(argv)).exitProcess(false).fail((msg, _err, yargs) => { + writeStderrLine(msg || _err?.message || "Unknown error"); + yargs.showHelp(); + process.exit(1); + }); const parsed = y.parseSync() as Record; - if (validationError) { - return { message: validationError }; - } - const resumeRaw = parsed.resume as string | undefined; let resume: ParsedCliArgs["resume"]; if (resumeRaw === undefined) { diff --git a/packages/cli/src/cli.tsx b/packages/cli/src/cli.tsx index 1ea702bc..edf5fdbd 100644 --- a/packages/cli/src/cli.tsx +++ b/packages/cli/src/cli.tsx @@ -4,108 +4,53 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; import { homedir } from "node:os"; import { setShellIfWindows, getProjectCode } from "@vegamo/deepcode-core"; -import { checkForNpmUpdate, promptForPendingUpdate, type PackageInfo } from "./common/update-check"; +import { checkForNpmUpdate, promptForPendingUpdate } from "./common/update-check"; import { AppContainer } from "./ui"; -import { hideBin } from "yargs/helpers"; -import { parseCliArgs } from "./cli-args"; -import { CLI_VERSION, GIT_COMMIT_INFO } from "./generated/git-commit"; +import { parseArguments } from "./cli-args"; +import { writeStderrLine, writeStdoutLine } from "./utils/stdioHelpers"; +import { getPackageJson } from "./utils/package"; +import { CLI_VERSION } from "./generated/git-commit"; -const args = hideBin(process.argv); -const packageInfo = readPackageInfo(); - -const HELP_TEXT = - [ - "", - "Usage: deepcode [options] [command]\n\nDeep Code - Launch an interactive CLI, use -p/--prompt for non-interactive mode", - "", - "Commands:", - " deepcode Launch the interactive TUI in the current directory", - "", - "Options:", - " -p, --prompt Launch with a pre-filled prompt", - " -r, --resume [sessionId] Resume a specific session by its ID. Use without an ID to show session picker", - " -v, --version Show version number", - " -h, --help Show help", - "", - "Configuration:", - " ~/.deepcode/settings.json User-level API key, model, base URL", - " ./.deepcode/settings.json Project-level settings", - " ./.deepcode/skills/*/SKILL.md Project-level native skills", - " ./.agents/skills/*/SKILL.md Project-level interoperable skills", - " ~/.deepcode/skills/*/SKILL.md User-level native skills", - " ~/.agents/skills/*/SKILL.md User-level interoperable skills", - "", - "Inside the TUI:", - " enter Send the prompt", - " shift+enter Insert a newline", - " home/end Move within the current line", - " alt+left/right Move by word", - " ctrl+w Delete the previous word", - " ctrl+v Paste an image from the clipboard", - " ctrl+x Clear pasted images", - " esc Interrupt the current model turn", - " / Open the skills/commands menu", - " /skills List available skills", - " /model Select model, thinking mode and effort control", - " /new Start a fresh conversation", - " /init Initialize an AGENTS.md file with instructions for LLM", - " /resume Pick a previous conversation to continue", - " /continue Continue the active conversation, or resume one if empty", - " /undo Restore code and/or conversation to a previous point", - " /mcp Show MCP server status and available tools", - " /raw Toggle display mode for viewing or collapsing reasoning content", - " /exit Quit", - " ctrl+d twice Quit", - ].join("\n") + "\n"; - -const parsed = parseCliArgs(args); - -if ("message" in parsed) { - process.stderr.write(parsed.message + "\n\n"); - process.stdout.write(HELP_TEXT); - process.exit(1); -} +configureWindowsShell(); +void main(); -if (parsed.version) { - process.stdout.write(`${packageInfo.version || "unknown"}\n`); - process.exit(0); -} +async function main(): Promise { + const packageInfo = await getPackageJson(); + const parsed = await parseArguments(); -if (parsed.help) { - process.stdout.write(HELP_TEXT); - process.exit(0); -} + // --version and --help are handled by yargs internally (prints output as side effect) + // but with .exitProcess(false) we need to exit manually. + if (parsed.version || parsed.help) { + process.exit(0); + } -let initialPrompt = parsed.prompt; -let resumeSessionId = parsed.resume; -const projectRoot = process.cwd(); -configureWindowsShell(); + let initialPrompt = parsed.prompt; + let resumeSessionId = parsed.resume; + const projectRoot = process.cwd(); -if (!process.stdin.isTTY) { - process.stderr.write("deepcode requires an interactive terminal (TTY). " + "Re-run from a real terminal session.\n"); - process.exit(1); -} + if (!process.stdin.isTTY) { + writeStderrLine("deepcode requires an interactive terminal (TTY). Re-run from a real terminal session.\n"); + process.exit(1); + } -// Validate --resume before entering TUI -if (typeof resumeSessionId === "string") { - const projectCode = getProjectCode(projectRoot); - const indexPath = join(homedir(), ".deepcode", "projects", projectCode, "sessions-index.json"); - try { - const index = JSON.parse(readFileSync(indexPath, "utf-8")); - const found = Array.isArray(index?.entries) && index.entries.some((e: { id: string }) => e.id === resumeSessionId); - if (!found) { - process.stderr.write(`No saved session found with ID "${resumeSessionId}".\n`); + // Validate --resume before entering TUI + if (typeof resumeSessionId === "string") { + const projectCode = getProjectCode(projectRoot); + const indexPath = join(homedir(), ".deepcode", "projects", projectCode, "sessions-index.json"); + try { + const index = JSON.parse(readFileSync(indexPath, "utf-8")); + const found = + Array.isArray(index?.entries) && index.entries.some((e: { id: string }) => e.id === resumeSessionId); + if (!found) { + writeStderrLine(`No saved session found with ID "${resumeSessionId}".\n`); + process.exit(1); + } + } catch { + writeStderrLine(`No saved session found with ID "${resumeSessionId}".\n`); process.exit(1); } - } catch { - process.stderr.write(`No saved session found with ID "${resumeSessionId}".\n`); - process.exit(1); } -} - -void main(); -async function main(): Promise { const updatePromptResult = await promptForPendingUpdate(packageInfo); if (updatePromptResult.installed) { process.exit(0); @@ -122,7 +67,7 @@ async function main(): Promise { const inkInstance = render( restartRef.current?.()} @@ -132,7 +77,7 @@ async function main(): Promise { restartRef.current = () => { restarting = true; - process.stdout.write("\u001B[2J\u001B[3J\u001B[H"); + writeStdoutLine("\u001B[2J\u001B[3J\u001B[H"); inkInstance.unmount(); startApp(); }; @@ -156,20 +101,7 @@ function configureWindowsShell(): void { setShellIfWindows(); } catch (error) { const message = error instanceof Error ? error.message : String(error); - process.stderr.write(`deepcode: ${message}\n`); + writeStderrLine(`deepcode: ${message}\n`); process.exit(1); } } - -function readPackageInfo(): PackageInfo { - try { - const pkg = require("../package.json") as { name?: unknown; version?: unknown }; - return { - name: typeof pkg.name === "string" ? pkg.name : "@vegamo/deepcode-cli", - version: typeof pkg.version === "string" ? pkg.version : (CLI_VERSION ?? ""), - gitCommit: GIT_COMMIT_INFO ?? "", - }; - } catch { - return { name: "@vegamo/deepcode-cli", version: CLI_VERSION ?? "", gitCommit: GIT_COMMIT_INFO ?? "" }; - } -} diff --git a/packages/cli/src/common/update-check.ts b/packages/cli/src/common/update-check.ts index 3b82e51a..fb387fe3 100644 --- a/packages/cli/src/common/update-check.ts +++ b/packages/cli/src/common/update-check.ts @@ -6,6 +6,7 @@ import * as path from "path"; import { render, type Instance } from "ink"; import { UpdatePrompt, type UpdatePromptChoice } from "../ui"; import { killProcessTree } from "@vegamo/deepcode-core"; +import type { PackageJson } from "../utils/package"; export type PackageInfo = { name: string; @@ -29,14 +30,14 @@ const MAX_NPM_VIEW_OUTPUT_CHARS = 64 * 1024; const TENCENT_MIRROR_REGISTRY = "https://mirrors.cloud.tencent.com/npm/"; export const UPDATE_SUCCESS_MESSAGE = "🎉 Update ran successfully! Please restart Deep Code."; -export async function promptForPendingUpdate(packageInfo: PackageInfo): Promise<{ installed: boolean }> { +export async function promptForPendingUpdate(packageInfo: PackageJson): Promise<{ installed: boolean }> { const state = readUpdateState(); const pending = state.pending; if (!pending) { return { installed: false }; } - if (compareVersions(packageInfo.version, pending.latestVersion) >= 0) { + if (compareVersions(packageInfo.version!, pending.latestVersion) >= 0) { writeUpdateState({ ...state, pending: null }); return { installed: false }; } @@ -49,7 +50,7 @@ export async function promptForPendingUpdate(packageInfo: PackageInfo): Promise< const installSpec = `${pending.packageName}@${pending.latestVersion}`; const installCommand = `npm install -g ${installSpec}`; const choice = await promptUpdateChoice({ - currentVersion: packageInfo.version, + currentVersion: packageInfo.version!, latestVersion: pending.latestVersion, installCommand, }); @@ -73,7 +74,7 @@ export async function promptForPendingUpdate(packageInfo: PackageInfo): Promise< return { installed: false }; } -export async function checkForNpmUpdate(packageInfo: PackageInfo): Promise { +export async function checkForNpmUpdate(packageInfo: PackageJson): Promise { if (!packageInfo.name || !packageInfo.version) { return; } diff --git a/packages/cli/src/tests/cli-args.test.ts b/packages/cli/src/tests/cli-args.test.ts index fd97de76..fe90eeed 100644 --- a/packages/cli/src/tests/cli-args.test.ts +++ b/packages/cli/src/tests/cli-args.test.ts @@ -1,47 +1,59 @@ import { test } from "node:test"; import assert from "node:assert/strict"; -import { parseCliArgs } from "../cli-args"; +import { parseArguments, isValidSessionId } from "../cli-args"; -// ── parseCliArgs: basic parsing ────────────────────────────────────────────── +// ── isValidSessionId ───────────────────────────────────────────────────────── -test("parseCliArgs returns prompt after -p", () => { - const r = parseCliArgs(["-p", "hello world"]); +test("isValidSessionId accepts valid UUID", () => { + assert.ok(isValidSessionId("0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6")); +}); + +test("isValidSessionId rejects invalid format", () => { + assert.ok(!isValidSessionId("not-a-uuid")); + assert.ok(!isValidSessionId("")); + assert.ok(!isValidSessionId("abc")); +}); + +// ── parseArguments: basic parsing ────────────────────────────────────────────── + +test("parseArguments returns prompt after -p", async () => { + const r = await parseArguments(["-p", "hello world"]); assert.ok(!("message" in r)); assert.equal(r.prompt, "hello world"); }); -test("parseCliArgs returns prompt after --prompt", () => { - const r = parseCliArgs(["--prompt", "hello world"]); +test("parseArguments returns prompt after --prompt", async () => { + const r = await parseArguments(["--prompt", "hello world"]); assert.ok(!("message" in r)); assert.equal(r.prompt, "hello world"); }); -test("parseCliArgs returns undefined prompt when -p is not present", () => { - const r = parseCliArgs(["--resume"]); +test("parseArguments returns undefined prompt when -p is not present", async () => { + const r = await parseArguments(["--resume"]); assert.ok(!("message" in r)); assert.equal(r.prompt, undefined); }); -test("parseCliArgs returns session ID after --resume", () => { - const r = parseCliArgs(["--resume", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"]); +test("parseArguments returns session ID after --resume", async () => { + const r = await parseArguments(["--resume", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"]); assert.ok(!("message" in r)); assert.equal(r.resume, "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"); }); -test("parseCliArgs returns true when --resume has no value", () => { - const r = parseCliArgs(["--resume"]); +test("parseArguments returns true when --resume has no value", async () => { + const r = await parseArguments(["--resume"]); assert.ok(!("message" in r)); assert.equal(r.resume, true); }); -test("parseCliArgs returns undefined resume when not present", () => { - const r = parseCliArgs(["-p", "test"]); +test("parseArguments returns undefined resume when not present", async () => { + const r = await parseArguments(["-p", "test"]); assert.ok(!("message" in r)); assert.equal(r.resume, undefined); }); -test("parseCliArgs returns defaults for empty args", () => { - const r = parseCliArgs([]); +test("parseArguments returns defaults for empty args", async () => { + const r = await parseArguments([]); assert.ok(!("message" in r)); assert.equal(r.prompt, undefined); assert.equal(r.resume, undefined); @@ -49,120 +61,151 @@ test("parseCliArgs returns defaults for empty args", () => { assert.equal(r.help, false); }); -// ── parseCliArgs: -r alias ─────────────────────────────────────────────────── +// ── parseArguments: -r alias ─────────────────────────────────────────────────── -test("parseCliArgs returns session ID after -r", () => { - const r = parseCliArgs(["-r", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"]); +test("parseArguments returns session ID after -r", async () => { + const r = await parseArguments(["-r", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"]); assert.ok(!("message" in r)); assert.equal(r.resume, "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"); }); -test("parseCliArgs returns true when -r has no value", () => { - const r = parseCliArgs(["-r"]); +test("parseArguments returns true when -r has no value", async () => { + const r = await parseArguments(["-r"]); assert.ok(!("message" in r)); assert.equal(r.resume, true); }); -test("parseCliArgs handles -r combined with -p", () => { - const r = parseCliArgs(["-r", "session-123", "-p", "hello"]); +test("parseArguments handles -r combined with -p", async () => { + const r = await parseArguments(["-r", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6", "-p", "hello"]); assert.ok(!("message" in r)); - assert.equal(r.resume, "session-123"); + assert.equal(r.resume, "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"); assert.equal(r.prompt, "hello"); }); -test("parseCliArgs rejects bare -r with -p", () => { - const r = parseCliArgs(["-r", "-p", "hello"]); - assert.ok("message" in r); - assert.match(r.message, /Cannot use --resume/); -}); - -// ── parseCliArgs: --version / --help ───────────────────────────────────────── +// ── parseArguments: --version / --help ───────────────────────────────────────── -test("parseCliArgs detects --version", () => { - const r = parseCliArgs(["--version"]); +test("parseArguments detects --version", async () => { + const r = await parseArguments(["--version"]); assert.ok(!("message" in r)); assert.equal(r.version, true); assert.equal(r.help, false); }); -test("parseCliArgs detects -v", () => { - const r = parseCliArgs(["-v"]); +test("parseArguments detects -v", async () => { + const r = await parseArguments(["-v"]); assert.ok(!("message" in r)); assert.equal(r.version, true); }); -test("parseCliArgs detects --help", () => { - const r = parseCliArgs(["--help"]); +test("parseArguments detects --help", async () => { + const r = await parseArguments(["--help"]); assert.ok(!("message" in r)); assert.equal(r.help, true); assert.equal(r.version, false); }); -test("parseCliArgs detects -h", () => { - const r = parseCliArgs(["-h"]); +test("parseArguments detects -h", async () => { + const r = await parseArguments(["-h"]); assert.ok(!("message" in r)); assert.equal(r.help, true); }); -test("parseCliArgs version and help are false when not passed", () => { - const r = parseCliArgs(["-p", "hello"]); +test("parseArguments version and help are false when not passed", async () => { + const r = await parseArguments(["-p", "hello"]); assert.ok(!("message" in r)); assert.equal(r.version, false); assert.equal(r.help, false); }); -test("parseCliArgs handles -v combined with -r (both flags set)", () => { - const r = parseCliArgs(["-v", "-r", "abc"]); +test("parseArguments handles -v combined with -r (both flags set)", async () => { + const r = await parseArguments(["-v", "-r", "abc"]); assert.ok(!("message" in r)); assert.equal(r.version, true); assert.equal(r.resume, "abc"); }); -// ── parseCliArgs: combined usage ───────────────────────────────────────────── +// ── parseArguments: combined usage ───────────────────────────────────────────── -test("parseCliArgs handles --resume combined with -p", () => { - const r = parseCliArgs(["--resume", "session-123", "-p", "hello"]); +test("parseArguments handles --resume combined with -p", async () => { + const r = await parseArguments(["--resume", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6", "-p", "hello"]); assert.ok(!("message" in r)); - assert.equal(r.resume, "session-123"); + assert.equal(r.resume, "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"); assert.equal(r.prompt, "hello"); }); -test("parseCliArgs handles -p before --resume ", () => { - const r = parseCliArgs(["-p", "hello", "--resume", "session-123"]); +test("parseArguments handles -p before --resume ", async () => { + const r = await parseArguments(["-p", "hello", "--resume", "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"]); assert.ok(!("message" in r)); - assert.equal(r.resume, "session-123"); + assert.equal(r.resume, "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"); assert.equal(r.prompt, "hello"); }); -// ── parseCliArgs: validation ───────────────────────────────────────────────── - -test("parseCliArgs rejects bare --resume with -p", () => { - const r = parseCliArgs(["--resume", "-p", "hello"]); - assert.ok("message" in r); - assert.match(r.message, /Cannot use --resume/); -}); - -test("parseCliArgs rejects -p with bare --resume (reversed order)", () => { - const r = parseCliArgs(["-p", "hello", "--resume"]); - assert.ok("message" in r); - assert.match(r.message, /Cannot use --resume/); -}); - -test("parseCliArgs rejects unknown flags in strict mode", () => { - const r = parseCliArgs(["--unknown-flag"]); - assert.ok("message" in r); - assert.match(r.message, /Unknown argument/); -}); - -test("parseCliArgs rejects empty -p value", () => { - const r = parseCliArgs(["-p", ""]); - assert.ok("message" in r); - assert.match(r.message, /non-empty/); -}); - -test("parseCliArgs --version takes precedence over --help", () => { - const r = parseCliArgs(["--version", "--help"]); +test("parseArguments --version takes precedence over --help", async () => { + const r = await parseArguments(["--version", "--help"]); assert.ok(!("message" in r)); assert.equal(r.version, true); assert.equal(r.help, true); }); + +// ── parseArguments: error cases (mock process.exit) ──────────────────────────── +// Command-level and top-level errors both call process.exit(1) via yargs .fail(). + +function withMockedExit(fn: (exitSpy: { calls: number[] }) => Promise): Promise { + const original = process.exit; + const stderrWrite = process.stderr.write; + // Suppress yargs help/error output during tests + process.stderr.write = (() => true) as typeof process.stderr.write; + const exitSpy: { calls: number[] } = { calls: [] }; + process.exit = ((code?: number) => { + exitSpy.calls.push(code ?? 0); + throw new Error(`process.exit(${code})`); + }) as typeof process.exit; + return fn(exitSpy).finally(() => { + process.exit = original; + process.stderr.write = stderrWrite; + }); +} + +test("parseArguments exits on unknown flags", async () => { + await withMockedExit(async (exitSpy) => { + try { + await parseArguments(["--unknown-flag"]); + } catch { + /* expected */ + } + assert.ok(exitSpy.calls.length >= 1); + }); +}); + +test("parseArguments exits on bare -r with -p", async () => { + await withMockedExit(async (exitSpy) => { + try { + await parseArguments(["-r", "-p", "hello"]); + } catch { + /* expected */ + } + assert.ok(exitSpy.calls.length >= 1); + }); +}); + +test("parseArguments exits on empty -p value", async () => { + await withMockedExit(async (exitSpy) => { + try { + await parseArguments(["-p", ""]); + } catch { + /* expected */ + } + assert.ok(exitSpy.calls.length >= 1); + }); +}); + +test("parseArguments exits on invalid --resume session ID", async () => { + await withMockedExit(async (exitSpy) => { + try { + await parseArguments(["--resume", "not-a-uuid"]); + } catch { + /* expected */ + } + assert.ok(exitSpy.calls.length >= 1); + }); +}); diff --git a/packages/cli/src/utils/package.ts b/packages/cli/src/utils/package.ts new file mode 100644 index 00000000..1f195294 --- /dev/null +++ b/packages/cli/src/utils/package.ts @@ -0,0 +1,29 @@ +import { readPackageUp, type PackageJson as BasePackageJson } from "read-package-up"; +import { fileURLToPath } from "node:url"; +import path from "node:path"; +import { CLI_VERSION } from "../generated/git-commit"; + +export type PackageJson = BasePackageJson & { + config?: { + sandboxImageUri?: string; + }; +}; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +let packageJson: PackageJson; + +export async function getPackageJson(): Promise { + if (packageJson) { + return packageJson; + } + + const result = await readPackageUp({ cwd: __dirname }); + if (!result) { + return { name: "@vegamo/deepcode-cli", version: CLI_VERSION ?? "" }; + } + + packageJson = result.packageJson; + return packageJson; +} diff --git a/packages/cli/src/utils/stdioHelpers.ts b/packages/cli/src/utils/stdioHelpers.ts new file mode 100644 index 00000000..f0202e99 --- /dev/null +++ b/packages/cli/src/utils/stdioHelpers.ts @@ -0,0 +1,25 @@ +/** + * Writes a message to stdout with a trailing newline. + * Use for normal command output that the user expects to see. + * Avoids double newlines if the message already ends with one. + */ +export const writeStdoutLine = (message: string): void => { + process.stdout.write(message.endsWith("\n") ? message : `${message}\n`); +}; + +/** + * Writes a message to stderr with a trailing newline. + * Use for error messages in CLI commands. + * Avoids double newlines if the message already ends with one. + */ +export const writeStderrLine = (message: string): void => { + process.stderr.write(message.endsWith("\n") ? message : `${message}\n`); +}; + +/** + * Clears the terminal screen. + * Use instead of console.clear() to satisfy no-console lint rules. + */ +export const clearScreen = (): void => { + console.clear(); +}; diff --git a/packages/cli/src/utils/version.ts b/packages/cli/src/utils/version.ts new file mode 100644 index 00000000..f41a5c1f --- /dev/null +++ b/packages/cli/src/utils/version.ts @@ -0,0 +1,6 @@ +import { getPackageJson } from "./package.js"; + +export async function getCliVersion(): Promise { + const pkgJson = await getPackageJson(); + return process.env["CLI_VERSION"] || pkgJson?.version || "unknown"; +} From 43d0c112f43090b24b099eaf608eabb8ba3e10e7 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Thu, 25 Jun 2026 14:49:14 +0800 Subject: [PATCH 56/72] fix: update code examples in statusline documentation and improve module provider abort handling --- docs/statusline.md | 4 +- docs/statusline_en.md | 2 +- packages/cli/src/tests/statusline.test.ts | 36 ++++++++++++++ .../cli/src/ui/statusline/module-provider.ts | 47 +++++++++++-------- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/docs/statusline.md b/docs/statusline.md index 4ab8a11d..4c731276 100644 --- a/docs/statusline.md +++ b/docs/statusline.md @@ -6,7 +6,7 @@ Deep Code CLI 支持通过插件向终端底部状态栏注入自定义信息( 在 `~/.deepcode/settings.json`(或项目级 `.deepcode/settings.json`)中添加 `statusline` 字段: -```jsonc +```json { "statusline": { "enabled": true, @@ -100,7 +100,7 @@ export default function tokensProvider({ projectRoot, session }) { ## 安全限制 -- **module provider 路径必须位于项目根目录或用户家目录之下**,绝对路径在这两个范围之外会被拒绝加载(防止从任意位置执行代码)。 +- **module provider 路径必须位于项目根目录或用户home目录之下**,绝对路径在这两个范围之外会被拒绝加载(防止从任意位置执行代码)。 - 单个 segment 文本被自动: - 取第一个非空行 - 去除 ANSI 转义序列 diff --git a/docs/statusline_en.md b/docs/statusline_en.md index bd14d91a..340c32cc 100644 --- a/docs/statusline_en.md +++ b/docs/statusline_en.md @@ -6,7 +6,7 @@ Deep Code CLI lets you inject custom information into the status line at the bot Add a `statusline` field to `~/.deepcode/settings.json` (or the project-level `.deepcode/settings.json`): -```jsonc +```json { "statusline": { "enabled": true, diff --git a/packages/cli/src/tests/statusline.test.ts b/packages/cli/src/tests/statusline.test.ts index 4417cca1..0336b626 100644 --- a/packages/cli/src/tests/statusline.test.ts +++ b/packages/cli/src/tests/statusline.test.ts @@ -171,6 +171,42 @@ test("loadModuleProvider succeeds for a well-formed module", async () => { } }); +test("loadModuleProvider removes abort listener after successful fetch", async () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "deepcode-statusline-")); + const modPath = path.join(dir, "cleanup.mjs"); + fs.writeFileSync(modPath, "export default () => 'ok';", "utf8"); + try { + const provider = await loadModuleProvider(modPath, undefined, "cleanup", 10_000); + assert.ok(provider); + + const ac = new AbortController(); + const signal = ac.signal; + const originalAdd = signal.addEventListener; + const originalRemove = signal.removeEventListener; + let abortListenerAdds = 0; + let abortListenerRemoves = 0; + signal.addEventListener = function (this: AbortSignal, ...args: Parameters) { + if (args[0] === "abort") { + abortListenerAdds += 1; + } + return originalAdd.apply(this, args); + } as AbortSignal["addEventListener"]; + signal.removeEventListener = function (this: AbortSignal, ...args: Parameters) { + if (args[0] === "abort") { + abortListenerRemoves += 1; + } + return originalRemove.apply(this, args); + } as AbortSignal["removeEventListener"]; + + const result = await provider!.fetch({ projectRoot: dir, signal }); + assert.equal(result, "ok"); + assert.equal(abortListenerAdds, 1); + assert.equal(abortListenerRemoves, 1); + } finally { + fs.rmSync(dir, { recursive: true, force: true }); + } +}); + test("resolveSettingsSources lets project-level providers override user-level by id", () => { const resolved = resolveSettingsSources( { diff --git a/packages/cli/src/ui/statusline/module-provider.ts b/packages/cli/src/ui/statusline/module-provider.ts index 0222bb6c..f45d6ab2 100644 --- a/packages/cli/src/ui/statusline/module-provider.ts +++ b/packages/cli/src/ui/statusline/module-provider.ts @@ -63,26 +63,33 @@ export async function loadModuleProvider( if (ctx.signal.aborted) { return ""; } - const result = await Promise.race([ - Promise.resolve().then(() => - providerFn({ - projectRoot: ctx.projectRoot, - session: ctx.getSessionInfo ? ctx.getSessionInfo() : null, - }) - ), - new Promise((_, reject) => { - const timer = setTimeout(() => reject(new Error("timeout")), timeout); - ctx.signal.addEventListener( - "abort", - () => { - clearTimeout(timer); - reject(new Error("aborted")); - }, - { once: true } - ); - }), - ]); - return typeof result === "string" ? result : ""; + let timer: ReturnType | null = null; + let onAbort: (() => void) | null = null; + const timeoutPromise = new Promise((_, reject) => { + timer = setTimeout(() => reject(new Error("timeout")), timeout); + onAbort = () => reject(new Error("aborted")); + ctx.signal.addEventListener("abort", onAbort, { once: true }); + }); + + try { + const result = await Promise.race([ + Promise.resolve().then(() => + providerFn({ + projectRoot: ctx.projectRoot, + session: ctx.getSessionInfo ? ctx.getSessionInfo() : null, + }) + ), + timeoutPromise, + ]); + return typeof result === "string" ? result : ""; + } finally { + if (timer) { + clearTimeout(timer); + } + if (onAbort) { + ctx.signal.removeEventListener("abort", onAbort); + } + } }, }; } catch { From 12b2c09f9652dd1b9f80c7bdf520037650873692 Mon Sep 17 00:00:00 2001 From: hcyang Date: Thu, 25 Jun 2026 16:09:43 +0800 Subject: [PATCH 57/72] =?UTF-8?q?fix(cli):=20=E4=BF=AE=E5=A4=8D=20Windows?= =?UTF-8?q?=20Shell=20=E9=85=8D=E7=BD=AE=E6=97=B6=E7=9A=84=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E8=A1=8C=E5=8F=82=E6=95=B0=E5=A4=84=E7=90=86=E9=A1=BA?= =?UTF-8?q?=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 Windows Shell 配置逻辑调整到 --version 和 --help 参数处理之后 - 避免在 Windows 无 Git Bash 环境下配置 Shell 时提前退出进程 - 确保命令行参数如 --version 和 --help 正常工作 - 添加 configureWindowsShell 函数注释说明其调用时机和作用 - 清理 cli.tsx 中的导入和调用顺序,提高代码可读性 --- packages/cli/src/cli.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/cli.tsx b/packages/cli/src/cli.tsx index edf5fdbd..af33bc42 100644 --- a/packages/cli/src/cli.tsx +++ b/packages/cli/src/cli.tsx @@ -11,7 +11,6 @@ import { writeStderrLine, writeStdoutLine } from "./utils/stdioHelpers"; import { getPackageJson } from "./utils/package"; import { CLI_VERSION } from "./generated/git-commit"; -configureWindowsShell(); void main(); async function main(): Promise { @@ -24,6 +23,11 @@ async function main(): Promise { process.exit(0); } + // Configure Windows shell AFTER --version/--help handling. + // On Windows without Git Bash, setShellIfWindows() throws and calls process.exit(1). + // If called before argument parsing, --help and --version would fail on those machines. + configureWindowsShell(); + let initialPrompt = parsed.prompt; let resumeSessionId = parsed.resume; const projectRoot = process.cwd(); @@ -95,6 +99,12 @@ async function main(): Promise { startApp(); } +/** + * Configure shell environment for Windows. + * Sets NoDefaultCurrentDirectoryInExePath and resolves Git Bash path. + * Must be called after --version/--help handling to avoid blocking those + * commands on Windows machines without Git Bash installed. + */ function configureWindowsShell(): void { process.env.NoDefaultCurrentDirectoryInExePath = "1"; try { From 7c8ece94105b964b4dcc92b73942462062cfbe90 Mon Sep 17 00:00:00 2001 From: hcyang Date: Thu, 25 Jun 2026 16:22:29 +0800 Subject: [PATCH 58/72] =?UTF-8?q?refactor(cli):=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E6=9C=AA=E4=BD=BF=E7=94=A8=E7=9A=84=20PackageInfo=20=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 packages/cli/src/common/update-check.ts 文件中未使用的 PackageInfo 类型 - 减少代码冗余,提升代码可维护性 - 保持类型定义的简洁性与准确性 --- packages/cli/src/common/update-check.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/cli/src/common/update-check.ts b/packages/cli/src/common/update-check.ts index fb387fe3..2dad85f8 100644 --- a/packages/cli/src/common/update-check.ts +++ b/packages/cli/src/common/update-check.ts @@ -8,12 +8,6 @@ import { UpdatePrompt, type UpdatePromptChoice } from "../ui"; import { killProcessTree } from "@vegamo/deepcode-core"; import type { PackageJson } from "../utils/package"; -export type PackageInfo = { - name: string; - version: string; - gitCommit?: string; -}; - type UpdateState = { pending?: { currentVersion: string; From 2fa60d54b78b9529f075c3ed8be2db0b6825ec9b Mon Sep 17 00:00:00 2001 From: hcyang Date: Thu, 25 Jun 2026 18:02:43 +0800 Subject: [PATCH 59/72] =?UTF-8?q?style(MessageView):=20=E5=9C=A8=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E8=A7=86=E5=9B=BE=E7=BB=84=E4=BB=B6=E4=B8=AD=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=B7=A6=E8=BE=B9=E8=B7=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为外层Box组件增加marginLeft样式属性 - 保持其他样式和布局不变 - 修正UI布局中提示符内容的左侧间距问题 --- packages/cli/src/ui/components/MessageView/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/ui/components/MessageView/index.tsx b/packages/cli/src/ui/components/MessageView/index.tsx index 66df9625..a413f748 100644 --- a/packages/cli/src/ui/components/MessageView/index.tsx +++ b/packages/cli/src/ui/components/MessageView/index.tsx @@ -145,7 +145,7 @@ function PromptEchoLine({ }): React.ReactElement { const contentWidth = getPromptEchoContentWidth(width); return ( - + {"> "} From 545a4f54dd6bbb620c7f9d6cc907f17f659e5dc4 Mon Sep 17 00:00:00 2001 From: hcyang Date: Thu, 25 Jun 2026 18:09:58 +0800 Subject: [PATCH 60/72] =?UTF-8?q?test(cli):=20=E8=B0=83=E6=95=B4=20Message?= =?UTF-8?q?View=20=E7=BB=84=E4=BB=B6=E4=B8=AD=E7=9A=84=E7=BC=A9=E8=BF=9B?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改了消息渲染输出的缩进,从无空格缩进改为增加空格 - 确保多行消息内容对齐显示更美观 - 更新相关测试断言以匹配新的缩进格式 --- packages/cli/src/tests/message-view.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/tests/message-view.test.ts b/packages/cli/src/tests/message-view.test.ts index fbd2b097..abe95ef3 100644 --- a/packages/cli/src/tests/message-view.test.ts +++ b/packages/cli/src/tests/message-view.test.ts @@ -132,7 +132,7 @@ test("MessageView echoes submitted user prompts with live prompt wrapping width" const msg = makeSessionMessage({ role: "user", content: "abcdefg" }); const output = renderToString(React.createElement(MessageView, { message: msg, width: 8 }), { columns: 8 }); - assert.equal(stripAnsi(output), "> abcdef\n g\n"); + assert.equal(stripAnsi(output), " > abcdef\n g\n"); }); test("MessageView echoes model changes with submitted prompt wrapping", () => { @@ -143,7 +143,7 @@ test("MessageView echoes model changes with submitted prompt wrapping", () => { }); const output = renderToString(React.createElement(MessageView, { message: msg, width: 8 }), { columns: 8 }); - assert.equal(stripAnsi(output), "> abcdef\n gh\n"); + assert.equal(stripAnsi(output), " > abcdef\n gh\n"); }); test("renderMessageToStdout renders assistant non-thinking messages with ✦", () => { From 7a447b80d86b7200bbf15003118e76363f2a1a47 Mon Sep 17 00:00:00 2001 From: hcyang Date: Thu, 25 Jun 2026 19:22:18 +0800 Subject: [PATCH 61/72] =?UTF-8?q?refactor(cli):=20=E7=BB=9F=E4=B8=80stdio?= =?UTF-8?q?=E8=BE=85=E5=8A=A9=E5=87=BD=E6=95=B0=E5=AF=BC=E5=85=A5=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将cli.tsx和cli-args.ts中stdioHelpers的导入路径调整为统一的stdio-helpers格式 - 规范了模块文件命名,提高代码一致性 - 未改动核心功能逻辑,仅更改导入路径字符串 --- packages/cli/src/cli-args.ts | 2 +- packages/cli/src/cli.tsx | 2 +- packages/cli/src/utils/{stdioHelpers.ts => stdio-helpers.ts} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename packages/cli/src/utils/{stdioHelpers.ts => stdio-helpers.ts} (100%) diff --git a/packages/cli/src/cli-args.ts b/packages/cli/src/cli-args.ts index 780869c0..b86eda41 100644 --- a/packages/cli/src/cli-args.ts +++ b/packages/cli/src/cli-args.ts @@ -6,7 +6,7 @@ import type { Argv } from "yargs"; import Yargs from "yargs"; import { getCliVersion } from "./utils/version"; -import { writeStderrLine } from "./utils/stdioHelpers"; +import { writeStderrLine } from "./utils/stdio-helpers"; import { hideBin } from "yargs/helpers"; // UUID v4 regex pattern for validation diff --git a/packages/cli/src/cli.tsx b/packages/cli/src/cli.tsx index af33bc42..80b11f08 100644 --- a/packages/cli/src/cli.tsx +++ b/packages/cli/src/cli.tsx @@ -7,7 +7,7 @@ import { setShellIfWindows, getProjectCode } from "@vegamo/deepcode-core"; import { checkForNpmUpdate, promptForPendingUpdate } from "./common/update-check"; import { AppContainer } from "./ui"; import { parseArguments } from "./cli-args"; -import { writeStderrLine, writeStdoutLine } from "./utils/stdioHelpers"; +import { writeStderrLine, writeStdoutLine } from "./utils/stdio-helpers"; import { getPackageJson } from "./utils/package"; import { CLI_VERSION } from "./generated/git-commit"; diff --git a/packages/cli/src/utils/stdioHelpers.ts b/packages/cli/src/utils/stdio-helpers.ts similarity index 100% rename from packages/cli/src/utils/stdioHelpers.ts rename to packages/cli/src/utils/stdio-helpers.ts From 34ea71fd0d45064be8a0f82d1cec55db9455df68 Mon Sep 17 00:00:00 2001 From: hcyang Date: Thu, 25 Jun 2026 19:24:07 +0800 Subject: [PATCH 62/72] =?UTF-8?q?refactor(cli):=20=E7=BB=9F=E4=B8=80stdio?= =?UTF-8?q?=E8=BE=85=E5=8A=A9=E5=87=BD=E6=95=B0=E5=AF=BC=E5=85=A5=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将cli.tsx和cli-args.ts中stdioHelpers的导入路径调整为统一的stdio-helpers格式 - 规范了模块文件命名,提高代码一致性 - 未改动核心功能逻辑,仅更改导入路径字符串 --- packages/cli/src/utils/package.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/cli/src/utils/package.ts b/packages/cli/src/utils/package.ts index 1f195294..3c1401af 100644 --- a/packages/cli/src/utils/package.ts +++ b/packages/cli/src/utils/package.ts @@ -3,11 +3,7 @@ import { fileURLToPath } from "node:url"; import path from "node:path"; import { CLI_VERSION } from "../generated/git-commit"; -export type PackageJson = BasePackageJson & { - config?: { - sandboxImageUri?: string; - }; -}; +export type PackageJson = BasePackageJson; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); From da9f09950854151e7c27185392cc5dced00fe850 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Fri, 26 Jun 2026 10:06:56 +0800 Subject: [PATCH 63/72] feat: move the resume hint out of the exit summary box --- packages/cli/src/tests/exit-summary.test.ts | 23 +++++++--- packages/cli/src/ui/exit-summary.ts | 16 +++---- packages/cli/src/ui/index.ts | 2 +- packages/cli/src/ui/views/App.tsx | 51 +++++++++++++++------ packages/cli/src/ui/views/PromptInput.tsx | 7 +-- 5 files changed, 67 insertions(+), 32 deletions(-) diff --git a/packages/cli/src/tests/exit-summary.test.ts b/packages/cli/src/tests/exit-summary.test.ts index fd6b8ad0..45317b1e 100644 --- a/packages/cli/src/tests/exit-summary.test.ts +++ b/packages/cli/src/tests/exit-summary.test.ts @@ -1,6 +1,6 @@ import { test } from "node:test"; import assert from "node:assert/strict"; -import { buildExitSummaryText } from "../ui"; +import { buildExitSummaryText, buildResumeHintText } from "../ui"; import type { ModelUsage, SessionEntry } from "@vegamo/deepcode-core"; const stripAnsi = (text: string): string => text.replace(/\u001b\[[0-9;]*[a-zA-Z]/g, ""); @@ -90,7 +90,7 @@ test("buildExitSummaryText does not derive usage rows from legacy aggregate usag assert.doesNotMatch(summary, /11,966/); }); -test("buildExitSummaryText shows resume hint when sessionId is provided", () => { +test("buildExitSummaryText does not show resume hint when sessionId is provided", () => { const sessionId = "0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"; const summary = stripAnsi( buildExitSummaryText({ @@ -100,8 +100,8 @@ test("buildExitSummaryText shows resume hint when sessionId is provided", () => ); assert.match(summary, /Goodbye!/); - assert.match(summary, /deepcode --resume 0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6/); - assert.match(summary, /To continue this session/); + assert.doesNotMatch(summary, /deepcode --resume 0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6/); + assert.doesNotMatch(summary, /To continue this session/); }); test("buildExitSummaryText does not show resume hint when sessionId is omitted", () => { @@ -116,7 +116,7 @@ test("buildExitSummaryText does not show resume hint when sessionId is omitted", assert.doesNotMatch(summary, /To continue this session/); }); -test("buildExitSummaryText shows resume hint with null session", () => { +test("buildExitSummaryText does not show resume hint with null session", () => { const summary = stripAnsi( buildExitSummaryText({ session: null, @@ -125,7 +125,18 @@ test("buildExitSummaryText shows resume hint with null session", () => { ); assert.match(summary, /Goodbye!/); - assert.match(summary, /deepcode --resume test-session-id/); + assert.doesNotMatch(summary, /deepcode --resume test-session-id/); + assert.doesNotMatch(summary, /To continue this session/); +}); + +test("buildResumeHintText shows resume command when sessionId is provided", () => { + const hint = stripAnsi(buildResumeHintText("0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6") ?? ""); + + assert.equal(hint, "To continue this session, run deepcode --resume 0a5cb7a5-c39d-4c39-a11b-05f8b22b8df6"); +}); + +test("buildResumeHintText returns null when sessionId is omitted", () => { + assert.equal(buildResumeHintText(), null); }); function buildSession(usage: ModelUsage | null, usagePerModel: Record | null = null): SessionEntry { diff --git a/packages/cli/src/ui/exit-summary.ts b/packages/cli/src/ui/exit-summary.ts index 1a28ab8f..67db1280 100644 --- a/packages/cli/src/ui/exit-summary.ts +++ b/packages/cli/src/ui/exit-summary.ts @@ -68,7 +68,7 @@ function extractUsageFields(usage: ModelUsage | null): UsageFields { } export function buildExitSummaryText(input: ExitSummaryInput): string { - const { session, sessionId } = input; + const { session } = input; const innerWidth = 98; const contentWidth = innerWidth - 4; // "│ " prefix + " │" suffix → 4 chars padding @@ -135,13 +135,6 @@ export function buildExitSummaryText(input: ExitSummaryInput): string { rows.push(""); - if (sessionId) { - const resumeHint = - chalk.dim(`To continue this session, run `) + chalk.hex("#229ac3")(`deepcode --resume ${sessionId}`); - rows.push(resumeHint); - rows.push(""); - } - const border = borderColor("─".repeat(innerWidth)); const top = `${borderColor("╭")}${border}${borderColor("╮")}`; const bottom = `${borderColor("╰")}${border}${borderColor("╯")}`; @@ -150,3 +143,10 @@ export function buildExitSummaryText(input: ExitSummaryInput): string { return [top, body, bottom].join("\n"); } + +export function buildResumeHintText(sessionId?: string): string | null { + if (!sessionId) { + return null; + } + return chalk.dim(`To continue this session, run `) + chalk.hex("#229ac3")(`deepcode --resume ${sessionId}`); +} diff --git a/packages/cli/src/ui/index.ts b/packages/cli/src/ui/index.ts index 8f155360..65415464 100644 --- a/packages/cli/src/ui/index.ts +++ b/packages/cli/src/ui/index.ts @@ -90,4 +90,4 @@ export { type FileMentionToken, } from "./core/file-mentions"; export { findExpandedThinkingId, isCollapsedThinking } from "./core/thinking-state"; -export { buildExitSummaryText } from "./exit-summary"; +export { buildExitSummaryText, buildResumeHintText } from "./exit-summary"; diff --git a/packages/cli/src/ui/views/App.tsx b/packages/cli/src/ui/views/App.tsx index 337832d5..456030c3 100644 --- a/packages/cli/src/ui/views/App.tsx +++ b/packages/cli/src/ui/views/App.tsx @@ -20,7 +20,7 @@ import { formatAskUserQuestionAnswers, } from "../core/ask-user-question"; import { PermissionPrompt, type PermissionPromptResult } from "./PermissionPrompt"; -import { buildExitSummaryText } from "../exit-summary"; +import { buildExitSummaryText, buildResumeHintText } from "../exit-summary"; import { RawMode, useRawModeContext } from "../contexts"; import { renderMessageToStdout } from "../components/MessageView/utils"; import { @@ -290,22 +290,40 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp }, [sessionManager]); writeRef.current = write; - const handlePrompt = useCallback( - async (submission: PromptSubmission) => { - if (submission.command === "exit") { - setIsExiting(true); - setTimeout(() => { - const activeSessionId = sessionManager.getActiveSessionId(); - const session = activeSessionId ? sessionManager.getSession(activeSessionId) : null; - const summary = buildExitSummaryText({ session, sessionId: activeSessionId ?? undefined }); - process.stdout.write("\n"); + const handleExit = useCallback( + ({ showCommand, showSummary }: { showCommand: boolean; showSummary: boolean }) => { + setIsExiting(true); + setTimeout(() => { + const activeSessionId = sessionManager.getActiveSessionId(); + const session = activeSessionId ? sessionManager.getSession(activeSessionId) : null; + const resumeHint = buildResumeHintText(activeSessionId ?? undefined); + + process.stdout.write("\n"); + if (showCommand) { process.stdout.write(chalk.rgb(34, 154, 195)("> /exit ")); process.stdout.write("\n\n"); + } + if (showSummary) { + const summary = buildExitSummaryText({ session, sessionId: activeSessionId ?? undefined }); process.stdout.write(summary); process.stdout.write("\n\n"); - sessionManager.dispose(); - exit(); - }, 0); + } + if (resumeHint) { + process.stdout.write(resumeHint); + process.stdout.write("\n"); + } + + sessionManager.dispose(); + exit(); + }, 0); + }, + [exit, sessionManager] + ); + + const handlePrompt = useCallback( + async (submission: PromptSubmission) => { + if (submission.command === "exit") { + handleExit({ showCommand: true, showSummary: true }); return; } if (submission.command === "new") { @@ -400,7 +418,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp [ sessionManager, pendingPermissionReply, - exit, + handleExit, onRestart, refreshSkills, refreshSessionsList, @@ -477,6 +495,10 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp [handlePrompt] ); + const handleExitShortcut = useCallback(() => { + handleExit({ showCommand: false, showSummary: false }); + }, [handleExit]); + const reloadActiveSessionView = useCallback( (sessionId: string): void => { resetStaticView(loadVisibleMessages(sessionManager, sessionId), { clearScreen: true }); @@ -959,6 +981,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp onRawModeChange={handleRawModeChange} onInterrupt={handleInterrupt} onToggleProcessStdout={handleToggleProcessStdout} + onExitShortcut={handleExitShortcut} placeholder="Type your message..." statusLineSegments={statusLineSegments} statusLineSeparator={resolvedSettings.statusline.separator} diff --git a/packages/cli/src/ui/views/PromptInput.tsx b/packages/cli/src/ui/views/PromptInput.tsx index 2bf720b1..3f548def 100644 --- a/packages/cli/src/ui/views/PromptInput.tsx +++ b/packages/cli/src/ui/views/PromptInput.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useMemo, useRef, useState } from "react"; -import { Box, Text, useApp, useStdout } from "ink"; +import { Box, Text, useStdout } from "ink"; import type { DOMElement } from "ink"; import chalk from "chalk"; import { ARGS_SEPARATOR } from "../constants"; @@ -101,6 +101,7 @@ type Props = { onRawModeChange?: (mode: string) => void; onInterrupt: () => void; onToggleProcessStdout?: () => void; + onExitShortcut?: () => void; }; const PROMPT_PREFIX_WIDTH = 2; @@ -132,9 +133,9 @@ export const PromptInput = React.memo(function PromptInput({ onModelConfigChange, onInterrupt, onToggleProcessStdout, + onExitShortcut, onRawModeChange, }: Props): React.ReactElement { - const { exit } = useApp(); const { stdout } = useStdout(); const inputTextRef = useRef(null); const [buffer, setBuffer] = useState(EMPTY_BUFFER); @@ -357,7 +358,7 @@ export const PromptInput = React.memo(function PromptInput({ } const now = Date.now(); if (pendingExit && now - lastCtrlDAt.current < 2000) { - exit(); + onExitShortcut?.(); return; } lastCtrlDAt.current = now; From 377e04161e925de4c3e7413946020e4dc48c4dcb Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Fri, 26 Jun 2026 10:36:58 +0800 Subject: [PATCH 64/72] fix: the new left margin need to be included in width calculations --- packages/cli/src/tests/message-view.test.ts | 20 ++++++++++++++++--- .../src/ui/components/MessageView/index.tsx | 6 ++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/tests/message-view.test.ts b/packages/cli/src/tests/message-view.test.ts index abe95ef3..c1c2d69d 100644 --- a/packages/cli/src/tests/message-view.test.ts +++ b/packages/cli/src/tests/message-view.test.ts @@ -127,12 +127,19 @@ test("renderMessageToStdout shows (no content) for empty user messages", () => { }); test("MessageView echoes submitted user prompts with live prompt wrapping width", () => { - assert.equal(getPromptEchoContentWidth(8), 6); + assert.equal(getPromptEchoContentWidth(8), 5); const msg = makeSessionMessage({ role: "user", content: "abcdefg" }); const output = renderToString(React.createElement(MessageView, { message: msg, width: 8 }), { columns: 8 }); - assert.equal(stripAnsi(output), " > abcdef\n g\n"); + const text = stripAnsi(output); + assert.equal(text, " > abcde\n fg\n"); + assert.ok( + text + .trimEnd() + .split("\n") + .every((line) => line.length <= 8) + ); }); test("MessageView echoes model changes with submitted prompt wrapping", () => { @@ -143,7 +150,14 @@ test("MessageView echoes model changes with submitted prompt wrapping", () => { }); const output = renderToString(React.createElement(MessageView, { message: msg, width: 8 }), { columns: 8 }); - assert.equal(stripAnsi(output), " > abcdef\n gh\n"); + const text = stripAnsi(output); + assert.equal(text, " > abcde\n fgh\n"); + assert.ok( + text + .trimEnd() + .split("\n") + .every((line) => line.length <= 8) + ); }); test("renderMessageToStdout renders assistant non-thinking messages with ✦", () => { diff --git a/packages/cli/src/ui/components/MessageView/index.tsx b/packages/cli/src/ui/components/MessageView/index.tsx index a413f748..12b8229d 100644 --- a/packages/cli/src/ui/components/MessageView/index.tsx +++ b/packages/cli/src/ui/components/MessageView/index.tsx @@ -13,6 +13,7 @@ import type { DiffPreviewLine, MessageViewProps } from "./types"; import { RawMode, useRawModeContext } from "../../contexts"; const PROMPT_ECHO_PREFIX_WIDTH = 2; +const PROMPT_ECHO_MARGIN_LEFT = 1; export function MessageView({ message, collapsed, width = 80 }: MessageViewProps): React.ReactElement | null { const { mode } = useRawModeContext(); @@ -131,7 +132,7 @@ export function MessageView({ message, collapsed, width = 80 }: MessageViewProps } export function getPromptEchoContentWidth(width: number): number { - return Math.max(1, width - PROMPT_ECHO_PREFIX_WIDTH); + return Math.max(1, width - PROMPT_ECHO_MARGIN_LEFT - PROMPT_ECHO_PREFIX_WIDTH); } function PromptEchoLine({ @@ -144,8 +145,9 @@ function PromptEchoLine({ attachmentCount?: number; }): React.ReactElement { const contentWidth = getPromptEchoContentWidth(width); + const containerWidth = Math.max(1, width - PROMPT_ECHO_MARGIN_LEFT); return ( - + {"> "} From ada6ca74f293425621216986482b0b155ccaed01 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Fri, 26 Jun 2026 13:28:26 +0800 Subject: [PATCH 65/72] feat: update AGENTS.md --- .deepcode/AGENTS.md | 16 +++++++++++----- README.md | 12 ++++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/.deepcode/AGENTS.md b/.deepcode/AGENTS.md index a1611307..7471cc15 100644 --- a/.deepcode/AGENTS.md +++ b/.deepcode/AGENTS.md @@ -14,12 +14,17 @@ packages/ │ ├── prompt.ts # System prompt builder & tool definitions │ └── settings.ts # Settings resolution from ~/.deepcode/settings.json ├── cli/src/ # Terminal UI (Ink/React) -│ ├── cli.tsx # Entry point — parses args (-p, -v), renders AppContainer -│ ├── ui/views/ # Top-level screens (App, PromptInput, SessionList, PermissionPrompt, etc.) +│ ├── cli.tsx # Entry point — renders AppContainer +│ ├── cli-args.ts # CLI argument parsing (yargs: -p, -r, -v, -h) +│ ├── common/ # Update checker +│ ├── utils/ # stdio helpers, version, package info +│ ├── generated/ # Build-time git commit info +│ ├── ui/views/ # Top-level screens (App, PromptInput, SessionList, PermissionPrompt, WelcomeScreen, UpdatePrompt, McpStatusList, etc.) │ ├── ui/components/ # Reusable Ink components (MessageView, DropdownMenu, ModelsDropdown, etc.) │ ├── ui/core/ # Prompt buffer, slash commands, file mentions, clipboard, undo/redo -│ ├── ui/hooks/ # Custom hooks (cursor, history navigation, paste handling, terminal input) +│ ├── ui/hooks/ # Custom hooks (cursor, history navigation, paste handling, terminal input, statusline) │ ├── ui/contexts/ # React contexts (AppContext, RawModeContext) +│ ├── ui/statusline/ # Pluggable statusline providers (command, module) │ └── tests/ # UI-focused tests with run-tests.mjs runner ├── vscode-ide-companion/ # VSCode extension companion │ └── src/ # extension.ts, provider.ts, utils.ts @@ -45,6 +50,7 @@ All commands run from the repo root. | `npm run check` | Runs typecheck + lint + format:check together | | `npm run build` | Orchestrates full build (scripts/build.js) — compiles core + bundles CLI + copies assets | | `npm run bundle` | Generates git commit info + esbuild bundle + copies bundled assets | +| `npm run build:vscode` | Builds the VSCode extension companion | | `npm test` | Runs all workspace tests (`npm run test --workspaces --if-present`) | | `npm run start` | Runs the locally built CLI (`scripts/start.js`) | | `npm run build-and-start` | Builds then starts the CLI | @@ -115,9 +121,9 @@ A **file history system** (`packages/core/src/common/file-history.ts`) provides **Slash commands**: `/skills`, `/model`, `/new`, `/init`, `/resume`, `/continue`, `/undo`, `/mcp`, `/raw`, `/exit`, plus dynamic `/skill-name` for each loaded skill. -**Key UI features**: `@` file mentions in the prompt input, `Ctrl+O` to view live process stdout, `Ctrl+V` to paste images, Shift+Enter for newlines, MCP server status display, undo selector, and permission prompts. +**Key UI features**: `@` file mentions in the prompt input, `Ctrl+O` to view live process stdout, `Ctrl+V` to paste images, `Ctrl+X` to clear images, Shift+Enter for newlines, pluggable statusline, MCP server status display, undo selector, and permission prompts. -**CLI flags**: `-p ` / `--prompt` to auto-submit a prompt on launch, `-v` / `--version`, `-h` / `--help`. +**CLI flags**: `-p ` / `--prompt` to auto-submit a prompt on launch, `-r [sessionId]` / `--resume [sessionId]` to resume a session or show the session picker, `-v` / `--version`, `-h` / `--help`. ## Agent-Specific Instructions diff --git a/README.md b/README.md index cde02314..39cd12bd 100644 --- a/README.md +++ b/README.md @@ -159,14 +159,18 @@ cd deepcode-cli # 安装依赖 npm install -# 本地开发(类型检查 + lint + 格式检查 + 构建) -npm run build - # 运行测试 npm test -# 链接到全局(即本地全局安装) +# CLI本地开发(类型检查 + lint + 格式检查 + 构建) +npm run build + +# CLI链接到全局(即本地全局安装) npm link + +# VSCode插件本地开发 +npm run build:vscode + ``` - 提交 PR 前请确保 `npm run check` 通过(类型检查 + lint + 格式检查) From 83c139efc8514578e089041b5319ff82afbaeb6a Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Fri, 26 Jun 2026 14:15:42 +0800 Subject: [PATCH 66/72] fix: initial-session Markdown rendering for VSCode extension --- packages/vscode-ide-companion/src/provider.ts | 10 +++++++--- .../vscode-ide-companion/src/tests/extension.test.ts | 12 ++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/vscode-ide-companion/src/provider.ts b/packages/vscode-ide-companion/src/provider.ts index 91aee0e4..2e3b4ac8 100644 --- a/packages/vscode-ide-companion/src/provider.ts +++ b/packages/vscode-ide-companion/src/provider.ts @@ -62,7 +62,7 @@ export async function handleWebviewMessage(message: unknown, deps: ProviderDeps) const msg = message as Record; if (msg.type === "ready") { - loadInitialSession(sessionManager, postMessage); + loadInitialSession(sessionManager, postMessage, renderMarkdown); await sendSkillsList(sessionManager, postMessage); return true; } @@ -138,7 +138,11 @@ export async function handleWebviewMessage(message: unknown, deps: ProviderDeps) return false; } -function loadInitialSession(sessionManager: ProviderDeps["sessionManager"], postMessage: PostMessageFn): void { +function loadInitialSession( + sessionManager: ProviderDeps["sessionManager"], + postMessage: PostMessageFn, + renderMarkdown: (text: string) => string +): void { const sessions = sessionManager.listSessions(); const sessionsList = toSessionList(sessions); @@ -152,7 +156,7 @@ function loadInitialSession(sessionManager: ProviderDeps["sessionManager"], post } const latestSession = sessions[0]; - loadSession(latestSession.id, sessionManager, postMessage, (t) => t); + loadSession(latestSession.id, sessionManager, postMessage, renderMarkdown); } export function loadSession( diff --git a/packages/vscode-ide-companion/src/tests/extension.test.ts b/packages/vscode-ide-companion/src/tests/extension.test.ts index 4f8d6e03..03f8e4e7 100644 --- a/packages/vscode-ide-companion/src/tests/extension.test.ts +++ b/packages/vscode-ide-companion/src/tests/extension.test.ts @@ -82,6 +82,18 @@ test("ready message triggers loadInitialSession and sendSkillsList", async () => assert.ok(types.includes("skillsList"), `Expected skillsList, got: ${types.join(", ")}`); }); +test("ready message renders markdown for initial session messages", async () => { + const deps = createDeps({ + messages: [{ role: "assistant", content: "**bold**", visible: true }], + }); + + await handleWebviewMessage({ type: "ready" }, deps); + + const loadMsg = deps.messages.find((m: any) => m.type === "loadSession") as any; + assert.ok(loadMsg, "Should send loadSession"); + assert.equal(loadMsg.messages[0].html, "

**bold**

"); +}); + test("ready with no sessions sends initializeEmpty", async () => { const deps = createDeps({ sessions: [] }); await handleWebviewMessage({ type: "ready" }, deps); From f2972d4547ab18788022ea5b8133878ba859b7c5 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Fri, 26 Jun 2026 14:27:20 +0800 Subject: [PATCH 67/72] chore: update package versions to 0.1.32 for deepcode-cli and deepcode-core, and 0.1.23 for deepcode-vscode --- package-lock.json | 6 +++--- packages/cli/package.json | 2 +- packages/core/package.json | 2 +- packages/vscode-ide-companion/package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 66cf2bce..00eda577 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7705,7 +7705,7 @@ }, "packages/cli": { "name": "@vegamo/deepcode-cli", - "version": "0.1.31", + "version": "0.1.32", "license": "MIT", "dependencies": { "@vegamo/deepcode-core": "file:../core", @@ -7751,7 +7751,7 @@ }, "packages/core": { "name": "@vegamo/deepcode-core", - "version": "0.1.31", + "version": "0.1.32", "license": "MIT", "dependencies": { "chalk": "^5.6.2", @@ -7786,7 +7786,7 @@ }, "packages/vscode-ide-companion": { "name": "deepcode-vscode", - "version": "0.1.22", + "version": "0.1.23", "license": "MIT", "dependencies": { "@vegamo/deepcode-core": "file:../core", diff --git a/packages/cli/package.json b/packages/cli/package.json index 1f657304..e3959fc4 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@vegamo/deepcode-cli", - "version": "0.1.31", + "version": "0.1.32", "description": "Deep Code CLI - Vibe coding for the deepseek-v4 model in your terminal", "license": "MIT", "type": "module", diff --git a/packages/core/package.json b/packages/core/package.json index 1f924389..41c9da31 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@vegamo/deepcode-core", - "version": "0.1.31", + "version": "0.1.32", "description": "Deep Code core library — LLM session management, tool execution, and shared utilities", "license": "MIT", "type": "module", diff --git a/packages/vscode-ide-companion/package.json b/packages/vscode-ide-companion/package.json index 6369f37b..fc7f8118 100644 --- a/packages/vscode-ide-companion/package.json +++ b/packages/vscode-ide-companion/package.json @@ -1,6 +1,6 @@ { "name": "deepcode-vscode", - "version": "0.1.22", + "version": "0.1.23", "publisher": "vegamo", "displayName": "Deep Code", "description": "Deep Code VSCode companion — AI-assisted development in your editor", From e47ef58cc94a155144fd1bd53f9eeddde9443df0 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Fri, 26 Jun 2026 14:53:49 +0800 Subject: [PATCH 68/72] chore: update package versions to 0.1.33 for deepcode-cli and deepcode-core, and enhance package validation in prepare-package script --- package-lock.json | 4 +- packages/cli/package.json | 4 +- packages/core/package.json | 2 +- scripts/prepare-package.js | 167 +++++++++++++++++++++++++++++++------ 4 files changed, 148 insertions(+), 29 deletions(-) diff --git a/package-lock.json b/package-lock.json index 00eda577..5c894763 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7705,7 +7705,7 @@ }, "packages/cli": { "name": "@vegamo/deepcode-cli", - "version": "0.1.32", + "version": "0.1.33", "license": "MIT", "dependencies": { "@vegamo/deepcode-core": "file:../core", @@ -7751,7 +7751,7 @@ }, "packages/core": { "name": "@vegamo/deepcode-core", - "version": "0.1.32", + "version": "0.1.33", "license": "MIT", "dependencies": { "chalk": "^5.6.2", diff --git a/packages/cli/package.json b/packages/cli/package.json index e3959fc4..c860e690 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@vegamo/deepcode-cli", - "version": "0.1.32", + "version": "0.1.33", "description": "Deep Code CLI - Vibe coding for the deepseek-v4 model in your terminal", "license": "MIT", "type": "module", @@ -15,6 +15,8 @@ "main": "./dist/cli.js", "files": [ "dist/cli.js", + "dist/chunks/**", + "dist/templates/**", "dist/bundled/**", "README.md", "LICENSE" diff --git a/packages/core/package.json b/packages/core/package.json index 41c9da31..bac0f126 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@vegamo/deepcode-core", - "version": "0.1.32", + "version": "0.1.33", "description": "Deep Code core library — LLM session management, tool execution, and shared utilities", "license": "MIT", "type": "module", diff --git a/scripts/prepare-package.js b/scripts/prepare-package.js index 02481c50..eb12dfea 100644 --- a/scripts/prepare-package.js +++ b/scripts/prepare-package.js @@ -27,18 +27,20 @@ function ok(msg) { function run(cmd, args, opts = {}) { const label = opts.label ?? `${cmd} ${args.join(" ")}`; - if (opts.dryRun) { + if (opts.dryRun && !opts.runInDryRun) { log(` (dry-run) ${label}`); return { status: 0, stdout: "" }; } const result = spawnSync(cmd, args, { stdio: opts.stdio ?? "inherit", cwd: opts.cwd ?? root, - shell: true, + shell: false, + encoding: opts.encoding, env: { ...process.env, ...opts.env }, }); if (result.status !== 0) { - fail(`Command failed: ${label}`); + const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim(); + fail(`Command failed: ${label}${output ? `\n${output}` : ""}`); } return result; } @@ -55,6 +57,70 @@ function isValidSemver(v) { return /^\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$/.test(v); } +function isValidNpmTag(v) { + return /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(v); +} + +function hasPackFile(files, expectedPath) { + return files.includes(expectedPath); +} + +function hasPackPrefix(files, expectedPrefix) { + return files.some((file) => file.startsWith(expectedPrefix)); +} + +function validatePacklist(cwd, checks, opts = {}) { + const label = opts.label ?? `npm pack --dry-run --json --ignore-scripts`; + const result = run("npm", ["pack", "--dry-run", "--json", "--ignore-scripts"], { + cwd, + label, + stdio: "pipe", + encoding: "utf-8", + runInDryRun: true, + }); + const output = result.stdout.trim(); + const packs = JSON.parse(output); + const pack = Array.isArray(packs) ? packs[0] : packs; + const files = (pack?.files ?? []).map((file) => file.path); + const missing = []; + + for (const check of checks) { + const found = check.type === "prefix" ? hasPackPrefix(files, check.value) : hasPackFile(files, check.value); + if (!found) { + missing.push(check.label ?? check.value); + } + } + + if (missing.length > 0) { + fail(`Package tarball is missing required files:\n - ${missing.join("\n - ")}`); + } + + ok(`Validated package tarball (${files.length} files)`); +} + +function hasGitChanges(paths) { + const result = spawnSync("git", ["diff", "--quiet", "--", ...paths], { + cwd: root, + shell: false, + }); + if (result.status === 0) { + return false; + } + if (result.status === 1) { + return true; + } + fail("Unable to check release file changes."); +} + +function gitTagExists(tagName) { + const result = spawnSync("git", ["rev-parse", "-q", "--verify", `refs/tags/${tagName}`], { + cwd: root, + shell: false, + stdio: "ignore", + }); + return result.status === 0; +} + // ── Parse args ─────────────────────────────────────────────────────────────── const args = process.argv.slice(2); @@ -103,6 +169,10 @@ if (!isValidSemver(version)) { fail(`Invalid semver version: ${version}`); } +if (!isValidNpmTag(tag)) { + fail(`Invalid npm dist-tag: ${tag}`); +} + const TOTAL_STEPS = 8; // ── Banner ─────────────────────────────────────────────────────────────────── @@ -119,7 +189,7 @@ step(1, TOTAL_STEPS, "Checking git state..."); const gitStatus = spawnSync("git", ["status", "--porcelain"], { cwd: root, encoding: "utf-8", - shell: true, + shell: false, }); if (gitStatus.stdout.trim()) { fail("Working tree is not clean. Commit or stash changes first."); @@ -130,7 +200,7 @@ if (!force) { const gitBranch = spawnSync("git", ["branch", "--show-current"], { cwd: root, encoding: "utf-8", - shell: true, + shell: false, }); const branch = gitBranch.stdout.trim(); if (branch !== "main") { @@ -147,7 +217,7 @@ if (!dryRun) { const whoami = spawnSync("npm", ["whoami"], { cwd: root, encoding: "utf-8", - shell: true, + shell: false, }); if (whoami.status !== 0) { fail("Not logged in to npm. Run `npm login` first."); @@ -182,6 +252,12 @@ if (!dryRun) { log(` (dry-run) packages/cli: ${oldVersion} → ${version}`); } +run("npm", ["install", "--package-lock-only", "--ignore-scripts"], { + dryRun, + label: "npm install --package-lock-only --ignore-scripts", +}); +ok("package-lock.json is up to date"); + // ── 4. Quality checks ──────────────────────────────────────────────────────── step(4, TOTAL_STEPS, "Running quality checks (typecheck + lint + format)..."); @@ -209,6 +285,7 @@ const cliRoot = join(root, "packages", "cli"); const distDir = join(cliRoot, "dist"); const distCliJs = join(distDir, "cli.js"); const distChunks = join(distDir, "chunks"); +const distTemplates = join(distDir, "templates"); const distBundled = join(distDir, "bundled"); if (!existsSync(distCliJs)) { @@ -217,10 +294,24 @@ if (!existsSync(distCliJs)) { if (!existsSync(distChunks)) { fail(`Chunks directory not found: ${distChunks}. Run "npm run build" first.`); } +if (!existsSync(distTemplates)) { + fail(`Templates directory not found: ${distTemplates}. Run "npm run build" first.`); +} if (!existsSync(distBundled)) { fail(`Bundled assets not found: ${distBundled}. Run "npm run build" first.`); } +validatePacklist( + cliRoot, + [ + { type: "file", value: "dist/cli.js" }, + { type: "prefix", value: "dist/chunks/", label: "dist/chunks/*.js" }, + { type: "prefix", value: "dist/templates/", label: "dist/templates/**" }, + { type: "prefix", value: "dist/bundled/", label: "dist/bundled/**" }, + ], + { label: "cd packages/cli && npm pack --dry-run --json --ignore-scripts" } +); + // Copy README.md and LICENSE into dist/ for (const file of ["README.md", "LICENSE"]) { const src = join(root, file); @@ -258,9 +349,53 @@ if (!dryRun) { } log(" Written dist/package.json with dependencies: {}"); +if (!dryRun) { + validatePacklist( + distDir, + [ + { type: "file", value: "cli.js" }, + { type: "prefix", value: "chunks/", label: "chunks/*.js" }, + { type: "prefix", value: "templates/", label: "templates/**" }, + { type: "prefix", value: "bundled/", label: "bundled/**" }, + ], + { label: "cd dist && npm pack --dry-run --json --ignore-scripts" } + ); +} else { + log(" (dry-run) skipped dist/package.json tarball validation because dist/package.json was not written"); +} + ok("dist/ prepared for publishing"); -// ── 7. Publish from dist/ ──────────────────────────────────────────────────── +// ── Git commit + tag ───────────────────────────────────────────────────────── + +const releaseFiles = ["packages/core/package.json", "packages/cli/package.json", "package-lock.json"]; +const tagName = `v${version}`; + +if (!dryRun) { + log("\nCreating git commit and tag..."); + if (hasGitChanges(releaseFiles)) { + run("git", ["add", ...releaseFiles], { + label: "git add packages/*/package.json package-lock.json", + }); + run("git", ["commit", "-m", `chore(release): v${version}`], { + label: `git commit -m "chore(release): v${version}"`, + }); + } else { + log(" No release file changes to commit; tagging current HEAD"); + } + + if (gitTagExists(tagName)) { + fail(`Git tag already exists: ${tagName}`); + } + run("git", ["tag", tagName], { + label: `git tag ${tagName}`, + }); + ok(`Created tag ${tagName}`); +} else { + log("\n (dry-run) git add + commit + tag"); +} + +// ── 8. Publish from dist/ ──────────────────────────────────────────────────── step(8, TOTAL_STEPS, "Publishing @vegamo/deepcode-cli from dist/..."); @@ -274,24 +409,6 @@ run("npm", publishArgs, { }); ok(`Published @vegamo/deepcode-cli@${version}`); -// ── Git commit + tag ───────────────────────────────────────────────────────── - -if (!dryRun) { - log("\nCreating git commit and tag..."); - run("git", ["add", "packages/core/package.json", "packages/cli/package.json"], { - label: "git add packages/*/package.json", - }); - run("git", ["commit", "-m", `chore(release): v${version}`], { - label: `git commit -m "chore(release): v${version}"`, - }); - run("git", ["tag", `v${version}`], { - label: `git tag v${version}`, - }); - ok(`Created commit and tag v${version}`); -} else { - log("\n (dry-run) git add + commit + tag"); -} - // ── Done ───────────────────────────────────────────────────────────────────── console.log("\n========================================="); From c18d0d81cadda282677190ef31c80fa473522a8d Mon Sep 17 00:00:00 2001 From: hcyang Date: Fri, 26 Jun 2026 15:24:19 +0800 Subject: [PATCH 69/72] =?UTF-8?q?refactor(ui):=20=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E6=89=80=E6=9C=89=20process.stdout.write=20=E4=B8=BA=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E7=9A=84=E5=86=99=E5=85=A5=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入 writeStdoutLine 函数替代重复的 process.stdout.write 调用 - 优化多处命令行输出,提升代码一致性和可维护性 - 修改退出提示、会话渲染及屏幕清理相关逻辑使用新函数 - 防止状态行在退出时显示,提升界面表现稳定性 --- packages/cli/src/ui/views/App.tsx | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/packages/cli/src/ui/views/App.tsx b/packages/cli/src/ui/views/App.tsx index 456030c3..24788502 100644 --- a/packages/cli/src/ui/views/App.tsx +++ b/packages/cli/src/ui/views/App.tsx @@ -48,6 +48,7 @@ import type { } from "@vegamo/deepcode-core"; import { SessionManager } from "@vegamo/deepcode-core"; import { getCompactPromptTokenThreshold } from "@vegamo/deepcode-core"; +import { writeStdoutLine } from "../../utils/stdio-helpers"; type View = "chat" | "session-list" | "undo" | "mcp-status"; @@ -145,8 +146,8 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp onAssistantMessage: (message: SessionMessage) => { setMessages((prev) => [...prev, message]); if (rawModeRef.current === RawMode.Raw) { - process.stdout.write("\n"); - process.stdout.write(renderMessageToStdout(message, rawModeRef.current) + "\n\n"); + writeStdoutLine("\n"); + writeStdoutLine(renderMessageToStdout(message, rawModeRef.current) + "\n\n"); } }, onSessionEntryUpdated: (entry) => { @@ -196,7 +197,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp const resetStaticView = useCallback( (loadedMessages: SessionMessage[], options?: { clearScreen?: boolean }): Promise => { if (options?.clearScreen) { - process.stdout.write(ANSI_CLEAR_SCREEN); + writeStdoutLine(ANSI_CLEAR_SCREEN); } setMessages([]); setWelcomeNonce((n) => n + 1); @@ -298,19 +299,19 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp const session = activeSessionId ? sessionManager.getSession(activeSessionId) : null; const resumeHint = buildResumeHintText(activeSessionId ?? undefined); - process.stdout.write("\n"); + writeStdoutLine("\n"); if (showCommand) { - process.stdout.write(chalk.rgb(34, 154, 195)("> /exit ")); - process.stdout.write("\n\n"); + writeStdoutLine(chalk.rgb(34, 154, 195)(" > /exit ")); + writeStdoutLine("\n"); } if (showSummary) { const summary = buildExitSummaryText({ session, sessionId: activeSessionId ?? undefined }); - process.stdout.write(summary); - process.stdout.write("\n\n"); + writeStdoutLine(summary); + writeStdoutLine("\n"); } if (resumeHint) { - process.stdout.write(resumeHint); - process.stdout.write("\n"); + writeStdoutLine(resumeHint); + writeStdoutLine("\n"); } sessionManager.dispose(); @@ -628,7 +629,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp setShowWelcome(false); setMessages([]); // Clear screen to remove stale formatted text. - process.stdout.write(ANSI_CLEAR_SCREEN); + writeStdoutLine(ANSI_CLEAR_SCREEN); setTimeout(() => { if (nextMode === RawMode.Raw) { @@ -667,7 +668,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp if (mode === RawMode.Raw) { // In raw mode, re-render all messages directly to stdout at the new width. // Use process.stdout.write instead of writeRef to avoid Ink interference. - process.stdout.write(ANSI_CLEAR_SCREEN); + writeStdoutLine(ANSI_CLEAR_SCREEN); const activeSessionId = sessionManager.getActiveSessionId(); const allMessages = activeSessionId ? loadVisibleMessages(sessionManager, activeSessionId) : []; renderRawModeMessages(allMessages, mode); @@ -898,7 +899,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp ); }}
- {busy || statusLine ? : null} + {(busy || statusLine) && !isExiting ? : null} {errorLine ? ( Error: {errorLine} From 47d1f03fafce9901142c27a0e7da699dea0e55ef Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Fri, 26 Jun 2026 17:22:42 +0800 Subject: [PATCH 70/72] feat: enhance prompt attachment manager to support multiple image attachments and improve preview handling --- .../resources/prompt-attachments.js | 72 ++++-- .../resources/webview.css | 1 + .../src/tests/extension.test.ts | 20 ++ .../src/tests/prompt-attachments.test.ts | 240 ++++++++++++++++++ 4 files changed, 307 insertions(+), 26 deletions(-) create mode 100644 packages/vscode-ide-companion/src/tests/prompt-attachments.test.ts diff --git a/packages/vscode-ide-companion/resources/prompt-attachments.js b/packages/vscode-ide-companion/resources/prompt-attachments.js index 81bfc174..e6c628ac 100644 --- a/packages/vscode-ide-companion/resources/prompt-attachments.js +++ b/packages/vscode-ide-companion/resources/prompt-attachments.js @@ -48,9 +48,11 @@ throw new Error("Prompt attachment manager requires promptInput, inputWrap, and toolsLine."); } - let attachment = null; + let attachments = []; + let nextAttachmentId = 0; let previewPopup = null; let previewImage = null; + let previewAnchor = null; function ensurePreviewPopup() { if (previewPopup) { @@ -68,6 +70,7 @@ if (!previewPopup) { return; } + previewAnchor = null; previewPopup.classList.remove("show"); } @@ -101,12 +104,13 @@ previewPopup.style.top = top + "px"; } - function showPreview(anchor) { + function showPreview(anchor, attachment) { if (!attachment) { return; } ensurePreviewPopup(); + previewAnchor = anchor; previewImage.src = attachment.dataUrl; previewPopup.classList.add("show"); updatePreviewPosition(anchor); @@ -114,24 +118,35 @@ function emitChange() { onAttachmentChange({ - hasAttachments: Boolean(attachment), - attachments: attachment ? [attachment] : [], + hasAttachments: attachments.length > 0, + attachments: attachments.slice(), }); } function clear() { - attachment = null; + attachments = []; toolsLine.innerHTML = ""; toolsLine.classList.remove("has-attachment"); hidePreview(); emitChange(); } - function createAttachmentNode() { + function removeAttachment(id) { + const nextAttachments = attachments.filter((attachment) => attachment.id !== id); + if (nextAttachments.length === attachments.length) { + return; + } + attachments = nextAttachments; + render(); + emitChange(); + } + + function createAttachmentNode(attachment) { const wrapper = createElement("div", "chat-attached-context-attachment show-file-icons"); wrapper.tabIndex = 0; wrapper.setAttribute("role", "button"); wrapper.setAttribute("aria-label", ATTACHMENT_LABEL + " (删除)"); + wrapper.dataset.attachmentId = String(attachment.id); wrapper.draggable = true; const removeButton = createElement("a", "monaco-button codicon codicon-close"); @@ -143,7 +158,7 @@ removeButton.addEventListener("click", (event) => { event.preventDefault(); event.stopPropagation(); - clear(); + removeAttachment(attachment.id); }); const iconLabel = createElement("div", "monaco-icon-label"); @@ -166,7 +181,7 @@ wrapper.appendChild(pill); wrapper.appendChild(text); - const show = () => showPreview(wrapper); + const show = () => showPreview(wrapper, attachment); wrapper.addEventListener("mouseenter", show); wrapper.addEventListener("focus", show); wrapper.addEventListener("mouseleave", hidePreview); @@ -177,7 +192,7 @@ wrapper.addEventListener("keydown", (event) => { if (event.key === "Delete" || event.key === "Backspace") { event.preventDefault(); - clear(); + removeAttachment(attachment.id); } }); @@ -186,37 +201,44 @@ function render() { toolsLine.innerHTML = ""; - toolsLine.classList.toggle("has-attachment", Boolean(attachment)); - if (!attachment) { + toolsLine.classList.toggle("has-attachment", attachments.length > 0); + if (attachments.length === 0) { hidePreview(); return; } - toolsLine.appendChild(createAttachmentNode()); + for (const attachment of attachments) { + toolsLine.appendChild(createAttachmentNode(attachment)); + } + if (previewAnchor && !toolsLine.contains(previewAnchor)) { + hidePreview(); + } } - function setAttachmentData(data) { + function addAttachmentData(data) { if (!data?.dataUrl) { return false; } - attachment = { + nextAttachmentId += 1; + attachments.push({ + id: nextAttachmentId, name: data.name || ATTACHMENT_LABEL, mimeType: data.mimeType || "image/png", dataUrl: data.dataUrl, label: ATTACHMENT_LABEL, - }; + }); render(); emitChange(); return true; } - async function setAttachmentFromFile(file) { + async function addAttachmentFromFile(file) { if (!isImageFile(file)) { return false; } const dataUrl = await readFileAsDataUrl(file); - return setAttachmentData({ + return addAttachmentData({ name: file.name || ATTACHMENT_LABEL, mimeType: file.type || "image/png", dataUrl, @@ -232,7 +254,7 @@ event.preventDefault(); try { - await setAttachmentFromFile(file); + await addAttachmentFromFile(file); } catch (error) { console.error("Failed to attach pasted image.", error); } @@ -241,18 +263,16 @@ promptInput.addEventListener("paste", handlePaste); window.addEventListener("resize", () => { - const attachmentNode = toolsLine.querySelector(".chat-attached-context-attachment"); - if (previewPopup?.classList.contains("show") && attachmentNode) { - updatePreviewPosition(attachmentNode); + if (previewPopup?.classList.contains("show") && previewAnchor) { + updatePreviewPosition(previewAnchor); } }); window.addEventListener( "scroll", () => { - const attachmentNode = toolsLine.querySelector(".chat-attached-context-attachment"); - if (previewPopup?.classList.contains("show") && attachmentNode) { - updatePreviewPosition(attachmentNode); + if (previewPopup?.classList.contains("show") && previewAnchor) { + updatePreviewPosition(previewAnchor); } }, true @@ -261,10 +281,10 @@ return { clear, hasAttachments() { - return Boolean(attachment); + return attachments.length > 0; }, getImageUrls() { - return attachment ? [attachment.dataUrl] : []; + return attachments.map((attachment) => attachment.dataUrl); }, }; } diff --git a/packages/vscode-ide-companion/resources/webview.css b/packages/vscode-ide-companion/resources/webview.css index ea1d71a2..98ffa62e 100644 --- a/packages/vscode-ide-companion/resources/webview.css +++ b/packages/vscode-ide-companion/resources/webview.css @@ -1121,6 +1121,7 @@ body { .tools-line { display: none; align-items: center; + flex-wrap: wrap; gap: 8px; min-height: 0; padding: 0 12px; diff --git a/packages/vscode-ide-companion/src/tests/extension.test.ts b/packages/vscode-ide-companion/src/tests/extension.test.ts index 03f8e4e7..9ea39656 100644 --- a/packages/vscode-ide-companion/src/tests/extension.test.ts +++ b/packages/vscode-ide-companion/src/tests/extension.test.ts @@ -267,6 +267,26 @@ test("userPrompt with images sends userMessage with image placeholder", async () assert.equal((userMsg as any).content, "粘贴的图像"); }); +test("userPrompt passes multiple image urls to the session manager", async () => { + const deps = createDeps(); + let submittedPrompt: any = null; + (deps.sessionManager as any).handleUserPrompt = (prompt: any) => { + submittedPrompt = prompt; + return Promise.resolve(); + }; + + await handleWebviewMessage( + { + type: "userPrompt", + prompt: "", + images: ["data:image/png;base64,abc", "data:image/jpeg;base64,def"], + }, + deps + ); + + assert.deepEqual(submittedPrompt?.imageUrls, ["data:image/png;base64,abc", "data:image/jpeg;base64,def"]); +}); + test("userPrompt with permissions (continue) does not send userMessage", async () => { const deps = createDeps(); await handleWebviewMessage( diff --git a/packages/vscode-ide-companion/src/tests/prompt-attachments.test.ts b/packages/vscode-ide-companion/src/tests/prompt-attachments.test.ts new file mode 100644 index 00000000..314826e3 --- /dev/null +++ b/packages/vscode-ide-companion/src/tests/prompt-attachments.test.ts @@ -0,0 +1,240 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import vm from "node:vm"; +import { fileURLToPath } from "node:url"; + +type EventHandler = (event: any) => unknown; + +class FakeClassList { + private readonly classes = new Set(); + + constructor(className = "") { + for (const classPart of className.split(/\s+/)) { + if (classPart) { + this.classes.add(classPart); + } + } + } + + add(className: string): void { + this.classes.add(className); + } + + remove(className: string): void { + this.classes.delete(className); + } + + contains(className: string): boolean { + return this.classes.has(className); + } + + toggle(className: string, force?: boolean): boolean { + const shouldAdd = force ?? !this.classes.has(className); + if (shouldAdd) { + this.classes.add(className); + } else { + this.classes.delete(className); + } + return shouldAdd; + } +} + +class FakeElement { + readonly tagName: string; + className = ""; + classList = new FakeClassList(); + children: FakeElement[] = []; + parent: FakeElement | null = null; + dataset: Record = {}; + style: Record = {}; + textContent = ""; + tabIndex = 0; + draggable = false; + href = ""; + src = ""; + alt = ""; + private readonly attributes = new Map(); + private readonly listeners = new Map(); + + constructor(tagName: string) { + this.tagName = tagName; + } + + setAttribute(name: string, value: string): void { + this.attributes.set(name, value); + } + + appendChild(child: FakeElement): FakeElement { + child.parent = this; + this.children.push(child); + return child; + } + + set innerHTML(_value: string) { + for (const child of this.children) { + child.parent = null; + } + this.children = []; + } + + get innerHTML(): string { + return ""; + } + + addEventListener(type: string, handler: EventHandler): void { + const listeners = this.listeners.get(type) ?? []; + listeners.push(handler); + this.listeners.set(type, listeners); + } + + async dispatchEvent(event: any): Promise { + event.type ??= ""; + for (const handler of this.listeners.get(event.type) ?? []) { + await handler(event); + } + } + + contains(candidate: FakeElement | null): boolean { + if (!candidate) { + return false; + } + if (candidate === this) { + return true; + } + return this.children.some((child) => child.contains(candidate)); + } + + querySelector(selector: string): FakeElement | null { + if (!selector.startsWith(".")) { + return null; + } + const className = selector.slice(1); + for (const child of this.children) { + if (child.className.split(/\s+/).includes(className)) { + return child; + } + const match = child.querySelector(selector); + if (match) { + return match; + } + } + return null; + } + + getBoundingClientRect(): { left: number; top: number; bottom: number; width: number; height: number } { + return { left: 20, top: 80, bottom: 100, width: 160, height: 40 }; + } +} + +class FakeDocument { + readonly body = new FakeElement("body"); + + createElement(tagName: string): FakeElement { + return new FakeElement(tagName); + } +} + +class FakeFileReader { + result: string | null = null; + onload: (() => void) | null = null; + onerror: (() => void) | null = null; + error: Error | null = null; + + readAsDataURL(file: { dataUrl?: string }): void { + this.result = file.dataUrl ?? ""; + this.onload?.(); + } +} + +function loadAttachmentManager(): { + manager: { clear: () => void; hasAttachments: () => boolean; getImageUrls: () => string[] }; + promptInput: FakeElement; + toolsLine: FakeElement; +} { + const __dirname = path.dirname(fileURLToPath(import.meta.url)); + const scriptPath = path.resolve(__dirname, "../../resources/prompt-attachments.js"); + const script = fs.readFileSync(scriptPath, "utf8"); + + const document = new FakeDocument(); + const window = { + innerWidth: 1024, + innerHeight: 768, + addEventListener: () => {}, + createPromptAttachmentManager: undefined as + | undefined + | ((options: Record) => { + clear: () => void; + hasAttachments: () => boolean; + getImageUrls: () => string[]; + }), + }; + + vm.runInNewContext(script, { console, document, window, FileReader: FakeFileReader }); + + const createPromptAttachmentManager = window.createPromptAttachmentManager; + if (typeof createPromptAttachmentManager !== "function") { + throw new Error("Prompt attachment manager was not registered."); + } + const promptInput = new FakeElement("textarea"); + const inputWrap = new FakeElement("div"); + const toolsLine = new FakeElement("div"); + const manager = createPromptAttachmentManager({ promptInput, inputWrap, toolsLine }); + + return { manager, promptInput, toolsLine }; +} + +async function pasteImage(promptInput: FakeElement, dataUrl: string): Promise { + let defaultPrevented = false; + await promptInput.dispatchEvent({ + type: "paste", + clipboardData: { + items: [ + { + kind: "file", + getAsFile: () => ({ type: "image/png", name: "image.png", dataUrl }), + }, + ], + }, + preventDefault: () => { + defaultPrevented = true; + }, + }); + assert.equal(defaultPrevented, true); +} + +test("prompt attachment manager appends pasted images instead of replacing the previous image", async () => { + const { manager, promptInput, toolsLine } = loadAttachmentManager(); + + await pasteImage(promptInput, "data:image/png;base64,first"); + await pasteImage(promptInput, "data:image/png;base64,second"); + + assert.equal(manager.hasAttachments(), true); + assert.deepEqual(Array.from(manager.getImageUrls()), ["data:image/png;base64,first", "data:image/png;base64,second"]); + assert.equal(toolsLine.children.length, 2); + assert.equal(toolsLine.classList.contains("has-attachment"), true); +}); + +test("prompt attachment manager removes one pasted image without clearing the rest", async () => { + const { manager, promptInput, toolsLine } = loadAttachmentManager(); + + await pasteImage(promptInput, "data:image/png;base64,first"); + await pasteImage(promptInput, "data:image/png;base64,second"); + + const firstAttachment = toolsLine.children[0]; + const removeButton = firstAttachment.children[0]; + await removeButton.dispatchEvent({ + type: "click", + preventDefault: () => {}, + stopPropagation: () => {}, + }); + + assert.deepEqual(Array.from(manager.getImageUrls()), ["data:image/png;base64,second"]); + assert.equal(toolsLine.children.length, 1); + + manager.clear(); + assert.equal(manager.hasAttachments(), false); + assert.deepEqual(Array.from(manager.getImageUrls()), []); + assert.equal(toolsLine.children.length, 0); +}); From 888a20ac01116ccf32f76bee4782bac916cc0dd3 Mon Sep 17 00:00:00 2001 From: Ji Zhang Date: Mon, 29 Jun 2026 11:48:22 +0800 Subject: [PATCH 71/72] feat: added writeStdout() for exact stdout writes with no trailing newline. --- packages/cli/src/ui/views/App.tsx | 10 +++++----- packages/cli/src/utils/stdio-helpers.ts | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/ui/views/App.tsx b/packages/cli/src/ui/views/App.tsx index 24788502..3b2886cd 100644 --- a/packages/cli/src/ui/views/App.tsx +++ b/packages/cli/src/ui/views/App.tsx @@ -48,7 +48,7 @@ import type { } from "@vegamo/deepcode-core"; import { SessionManager } from "@vegamo/deepcode-core"; import { getCompactPromptTokenThreshold } from "@vegamo/deepcode-core"; -import { writeStdoutLine } from "../../utils/stdio-helpers"; +import { writeStdout, writeStdoutLine } from "../../utils/stdio-helpers"; type View = "chat" | "session-list" | "undo" | "mcp-status"; @@ -197,7 +197,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp const resetStaticView = useCallback( (loadedMessages: SessionMessage[], options?: { clearScreen?: boolean }): Promise => { if (options?.clearScreen) { - writeStdoutLine(ANSI_CLEAR_SCREEN); + writeStdout(ANSI_CLEAR_SCREEN); } setMessages([]); setWelcomeNonce((n) => n + 1); @@ -629,7 +629,7 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp setShowWelcome(false); setMessages([]); // Clear screen to remove stale formatted text. - writeStdoutLine(ANSI_CLEAR_SCREEN); + writeStdout(ANSI_CLEAR_SCREEN); setTimeout(() => { if (nextMode === RawMode.Raw) { @@ -667,8 +667,8 @@ function App({ projectRoot, initialPrompt, resumeSessionId, onRestart }: AppProp if (mode === RawMode.Raw) { // In raw mode, re-render all messages directly to stdout at the new width. - // Use process.stdout.write instead of writeRef to avoid Ink interference. - writeStdoutLine(ANSI_CLEAR_SCREEN); + // Use direct stdout instead of writeRef to avoid Ink interference. + writeStdout(ANSI_CLEAR_SCREEN); const activeSessionId = sessionManager.getActiveSessionId(); const allMessages = activeSessionId ? loadVisibleMessages(sessionManager, activeSessionId) : []; renderRawModeMessages(allMessages, mode); diff --git a/packages/cli/src/utils/stdio-helpers.ts b/packages/cli/src/utils/stdio-helpers.ts index f0202e99..3f117267 100644 --- a/packages/cli/src/utils/stdio-helpers.ts +++ b/packages/cli/src/utils/stdio-helpers.ts @@ -1,3 +1,11 @@ +/** + * Writes a message to stdout exactly as provided. + * Use for terminal control sequences or output that manages its own spacing. + */ +export const writeStdout = (message: string): void => { + process.stdout.write(message); +}; + /** * Writes a message to stdout with a trailing newline. * Use for normal command output that the user expects to see. From 8625cb3a055129f338d32f740c1ab1afc7ebeeea Mon Sep 17 00:00:00 2001 From: hcyang Date: Mon, 29 Jun 2026 14:03:15 +0800 Subject: [PATCH 72/72] =?UTF-8?q?style(cli):=20=E4=BC=98=E5=8C=96=E9=80=89?= =?UTF-8?q?=E9=A1=B9=E6=8F=8F=E8=BF=B0=E7=9A=84=E5=B8=83=E5=B1=80=E9=97=B4?= =?UTF-8?q?=E8=B7=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在选项描述外围添加了左侧外边距的容器Box - 改进了文本显示的缩进和视觉层次感 - 保持了原有的文本颜色和显示逻辑不变 - 提升了用户界面的一致性和可读性 --- packages/cli/src/ui/views/AskUserQuestionPrompt.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/ui/views/AskUserQuestionPrompt.tsx b/packages/cli/src/ui/views/AskUserQuestionPrompt.tsx index a2f91adb..ccce5f7e 100644 --- a/packages/cli/src/ui/views/AskUserQuestionPrompt.tsx +++ b/packages/cli/src/ui/views/AskUserQuestionPrompt.tsx @@ -206,7 +206,11 @@ export function AskUserQuestionPrompt({ questions, onSubmit, onCancel }: Props): )} ) : null} - {option.description ? {option.description} : null} + {option.description ? ( + + {option.description} + + ) : null} ); })}