From d2be401053e8522ede0254fc9b4ad8277889874f Mon Sep 17 00:00:00 2001 From: yashwanth-kumar-26 Date: Wed, 8 Apr 2026 23:06:07 +0530 Subject: [PATCH 1/4] add support for Cline CLI and Kilo Code CLI, update README and CONTRIBUTING documentation --- CONTRIBUTING.md | 16 ++++ README.md | 4 +- editors/cline-cli.js | 126 ++++++++++++++++++++++++++++ editors/index.js | 4 +- editors/kilocode-cli.js | 178 ++++++++++++++++++++++++++++++++++++++++ package-lock.json | 8 +- package.json | 2 +- ui/src/lib/constants.js | 4 + 8 files changed, 335 insertions(+), 7 deletions(-) create mode 100644 editors/cline-cli.js create mode 100644 editors/kilocode-cli.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed041d4..2d83f5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -165,6 +165,22 @@ Reads from `~/.local/share/opencode/opencode.db`: - SQLite database with `session`, `message`, and `project` tables - Messages queried directly via SQL with full content, model, and token data +### Kiro CLI + +Reads from `~/.kiro/sessions.db`: +- SQLite database with `sessions` and `messages` tables +- Sessions keyed by directory path with UUID identifiers +- Messages contain role, content, model, and timestamps + +### Cline CLI + +Reads from `~/.cline/data/tasks//`: +- `task_metadata.json` — task metadata including working directory +- `api_conversation_history.json` — full conversation in OpenAI format +- `ui_messages.json` — UI messages (optional) +- Supports token extraction from `usage` field +- Tool calls extracted from `tool_calls` array + --- ## Database Schema diff --git a/README.md b/README.md index 35530a2..2b6aa1c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@

