@kkeve/suite 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -0
- package/dist/bin/keve.d.ts +13 -0
- package/dist/bin/keve.js +164 -0
- package/dist/commands/auth-update.d.ts +16 -0
- package/dist/commands/auth-update.js +88 -0
- package/dist/commands/clean.d.ts +10 -0
- package/dist/commands/clean.js +78 -0
- package/dist/commands/config.d.ts +17 -0
- package/dist/commands/config.js +99 -0
- package/dist/commands/init.d.ts +15 -0
- package/dist/commands/init.js +292 -0
- package/dist/commands/report.d.ts +12 -0
- package/dist/commands/report.js +159 -0
- package/dist/commands/run.d.ts +29 -0
- package/dist/commands/run.js +417 -0
- package/dist/commands/test.d.ts +12 -0
- package/dist/commands/test.js +102 -0
- package/dist/commands/vitest.d.ts +14 -0
- package/dist/commands/vitest.js +166 -0
- package/dist/config.d.ts +109 -0
- package/dist/config.js +291 -0
- package/dist/core/action-log-writer.d.ts +47 -0
- package/dist/{tools/write-file.js → core/action-log-writer.js} +42 -26
- package/dist/core/auth.d.ts +17 -0
- package/dist/core/auth.js +224 -0
- package/dist/core/cdp-resolver.d.ts +5 -0
- package/dist/core/cdp-resolver.js +93 -0
- package/dist/core/generateReport/report.d.ts +19 -0
- package/dist/core/generateReport/report.js +91 -0
- package/dist/core/generateReport/reportData.d.ts +215 -0
- package/dist/core/generateReport/reportData.js +735 -0
- package/dist/core/global-setup.d.ts +6 -0
- package/dist/core/global-setup.js +113 -0
- package/dist/core/keve-aspect.d.ts +54 -0
- package/dist/core/keve-aspect.js +52 -0
- package/dist/core/keve-decorators.d.ts +51 -0
- package/dist/core/keve-decorators.js +95 -0
- package/dist/core/keve-registry.d.ts +38 -0
- package/dist/core/keve-registry.js +25 -0
- package/dist/core/keve-report.d.ts +27 -0
- package/dist/core/keve-report.js +357 -0
- package/dist/core/keve-test.d.ts +36 -0
- package/dist/core/keve-test.js +364 -0
- package/dist/core/learned-actions.d.ts +24 -0
- package/dist/core/learned-actions.js +65 -0
- package/dist/core/pw-config.d.ts +19 -0
- package/dist/core/pw-config.js +180 -0
- package/dist/index.d.ts +8 -23
- package/dist/index.js +36 -43
- package/dist/page-agent/agent.d.ts +129 -0
- package/dist/page-agent/agent.js +585 -0
- package/dist/page-agent/hooks.d.ts +13 -0
- package/dist/page-agent/hooks.js +218 -0
- package/dist/page-agent/tools.d.ts +29 -0
- package/dist/page-agent/tools.js +297 -0
- package/doc/README.md +124 -0
- package/doc/agents/keve-dev-test-agent.md +140 -0
- package/doc/agents/keve-test-agent.md +178 -0
- package/doc/asserts//346/265/213/350/257/225/345/220/204/351/230/266/346/256/265/350/257/264/346/230/216.png +0 -0
- package/doc/keve-agent-demo.html +370 -0
- package/doc/skills/keve-bddcase-gen/SKILL.md +332 -0
- package/doc/skills/keve-bddcase-gen/references/test-case-rules.md +91 -0
- package/doc/skills/keve-bddcase-gen/references/test-cases-example.md +103 -0
- package/doc/skills/keve-component-gen/SKILL.md +255 -0
- package/doc/skills/keve-component-gen/references/component-mock-strategy.md +74 -0
- package/doc/skills/keve-component-gen/references/component-model-template.md +98 -0
- package/doc/skills/keve-component-gen/references/component-test-template.md +100 -0
- package/doc/skills/keve-component-gen/references/vue-test-utils-guide.md +91 -0
- package/doc/skills/keve-e2e-gen/SKILL.md +179 -0
- package/doc/skills/keve-e2e-gen/references/code-analysis-guide.md +208 -0
- package/doc/skills/keve-e2e-gen/references/decisions.md +36 -0
- package/doc/skills/keve-e2e-gen/references/pom-generation-guide.md +140 -0
- package/doc/skills/keve-e2e-gen/references/script-generation-guide.md +236 -0
- package/doc/skills/keve-e2e-gen/references/test-auditor-guide.md +189 -0
- package/doc/skills/keve-e2e-gen/scripts/extract-components.sh +85 -0
- package/doc/skills/keve-e2e-gen/scripts/inject-testids.sh +95 -0
- package/doc/skills/keve-static-analysis/SKILL.md +362 -0
- package/doc/skills/keve-static-analysis/references/codegraph-analysis-guide.md +108 -0
- package/doc/skills/keve-static-analysis/references/git-impact-analysis.md +81 -0
- package/doc/skills/keve-static-analysis/references/lint-fix-guide.md +69 -0
- package/doc/skills/keve-static-analysis/references/runtime-risk-patterns.md +92 -0
- package/doc/skills/keve-static-analysis/references/security-scan-guide.md +32 -0
- package/doc/skills/keve-static-analysis/references/ts-error-patterns.md +98 -0
- package/doc/skills/keve-static-analysis/references/vue-security-guide.md +72 -0
- package/doc/skills/keve-test-eval/SKILL.md +78 -0
- package/doc/skills/keve-test-eval/references/common-fix-guide.md +166 -0
- package/doc/skills/keve-test-eval/references/confidence-data-guide.md +78 -0
- package/doc/skills/keve-test-eval/references/fix-loop-guide.md +67 -0
- package/doc/skills/keve-unit-gen/SKILL.md +203 -0
- package/doc/skills/keve-unit-gen/references/boundary-conditions.md +78 -0
- package/doc/skills/keve-unit-gen/references/unit-mock-strategy.md +71 -0
- package/doc/skills/keve-unit-gen/references/unit-test-template.md +105 -0
- package/package.json +47 -25
- package/dist/agent/factory.d.ts +0 -25
- package/dist/agent/factory.js +0 -99
- package/dist/agent/index.d.ts +0 -3
- package/dist/agent/index.js +0 -7
- package/dist/agent/loader.d.ts +0 -22
- package/dist/agent/loader.js +0 -117
- package/dist/agent/types.d.ts +0 -9
- package/dist/agent/types.js +0 -2
- package/dist/agent-loop/complete-task.d.ts +0 -28
- package/dist/agent-loop/complete-task.js +0 -70
- package/dist/agent-loop/index.d.ts +0 -16
- package/dist/agent-loop/index.js +0 -26
- package/dist/agent-loop/loop.d.ts +0 -42
- package/dist/agent-loop/loop.js +0 -282
- package/dist/agent-loop/runtime.d.ts +0 -40
- package/dist/agent-loop/runtime.js +0 -163
- package/dist/agent-loop/types.d.ts +0 -161
- package/dist/agent-loop/types.js +0 -105
- package/dist/context/index.d.ts +0 -8
- package/dist/context/index.js +0 -29
- package/dist/context/tokenCalculation.d.ts +0 -55
- package/dist/context/tokenCalculation.js +0 -95
- package/dist/context/truncation.d.ts +0 -67
- package/dist/context/truncation.js +0 -142
- package/dist/context/types.d.ts +0 -7
- package/dist/context/types.js +0 -27
- package/dist/llm/OpenAIClient.d.ts +0 -31
- package/dist/llm/OpenAIClient.js +0 -455
- package/dist/llm/constants.d.ts +0 -2
- package/dist/llm/constants.js +0 -6
- package/dist/llm/errors.d.ts +0 -25
- package/dist/llm/errors.js +0 -51
- package/dist/llm/index.d.ts +0 -49
- package/dist/llm/index.js +0 -158
- package/dist/llm/types.d.ts +0 -124
- package/dist/llm/types.js +0 -2
- package/dist/llm/utils.d.ts +0 -29
- package/dist/llm/utils.js +0 -284
- package/dist/skill/frontmatter-parser.d.ts +0 -50
- package/dist/skill/frontmatter-parser.js +0 -152
- package/dist/skill/index.d.ts +0 -12
- package/dist/skill/index.js +0 -17
- package/dist/skill/loader.d.ts +0 -96
- package/dist/skill/loader.js +0 -256
- package/dist/tools/ask-user.d.ts +0 -8
- package/dist/tools/ask-user.js +0 -47
- package/dist/tools/bash.d.ts +0 -47
- package/dist/tools/bash.js +0 -213
- package/dist/tools/edit-file.d.ts +0 -9
- package/dist/tools/edit-file.js +0 -76
- package/dist/tools/glob.d.ts +0 -8
- package/dist/tools/glob.js +0 -101
- package/dist/tools/grep.d.ts +0 -10
- package/dist/tools/grep.js +0 -76
- package/dist/tools/index.d.ts +0 -24
- package/dist/tools/index.js +0 -47
- package/dist/tools/read-files.d.ts +0 -8
- package/dist/tools/read-files.js +0 -81
- package/dist/tools/write-file.d.ts +0 -8
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* SKILL.md Frontmatter Parser
|
|
4
|
-
*
|
|
5
|
-
* Reference: gemini-cli skillLoader.ts (skills/skillLoader.ts L34-110)
|
|
6
|
-
* Parses YAML frontmatter from SKILL.md files to extract name, description,
|
|
7
|
-
* and allowed-tools. Uses the 'yaml' npm package for robust YAML parsing,
|
|
8
|
-
* with a fallback simple parser for malformed YAML (e.g. descriptions with colons).
|
|
9
|
-
*/
|
|
10
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
11
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
12
|
-
};
|
|
13
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.FRONTMATTER_REGEX = void 0;
|
|
15
|
-
exports.parseSkillFrontmatter = parseSkillFrontmatter;
|
|
16
|
-
exports.parseFrontmatterYaml = parseFrontmatterYaml;
|
|
17
|
-
const yaml_1 = __importDefault(require("yaml"));
|
|
18
|
-
/**
|
|
19
|
-
* Regex for extracting frontmatter from markdown files.
|
|
20
|
-
* Matches ---\n<yaml content>\n--- at the start of the file.
|
|
21
|
-
*/
|
|
22
|
-
exports.FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n([\s\S]*))?/;
|
|
23
|
-
/**
|
|
24
|
-
* Parse frontmatter from a SKILL.md file string.
|
|
25
|
-
*
|
|
26
|
-
* Returns the name, description, allowedTools from the YAML frontmatter,
|
|
27
|
-
* and the body (content after the frontmatter).
|
|
28
|
-
*
|
|
29
|
-
* @param content The full SKILL.md file content
|
|
30
|
-
* @returns Parsed frontmatter and body, or null if no valid frontmatter found
|
|
31
|
-
*/
|
|
32
|
-
function parseSkillFrontmatter(content) {
|
|
33
|
-
const match = content.match(exports.FRONTMATTER_REGEX);
|
|
34
|
-
if (!match) {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
const frontmatter = parseFrontmatterYaml(match[1]);
|
|
38
|
-
if (!frontmatter) {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
// Sanitize name for use as a filename/directory name
|
|
42
|
-
const sanitizedName = frontmatter.name.replace(/[:\\/<>*?"|]/g, '-');
|
|
43
|
-
// Body is the content after the closing ---
|
|
44
|
-
const body = match[2]?.trim() ?? '';
|
|
45
|
-
return {
|
|
46
|
-
name: sanitizedName,
|
|
47
|
-
description: frontmatter.description,
|
|
48
|
-
allowedTools: frontmatter.allowedTools,
|
|
49
|
-
outputType: frontmatter.outputType,
|
|
50
|
-
body,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Parse YAML frontmatter content using the yaml library
|
|
55
|
-
* with a fallback to simple key-value parsing.
|
|
56
|
-
*
|
|
57
|
-
* Reference: gemini-cli skillLoader.ts parseFrontmatter (L41-61)
|
|
58
|
-
*
|
|
59
|
-
* Uses YAML.parse() (yaml v2 API) instead of the deprecated YAML.load().
|
|
60
|
-
*/
|
|
61
|
-
function parseFrontmatterYaml(yamlContent) {
|
|
62
|
-
// Try YAML parsing first (handles complex cases like multi-line descriptions, arrays)
|
|
63
|
-
try {
|
|
64
|
-
const parsed = yaml_1.default.parse(yamlContent);
|
|
65
|
-
if (parsed && typeof parsed === 'object') {
|
|
66
|
-
const record = parsed;
|
|
67
|
-
const name = typeof record.name === 'string' ? record.name : undefined;
|
|
68
|
-
const description = typeof record.description === 'string' ? record.description : undefined;
|
|
69
|
-
if (!name || !description) {
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
// Extract allowed-tools (array or string)
|
|
73
|
-
let allowedTools;
|
|
74
|
-
const allowedToolsRaw = record['allowed-tools'];
|
|
75
|
-
if (Array.isArray(allowedToolsRaw)) {
|
|
76
|
-
allowedTools = allowedToolsRaw.map(String);
|
|
77
|
-
}
|
|
78
|
-
else if (typeof allowedToolsRaw === 'string') {
|
|
79
|
-
allowedTools = allowedToolsRaw.split(/\s+/).filter(Boolean);
|
|
80
|
-
}
|
|
81
|
-
// Extract output-type (string)
|
|
82
|
-
const outputType = typeof record['output-type'] === 'string' ? record['output-type'] : undefined;
|
|
83
|
-
return { name, description, allowedTools, outputType };
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
catch (yamlError) {
|
|
87
|
-
// YAML parsing failed — fall back to simple parser
|
|
88
|
-
console.warn('[SkillLoader] YAML frontmatter parsing failed, using simple parser:', yamlError);
|
|
89
|
-
}
|
|
90
|
-
return parseSimpleFrontmatter(yamlContent);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Simple frontmatter parser that extracts name, description, and allowed-tools fields.
|
|
94
|
-
* Handles cases where values contain colons that would break YAML parsing.
|
|
95
|
-
*
|
|
96
|
-
* Reference: gemini-cli skillLoader.ts parseSimpleFrontmatter (L67-110)
|
|
97
|
-
*/
|
|
98
|
-
function parseSimpleFrontmatter(content) {
|
|
99
|
-
const lines = content.split(/\r?\n/);
|
|
100
|
-
let name;
|
|
101
|
-
let description;
|
|
102
|
-
let allowedTools;
|
|
103
|
-
let outputType;
|
|
104
|
-
for (let i = 0; i < lines.length; i++) {
|
|
105
|
-
const line = lines[i];
|
|
106
|
-
// Match "name:" at the start of the line
|
|
107
|
-
const nameMatch = line.match(/^\s*name:\s*(.*)$/);
|
|
108
|
-
if (nameMatch) {
|
|
109
|
-
name = nameMatch[1].trim();
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
// Match "description:" at the start of the line
|
|
113
|
-
const descMatch = line.match(/^\s*description:\s*(.*)$/);
|
|
114
|
-
if (descMatch) {
|
|
115
|
-
const descLines = [descMatch[1].trim()];
|
|
116
|
-
// Check for multi-line description (indented continuation lines)
|
|
117
|
-
while (i + 1 < lines.length) {
|
|
118
|
-
const nextLine = lines[i + 1];
|
|
119
|
-
// If next line is indented, it's a continuation of the description
|
|
120
|
-
if (nextLine.match(/^[ \t]+\S/)) {
|
|
121
|
-
descLines.push(nextLine.trim());
|
|
122
|
-
i++;
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
description = descLines.filter(Boolean).join(' ');
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
// Match "output-type:" at the start of the line
|
|
132
|
-
const outputMatch = line.match(/^\s*output-type:\s*(.*)$/);
|
|
133
|
-
if (outputMatch) {
|
|
134
|
-
outputType = outputMatch[1].trim();
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
// Match "allowed-tools:" at the start of the line
|
|
138
|
-
const toolsMatch = line.match(/^\s*allowed-tools:\s*(.*)$/);
|
|
139
|
-
if (toolsMatch) {
|
|
140
|
-
const toolsRaw = toolsMatch[1].trim();
|
|
141
|
-
// Simple format: space-separated list (e.g. "Bash(shell:*) Bash(git:*) ask_user_questions")
|
|
142
|
-
if (toolsRaw) {
|
|
143
|
-
allowedTools = toolsRaw.split(/\s+/).filter(Boolean);
|
|
144
|
-
}
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
if (name !== undefined && description !== undefined) {
|
|
149
|
-
return { name, description, allowedTools, outputType };
|
|
150
|
-
}
|
|
151
|
-
return null;
|
|
152
|
-
}
|
package/dist/skill/index.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skill module — SKILL.md discovery, loading, and execution
|
|
3
|
-
*
|
|
4
|
-
* Provides the SkillLoader for discovering SKILL.md files with
|
|
5
|
-
* Progressive Disclosure (frontmatter scan → full content → references),
|
|
6
|
-
* and the SkillExecutor for running skills through the AgentLoop.
|
|
7
|
-
*
|
|
8
|
-
* Reference: gemini-cli skillLoader.ts + skill-extraction-agent.ts
|
|
9
|
-
*/
|
|
10
|
-
export { SkillLoader } from './loader';
|
|
11
|
-
export type { SkillDefinition } from './loader';
|
|
12
|
-
export { parseSkillFrontmatter, FRONTMATTER_REGEX } from './frontmatter-parser';
|
package/dist/skill/index.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Skill module — SKILL.md discovery, loading, and execution
|
|
4
|
-
*
|
|
5
|
-
* Provides the SkillLoader for discovering SKILL.md files with
|
|
6
|
-
* Progressive Disclosure (frontmatter scan → full content → references),
|
|
7
|
-
* and the SkillExecutor for running skills through the AgentLoop.
|
|
8
|
-
*
|
|
9
|
-
* Reference: gemini-cli skillLoader.ts + skill-extraction-agent.ts
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.FRONTMATTER_REGEX = exports.parseSkillFrontmatter = exports.SkillLoader = void 0;
|
|
13
|
-
var loader_1 = require("./loader");
|
|
14
|
-
Object.defineProperty(exports, "SkillLoader", { enumerable: true, get: function () { return loader_1.SkillLoader; } });
|
|
15
|
-
var frontmatter_parser_1 = require("./frontmatter-parser");
|
|
16
|
-
Object.defineProperty(exports, "parseSkillFrontmatter", { enumerable: true, get: function () { return frontmatter_parser_1.parseSkillFrontmatter; } });
|
|
17
|
-
Object.defineProperty(exports, "FRONTMATTER_REGEX", { enumerable: true, get: function () { return frontmatter_parser_1.FRONTMATTER_REGEX; } });
|
package/dist/skill/loader.d.ts
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skill Loader — discovers and loads SKILL.md files
|
|
3
|
-
*
|
|
4
|
-
* Reference: gemini-cli skillLoader.ts (skills/skillLoader.ts)
|
|
5
|
-
*
|
|
6
|
-
* Progressive Disclosure three levels:
|
|
7
|
-
* 1. scanSkillDirs() → scan all SKILL.md frontmatter (name + description only)
|
|
8
|
-
* 2. loadSkillContent() → load the full SKILL.md body for a matched skill
|
|
9
|
-
* 3. loadSkillReference() → load a specific reference file from the skill's references/ dir
|
|
10
|
-
*
|
|
11
|
-
* Skill directory scan priority:
|
|
12
|
-
* - packages/agent/skills/x/SKILL.md — project built-in skills (canonical location)
|
|
13
|
-
* - Future: user-defined skill directories (from config)
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* A loaded skill definition.
|
|
17
|
-
* Reference: gemini-cli SkillDefinition (skills/skillLoader.ts L17-32)
|
|
18
|
-
*/
|
|
19
|
-
export interface SkillDefinition {
|
|
20
|
-
/** The unique name of the skill (sanitized from frontmatter). */
|
|
21
|
-
name: string;
|
|
22
|
-
/** A concise description of what the skill does. */
|
|
23
|
-
description: string;
|
|
24
|
-
/** The absolute path to the skill's SKILL.md file on disk. */
|
|
25
|
-
location: string;
|
|
26
|
-
/** The core logic/instructions of the skill (SKILL.md body). */
|
|
27
|
-
body: string;
|
|
28
|
-
/** Whether the skill is currently disabled. */
|
|
29
|
-
disabled?: boolean;
|
|
30
|
-
/** Whether the skill is a built-in skill. */
|
|
31
|
-
isBuiltin?: boolean;
|
|
32
|
-
/** Allowed tools for this skill (from frontmatter). */
|
|
33
|
-
allowedTools?: string[];
|
|
34
|
-
/** Output artifact type for Pipeline routing (e.g. 'code_knowledge', 'case_list'). */
|
|
35
|
-
outputType?: string;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Skill loader for discovering and loading SKILL.md files.
|
|
39
|
-
*
|
|
40
|
-
* Usage:
|
|
41
|
-
* ```typescript
|
|
42
|
-
* const loader = new SkillLoader(['packages/agent/demo/skills'])
|
|
43
|
-
* const skills = await loader.scanSkillDirs()
|
|
44
|
-
* // Find matching skill
|
|
45
|
-
* const matched = loader.matchSkill('test case generation', skills)
|
|
46
|
-
* // Load full content
|
|
47
|
-
* const content = await loader.loadSkillContent(matched.name)
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
export declare class SkillLoader {
|
|
51
|
-
private skillDirs;
|
|
52
|
-
private skillCache;
|
|
53
|
-
constructor(skillDirs: string[]);
|
|
54
|
-
/**
|
|
55
|
-
* Level 1: Scan skill directories and load all SKILL.md frontmatter.
|
|
56
|
-
* Returns SkillDefinition objects with name, description, location, and body.
|
|
57
|
-
*
|
|
58
|
-
* Reference: gemini-cli loadSkillsFromDir (skills/skillLoader.ts L115-159)
|
|
59
|
-
*/
|
|
60
|
-
scanSkillDirs(): Promise<SkillDefinition[]>;
|
|
61
|
-
/**
|
|
62
|
-
* Level 2: Load the full SKILL.md body content for a specific skill.
|
|
63
|
-
* If the skill was already scanned, returns the cached body.
|
|
64
|
-
* Otherwise, loads it from disk.
|
|
65
|
-
*/
|
|
66
|
-
loadSkillContent(skillName: string): Promise<string | null>;
|
|
67
|
-
/**
|
|
68
|
-
* Level 3: Load a reference file from a skill's directory.
|
|
69
|
-
* Reference files are typically in a references/ subdirectory next to SKILL.md.
|
|
70
|
-
*/
|
|
71
|
-
loadSkillReference(skillName: string, referencePath: string): Promise<string | null>;
|
|
72
|
-
/**
|
|
73
|
-
* Match a skill by query string against available skills' names and descriptions.
|
|
74
|
-
* Uses simple keyword matching — finds the skill whose name or description
|
|
75
|
-
* best matches the query.
|
|
76
|
-
*/
|
|
77
|
-
matchSkill(query: string, availableSkills: SkillDefinition[]): SkillDefinition | null;
|
|
78
|
-
/**
|
|
79
|
-
* Get a cached skill definition by name.
|
|
80
|
-
*/
|
|
81
|
-
getCachedSkill(skillName: string): SkillDefinition | undefined;
|
|
82
|
-
/**
|
|
83
|
-
* Get all cached skill definitions.
|
|
84
|
-
*/
|
|
85
|
-
getAllCachedSkills(): SkillDefinition[];
|
|
86
|
-
/**
|
|
87
|
-
* Load all skills from a directory.
|
|
88
|
-
* Reference: gemini-cli loadSkillsFromDir (skills/skillLoader.ts L115-159)
|
|
89
|
-
*/
|
|
90
|
-
private loadSkillsFromDir;
|
|
91
|
-
/**
|
|
92
|
-
* Load a single skill from a SKILL.md file.
|
|
93
|
-
* Reference: gemini-cli loadSkillFromFile (skills/skillLoader.ts L164-192)
|
|
94
|
-
*/
|
|
95
|
-
private loadSkillFromFile;
|
|
96
|
-
}
|
package/dist/skill/loader.js
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Skill Loader — discovers and loads SKILL.md files
|
|
4
|
-
*
|
|
5
|
-
* Reference: gemini-cli skillLoader.ts (skills/skillLoader.ts)
|
|
6
|
-
*
|
|
7
|
-
* Progressive Disclosure three levels:
|
|
8
|
-
* 1. scanSkillDirs() → scan all SKILL.md frontmatter (name + description only)
|
|
9
|
-
* 2. loadSkillContent() → load the full SKILL.md body for a matched skill
|
|
10
|
-
* 3. loadSkillReference() → load a specific reference file from the skill's references/ dir
|
|
11
|
-
*
|
|
12
|
-
* Skill directory scan priority:
|
|
13
|
-
* - packages/agent/skills/x/SKILL.md — project built-in skills (canonical location)
|
|
14
|
-
* - Future: user-defined skill directories (from config)
|
|
15
|
-
*/
|
|
16
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
-
if (k2 === undefined) k2 = k;
|
|
18
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
-
}
|
|
22
|
-
Object.defineProperty(o, k2, desc);
|
|
23
|
-
}) : (function(o, m, k, k2) {
|
|
24
|
-
if (k2 === undefined) k2 = k;
|
|
25
|
-
o[k2] = m[k];
|
|
26
|
-
}));
|
|
27
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
-
}) : function(o, v) {
|
|
30
|
-
o["default"] = v;
|
|
31
|
-
});
|
|
32
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
-
var ownKeys = function(o) {
|
|
34
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
-
var ar = [];
|
|
36
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
-
return ar;
|
|
38
|
-
};
|
|
39
|
-
return ownKeys(o);
|
|
40
|
-
};
|
|
41
|
-
return function (mod) {
|
|
42
|
-
if (mod && mod.__esModule) return mod;
|
|
43
|
-
var result = {};
|
|
44
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
-
__setModuleDefault(result, mod);
|
|
46
|
-
return result;
|
|
47
|
-
};
|
|
48
|
-
})();
|
|
49
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
-
exports.SkillLoader = void 0;
|
|
51
|
-
const fs = __importStar(require("node:fs/promises"));
|
|
52
|
-
const path = __importStar(require("node:path"));
|
|
53
|
-
const glob_1 = require("glob");
|
|
54
|
-
const frontmatter_parser_1 = require("./frontmatter-parser");
|
|
55
|
-
/**
|
|
56
|
-
* Skill loader for discovering and loading SKILL.md files.
|
|
57
|
-
*
|
|
58
|
-
* Usage:
|
|
59
|
-
* ```typescript
|
|
60
|
-
* const loader = new SkillLoader(['packages/agent/demo/skills'])
|
|
61
|
-
* const skills = await loader.scanSkillDirs()
|
|
62
|
-
* // Find matching skill
|
|
63
|
-
* const matched = loader.matchSkill('test case generation', skills)
|
|
64
|
-
* // Load full content
|
|
65
|
-
* const content = await loader.loadSkillContent(matched.name)
|
|
66
|
-
* ```
|
|
67
|
-
*/
|
|
68
|
-
class SkillLoader {
|
|
69
|
-
skillDirs;
|
|
70
|
-
skillCache = new Map();
|
|
71
|
-
constructor(skillDirs) {
|
|
72
|
-
this.skillDirs = skillDirs;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Level 1: Scan skill directories and load all SKILL.md frontmatter.
|
|
76
|
-
* Returns SkillDefinition objects with name, description, location, and body.
|
|
77
|
-
*
|
|
78
|
-
* Reference: gemini-cli loadSkillsFromDir (skills/skillLoader.ts L115-159)
|
|
79
|
-
*/
|
|
80
|
-
async scanSkillDirs() {
|
|
81
|
-
const discoveredSkills = [];
|
|
82
|
-
for (const dir of this.skillDirs) {
|
|
83
|
-
const skillsFromDir = await this.loadSkillsFromDir(dir);
|
|
84
|
-
for (const skill of skillsFromDir) {
|
|
85
|
-
this.skillCache.set(skill.name, skill);
|
|
86
|
-
discoveredSkills.push(skill);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return discoveredSkills;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Level 2: Load the full SKILL.md body content for a specific skill.
|
|
93
|
-
* If the skill was already scanned, returns the cached body.
|
|
94
|
-
* Otherwise, loads it from disk.
|
|
95
|
-
*/
|
|
96
|
-
async loadSkillContent(skillName) {
|
|
97
|
-
const cached = this.skillCache.get(skillName);
|
|
98
|
-
if (cached) {
|
|
99
|
-
return cached.body;
|
|
100
|
-
}
|
|
101
|
-
// Try to find and load the skill file
|
|
102
|
-
for (const dir of this.skillDirs) {
|
|
103
|
-
const absoluteSearchPath = path.resolve(dir);
|
|
104
|
-
try {
|
|
105
|
-
const pattern = ['SKILL.md', '*/SKILL.md'];
|
|
106
|
-
const skillFiles = await (0, glob_1.glob)(pattern, {
|
|
107
|
-
cwd: absoluteSearchPath,
|
|
108
|
-
absolute: true,
|
|
109
|
-
nodir: true,
|
|
110
|
-
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
111
|
-
});
|
|
112
|
-
for (const skillFile of skillFiles) {
|
|
113
|
-
const skill = await this.loadSkillFromFile(skillFile);
|
|
114
|
-
if (skill && skill.name === skillName) {
|
|
115
|
-
this.skillCache.set(skill.name, skill);
|
|
116
|
-
return skill.body;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
catch (err) {
|
|
121
|
-
console.warn(`[SkillLoader] Failed to search skill '${skillName}' in ${absoluteSearchPath}:`, err instanceof Error ? err.message : err);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Level 3: Load a reference file from a skill's directory.
|
|
128
|
-
* Reference files are typically in a references/ subdirectory next to SKILL.md.
|
|
129
|
-
*/
|
|
130
|
-
async loadSkillReference(skillName, referencePath) {
|
|
131
|
-
const cached = this.skillCache.get(skillName);
|
|
132
|
-
if (!cached) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
// The skill's location is the SKILL.md file path
|
|
136
|
-
// References are in the same directory or a references/ subdirectory
|
|
137
|
-
const skillDir = path.dirname(cached.location);
|
|
138
|
-
const refAbsolutePath = path.resolve(skillDir, referencePath);
|
|
139
|
-
try {
|
|
140
|
-
return await fs.readFile(refAbsolutePath, 'utf-8');
|
|
141
|
-
}
|
|
142
|
-
catch {
|
|
143
|
-
console.warn(`[SkillLoader] Reference file not found: ${refAbsolutePath}`);
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Match a skill by query string against available skills' names and descriptions.
|
|
149
|
-
* Uses simple keyword matching — finds the skill whose name or description
|
|
150
|
-
* best matches the query.
|
|
151
|
-
*/
|
|
152
|
-
matchSkill(query, availableSkills) {
|
|
153
|
-
if (availableSkills.length === 0) {
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
const lowerQuery = query.toLowerCase();
|
|
157
|
-
const queryWords = lowerQuery.split(/\s+/);
|
|
158
|
-
// Score each skill by how many query words appear in name/description
|
|
159
|
-
let bestMatch = null;
|
|
160
|
-
let bestScore = 0;
|
|
161
|
-
for (const skill of availableSkills) {
|
|
162
|
-
if (skill.disabled)
|
|
163
|
-
continue;
|
|
164
|
-
const searchableText = `${skill.name} ${skill.description}`.toLowerCase();
|
|
165
|
-
let score = 0;
|
|
166
|
-
for (const word of queryWords) {
|
|
167
|
-
if (searchableText.includes(word)) {
|
|
168
|
-
score++;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
// Bonus for exact name match
|
|
172
|
-
if (skill.name.toLowerCase() === lowerQuery) {
|
|
173
|
-
score += 10;
|
|
174
|
-
}
|
|
175
|
-
// Bonus for name being a substring of query
|
|
176
|
-
if (lowerQuery.includes(skill.name.toLowerCase())) {
|
|
177
|
-
score += 5;
|
|
178
|
-
}
|
|
179
|
-
if (score > bestScore) {
|
|
180
|
-
bestScore = score;
|
|
181
|
-
bestMatch = skill;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return bestMatch;
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Get a cached skill definition by name.
|
|
188
|
-
*/
|
|
189
|
-
getCachedSkill(skillName) {
|
|
190
|
-
return this.skillCache.get(skillName);
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Get all cached skill definitions.
|
|
194
|
-
*/
|
|
195
|
-
getAllCachedSkills() {
|
|
196
|
-
return Array.from(this.skillCache.values());
|
|
197
|
-
}
|
|
198
|
-
// ===== Private methods =====
|
|
199
|
-
/**
|
|
200
|
-
* Load all skills from a directory.
|
|
201
|
-
* Reference: gemini-cli loadSkillsFromDir (skills/skillLoader.ts L115-159)
|
|
202
|
-
*/
|
|
203
|
-
async loadSkillsFromDir(dir) {
|
|
204
|
-
const discoveredSkills = [];
|
|
205
|
-
try {
|
|
206
|
-
const absoluteSearchPath = path.resolve(dir);
|
|
207
|
-
const stats = await fs.stat(absoluteSearchPath).catch(() => null);
|
|
208
|
-
if (!stats || !stats.isDirectory()) {
|
|
209
|
-
return [];
|
|
210
|
-
}
|
|
211
|
-
const pattern = ['SKILL.md', '*/SKILL.md'];
|
|
212
|
-
const skillFiles = await (0, glob_1.glob)(pattern, {
|
|
213
|
-
cwd: absoluteSearchPath,
|
|
214
|
-
absolute: true,
|
|
215
|
-
nodir: true,
|
|
216
|
-
ignore: ['**/node_modules/**', '**/.git/**'],
|
|
217
|
-
});
|
|
218
|
-
for (const skillFile of skillFiles) {
|
|
219
|
-
const skill = await this.loadSkillFromFile(skillFile);
|
|
220
|
-
if (skill) {
|
|
221
|
-
discoveredSkills.push(skill);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
catch (error) {
|
|
226
|
-
console.warn(`[SkillLoader] Error discovering skills in ${dir}:`, error);
|
|
227
|
-
}
|
|
228
|
-
return discoveredSkills;
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Load a single skill from a SKILL.md file.
|
|
232
|
-
* Reference: gemini-cli loadSkillFromFile (skills/skillLoader.ts L164-192)
|
|
233
|
-
*/
|
|
234
|
-
async loadSkillFromFile(filePath) {
|
|
235
|
-
try {
|
|
236
|
-
const content = await fs.readFile(filePath, 'utf-8');
|
|
237
|
-
const parsed = (0, frontmatter_parser_1.parseSkillFrontmatter)(content);
|
|
238
|
-
if (!parsed) {
|
|
239
|
-
return null;
|
|
240
|
-
}
|
|
241
|
-
return {
|
|
242
|
-
name: parsed.name,
|
|
243
|
-
description: parsed.description,
|
|
244
|
-
location: filePath,
|
|
245
|
-
body: parsed.body,
|
|
246
|
-
allowedTools: parsed.allowedTools,
|
|
247
|
-
outputType: parsed.outputType,
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
catch (error) {
|
|
251
|
-
console.warn(`[SkillLoader] Error parsing skill file ${filePath}:`, error);
|
|
252
|
-
return null;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
exports.SkillLoader = SkillLoader;
|
package/dist/tools/ask-user.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ask_user Tool — ask the user a question and wait for confirmation
|
|
3
|
-
*
|
|
4
|
-
* Publishes an input_required event via eventBus,
|
|
5
|
-
* handled by the upper layer (Server) for user interaction.
|
|
6
|
-
*/
|
|
7
|
-
import type { ToolDefinition } from '../agent-loop/types';
|
|
8
|
-
export declare const askUserTool: ToolDefinition;
|
package/dist/tools/ask-user.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* ask_user Tool — ask the user a question and wait for confirmation
|
|
4
|
-
*
|
|
5
|
-
* Publishes an input_required event via eventBus,
|
|
6
|
-
* handled by the upper layer (Server) for user interaction.
|
|
7
|
-
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.askUserTool = void 0;
|
|
10
|
-
const v4_1 = require("zod/v4");
|
|
11
|
-
const AskUserSchema = v4_1.z.object({
|
|
12
|
-
/** Question to ask the user */
|
|
13
|
-
question: v4_1.z.string().describe('Question to ask the user'),
|
|
14
|
-
/** Optional choices for the user */
|
|
15
|
-
options: v4_1.z.array(v4_1.z.object({
|
|
16
|
-
label: v4_1.z.string().describe('Option label'),
|
|
17
|
-
description: v4_1.z.string().optional().describe('Option description'),
|
|
18
|
-
})).optional().describe('Array of options for the user to choose from'),
|
|
19
|
-
/** Type of confirmation needed */
|
|
20
|
-
type: v4_1.z.enum(['confirm', 'choice', 'text']).default('choice').describe('Type: confirm (yes/no), choice (select), text (free input)'),
|
|
21
|
-
});
|
|
22
|
-
exports.askUserTool = {
|
|
23
|
-
name: 'ask_user',
|
|
24
|
-
description: `Ask the user a question and wait for their response.
|
|
25
|
-
Use this when:
|
|
26
|
-
- PRD and code implementation are inconsistent and need confirmation
|
|
27
|
-
- Multiple approaches are possible and user preference is needed
|
|
28
|
-
- Information is missing and cannot be determined from available context
|
|
29
|
-
|
|
30
|
-
The skill execution pauses until the user responds.`,
|
|
31
|
-
inputSchema: AskUserSchema,
|
|
32
|
-
async execute(args) {
|
|
33
|
-
// In AgentLoop mode, this would be handled by the event system
|
|
34
|
-
// For Phase 1 (hybrid mode), we use a callback approach
|
|
35
|
-
const callback = globalThis.__askUserCallback;
|
|
36
|
-
if (callback) {
|
|
37
|
-
const answer = await callback(args.question, args.options);
|
|
38
|
-
return { answer, confirmed: true };
|
|
39
|
-
}
|
|
40
|
-
// Fallback: no user interaction available — tell LLM to decide on its own
|
|
41
|
-
console.warn(`[ask_user] No callback registered. Question: ${args.question}`);
|
|
42
|
-
return {
|
|
43
|
-
answer: `Unable to reach user. Please decide based on available information and continue. Do not call ask_user again.`,
|
|
44
|
-
confirmed: true,
|
|
45
|
-
};
|
|
46
|
-
},
|
|
47
|
-
};
|
package/dist/tools/bash.d.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bash Tool — shell command execution with scope-based permission control
|
|
3
|
-
*
|
|
4
|
-
* Scope patterns (aligned with keve-agent SKILL.md allowed-tools):
|
|
5
|
-
* Bash(git:*) → only git commands allowed
|
|
6
|
-
* Bash(npx:*) → only npx commands allowed
|
|
7
|
-
* Bash(npm:*) → only npm commands allowed
|
|
8
|
-
* Bash(node:*) → only node commands allowed
|
|
9
|
-
* Bash(shell:*) → any command allowed
|
|
10
|
-
*
|
|
11
|
-
* When LLM calls bash tool, the 'scope' parameter is validated against
|
|
12
|
-
* the skill's allowed-tools list by the ToolCaller.
|
|
13
|
-
*/
|
|
14
|
-
import { z } from 'zod/v4';
|
|
15
|
-
import type { ToolDefinition } from '../agent-loop/types';
|
|
16
|
-
export declare const BashInputSchema: z.ZodObject<{
|
|
17
|
-
command: z.ZodString;
|
|
18
|
-
scope: z.ZodDefault<z.ZodString>;
|
|
19
|
-
cwd: z.ZodOptional<z.ZodString>;
|
|
20
|
-
timeout: z.ZodDefault<z.ZodNumber>;
|
|
21
|
-
}, z.core.$strip>;
|
|
22
|
-
export type BashInput = z.infer<typeof BashInputSchema>;
|
|
23
|
-
/**
|
|
24
|
-
* Validate that a command matches the allowed scope.
|
|
25
|
-
* Extracts the first word (the binary name) and checks against scope.
|
|
26
|
-
*
|
|
27
|
-
* @param command - The shell command to validate
|
|
28
|
-
* @param allowedScopes - Array of allowed scopes (e.g., ['git', 'npx', 'shell'])
|
|
29
|
-
* @returns true if command is within allowed scopes
|
|
30
|
-
*/
|
|
31
|
-
export declare function isCommandInScope(command: string, allowedScopes: string[]): boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Parse Bash(scope:*) patterns from allowed-tools list.
|
|
34
|
-
* Input: ['Bash(git:*)', 'Bash(npx:*)', 'codegraph_impact']
|
|
35
|
-
* Output: ['git', 'npx']
|
|
36
|
-
*/
|
|
37
|
-
export declare function parseBashScopes(allowedTools: string[]): string[];
|
|
38
|
-
/**
|
|
39
|
-
* Check if a command attempts to write to a read-only path.
|
|
40
|
-
* Uses static analysis of the command string.
|
|
41
|
-
*
|
|
42
|
-
* @param command - The shell command to check
|
|
43
|
-
* @param readOnlyPaths - Array of directory paths that are read-only
|
|
44
|
-
* @returns Error message if write is detected, or null if command is safe
|
|
45
|
-
*/
|
|
46
|
-
export declare function checkReadOnlyPathWrite(command: string, readOnlyPaths: string[]): string | null;
|
|
47
|
-
export declare const bashTool: ToolDefinition;
|