@s_s/agent-kit 1.0.0
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 +317 -0
- package/build/create-kit.d.ts +16 -0
- package/build/create-kit.js +54 -0
- package/build/create-kit.js.map +1 -0
- package/build/detect.d.ts +13 -0
- package/build/detect.js +34 -0
- package/build/detect.js.map +1 -0
- package/build/hook-capabilities.d.ts +87 -0
- package/build/hook-capabilities.js +191 -0
- package/build/hook-capabilities.js.map +1 -0
- package/build/hook-registry.d.ts +158 -0
- package/build/hook-registry.js +223 -0
- package/build/hook-registry.js.map +1 -0
- package/build/hook-translators/claude-code.d.ts +26 -0
- package/build/hook-translators/claude-code.js +351 -0
- package/build/hook-translators/claude-code.js.map +1 -0
- package/build/hook-translators/index.d.ts +4 -0
- package/build/hook-translators/index.js +4 -0
- package/build/hook-translators/index.js.map +1 -0
- package/build/hook-translators/openclaw.d.ts +25 -0
- package/build/hook-translators/openclaw.js +272 -0
- package/build/hook-translators/openclaw.js.map +1 -0
- package/build/hook-translators/opencode.d.ts +23 -0
- package/build/hook-translators/opencode.js +254 -0
- package/build/hook-translators/opencode.js.map +1 -0
- package/build/hook-translators/types.d.ts +59 -0
- package/build/hook-translators/types.js +2 -0
- package/build/hook-translators/types.js.map +1 -0
- package/build/hook-types.d.ts +155 -0
- package/build/hook-types.js +2 -0
- package/build/hook-types.js.map +1 -0
- package/build/hooks.d.ts +30 -0
- package/build/hooks.js +333 -0
- package/build/hooks.js.map +1 -0
- package/build/index.d.ts +9 -0
- package/build/index.js +11 -0
- package/build/index.js.map +1 -0
- package/build/platform.d.ts +17 -0
- package/build/platform.js +79 -0
- package/build/platform.js.map +1 -0
- package/build/prompt.d.ts +21 -0
- package/build/prompt.js +87 -0
- package/build/prompt.js.map +1 -0
- package/build/register.d.ts +18 -0
- package/build/register.js +34 -0
- package/build/register.js.map +1 -0
- package/build/types.d.ts +111 -0
- package/build/types.js +53 -0
- package/build/types.js.map +1 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# Agent Kit
|
|
2
|
+
|
|
3
|
+
MCP Server / Skill 开发基础设施库。提供 agent 检测、prompt 注入、hook 安装和跨平台数据目录等通用能力,让多个 MCP/Skill 项目共享同一套 agent 适配层,避免重复实现。
|
|
4
|
+
|
|
5
|
+
## 功能
|
|
6
|
+
|
|
7
|
+
- **Agent 检测** — 通过文件系统特征或 MCP clientInfo 自动识别 agent 类型(OpenCode、Claude Code、OpenClaw、Codex)
|
|
8
|
+
- **Prompt 注入** — 向 agent 配置文件(`AGENTS.md`、`CLAUDE.md`、manifests 等)注入自定义指令,支持幂等更新
|
|
9
|
+
- **Intent-based Hook 系统** — 按意图声明,自动翻译为各 agent 原生格式,支持三层优先级和显式降级
|
|
10
|
+
- **跨平台数据目录** — 自动适配 macOS / Linux / Windows,支持 global / project 两种作用域
|
|
11
|
+
- **零运行时依赖** — 纯 TypeScript,零 dependencies
|
|
12
|
+
- **工厂模式** — `createKit(name)` 返回绑定了工具名的函数集,支持解构,无全局状态
|
|
13
|
+
|
|
14
|
+
## 安装
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @s_s/agent-kit
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 快速开始
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { createKit, hooks, detectAgent } from '@s_s/agent-kit';
|
|
24
|
+
|
|
25
|
+
// 1. 创建 kit 实例(支持解构)
|
|
26
|
+
const { injectPrompt, installHooks, getDataDir } = createKit('my-mcp');
|
|
27
|
+
|
|
28
|
+
// 2. 声明 hook 意图(全局 API,不绑定实例)
|
|
29
|
+
hooks.inject({
|
|
30
|
+
perTurn: 'Remember to use my-mcp tools when relevant.',
|
|
31
|
+
sessionStart: 'Welcome! Check my-mcp for context.',
|
|
32
|
+
compaction: 'Preserve my-mcp context during compaction.',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
hooks.beforeToolCall({
|
|
36
|
+
match: /^Bash/,
|
|
37
|
+
handler: (ctx) => {
|
|
38
|
+
if (ctx.args.command?.includes('rm -rf')) {
|
|
39
|
+
return { block: true, reason: 'Dangerous command blocked' };
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// 3. 检测当前 agent
|
|
45
|
+
const agent = await detectAgent();
|
|
46
|
+
if (!agent) throw new Error('No supported agent detected');
|
|
47
|
+
|
|
48
|
+
// 4. 注入 prompt 到 agent 配置文件
|
|
49
|
+
await injectPrompt(agent, '## My MCP\nInstructions for the agent...');
|
|
50
|
+
|
|
51
|
+
// 5. 安装 hooks(自动翻译为 agent 原生格式)
|
|
52
|
+
const result = await installHooks(agent);
|
|
53
|
+
console.log(`Hooks installed: ${result.filesWritten.join(', ')}`);
|
|
54
|
+
console.log(`Warnings: ${result.warnings.join('\n')}`);
|
|
55
|
+
|
|
56
|
+
// 6. 获取数据目录路径
|
|
57
|
+
const dataDir = getDataDir(); // global scope
|
|
58
|
+
const projectDir = getDataDir({ scope: 'project', projectRoot: '/path/to/project' });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## API
|
|
62
|
+
|
|
63
|
+
### `createKit(name, options?)`
|
|
64
|
+
|
|
65
|
+
创建一个绑定了工具名的 kit 实例。返回的对象包含所有需要工具名的函数。
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
createKit(name: string, options?: KitOptions): Kit
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
| 参数 | 类型 | 说明 |
|
|
72
|
+
| --------------------- | --------------------------------------- | -------------------------------- |
|
|
73
|
+
| `name` | `string` | 工具名称(必填) |
|
|
74
|
+
| `options.dirs` | `{ global?: string, project?: string }` | 自定义数据目录名 |
|
|
75
|
+
| `options.envOverride` | `string` | 覆盖全局数据目录路径的环境变量名 |
|
|
76
|
+
|
|
77
|
+
`name` 是整个包的核心锚点:
|
|
78
|
+
|
|
79
|
+
- Prompt 标记:`<!-- {name}:start -->` / `<!-- {name}:end -->`
|
|
80
|
+
- Hook 目录 / 文件名前缀
|
|
81
|
+
- 项目级数据目录:`.{name}`
|
|
82
|
+
- 环境变量:`{NAME}_DATA_DIR`(默认,大写 + 下划线)
|
|
83
|
+
|
|
84
|
+
返回的 Kit 对象包含以下方法:
|
|
85
|
+
|
|
86
|
+
| 方法 | 说明 |
|
|
87
|
+
| --------------------------------------- | ----------------------------- |
|
|
88
|
+
| `injectPrompt(agent, prompt, options?)` | 注入 prompt 到 agent 配置文件 |
|
|
89
|
+
| `hasPromptInjected(agent, options?)` | 检查 prompt 是否已注入 |
|
|
90
|
+
| `installHooks(agent)` | 安装 hooks |
|
|
91
|
+
| `uninstallHooks(agent)` | 卸载 hooks |
|
|
92
|
+
| `hasHooksInstalled(agent)` | 检查 hooks 是否已安装 |
|
|
93
|
+
| `getDataDir(options?)` | 获取跨平台数据目录路径 |
|
|
94
|
+
|
|
95
|
+
### Hook 系统
|
|
96
|
+
|
|
97
|
+
Hook 系统分为两个阶段:**声明**和**安装**。
|
|
98
|
+
|
|
99
|
+
1. **声明**:通过全局 `hooks.*` API 声明意图(`inject` / `beforeToolCall` / `afterToolCall` / `onSession` / `onPermission`),以及 `raw` / `extend` 两种高级注册方式
|
|
100
|
+
2. **安装**:调用 `kit.installHooks(agent)` 时,从全局注册中心读取所有声明,翻译为目标 agent 的原生格式并写入磁盘
|
|
101
|
+
|
|
102
|
+
详细的 API 说明、示例、三层优先级机制和降级行为,请参阅 **[Hook 使用指南](docs/hook-usage.md)**。各 agent 原生 hook 能力的完整横向对比,请参阅 **[Hook 横向对比](docs/hooks-comparison.md)**。
|
|
103
|
+
|
|
104
|
+
### Kit 方法详情
|
|
105
|
+
|
|
106
|
+
#### `kit.injectPrompt(agent, prompt, options?)`
|
|
107
|
+
|
|
108
|
+
向 agent 配置文件注入提示内容。
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
injectPrompt(agent: AgentType, prompt: string, options?: ScopeOptions): Promise<void>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
- 首次调用:追加到文件末尾
|
|
115
|
+
- 后续调用:替换已有标记块(幂等更新)
|
|
116
|
+
- 自动创建目录和文件
|
|
117
|
+
|
|
118
|
+
#### `kit.installHooks(agent)`
|
|
119
|
+
|
|
120
|
+
为指定 agent 安装 hooks。从 hook 注册中心读取所有声明,翻译为原生格式,写入文件。
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
installHooks(agent: AgentType): Promise<HookInstallResult>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
返回值包含完整的降级信息:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
interface HookInstallResult {
|
|
130
|
+
success: boolean;
|
|
131
|
+
hookDir: string;
|
|
132
|
+
filesWritten: string[];
|
|
133
|
+
settingsUpdated: boolean;
|
|
134
|
+
notes: string[];
|
|
135
|
+
warnings: string[]; // 降级/冲突警告
|
|
136
|
+
skipped: SkippedIntent[]; // 被跳过的意图
|
|
137
|
+
error?: string;
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
各 agent 的翻译方式:
|
|
142
|
+
|
|
143
|
+
| Agent | 生成内容 |
|
|
144
|
+
| ------------------- | ------------------------------------------------------- |
|
|
145
|
+
| claude-code / codex | Shell 脚本(多个原生 hook),自动注册到 `settings.json` |
|
|
146
|
+
| openclaw | `HOOK.md` + `handler.ts`(内部 hook + 插件 hook) |
|
|
147
|
+
| opencode | 单个 TypeScript 插件文件(多个 hook 合并) |
|
|
148
|
+
|
|
149
|
+
#### `kit.uninstallHooks(agent)`
|
|
150
|
+
|
|
151
|
+
清理已安装的 hook 文件和 settings.json 条目。
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
uninstallHooks(agent: AgentType): Promise<{ success: boolean; removed: string[]; error?: string }>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
#### `kit.getDataDir(options?)`
|
|
158
|
+
|
|
159
|
+
获取跨平台数据目录路径。
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
getDataDir(options?: ScopeOptions): string
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
| 作用域 | 路径 |
|
|
166
|
+
| ---------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
167
|
+
| `global`(默认) | macOS: `~/Library/Application Support/{name}` / Linux: `~/.local/share/{name}` / Windows: `%APPDATA%/{name}` |
|
|
168
|
+
| `project` | `{projectRoot}/.{name}` |
|
|
169
|
+
|
|
170
|
+
全局路径可通过环境变量覆盖(默认变量名:`{NAME}_DATA_DIR`)。
|
|
171
|
+
|
|
172
|
+
### 独立函数
|
|
173
|
+
|
|
174
|
+
以下函数不依赖 kit 实例,可直接使用。
|
|
175
|
+
|
|
176
|
+
#### `detectAgent(cwd?)`
|
|
177
|
+
|
|
178
|
+
通过文件系统特征检测当前环境中的 agent 类型。
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
detectAgent(cwd?: string): Promise<AgentType | null>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
按固定顺序检测:opencode → claude-code → openclaw → codex。返回第一个匹配的类型,或 `null`。
|
|
185
|
+
|
|
186
|
+
#### `detectAgentFromClient(clientName)`
|
|
187
|
+
|
|
188
|
+
将 MCP `clientInfo.name` 映射为 `AgentType`。
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
detectAgentFromClient(clientName: string): AgentType | null
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
| clientName | AgentType |
|
|
195
|
+
| --------------------- | ------------- |
|
|
196
|
+
| `opencode` | `opencode` |
|
|
197
|
+
| `claude-code` | `claude-code` |
|
|
198
|
+
| `openclaw-acp-client` | `openclaw` |
|
|
199
|
+
| `codex-mcp-client` | `codex` |
|
|
200
|
+
|
|
201
|
+
#### `detectProjectRoot(cwd?)`
|
|
202
|
+
|
|
203
|
+
检测项目根目录。
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
detectProjectRoot(cwd?: string): Promise<string>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
优先使用 `git rev-parse --show-toplevel`,失败则向上遍历查找标记文件(`.git`、`package.json`、`pyproject.toml`、`Cargo.toml`、`go.mod`),都未找到则回退到 `cwd`。
|
|
210
|
+
|
|
211
|
+
### 能力矩阵 API
|
|
212
|
+
|
|
213
|
+
编程式查询各 agent 对各 intent 的支持程度。
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { CAPABILITY_MATRIX, checkDegradation, isIntentFullyUnsupported } from '@s_s/agent-kit';
|
|
217
|
+
|
|
218
|
+
// 查询特定能力
|
|
219
|
+
CAPABILITY_MATRIX.opencode.beforeToolCall.block.level; // 'partial'
|
|
220
|
+
|
|
221
|
+
// 检查某 intent 在某 agent 上的降级情况
|
|
222
|
+
const warnings = checkDegradation('opencode', 'beforeToolCall');
|
|
223
|
+
|
|
224
|
+
// 检查是否完全不支持
|
|
225
|
+
isIntentFullyUnsupported('openclaw', 'onPermission'); // true
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## 类型
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
type AgentType = 'opencode' | 'claude-code' | 'openclaw' | 'codex';
|
|
232
|
+
|
|
233
|
+
type StorageScope = 'global' | 'project';
|
|
234
|
+
|
|
235
|
+
interface ScopeOptions {
|
|
236
|
+
scope?: StorageScope; // 默认 'global'
|
|
237
|
+
projectRoot?: string; // scope 为 'project' 时必填
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
interface KitOptions {
|
|
241
|
+
dirs?: { global?: string; project?: string };
|
|
242
|
+
envOverride?: string;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
interface Kit {
|
|
246
|
+
readonly name: string;
|
|
247
|
+
injectPrompt(agent: AgentType, prompt: string, options?: ScopeOptions): Promise<void>;
|
|
248
|
+
hasPromptInjected(agent: AgentType, options?: ScopeOptions): Promise<boolean>;
|
|
249
|
+
installHooks(agent: AgentType): Promise<HookInstallResult>;
|
|
250
|
+
uninstallHooks(agent: AgentType): Promise<{ success: boolean; removed: string[]; error?: string }>;
|
|
251
|
+
hasHooksInstalled(agent: AgentType): Promise<boolean>;
|
|
252
|
+
getDataDir(options?: ScopeOptions): string;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
interface HookInstallResult {
|
|
256
|
+
success: boolean;
|
|
257
|
+
hookDir: string;
|
|
258
|
+
filesWritten: string[];
|
|
259
|
+
settingsUpdated: boolean;
|
|
260
|
+
notes: string[];
|
|
261
|
+
warnings: string[];
|
|
262
|
+
skipped: SkippedIntent[];
|
|
263
|
+
error?: string;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
interface SkippedIntent {
|
|
267
|
+
intent: string;
|
|
268
|
+
agent: string;
|
|
269
|
+
reason: string;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
type SupportLevel = 'supported' | 'partial' | 'unsupported';
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## 支持的 Agent
|
|
276
|
+
|
|
277
|
+
| Agent | 检测方式 | Prompt 目标文件 | Hook 形式 |
|
|
278
|
+
| ----------- | ----------------------- | --------------- | -------------------------- |
|
|
279
|
+
| OpenCode | `opencode.json` | `AGENTS.md` | TypeScript 插件 |
|
|
280
|
+
| Claude Code | `.claude/settings.json` | `CLAUDE.md` | Shell 脚本 + settings.json |
|
|
281
|
+
| OpenClaw | `.openclaw/` | manifest | `HOOK.md` + `handler.ts` |
|
|
282
|
+
| Codex | `.codex/` | `AGENTS.md` | Shell 脚本 + settings.json |
|
|
283
|
+
|
|
284
|
+
> 各 agent 的完整 hook 能力横向对比,请参阅 [docs/hooks-comparison.md](docs/hooks-comparison.md)。
|
|
285
|
+
|
|
286
|
+
## 开发
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
git clone git@github.com:nousyn/agent-kit.git
|
|
290
|
+
cd agent-kit
|
|
291
|
+
npm install
|
|
292
|
+
npm run build
|
|
293
|
+
npm test
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### 脚本
|
|
297
|
+
|
|
298
|
+
| 命令 | 说明 |
|
|
299
|
+
| ---------------------- | ------------------ |
|
|
300
|
+
| `npm run build` | 编译 TypeScript |
|
|
301
|
+
| `npm run dev` | 监听模式编译 |
|
|
302
|
+
| `npm test` | 运行测试(Vitest) |
|
|
303
|
+
| `npm run test:watch` | 监听模式测试 |
|
|
304
|
+
| `npm run prettier:fix` | 格式化所有文件 |
|
|
305
|
+
| `npm run release` | 交互式发布流程 |
|
|
306
|
+
|
|
307
|
+
### 发布
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
npm run release
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
交互式脚本,依次执行:git 检查 → 分支检查 → 版本选择 → 格式化 → 测试 → 构建 → 发布 → 推送。
|
|
314
|
+
|
|
315
|
+
## 许可证
|
|
316
|
+
|
|
317
|
+
MIT
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Kit, KitOptions } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a kit instance bound to the given tool name.
|
|
4
|
+
*
|
|
5
|
+
* The returned object contains all kit functions (injectPrompt, installHooks,
|
|
6
|
+
* getDataDir, etc.) with the tool name captured in a closure — no global state.
|
|
7
|
+
*
|
|
8
|
+
* Supports destructuring:
|
|
9
|
+
* ```ts
|
|
10
|
+
* const { injectPrompt, installHooks } = createKit('my-mcp');
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* @param name - Tool name. Used for prompt markers, hook directories, data directories, etc.
|
|
14
|
+
* @param options - Optional configuration (dirs, envOverride).
|
|
15
|
+
*/
|
|
16
|
+
export declare function createKit(name: string, options?: KitOptions): Kit;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { injectPrompt, hasPromptInjected } from './prompt.js';
|
|
2
|
+
import { installHooks, uninstallHooks, hasHooksInstalled } from './hooks.js';
|
|
3
|
+
import { getDataDir } from './platform.js';
|
|
4
|
+
/**
|
|
5
|
+
* Create a kit instance bound to the given tool name.
|
|
6
|
+
*
|
|
7
|
+
* The returned object contains all kit functions (injectPrompt, installHooks,
|
|
8
|
+
* getDataDir, etc.) with the tool name captured in a closure — no global state.
|
|
9
|
+
*
|
|
10
|
+
* Supports destructuring:
|
|
11
|
+
* ```ts
|
|
12
|
+
* const { injectPrompt, installHooks } = createKit('my-mcp');
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @param name - Tool name. Used for prompt markers, hook directories, data directories, etc.
|
|
16
|
+
* @param options - Optional configuration (dirs, envOverride).
|
|
17
|
+
*/
|
|
18
|
+
export function createKit(name, options) {
|
|
19
|
+
if (!name || !name.trim()) {
|
|
20
|
+
throw new Error('createKit: name is required and cannot be empty.');
|
|
21
|
+
}
|
|
22
|
+
const config = {
|
|
23
|
+
name,
|
|
24
|
+
dirs: options?.dirs,
|
|
25
|
+
envOverride: options?.envOverride,
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
get name() {
|
|
29
|
+
return name;
|
|
30
|
+
},
|
|
31
|
+
injectPrompt(agent, prompt, scopeOptions) {
|
|
32
|
+
if (!prompt || !prompt.trim()) {
|
|
33
|
+
throw new Error('injectPrompt: prompt is required and cannot be empty.');
|
|
34
|
+
}
|
|
35
|
+
return injectPrompt(name, prompt, agent, scopeOptions);
|
|
36
|
+
},
|
|
37
|
+
hasPromptInjected(agent, scopeOptions) {
|
|
38
|
+
return hasPromptInjected(name, agent, scopeOptions);
|
|
39
|
+
},
|
|
40
|
+
installHooks(agent) {
|
|
41
|
+
return installHooks(name, agent);
|
|
42
|
+
},
|
|
43
|
+
uninstallHooks(agent) {
|
|
44
|
+
return uninstallHooks(name, agent);
|
|
45
|
+
},
|
|
46
|
+
hasHooksInstalled(agent) {
|
|
47
|
+
return hasHooksInstalled(name, agent);
|
|
48
|
+
},
|
|
49
|
+
getDataDir(scopeOptions) {
|
|
50
|
+
return getDataDir(config, scopeOptions);
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=create-kit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-kit.js","sourceRoot":"","sources":["../src/create-kit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,OAAoB;IACxD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,MAAM,GAAsB;QAC9B,IAAI;QACJ,IAAI,EAAE,OAAO,EAAE,IAAI;QACnB,WAAW,EAAE,OAAO,EAAE,WAAW;KACpC,CAAC;IAEF,OAAO;QACH,IAAI,IAAI;YACJ,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,YAAY,CAAC,KAAgB,EAAE,MAAc,EAAE,YAA2B;YACtE,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;YAC7E,CAAC;YACD,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;QAC3D,CAAC;QAED,iBAAiB,CAAC,KAAgB,EAAE,YAA2B;YAC3D,OAAO,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;QACxD,CAAC;QAED,YAAY,CAAC,KAAgB;YACzB,OAAO,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QAED,cAAc,CAAC,KAAgB;YAC3B,OAAO,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;QAED,iBAAiB,CAAC,KAAgB;YAC9B,OAAO,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1C,CAAC;QAED,UAAU,CAAC,YAA2B;YAClC,OAAO,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC5C,CAAC;KACJ,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AgentType } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Detect which agent is present by checking characteristic files.
|
|
4
|
+
*
|
|
5
|
+
* Independent function — does not require register().
|
|
6
|
+
*/
|
|
7
|
+
export declare function detectAgent(cwd?: string): Promise<AgentType | null>;
|
|
8
|
+
/**
|
|
9
|
+
* Map an MCP clientInfo.name to AgentType.
|
|
10
|
+
*
|
|
11
|
+
* Independent function — does not require register().
|
|
12
|
+
*/
|
|
13
|
+
export declare function detectAgentFromClient(clientName: string): AgentType | null;
|
package/build/detect.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import { AGENT_REGISTRY, CLIENT_NAME_MAP } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Detect which agent is present by checking characteristic files.
|
|
6
|
+
*
|
|
7
|
+
* Independent function — does not require register().
|
|
8
|
+
*/
|
|
9
|
+
export async function detectAgent(cwd) {
|
|
10
|
+
const startDir = cwd ?? process.cwd();
|
|
11
|
+
const home = os.homedir();
|
|
12
|
+
for (const [agentType, entry] of Object.entries(AGENT_REGISTRY)) {
|
|
13
|
+
const paths = entry.detectionPaths(startDir, home);
|
|
14
|
+
for (const p of paths) {
|
|
15
|
+
try {
|
|
16
|
+
await fs.access(p);
|
|
17
|
+
return agentType;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Map an MCP clientInfo.name to AgentType.
|
|
28
|
+
*
|
|
29
|
+
* Independent function — does not require register().
|
|
30
|
+
*/
|
|
31
|
+
export function detectAgentFromClient(clientName) {
|
|
32
|
+
return CLIENT_NAME_MAP[clientName] ?? null;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAY;IAC1C,MAAM,QAAQ,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAE1B,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACnD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACpB,IAAI,CAAC;gBACD,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;gBACnB,OAAO,SAAsB,CAAC;YAClC,CAAC;YAAC,MAAM,CAAC;gBACL,SAAS;YACb,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAkB;IACpD,OAAO,eAAe,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { AgentType } from './types.js';
|
|
2
|
+
import type { IntentType } from './hook-types.js';
|
|
3
|
+
/** How well an agent supports a particular intent sub-capability. */
|
|
4
|
+
export type SupportLevel = 'supported' | 'partial' | 'unsupported';
|
|
5
|
+
/**
|
|
6
|
+
* Capability entry describing support for a specific intent sub-capability on a specific agent.
|
|
7
|
+
*/
|
|
8
|
+
export interface CapabilityEntry {
|
|
9
|
+
level: SupportLevel;
|
|
10
|
+
/** Human-readable note explaining partial/unsupported status. */
|
|
11
|
+
note?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Sub-capabilities per intent type.
|
|
15
|
+
*/
|
|
16
|
+
export interface IntentCapabilities {
|
|
17
|
+
inject: {
|
|
18
|
+
perTurn: CapabilityEntry;
|
|
19
|
+
sessionStart: CapabilityEntry;
|
|
20
|
+
compaction: CapabilityEntry;
|
|
21
|
+
sessionEnd: CapabilityEntry;
|
|
22
|
+
};
|
|
23
|
+
beforeToolCall: {
|
|
24
|
+
intercept: CapabilityEntry;
|
|
25
|
+
block: CapabilityEntry;
|
|
26
|
+
modifyArgs: CapabilityEntry;
|
|
27
|
+
matcher: CapabilityEntry;
|
|
28
|
+
};
|
|
29
|
+
afterToolCall: {
|
|
30
|
+
observe: CapabilityEntry;
|
|
31
|
+
matcher: CapabilityEntry;
|
|
32
|
+
};
|
|
33
|
+
onSession: {
|
|
34
|
+
start: CapabilityEntry;
|
|
35
|
+
end: CapabilityEntry;
|
|
36
|
+
};
|
|
37
|
+
onPermission: {
|
|
38
|
+
decide: CapabilityEntry;
|
|
39
|
+
matcher: CapabilityEntry;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The capability matrix: intent sub-capability × agent → support level.
|
|
44
|
+
*
|
|
45
|
+
* This is the single source of truth for what each agent can and cannot do
|
|
46
|
+
* with each intent type. Used by installHooks() to generate precise warnings.
|
|
47
|
+
*/
|
|
48
|
+
export declare const CAPABILITY_MATRIX: Record<AgentType, IntentCapabilities>;
|
|
49
|
+
/**
|
|
50
|
+
* A degradation warning for a specific intent on a specific agent.
|
|
51
|
+
*/
|
|
52
|
+
export interface DegradationWarning {
|
|
53
|
+
agent: AgentType;
|
|
54
|
+
intent: IntentType;
|
|
55
|
+
capability: string;
|
|
56
|
+
level: SupportLevel;
|
|
57
|
+
message: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check all sub-capabilities for a given intent type on a given agent.
|
|
61
|
+
* Returns warnings for any partial or unsupported sub-capabilities.
|
|
62
|
+
*
|
|
63
|
+
* Only checks sub-capabilities that the intent actually uses.
|
|
64
|
+
* For example, if an inject intent has no `compaction` field, the compaction
|
|
65
|
+
* capability is not checked.
|
|
66
|
+
*/
|
|
67
|
+
export declare function checkDegradation(agent: AgentType, intentType: IntentType, usedCapabilities?: string[]): DegradationWarning[];
|
|
68
|
+
/**
|
|
69
|
+
* Check degradation for all registered intents on a specific agent.
|
|
70
|
+
* Analyzes which sub-capabilities each intent actually uses and only
|
|
71
|
+
* warns about those.
|
|
72
|
+
*/
|
|
73
|
+
export declare function checkAllDegradation(agent: AgentType, intentTypes: IntentType[]): DegradationWarning[];
|
|
74
|
+
/**
|
|
75
|
+
* Check if a specific intent type is fully unsupported on an agent.
|
|
76
|
+
* Returns true only if ALL sub-capabilities are unsupported.
|
|
77
|
+
*/
|
|
78
|
+
export declare function isIntentFullyUnsupported(agent: AgentType, intentType: IntentType): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Detect conflicts between intent-generated hooks and raw hooks.
|
|
81
|
+
*
|
|
82
|
+
* @param agent - The target agent.
|
|
83
|
+
* @param intentNativeHooks - Set of native hook names generated by intents.
|
|
84
|
+
* @param rawNativeHooks - Set of native hook names registered via hooks.raw().
|
|
85
|
+
* @returns Warning messages for each conflict.
|
|
86
|
+
*/
|
|
87
|
+
export declare function detectConflicts(agent: AgentType, intentNativeHooks: Set<string>, rawNativeHooks: Set<string>): string[];
|