npm - editors + editors license node deno @@ -154,6 +154,8 @@ npx agentlytics --collect | **Command Code** | ✅ | ✅ | ❌ | ❌ | | **Goose** | ✅ | ✅ | ✅ | ❌ | | **Kiro** | ✅ | ✅ | ✅ | ❌ | +| **Kilo Code CLI** | ✅ | ✅ | ✅ | ✅ | +| **Cline CLI** | ✅ | ✅ | ✅ | ✅ | > Windsurf, Windsurf Next, and Antigravity must be running during scan. diff --git a/editors/cline-cli.js b/editors/cline-cli.js new file mode 100644 index 0000000..33b1e89 --- /dev/null +++ b/editors/cline-cli.js @@ -0,0 +1,126 @@ +const path = require('path'); +const fs = require('fs'); +const os = require('os'); + +const name = 'cline-cli'; +const sources = ['cline-cli']; + +function getClineDir() { + if (process.platform === 'win32') { + return path.join(process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'), 'cline'); + } else if (process.platform === 'darwin') { + return path.join(os.homedir(), 'Library', 'Application Support', 'cline'); + } + return path.join(os.homedir(), '.cline'); +} + +const CLINE_DIR = getClineDir(); +const CLINE_DATA_DIR = path.join(CLINE_DIR, 'data'); +const SESSIONS_DIR = path.join(CLINE_DATA_DIR, 'sessions'); + +function getChats() { + const chats = []; + if (!fs.existsSync(SESSIONS_DIR)) return chats; + + try { + const sessionDirs = fs.readdirSync(SESSIONS_DIR); + for (const sessionDir of sessionDirs) { + const sessionPath = path.join(SESSIONS_DIR, sessionDir); + if (!fs.statSync(sessionPath).isDirectory()) continue; + + const sessionJsonPath = path.join(sessionPath, `${sessionDir}.json`); + let sessionData = null; + try { + sessionData = JSON.parse(fs.readFileSync(sessionJsonPath, 'utf-8')); + } catch { continue; } + + if (!sessionData) continue; + + const startedAt = sessionData.started_at ? new Date(sessionData.started_at).getTime() : null; + const endedAt = sessionData.ended_at ? new Date(sessionData.ended_at).getTime() : startedAt; + + chats.push({ + source: 'cline-cli', + composerId: sessionData.session_id || sessionDir, + name: sessionData.metadata?.title || sessionData.prompt?.substring(0, 100) || null, + createdAt: startedAt, + lastUpdatedAt: endedAt, + mode: 'cline-cli', + folder: sessionData.cwd || sessionData.workspace_root || null, + encrypted: false, + bubbleCount: 0, + _sessionId: sessionDir, + _messagesPath: sessionData.messages_path, + }); + } + } catch {} + + chats.sort((a, b) => (b.lastUpdatedAt || b.createdAt || 0) - (a.lastUpdatedAt || b.createdAt || 0)); + return chats; +} + +function getMessages(chat) { + const messages = []; + if (!chat._sessionId || !chat._messagesPath) return messages; + + if (!fs.existsSync(chat._messagesPath)) return messages; + + try { + const messagesFile = JSON.parse(fs.readFileSync(chat._messagesPath, 'utf-8')); + const messagesData = Array.isArray(messagesFile) ? messagesFile : (messagesFile.messages || []); + + for (const msg of messagesData) { + const role = msg.role === 'user' ? 'user' : msg.role === 'assistant' ? 'assistant' : msg.role === 'system' ? 'system' : null; + if (!role) continue; + + let content = ''; + if (Array.isArray(msg.content)) { + content = msg.content.map(c => { + if (typeof c === 'string') return c; + if (c.type === 'text') return c.text || ''; + if (c.type === 'tool_use') return `[tool-call: ${c.name}]`; + if (c.type === 'tool_result') return c.content || ''; + if (c.type === 'thinking') return c.thinking || ''; + return c.text || c.content || ''; + }).join(''); + } else if (typeof msg.content === 'string') { + content = msg.content; + } + + if (!content) continue; + + const message = { role, content }; + + if (msg.model) message._model = msg.model; + if (msg.usage) { + message._inputTokens = msg.usage.prompt_tokens || msg.usage.input_tokens || null; + message._outputTokens = msg.usage.completion_tokens || msg.usage.output_tokens || null; + } + + if (msg.tool_calls && msg.tool_calls.length > 0) { + message._toolCalls = msg.tool_calls.map(tc => ({ + name: tc.function?.name || tc.name || 'unknown', + args: tc.function?.arguments || tc.arguments || {}, + })); + } + + messages.push(message); + } + } catch {} + + return messages; +} + +function resetCache() {} + +function getMCPServers() { + const { parseMcpConfigFile } = require('./base'); + const configPath = path.join(CLINE_DATA_DIR, 'settings', 'cline_mcp_settings.json'); + return parseMcpConfigFile(configPath, { editor: 'cline-cli', label: 'Cline CLI', scope: 'global' }); +} + +const labels = { + 'cline-cli': 'Cline CLI', +}; + +module.exports = { name, sources, labels, getChats, getMessages, resetCache, getMCPServers }; \ No newline at end of file diff --git a/editors/index.js b/editors/index.js index 0f0c2d1..b6c85af 100644 --- a/editors/index.js +++ b/editors/index.js @@ -12,8 +12,10 @@ const cursorAgent = require('./cursor-agent'); const commandcode = require('./commandcode'); const goose = require('./goose'); const kiro = require('./kiro'); +const clineCli = require('./cline-cli'); +const kilocodeCli = require('./kilocode-cli'); -const editors = [cursor, windsurf, antigravity, claude, vscode, zed, opencode, codex, gemini, copilot, cursorAgent, commandcode, goose, kiro]; +const editors = [cursor, windsurf, antigravity, claude, vscode, zed, opencode, codex, gemini, copilot, cursorAgent, commandcode, goose, kiro, clineCli, kilocodeCli]; // Build a unified source → display-label map from all editor modules const editorLabels = {}; diff --git a/editors/kilocode-cli.js b/editors/kilocode-cli.js new file mode 100644 index 0000000..c951712 --- /dev/null +++ b/editors/kilocode-cli.js @@ -0,0 +1,178 @@ +const path = require('path'); +const fs = require('fs'); +const os = require('os'); + +const name = 'kilocode-cli'; +const sources = ['kilocode-cli']; + +function getKiloDbPath() { + if (process.platform === 'win32') { + return path.join(process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'), 'kilo', 'kilo.db'); + } else if (process.platform === 'darwin') { + return path.join(os.homedir(), 'Library', 'Application Support', 'kilo', 'kilo.db'); + } + return path.join(os.homedir(), '.local', 'share', 'kilo', 'kilo.db'); +} + +const KILO_DB_PATH = getKiloDbPath(); + +function getChats() { + const chats = []; + if (!fs.existsSync(KILO_DB_PATH)) return chats; + + let db; + try { + db = require('better-sqlite3')(KILO_DB_PATH); + } catch { return chats; } + + try { + const sessions = db.prepare(` + SELECT id, title, directory, time_created, time_updated + FROM session + ORDER BY time_updated DESC + `).all(); + + for (const session of sessions) { + chats.push({ + source: 'kilocode-cli', + composerId: session.id, + name: session.title || null, + createdAt: session.time_created || null, + lastUpdatedAt: session.time_updated || null, + mode: 'kilocode', + folder: session.directory || null, + encrypted: false, + bubbleCount: 0, + _sessionId: session.id, + }); + } + } catch {} + + try { db.close(); } catch {} + return chats; +} + +function getMessages(chat) { + const messages = []; + if (!chat._sessionId) return messages; + + if (!fs.existsSync(KILO_DB_PATH)) return messages; + + let db; + try { + db = require('better-sqlite3')(KILO_DB_PATH); + } catch { return messages; } + + try { + const messagesData = db.prepare(` + SELECT id, data, time_created + FROM message + WHERE session_id = ? + ORDER BY time_created ASC + `).all(chat._sessionId); + + const partsData = db.prepare(` + SELECT id, data, time_created + FROM part + WHERE session_id = ? + ORDER BY time_created ASC + `).all(chat._sessionId); + + let currentRole = 'user'; + let currentContent = ''; + let currentModel = null; + let currentTokens = null; + + for (const msg of messagesData) { + try { + const data = JSON.parse(msg.data); + if (data.role === 'user') { + if (currentContent || currentRole === 'assistant') { + const m = { role: currentRole, content: currentContent }; + if (currentModel) m._model = currentModel; + if (currentTokens) { + if (currentTokens.input) m._inputTokens = currentTokens.input; + if (currentTokens.output) m._outputTokens = currentTokens.output; + } + messages.push(m); + } + currentRole = 'user'; + currentContent = data.content || ''; + currentModel = data.model?.providerID && data.model?.modelID + ? `${data.model.providerID}/${data.model.modelID}` + : data.model?.modelID || null; + currentTokens = null; + } else if (data.role === 'assistant') { + if (currentRole === 'user' && currentContent) { + const m = { role: 'user', content: currentContent }; + if (currentModel) m._model = currentModel; + messages.push(m); + } + currentRole = 'assistant'; + currentContent = ''; + + if (data.model?.modelID) { + currentModel = data.model?.providerID && data.model?.modelID + ? `${data.model.providerID}/${data.model.modelID}` + : data.model.modelID; + } + if (data.tokens) currentTokens = data.tokens; + } + } catch {} + } + + for (const part of partsData) { + try { + const data = JSON.parse(part.data); + + if (data.type === 'text' && data.text) { + currentContent += (currentContent ? '\n\n' : '') + data.text; + } else if (data.type === 'tool') { + const toolName = data.tool || 'tool'; + const toolInput = data.state?.input || {}; + currentContent += (currentContent ? '\n\n' : '') + `[tool-call: ${toolName}]`; + if (toolInput.command) currentContent += ` ${toolInput.command}`; + else if (toolInput.filePath) currentContent += ` ${toolInput.filePath}`; + messages.push({ + role: 'assistant', + content: currentContent, + _toolCalls: [{ + name: toolName, + args: toolInput, + }], + }); + currentContent = ''; + + if (data.state?.output && !data.state.error) { + currentContent += `[tool-result]\n${data.state.output}`; + } + } else if (data.type === 'file') { + currentContent += (currentContent ? '\n\n' : '') + `[file: ${data.filename || data.url}]`; + } else if (data.type === 'step-finish' && data.tokens) { + currentTokens = data.tokens; + } + } catch {} + } + + if (currentContent || currentRole === 'assistant') { + const m = { role: currentRole, content: currentContent }; + if (currentModel) m._model = currentModel; + if (currentTokens) { + if (currentTokens.input) m._inputTokens = currentTokens.input; + if (currentTokens.output) m._outputTokens = currentTokens.output; + } + if (m.content || m._toolCalls) messages.push(m); + } + } catch {} + + try { db.close(); } catch {} + return messages.filter(m => m.content || m._toolCalls); +} + +function resetCache() {} + +const labels = { + 'kilocode-cli': 'Kilo Code CLI', +}; + +module.exports = { name, sources, labels, getChats, getMessages, resetCache }; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0b9f87e..3ee6a8c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@modelcontextprotocol/sdk": "^1.27.1", - "better-sqlite3": "^12.6.2", + "better-sqlite3": "^12.8.0", "chalk": "^4.1.2", "express": "^4.22.1", "log-update": "^4.0.0", @@ -496,9 +496,9 @@ "license": "MIT" }, "node_modules/better-sqlite3": { - "version": "12.6.2", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.6.2.tgz", - "integrity": "sha512-8VYKM3MjCa9WcaSAI3hzwhmyHVlH8tiGFwf0RlTsZPWJ1I5MkzjiudCo4KC4DxOaL/53A5B1sI/IbldNFDbsKA==", + "version": "12.8.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.8.0.tgz", + "integrity": "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index a352ff4..105e920 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ }, "dependencies": { "@modelcontextprotocol/sdk": "^1.27.1", - "better-sqlite3": "^12.6.2", + "better-sqlite3": "^12.8.0", "chalk": "^4.1.2", "express": "^4.22.1", "log-update": "^4.0.0", diff --git a/ui/src/lib/constants.js b/ui/src/lib/constants.js index 2e73a8b..575709a 100644 --- a/ui/src/lib/constants.js +++ b/ui/src/lib/constants.js @@ -16,6 +16,8 @@ export const EDITOR_COLORS = { 'commandcode': '#e11d48', 'goose': '#333333', 'kiro': '#ff9900', + 'cline-cli': '#00d4ff', + 'kilocode-cli': '#8b5cf6', }; export const EDITOR_LABELS = { @@ -36,6 +38,8 @@ export const EDITOR_LABELS = { 'commandcode': 'Command Code', 'goose': 'Goose', 'kiro': 'Kiro', + 'cline-cli': 'Cline CLI', + 'kilocode-cli': 'Kilo Code CLI', }; export function editorColor(src) { From 4f428b48f7a5fb5956fbc6be6a90af96fdd1e008 Mon Sep 17 00:00:00 2001 From: yashwanth-kumar-26 Date: Wed, 8 Apr 2026 23:10:28 +0530 Subject: [PATCH 2/4] update CONTRIBUTING.md with Kilo Code CLI details and Kiro CLI session paths --- CONTRIBUTING.md | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2d83f5f..26209b2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -165,21 +165,39 @@ Reads from `~/.local/share/opencode/opencode.db`: - SQLite database with `session`, `message`, and `project` tables - Messages queried directly via SQL with full content, model, and token data -### Kiro CLI +### Kiro Reads from `~/.kiro/sessions.db`: - SQLite database with `sessions` and `messages` tables - Sessions keyed by directory path with UUID identifiers - Messages contain role, content, model, and timestamps +### Kilo Code CLI + +Reads from platform-specific SQLite database: +- Linux: `~/.local/share/kilo/kilo.db` +- macOS: `~/Library/Application Support/kilo/kilo.db` +- Windows: `%APPDATA%/kilo/kilo.db` + +Database tables: +- `session` — session metadata with id, title, directory, timestamps +- `message` — messages with role, content, model, usage +- `part` — message content blocks including tool calls and tool results +- Tool calls extracted from `part` table where `type: 'tool'` +- Token usage from `part` table where `type: 'step-finish'` + ### Cline CLI -Reads from `~/.cline/data/tasks//`: -- `task_metadata.json` — task metadata including working directory -- `api_conversation_history.json` — full conversation in OpenAI format -- `ui_messages.json` — UI messages (optional) +Reads from platform-specific session directories: +- Linux: `~/.cline/data/sessions//` +- macOS: `~/Library/Application Support/cline/data/sessions//` +- Windows: `%APPDATA%/cline/data/sessions//` + +Files: +- `.json` — session metadata including cwd, model, started_at +- `.messages.json` — full conversation in OpenAI format - Supports token extraction from `usage` field -- Tool calls extracted from `tool_calls` array +- Tool calls extracted from `tool_use` content blocks --- From 219dbd8aee2aea52cb7f08d9633e29899ea3baaf Mon Sep 17 00:00:00 2001 From: yashwanth-kumar-26 Date: Wed, 8 Apr 2026 23:29:59 +0530 Subject: [PATCH 3/4] updated database access to use readonly mode for Cline-cli and Kilocode-cli --- CONTRIBUTING.md | 8 ++++---- editors/cline-cli.js | 17 ++++++++++++----- editors/kilocode-cli.js | 6 ++++-- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 26209b2..7686d23 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -167,10 +167,10 @@ Reads from `~/.local/share/opencode/opencode.db`: ### Kiro -Reads from `~/.kiro/sessions.db`: -- SQLite database with `sessions` and `messages` tables -- Sessions keyed by directory path with UUID identifiers -- Messages contain role, content, model, and timestamps +Reads from `~/Library/Application Support/Kiro/User/globalStorage/kiro.kiroagent/`: +- `workspace-sessions/` — base64-encoded workspace folder names +- Per-workspace `.chat` files with JSON session metadata and messages +- Messages stored in blob format with role, content, model, and timestamps ### Kilo Code CLI diff --git a/editors/cline-cli.js b/editors/cline-cli.js index 33b1e89..a5de1b7 100644 --- a/editors/cline-cli.js +++ b/editors/cline-cli.js @@ -55,7 +55,11 @@ function getChats() { } } catch {} - chats.sort((a, b) => (b.lastUpdatedAt || b.createdAt || 0) - (a.lastUpdatedAt || b.createdAt || 0)); + chats.sort((a, b) => { + const ta = a.lastUpdatedAt || a.createdAt || 0; + const tb = b.lastUpdatedAt || b.createdAt || 0; + return tb - ta; + }); return chats; } @@ -98,10 +102,13 @@ function getMessages(chat) { } if (msg.tool_calls && msg.tool_calls.length > 0) { - message._toolCalls = msg.tool_calls.map(tc => ({ - name: tc.function?.name || tc.name || 'unknown', - args: tc.function?.arguments || tc.arguments || {}, - })); + message._toolCalls = msg.tool_calls.map(tc => { + let args = tc.function?.arguments || tc.arguments || {}; + if (typeof args === 'string') { + try { args = JSON.parse(args); } catch { args = {}; } + } + return { name: tc.function?.name || tc.name || 'unknown', args }; + }); } messages.push(message); diff --git a/editors/kilocode-cli.js b/editors/kilocode-cli.js index c951712..448d0bc 100644 --- a/editors/kilocode-cli.js +++ b/editors/kilocode-cli.js @@ -22,7 +22,8 @@ function getChats() { let db; try { - db = require('better-sqlite3')(KILO_DB_PATH); + const Database = require('better-sqlite3'); + db = new Database(KILO_DB_PATH, { readonly: true }); } catch { return chats; } try { @@ -60,7 +61,8 @@ function getMessages(chat) { let db; try { - db = require('better-sqlite3')(KILO_DB_PATH); + const Database = require('better-sqlite3'); + db = new Database(KILO_DB_PATH, { readonly: true }); } catch { return messages; } try { From 3d21fc7a14a9acdd920e5ab4aaabdee08d24eaed Mon Sep 17 00:00:00 2001 From: yashwanth-kumar-26 Date: Thu, 30 Apr 2026 18:48:18 +0530 Subject: [PATCH 4/4] chore(package): update dependencies in package-lock.json to latest versions --- package-lock.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3ee6a8c..9c876a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,9 +24,9 @@ } }, "node_modules/@hono/node-server": { - "version": "1.19.11", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.11.tgz", - "integrity": "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==", + "version": "1.19.14", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", + "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", "license": "MIT", "engines": { "node": ">=18.14.1" @@ -1155,9 +1155,9 @@ } }, "node_modules/hono": { - "version": "4.12.7", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz", - "integrity": "sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw==", + "version": "4.12.15", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.15.tgz", + "integrity": "sha512-qM0jDhFEaCBb4TxoW7f53Qrpv9RBiayUHo0S52JudprkhvpjIrGoU1mnnr29Fvd1U335ZFPZQY1wlkqgfGXyLg==", "license": "MIT", "engines": { "node": ">=16.9.0" @@ -1563,9 +1563,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, "node_modules/pkce-challenge": { @@ -1763,9 +1763,9 @@ "license": "MIT" }, "node_modules/router/node_modules/path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", "license": "MIT", "funding": { "type": "opencollective",