mirror of
https://github.com/Egonex-AI/Understand-Anything.git
synced 2026-06-22 10:58:03 +08:00
feat(skill): scaffold skill package with /understand-chat command
Add the @understand-anything/skill package with context-builder (search + 1-hop expansion + layer resolution), chat prompt builder, skill definition for Claude Code, and 14 passing tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: understand-chat
|
||||
description: Ask questions about the current codebase using the knowledge graph
|
||||
arguments: query
|
||||
---
|
||||
|
||||
# /understand-chat
|
||||
|
||||
Answer questions about this codebase using the knowledge graph at `.understand-anything/knowledge-graph.json`.
|
||||
|
||||
## Instructions
|
||||
|
||||
1. Read the knowledge graph file at `.understand-anything/knowledge-graph.json` in the current project root
|
||||
2. If the file doesn't exist, tell the user to run `/understand` first to analyze the project
|
||||
3. Use the knowledge graph context to answer the user's query: "${ARGUMENTS}"
|
||||
4. Reference specific files, functions, and relationships from the graph
|
||||
5. If the project has layers defined, explain which layer(s) are relevant
|
||||
6. Be concise but thorough -- link concepts to actual code locations
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "@understand-anything/skill",
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@understand-anything/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.0.0",
|
||||
"typescript": "^5.7.0",
|
||||
"vitest": "^3.1.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { buildChatContext, formatContextForPrompt } from "../context-builder.js";
|
||||
import type { KnowledgeGraph, GraphNode, GraphEdge, Layer } from "@understand-anything/core";
|
||||
|
||||
const makeNode = (
|
||||
overrides: Partial<GraphNode> & { id: string; name: string },
|
||||
): GraphNode => ({
|
||||
type: "file",
|
||||
summary: "",
|
||||
tags: [],
|
||||
complexity: "simple",
|
||||
...overrides,
|
||||
});
|
||||
|
||||
const sampleNodes: GraphNode[] = [
|
||||
makeNode({
|
||||
id: "auth-ctrl",
|
||||
name: "AuthenticationController",
|
||||
type: "class",
|
||||
filePath: "src/controllers/auth.ts",
|
||||
summary: "Handles user login, logout, and session management",
|
||||
tags: ["auth", "controller", "security"],
|
||||
complexity: "complex",
|
||||
languageNotes: "Uses Express middleware pattern",
|
||||
}),
|
||||
makeNode({
|
||||
id: "db-pool",
|
||||
name: "DatabasePool",
|
||||
type: "class",
|
||||
filePath: "src/db/pool.ts",
|
||||
summary: "Manages PostgreSQL connection pooling",
|
||||
tags: ["database", "connection"],
|
||||
complexity: "moderate",
|
||||
}),
|
||||
makeNode({
|
||||
id: "user-model",
|
||||
name: "UserModel",
|
||||
type: "class",
|
||||
filePath: "src/models/user.ts",
|
||||
summary: "ORM model for the users table",
|
||||
tags: ["model", "database", "user"],
|
||||
complexity: "moderate",
|
||||
}),
|
||||
makeNode({
|
||||
id: "auth-middleware",
|
||||
name: "authMiddleware",
|
||||
type: "function",
|
||||
filePath: "src/middleware/auth.ts",
|
||||
summary: "Express middleware that validates JWT tokens for authentication",
|
||||
tags: ["auth", "middleware", "security"],
|
||||
complexity: "simple",
|
||||
}),
|
||||
makeNode({
|
||||
id: "config",
|
||||
name: "config.ts",
|
||||
type: "file",
|
||||
filePath: "src/config.ts",
|
||||
summary: "Application configuration and environment variables",
|
||||
tags: ["config", "env"],
|
||||
complexity: "simple",
|
||||
}),
|
||||
];
|
||||
|
||||
const sampleEdges: GraphEdge[] = [
|
||||
{
|
||||
source: "auth-ctrl",
|
||||
target: "user-model",
|
||||
type: "depends_on",
|
||||
direction: "forward",
|
||||
description: "AuthenticationController uses UserModel for user lookup",
|
||||
weight: 0.9,
|
||||
},
|
||||
{
|
||||
source: "auth-ctrl",
|
||||
target: "auth-middleware",
|
||||
type: "calls",
|
||||
direction: "forward",
|
||||
description: "Controller registers auth middleware",
|
||||
weight: 0.7,
|
||||
},
|
||||
{
|
||||
source: "user-model",
|
||||
target: "db-pool",
|
||||
type: "depends_on",
|
||||
direction: "forward",
|
||||
description: "UserModel uses DatabasePool for queries",
|
||||
weight: 0.8,
|
||||
},
|
||||
];
|
||||
|
||||
const sampleLayers: Layer[] = [
|
||||
{
|
||||
id: "layer-api",
|
||||
name: "API Layer",
|
||||
description: "HTTP controllers and middleware",
|
||||
nodeIds: ["auth-ctrl", "auth-middleware"],
|
||||
},
|
||||
{
|
||||
id: "layer-data",
|
||||
name: "Data Layer",
|
||||
description: "Database models and connections",
|
||||
nodeIds: ["user-model", "db-pool"],
|
||||
},
|
||||
];
|
||||
|
||||
const sampleGraph: KnowledgeGraph = {
|
||||
version: "1.0.0",
|
||||
project: {
|
||||
name: "test-project",
|
||||
languages: ["TypeScript"],
|
||||
frameworks: ["Express"],
|
||||
description: "A test project for unit tests",
|
||||
analyzedAt: "2026-03-14T00:00:00Z",
|
||||
gitCommitHash: "abc123",
|
||||
},
|
||||
nodes: sampleNodes,
|
||||
edges: sampleEdges,
|
||||
layers: sampleLayers,
|
||||
tour: [],
|
||||
};
|
||||
|
||||
describe("buildChatContext", () => {
|
||||
it("finds relevant nodes for a query", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "authentication");
|
||||
expect(ctx.relevantNodes.length).toBeGreaterThan(0);
|
||||
const nodeNames = ctx.relevantNodes.map((n) => n.name);
|
||||
expect(nodeNames).toContain("AuthenticationController");
|
||||
});
|
||||
|
||||
it("includes connected nodes via 1-hop expansion", () => {
|
||||
// Searching for "authentication" should find auth-ctrl directly.
|
||||
// auth-ctrl connects to user-model and auth-middleware via edges,
|
||||
// so those should also appear in relevantNodes.
|
||||
const ctx = buildChatContext(sampleGraph, "authentication");
|
||||
const nodeIds = ctx.relevantNodes.map((n) => n.id);
|
||||
// auth-ctrl is a direct match
|
||||
expect(nodeIds).toContain("auth-ctrl");
|
||||
// user-model and auth-middleware are 1-hop connected
|
||||
expect(nodeIds).toContain("user-model");
|
||||
expect(nodeIds).toContain("auth-middleware");
|
||||
});
|
||||
|
||||
it("includes project metadata", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "database");
|
||||
expect(ctx.projectName).toBe("test-project");
|
||||
expect(ctx.projectDescription).toBe("A test project for unit tests");
|
||||
expect(ctx.languages).toEqual(["TypeScript"]);
|
||||
expect(ctx.frameworks).toEqual(["Express"]);
|
||||
});
|
||||
|
||||
it("includes relevant layers containing matched nodes", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "authentication");
|
||||
const layerNames = ctx.relevantLayers.map((l) => l.name);
|
||||
// auth-ctrl is in API Layer
|
||||
expect(layerNames).toContain("API Layer");
|
||||
});
|
||||
|
||||
it("includes relevant edges between relevant nodes", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "authentication");
|
||||
expect(ctx.relevantEdges.length).toBeGreaterThan(0);
|
||||
// Should include the edge from auth-ctrl to user-model
|
||||
const hasAuthToUser = ctx.relevantEdges.some(
|
||||
(e) => e.source === "auth-ctrl" && e.target === "user-model",
|
||||
);
|
||||
expect(hasAuthToUser).toBe(true);
|
||||
});
|
||||
|
||||
it("stores the original query", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "database pool");
|
||||
expect(ctx.query).toBe("database pool");
|
||||
});
|
||||
|
||||
it("respects maxNodes parameter", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "auth", 1);
|
||||
// With maxNodes=1, only 1 search result (before expansion)
|
||||
// Expansion may add connected nodes, but initial search is limited
|
||||
expect(ctx.relevantNodes.length).toBeGreaterThanOrEqual(1);
|
||||
// Should still be bounded reasonably
|
||||
expect(ctx.relevantNodes.length).toBeLessThanOrEqual(sampleNodes.length);
|
||||
});
|
||||
|
||||
it("returns empty relevantNodes for a query with no matches", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "xyznonexistent");
|
||||
expect(ctx.relevantNodes.length).toBe(0);
|
||||
expect(ctx.relevantEdges.length).toBe(0);
|
||||
expect(ctx.relevantLayers.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatContextForPrompt", () => {
|
||||
it("produces a string containing node names and summaries", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "authentication");
|
||||
const formatted = formatContextForPrompt(ctx);
|
||||
expect(formatted).toContain("AuthenticationController");
|
||||
expect(formatted).toContain("Handles user login, logout, and session management");
|
||||
});
|
||||
|
||||
it("includes project header information", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "authentication");
|
||||
const formatted = formatContextForPrompt(ctx);
|
||||
expect(formatted).toContain("test-project");
|
||||
expect(formatted).toContain("TypeScript");
|
||||
expect(formatted).toContain("Express");
|
||||
});
|
||||
|
||||
it("includes edge/relationship descriptions", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "authentication");
|
||||
const formatted = formatContextForPrompt(ctx);
|
||||
// Should reference the relationship between auth-ctrl and user-model
|
||||
expect(formatted).toContain("AuthenticationController");
|
||||
expect(formatted).toContain("UserModel");
|
||||
// Edge type or description should appear
|
||||
expect(formatted).toContain("depends_on");
|
||||
});
|
||||
|
||||
it("includes layer information when layers are present", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "authentication");
|
||||
const formatted = formatContextForPrompt(ctx);
|
||||
expect(formatted).toContain("API Layer");
|
||||
});
|
||||
|
||||
it("includes file paths for nodes that have them", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "authentication");
|
||||
const formatted = formatContextForPrompt(ctx);
|
||||
expect(formatted).toContain("src/controllers/auth.ts");
|
||||
});
|
||||
|
||||
it("includes complexity and type information", () => {
|
||||
const ctx = buildChatContext(sampleGraph, "authentication");
|
||||
const formatted = formatContextForPrompt(ctx);
|
||||
expect(formatted).toContain("complex");
|
||||
expect(formatted).toContain("class");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,147 @@
|
||||
import { SearchEngine } from "@understand-anything/core";
|
||||
import type {
|
||||
KnowledgeGraph,
|
||||
GraphNode,
|
||||
GraphEdge,
|
||||
Layer,
|
||||
} from "@understand-anything/core";
|
||||
|
||||
export interface ChatContext {
|
||||
projectName: string;
|
||||
projectDescription: string;
|
||||
languages: string[];
|
||||
frameworks: string[];
|
||||
relevantNodes: GraphNode[];
|
||||
relevantEdges: GraphEdge[];
|
||||
relevantLayers: Layer[];
|
||||
query: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a ChatContext by searching the knowledge graph for nodes relevant
|
||||
* to the user's query, expanding 1 hop via edges, and collecting the
|
||||
* associated layers.
|
||||
*/
|
||||
export function buildChatContext(
|
||||
graph: KnowledgeGraph,
|
||||
query: string,
|
||||
maxNodes?: number,
|
||||
): ChatContext {
|
||||
const limit = maxNodes ?? 15;
|
||||
|
||||
// 1. Use SearchEngine to find relevant nodes
|
||||
const engine = new SearchEngine(graph.nodes);
|
||||
const searchResults = engine.search(query, { limit });
|
||||
|
||||
// Build a set of matched node IDs
|
||||
const matchedIds = new Set(searchResults.map((r) => r.nodeId));
|
||||
|
||||
// 2. Expand to connected nodes (1 hop via edges)
|
||||
const expandedIds = new Set(matchedIds);
|
||||
for (const edge of graph.edges) {
|
||||
if (matchedIds.has(edge.source)) {
|
||||
expandedIds.add(edge.target);
|
||||
}
|
||||
if (matchedIds.has(edge.target)) {
|
||||
expandedIds.add(edge.source);
|
||||
}
|
||||
}
|
||||
|
||||
// Collect the actual node objects
|
||||
const nodeMap = new Map(graph.nodes.map((n) => [n.id, n]));
|
||||
const relevantNodes: GraphNode[] = [];
|
||||
for (const id of expandedIds) {
|
||||
const node = nodeMap.get(id);
|
||||
if (node) {
|
||||
relevantNodes.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Collect edges where both endpoints are in the relevant set
|
||||
const relevantEdges = graph.edges.filter(
|
||||
(e) => expandedIds.has(e.source) && expandedIds.has(e.target),
|
||||
);
|
||||
|
||||
// 4. Find layers containing any relevant node
|
||||
const relevantLayers = graph.layers.filter((layer) =>
|
||||
layer.nodeIds.some((id) => expandedIds.has(id)),
|
||||
);
|
||||
|
||||
return {
|
||||
projectName: graph.project.name,
|
||||
projectDescription: graph.project.description,
|
||||
languages: graph.project.languages,
|
||||
frameworks: graph.project.frameworks,
|
||||
relevantNodes,
|
||||
relevantEdges,
|
||||
relevantLayers,
|
||||
query,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the ChatContext as a readable markdown string for LLM consumption.
|
||||
*/
|
||||
export function formatContextForPrompt(context: ChatContext): string {
|
||||
const lines: string[] = [];
|
||||
|
||||
// Project header
|
||||
lines.push(`# Project: ${context.projectName}`);
|
||||
lines.push("");
|
||||
lines.push(context.projectDescription);
|
||||
lines.push("");
|
||||
lines.push(`**Languages:** ${context.languages.join(", ")}`);
|
||||
lines.push(`**Frameworks:** ${context.frameworks.join(", ")}`);
|
||||
lines.push("");
|
||||
|
||||
// Layers section
|
||||
if (context.relevantLayers.length > 0) {
|
||||
lines.push("## Relevant Layers");
|
||||
lines.push("");
|
||||
for (const layer of context.relevantLayers) {
|
||||
lines.push(`### ${layer.name}`);
|
||||
lines.push(layer.description);
|
||||
lines.push("");
|
||||
}
|
||||
}
|
||||
|
||||
// Nodes section
|
||||
if (context.relevantNodes.length > 0) {
|
||||
lines.push("## Code Components");
|
||||
lines.push("");
|
||||
for (const node of context.relevantNodes) {
|
||||
lines.push(`### ${node.name} (${node.type})`);
|
||||
if (node.filePath) {
|
||||
lines.push(`- **File:** ${node.filePath}`);
|
||||
}
|
||||
lines.push(`- **Complexity:** ${node.complexity}`);
|
||||
lines.push(`- **Summary:** ${node.summary}`);
|
||||
if (node.tags.length > 0) {
|
||||
lines.push(`- **Tags:** ${node.tags.join(", ")}`);
|
||||
}
|
||||
if (node.languageNotes) {
|
||||
lines.push(`- **Language Notes:** ${node.languageNotes}`);
|
||||
}
|
||||
lines.push("");
|
||||
}
|
||||
}
|
||||
|
||||
// Edges/relationships section
|
||||
if (context.relevantEdges.length > 0) {
|
||||
const nodeMap = new Map(context.relevantNodes.map((n) => [n.id, n]));
|
||||
lines.push("## Relationships");
|
||||
lines.push("");
|
||||
for (const edge of context.relevantEdges) {
|
||||
const sourceName = nodeMap.get(edge.source)?.name ?? edge.source;
|
||||
const targetName = nodeMap.get(edge.target)?.name ?? edge.target;
|
||||
let line = `- ${sourceName} --[${edge.type}]--> ${targetName}`;
|
||||
if (edge.description) {
|
||||
line += `: ${edge.description}`;
|
||||
}
|
||||
lines.push(line);
|
||||
}
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
return lines.join("\n");
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export {
|
||||
buildChatContext,
|
||||
formatContextForPrompt,
|
||||
type ChatContext,
|
||||
} from "./context-builder.js";
|
||||
export { buildChatPrompt } from "./understand-chat.js";
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { KnowledgeGraph } from "@understand-anything/core";
|
||||
import { buildChatContext, formatContextForPrompt } from "./context-builder.js";
|
||||
|
||||
/**
|
||||
* Build a complete chat prompt by combining knowledge graph context
|
||||
* with a system instruction for answering codebase questions.
|
||||
*/
|
||||
export function buildChatPrompt(
|
||||
graph: KnowledgeGraph,
|
||||
query: string,
|
||||
): string {
|
||||
const context = buildChatContext(graph, query);
|
||||
const formattedContext = formatContextForPrompt(context);
|
||||
|
||||
return [
|
||||
"You are a knowledgeable assistant that answers questions about a software codebase.",
|
||||
"Use the following knowledge graph context to inform your answer.",
|
||||
"Reference specific files, functions, classes, and relationships from the graph.",
|
||||
"If layers are present, explain which architectural layer(s) are relevant.",
|
||||
"Be concise but thorough — link concepts to actual code locations.",
|
||||
"",
|
||||
"---",
|
||||
"",
|
||||
formattedContext,
|
||||
"---",
|
||||
"",
|
||||
`**User question:** ${query}`,
|
||||
].join("\n");
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
Generated
+126
@@ -89,6 +89,22 @@ importers:
|
||||
specifier: ^6.0.0
|
||||
version: 6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1)
|
||||
|
||||
packages/skill:
|
||||
dependencies:
|
||||
'@understand-anything/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^22.0.0
|
||||
version: 22.19.15
|
||||
typescript:
|
||||
specifier: ^5.7.0
|
||||
version: 5.9.3
|
||||
vitest:
|
||||
specifier: ^3.1.0
|
||||
version: 3.2.4(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)
|
||||
|
||||
packages:
|
||||
|
||||
'@babel/code-frame@7.29.0':
|
||||
@@ -775,6 +791,9 @@ packages:
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
|
||||
'@types/node@22.19.15':
|
||||
resolution: {integrity: sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==}
|
||||
|
||||
'@types/node@25.5.0':
|
||||
resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==}
|
||||
|
||||
@@ -1231,6 +1250,9 @@ packages:
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
undici-types@6.21.0:
|
||||
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
||||
|
||||
undici-types@7.18.2:
|
||||
resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
|
||||
|
||||
@@ -1907,6 +1929,10 @@ snapshots:
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
'@types/node@22.19.15':
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
||||
'@types/node@25.5.0':
|
||||
dependencies:
|
||||
undici-types: 7.18.2
|
||||
@@ -1942,6 +1968,14 @@ snapshots:
|
||||
chai: 5.3.3
|
||||
tinyrainbow: 2.0.0
|
||||
|
||||
'@vitest/mocker@3.2.4(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1))':
|
||||
dependencies:
|
||||
'@vitest/spy': 3.2.4
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
vite: 7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)
|
||||
|
||||
'@vitest/mocker@3.2.4(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1))':
|
||||
dependencies:
|
||||
'@vitest/spy': 3.2.4
|
||||
@@ -2362,6 +2396,8 @@ snapshots:
|
||||
|
||||
typescript@5.9.3: {}
|
||||
|
||||
undici-types@6.21.0: {}
|
||||
|
||||
undici-types@7.18.2: {}
|
||||
|
||||
update-browserslist-db@1.2.3(browserslist@4.28.1):
|
||||
@@ -2374,6 +2410,27 @@ snapshots:
|
||||
dependencies:
|
||||
react: 19.2.4
|
||||
|
||||
vite-node@3.2.4(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.3
|
||||
es-module-lexer: 1.7.0
|
||||
pathe: 2.0.3
|
||||
vite: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vite-node@3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
@@ -2395,6 +2452,20 @@ snapshots:
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vite@6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1):
|
||||
dependencies:
|
||||
esbuild: 0.25.12
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
picomatch: 4.0.3
|
||||
postcss: 8.5.8
|
||||
rollup: 4.59.0
|
||||
tinyglobby: 0.2.15
|
||||
optionalDependencies:
|
||||
'@types/node': 22.19.15
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.6.1
|
||||
lightningcss: 1.31.1
|
||||
|
||||
vite@6.4.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1):
|
||||
dependencies:
|
||||
esbuild: 0.25.12
|
||||
@@ -2409,6 +2480,20 @@ snapshots:
|
||||
jiti: 2.6.1
|
||||
lightningcss: 1.31.1
|
||||
|
||||
vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1):
|
||||
dependencies:
|
||||
esbuild: 0.27.4
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
picomatch: 4.0.3
|
||||
postcss: 8.5.8
|
||||
rollup: 4.59.0
|
||||
tinyglobby: 0.2.15
|
||||
optionalDependencies:
|
||||
'@types/node': 22.19.15
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.6.1
|
||||
lightningcss: 1.31.1
|
||||
|
||||
vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1):
|
||||
dependencies:
|
||||
esbuild: 0.27.4
|
||||
@@ -2423,6 +2508,47 @@ snapshots:
|
||||
jiti: 2.6.1
|
||||
lightningcss: 1.31.1
|
||||
|
||||
vitest@3.2.4(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1):
|
||||
dependencies:
|
||||
'@types/chai': 5.2.3
|
||||
'@vitest/expect': 3.2.4
|
||||
'@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1))
|
||||
'@vitest/pretty-format': 3.2.4
|
||||
'@vitest/runner': 3.2.4
|
||||
'@vitest/snapshot': 3.2.4
|
||||
'@vitest/spy': 3.2.4
|
||||
'@vitest/utils': 3.2.4
|
||||
chai: 5.3.3
|
||||
debug: 4.4.3
|
||||
expect-type: 1.3.0
|
||||
magic-string: 0.30.21
|
||||
pathe: 2.0.3
|
||||
picomatch: 4.0.3
|
||||
std-env: 3.10.0
|
||||
tinybench: 2.9.0
|
||||
tinyexec: 0.3.2
|
||||
tinyglobby: 0.2.15
|
||||
tinypool: 1.1.1
|
||||
tinyrainbow: 2.0.0
|
||||
vite: 7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)
|
||||
vite-node: 3.2.4(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/node': 22.19.15
|
||||
transitivePeerDependencies:
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- msw
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vitest@3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.31.1):
|
||||
dependencies:
|
||||
'@types/chai': 5.2.3
|
||||
|
||||
Reference in New Issue
Block a user