@agentplugins/adapter-kimi 0.1.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 ADDED
@@ -0,0 +1,47 @@
1
+ # @agentplugins/adapter-kimi
2
+
3
+ > AgentPlugins platform adapter for [Kimi (Moonshot AI)](https://www.moonshot.cn/).
4
+
5
+ Compiles a universal `PluginManifest` into Kimi's plugin layout: `kimi.plugin.json` manifest, hook wiring, and MCP server config. Inline handlers are wrapped as command scripts.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @agentplugins/adapter-kimi
11
+ ```
12
+
13
+ Typically installed transitively via [`@agentplugins/cli`](https://www.npmjs.com/package/@agentplugins/cli).
14
+
15
+ ## Usage
16
+
17
+ ```typescript
18
+ import { createKimiAdapter } from '@agentplugins/adapter-kimi';
19
+
20
+ const adapter = createKimiAdapter();
21
+ const output = await adapter.compile(manifest);
22
+ ```
23
+
24
+ Or via the CLI:
25
+
26
+ ```bash
27
+ npx agentplugins build --target kimi
28
+ ```
29
+
30
+ ## Output shape
31
+
32
+ A successful build writes to `dist/kimi/`:
33
+
34
+ ```
35
+ dist/kimi/
36
+ ├── kimi.plugin.json
37
+ ├── hooks/
38
+ │ └── hooks.json
39
+ ├── skills/
40
+ └── .mcp.json
41
+ ```
42
+
43
+ Install with: `cp -r dist/kimi ~/.kimi/plugins/`
44
+
45
+ ## License
46
+
47
+ MIT
@@ -0,0 +1,172 @@
1
+ import { PlatformAdapter, TargetPlatform, UniversalHookName, HandlerType, PluginManifest, ValidationIssue, AdapterOutput } from '@agentplugins/core';
2
+
3
+ /**
4
+ * @agentplugins/adapter-kimi
5
+ *
6
+ * Platform adapter for Kimi (Moonshot AI) — AgentPlugins plugin system.
7
+ *
8
+ * Kimi plugins are installed via the `/plugins install <github-url|local-path>`
9
+ * command in the Kimi chat interface. They are **user-level only**; there is no
10
+ * project-level scope. Any change to a plugin requires a `/new` session restart
11
+ * to take effect.
12
+ *
13
+ * Architecture overview
14
+ * ---------------------
15
+ * - Manifest : `kimi.plugin.json` (JSON)
16
+ * - Hooks : Command-based (JSON over stdin / stdout), FAIL-OPEN
17
+ * - Skills : Markdown files with YAML frontmatter (`SKILL.md`)
18
+ * - Registration : `/plugins install <url>`
19
+ * - Security model : Conservative loading + trust badges; hooks are *not* a
20
+ * sole security barrier (they fail open)
21
+ *
22
+ * Supported universal hooks
23
+ * -------------------------
24
+ * | Universal hook | Kimi event |
25
+ * |----------------------|-------------------|
26
+ * | preToolUse | PreToolUse |
27
+ * | userPromptSubmit | UserPromptSubmit |
28
+ * | sessionStart | SessionStart |
29
+ * | notification | Notification |
30
+ * | permissionRequest | PermissionRequest |
31
+ *
32
+ * Unsupported hooks (explicitly rejected during validation):
33
+ * sessionEnd, userPromptExpansion, postToolUse, postToolUseFailure,
34
+ * permissionDenied, subagentStart, subagentStop, preCompact, postCompact,
35
+ * stop, stopFailure, fileChanged, cwdChanged, setup
36
+ */
37
+
38
+ /**
39
+ * Shape of the `kimi.plugin.json` manifest.
40
+ *
41
+ * @see https://platform.moonshot.cn/docs/plugins/kimi-plugin-json
42
+ */
43
+ interface KimiPluginJson {
44
+ /** Plugin machine-name (kebab-case, unique within user scope). */
45
+ name: string;
46
+ /** Relative path to the skills directory containing `SKILL.md` files. */
47
+ skills: string;
48
+ /**
49
+ * Relative path to the session-start hook entry point.
50
+ * Executed once when a new chat session begins.
51
+ */
52
+ sessionStart?: string;
53
+ /**
54
+ * Relative path to an MCP (Model Context Protocol) server config JSON.
55
+ * Optional — only needed if the plugin exposes MCP-based tools.
56
+ */
57
+ mcpServers?: string;
58
+ /** Display metadata shown in the Kimi plugin store / `/plugins list`. */
59
+ interface: {
60
+ /** Human-readable plugin name. */
61
+ displayName: string;
62
+ /** Short description (≤ 120 chars recommended). */
63
+ description: string;
64
+ /** Optional icon URL or emoji. */
65
+ icon?: string;
66
+ };
67
+ }
68
+ /**
69
+ * Shape of the `kimi-hooks.json` configuration file.
70
+ *
71
+ * Each top-level key is a Kimi event name. Under each event lives a list of
72
+ * matcher rules; every matching rule runs its `hooks` array in order.
73
+ *
74
+ * Kimi hooks are **fail-open**: if a hook process exits non-zero or times out,
75
+ * Kimi logs the failure but continues execution. This is by design — hooks are
76
+ * *not* a security barrier on their own.
77
+ */
78
+ interface KimiHooksJson {
79
+ hooks: Record<string, Array<{
80
+ /** Glob-style matcher (`*`, `read_file`, etc.). */
81
+ matcher: string;
82
+ /** Ordered list of hook invocations for this matcher. */
83
+ hooks: Array<{
84
+ type: "command";
85
+ command: string;
86
+ /** Message shown in the Kimi UI while the hook runs. */
87
+ statusMessage?: string;
88
+ }>;
89
+ }>>;
90
+ }
91
+ /**
92
+ * Shape of a single `SKILL.md` file’s YAML frontmatter.
93
+ */
94
+ interface SkillFrontmatter {
95
+ name: string;
96
+ description: string;
97
+ version?: string;
98
+ author?: string;
99
+ tags?: string[];
100
+ tools?: string[];
101
+ }
102
+ /**
103
+ * Kimi (Moonshot AI) platform adapter for AgentPlugins.
104
+ *
105
+ * Transforms universal AgentPlugins plugins into the Kimi-native format:
106
+ * - `kimi.plugin.json` — main manifest
107
+ * - `kimi-hooks.json` — command-based hook configuration
108
+ * - `skills/SKILL__*.md` — Markdown skill files with YAML frontmatter
109
+ *
110
+ * ### Hook model
111
+ * Kimi uses a **fail-open** command-based hook system. Hooks communicate with
112
+ * Kimi via JSON messages over stdin/stdout. If a hook fails (non-zero exit,
113
+ * timeout), Kimi logs the error but continues — hooks are not a security
114
+ * barrier on their own.
115
+ *
116
+ * ### Installation flow
117
+ * 1. User runs `/plugins install <url>` in Kimi chat
118
+ * 2. Kimi downloads and validates `kimi.plugin.json`
119
+ * 3. On session start (`/new`), `sessionStart` hook runs
120
+ * 4. Registered event hooks fire as their mapped events occur
121
+ *
122
+ * ### Session lifecycle
123
+ * - Plugins are **user-scoped** (no project-level isolation)
124
+ * - Any plugin change requires `/new` session restart
125
+ * - Hooks are re-evaluated on every session start
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * import { KimiAdapter } from "@agentplugins/adapter-kimi";
130
+ *
131
+ * const adapter = new KimiAdapter();
132
+ * const issues = adapter.validate(manifest);
133
+ * if (issues.every((i) => i.severity !== "error")) {
134
+ * const output = adapter.compile(manifest);
135
+ * // write output.files to disk...
136
+ * }
137
+ * ```
138
+ */
139
+ declare class KimiAdapter implements PlatformAdapter {
140
+ /** @inheritDoc */
141
+ readonly name: TargetPlatform;
142
+ /** @inheritDoc */
143
+ readonly displayName: string;
144
+ /** @inheritDoc */
145
+ readonly supportedHooks: readonly UniversalHookName[];
146
+ /** @inheritDoc */
147
+ readonly supportedHandlers: readonly HandlerType[];
148
+ /** @inheritDoc */
149
+ readonly manifestPath: string;
150
+ /** @inheritDoc */
151
+ readonly manifestFormat: "json";
152
+ /**
153
+ * Validates a universal plugin manifest for Kimi compatibility.
154
+ *
155
+ * @param manifest — The plugin manifest to validate.
156
+ * @returns Array of validation issues (empty if fully valid).
157
+ */
158
+ validate(manifest: PluginManifest): ValidationIssue[];
159
+ /**
160
+ * Compiles a universal plugin manifest into Kimi-native artifacts.
161
+ *
162
+ * @param manifest — The plugin manifest to compile.
163
+ * @returns AdapterOutput containing all files to write.
164
+ */
165
+ compile(manifest: PluginManifest): AdapterOutput;
166
+ }
167
+ /** Default adapter instance for convenience imports. */
168
+ declare const kimiAdapter: KimiAdapter;
169
+ /** Factory function for creating a new Kimi adapter instance. */
170
+ declare function createKimiAdapter(): PlatformAdapter;
171
+
172
+ export { KimiAdapter, type KimiHooksJson, type KimiPluginJson, type SkillFrontmatter, createKimiAdapter, KimiAdapter as default, kimiAdapter };
@@ -0,0 +1,172 @@
1
+ import { PlatformAdapter, TargetPlatform, UniversalHookName, HandlerType, PluginManifest, ValidationIssue, AdapterOutput } from '@agentplugins/core';
2
+
3
+ /**
4
+ * @agentplugins/adapter-kimi
5
+ *
6
+ * Platform adapter for Kimi (Moonshot AI) — AgentPlugins plugin system.
7
+ *
8
+ * Kimi plugins are installed via the `/plugins install <github-url|local-path>`
9
+ * command in the Kimi chat interface. They are **user-level only**; there is no
10
+ * project-level scope. Any change to a plugin requires a `/new` session restart
11
+ * to take effect.
12
+ *
13
+ * Architecture overview
14
+ * ---------------------
15
+ * - Manifest : `kimi.plugin.json` (JSON)
16
+ * - Hooks : Command-based (JSON over stdin / stdout), FAIL-OPEN
17
+ * - Skills : Markdown files with YAML frontmatter (`SKILL.md`)
18
+ * - Registration : `/plugins install <url>`
19
+ * - Security model : Conservative loading + trust badges; hooks are *not* a
20
+ * sole security barrier (they fail open)
21
+ *
22
+ * Supported universal hooks
23
+ * -------------------------
24
+ * | Universal hook | Kimi event |
25
+ * |----------------------|-------------------|
26
+ * | preToolUse | PreToolUse |
27
+ * | userPromptSubmit | UserPromptSubmit |
28
+ * | sessionStart | SessionStart |
29
+ * | notification | Notification |
30
+ * | permissionRequest | PermissionRequest |
31
+ *
32
+ * Unsupported hooks (explicitly rejected during validation):
33
+ * sessionEnd, userPromptExpansion, postToolUse, postToolUseFailure,
34
+ * permissionDenied, subagentStart, subagentStop, preCompact, postCompact,
35
+ * stop, stopFailure, fileChanged, cwdChanged, setup
36
+ */
37
+
38
+ /**
39
+ * Shape of the `kimi.plugin.json` manifest.
40
+ *
41
+ * @see https://platform.moonshot.cn/docs/plugins/kimi-plugin-json
42
+ */
43
+ interface KimiPluginJson {
44
+ /** Plugin machine-name (kebab-case, unique within user scope). */
45
+ name: string;
46
+ /** Relative path to the skills directory containing `SKILL.md` files. */
47
+ skills: string;
48
+ /**
49
+ * Relative path to the session-start hook entry point.
50
+ * Executed once when a new chat session begins.
51
+ */
52
+ sessionStart?: string;
53
+ /**
54
+ * Relative path to an MCP (Model Context Protocol) server config JSON.
55
+ * Optional — only needed if the plugin exposes MCP-based tools.
56
+ */
57
+ mcpServers?: string;
58
+ /** Display metadata shown in the Kimi plugin store / `/plugins list`. */
59
+ interface: {
60
+ /** Human-readable plugin name. */
61
+ displayName: string;
62
+ /** Short description (≤ 120 chars recommended). */
63
+ description: string;
64
+ /** Optional icon URL or emoji. */
65
+ icon?: string;
66
+ };
67
+ }
68
+ /**
69
+ * Shape of the `kimi-hooks.json` configuration file.
70
+ *
71
+ * Each top-level key is a Kimi event name. Under each event lives a list of
72
+ * matcher rules; every matching rule runs its `hooks` array in order.
73
+ *
74
+ * Kimi hooks are **fail-open**: if a hook process exits non-zero or times out,
75
+ * Kimi logs the failure but continues execution. This is by design — hooks are
76
+ * *not* a security barrier on their own.
77
+ */
78
+ interface KimiHooksJson {
79
+ hooks: Record<string, Array<{
80
+ /** Glob-style matcher (`*`, `read_file`, etc.). */
81
+ matcher: string;
82
+ /** Ordered list of hook invocations for this matcher. */
83
+ hooks: Array<{
84
+ type: "command";
85
+ command: string;
86
+ /** Message shown in the Kimi UI while the hook runs. */
87
+ statusMessage?: string;
88
+ }>;
89
+ }>>;
90
+ }
91
+ /**
92
+ * Shape of a single `SKILL.md` file’s YAML frontmatter.
93
+ */
94
+ interface SkillFrontmatter {
95
+ name: string;
96
+ description: string;
97
+ version?: string;
98
+ author?: string;
99
+ tags?: string[];
100
+ tools?: string[];
101
+ }
102
+ /**
103
+ * Kimi (Moonshot AI) platform adapter for AgentPlugins.
104
+ *
105
+ * Transforms universal AgentPlugins plugins into the Kimi-native format:
106
+ * - `kimi.plugin.json` — main manifest
107
+ * - `kimi-hooks.json` — command-based hook configuration
108
+ * - `skills/SKILL__*.md` — Markdown skill files with YAML frontmatter
109
+ *
110
+ * ### Hook model
111
+ * Kimi uses a **fail-open** command-based hook system. Hooks communicate with
112
+ * Kimi via JSON messages over stdin/stdout. If a hook fails (non-zero exit,
113
+ * timeout), Kimi logs the error but continues — hooks are not a security
114
+ * barrier on their own.
115
+ *
116
+ * ### Installation flow
117
+ * 1. User runs `/plugins install <url>` in Kimi chat
118
+ * 2. Kimi downloads and validates `kimi.plugin.json`
119
+ * 3. On session start (`/new`), `sessionStart` hook runs
120
+ * 4. Registered event hooks fire as their mapped events occur
121
+ *
122
+ * ### Session lifecycle
123
+ * - Plugins are **user-scoped** (no project-level isolation)
124
+ * - Any plugin change requires `/new` session restart
125
+ * - Hooks are re-evaluated on every session start
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * import { KimiAdapter } from "@agentplugins/adapter-kimi";
130
+ *
131
+ * const adapter = new KimiAdapter();
132
+ * const issues = adapter.validate(manifest);
133
+ * if (issues.every((i) => i.severity !== "error")) {
134
+ * const output = adapter.compile(manifest);
135
+ * // write output.files to disk...
136
+ * }
137
+ * ```
138
+ */
139
+ declare class KimiAdapter implements PlatformAdapter {
140
+ /** @inheritDoc */
141
+ readonly name: TargetPlatform;
142
+ /** @inheritDoc */
143
+ readonly displayName: string;
144
+ /** @inheritDoc */
145
+ readonly supportedHooks: readonly UniversalHookName[];
146
+ /** @inheritDoc */
147
+ readonly supportedHandlers: readonly HandlerType[];
148
+ /** @inheritDoc */
149
+ readonly manifestPath: string;
150
+ /** @inheritDoc */
151
+ readonly manifestFormat: "json";
152
+ /**
153
+ * Validates a universal plugin manifest for Kimi compatibility.
154
+ *
155
+ * @param manifest — The plugin manifest to validate.
156
+ * @returns Array of validation issues (empty if fully valid).
157
+ */
158
+ validate(manifest: PluginManifest): ValidationIssue[];
159
+ /**
160
+ * Compiles a universal plugin manifest into Kimi-native artifacts.
161
+ *
162
+ * @param manifest — The plugin manifest to compile.
163
+ * @returns AdapterOutput containing all files to write.
164
+ */
165
+ compile(manifest: PluginManifest): AdapterOutput;
166
+ }
167
+ /** Default adapter instance for convenience imports. */
168
+ declare const kimiAdapter: KimiAdapter;
169
+ /** Factory function for creating a new Kimi adapter instance. */
170
+ declare function createKimiAdapter(): PlatformAdapter;
171
+
172
+ export { KimiAdapter, type KimiHooksJson, type KimiPluginJson, type SkillFrontmatter, createKimiAdapter, KimiAdapter as default, kimiAdapter };
package/dist/index.js ADDED
@@ -0,0 +1,439 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ KimiAdapter: () => KimiAdapter,
24
+ createKimiAdapter: () => createKimiAdapter,
25
+ default: () => index_default,
26
+ kimiAdapter: () => kimiAdapter
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+ var import_core = require("@agentplugins/core");
30
+ var PLATFORM_NAME = "kimi";
31
+ var PLATFORM_DISPLAY_NAME = "Kimi (Moonshot AI)";
32
+ var MANIFEST_FILENAME = "kimi.plugin.json";
33
+ var MANIFEST_FORMAT = "json";
34
+ var SUPPORTED_HOOKS = [
35
+ "preToolUse",
36
+ "userPromptSubmit",
37
+ "sessionStart",
38
+ "notification",
39
+ "permissionRequest"
40
+ ];
41
+ var SUPPORTED_HANDLERS = ["command"];
42
+ var HOOK_NAME_MAP = {
43
+ preToolUse: "PreToolUse",
44
+ userPromptSubmit: "UserPromptSubmit",
45
+ sessionStart: "SessionStart",
46
+ notification: "Notification",
47
+ permissionRequest: "PermissionRequest",
48
+ // — unsupported mappings (not present in SUPPORTED_HOOKS) —
49
+ sessionEnd: "SessionEnd",
50
+ userPromptExpansion: "UserPromptExpansion",
51
+ postToolUse: "PostToolUse",
52
+ postToolUseFailure: "PostToolUseFailure",
53
+ permissionDenied: "PermissionDenied",
54
+ subagentStart: "SubagentStart",
55
+ subagentStop: "SubagentStop",
56
+ preCompact: "PreCompact",
57
+ postCompact: "PostCompact",
58
+ stop: "Stop",
59
+ stopFailure: "StopFailure",
60
+ fileChanged: "FileChanged",
61
+ cwdChanged: "CwdChanged",
62
+ setup: "Setup"
63
+ };
64
+ var UNSUPPORTED_HOOKS = [
65
+ "sessionEnd",
66
+ "userPromptExpansion",
67
+ "postToolUse",
68
+ "postToolUseFailure",
69
+ "permissionDenied",
70
+ "subagentStart",
71
+ "subagentStop",
72
+ "preCompact",
73
+ "postCompact",
74
+ "stop",
75
+ "stopFailure",
76
+ "fileChanged",
77
+ "cwdChanged",
78
+ "setup"
79
+ ];
80
+ function validateForKimi(manifest) {
81
+ const issues = [];
82
+ if (!manifest.name || manifest.name.trim().length === 0) {
83
+ issues.push({
84
+ severity: import_core.Severity.ERROR,
85
+ field: "name",
86
+ message: "Plugin 'name' is required for kimi.plugin.json."
87
+ });
88
+ } else if (!/^[a-z0-9-]+$/.test(manifest.name)) {
89
+ issues.push({
90
+ severity: import_core.Severity.WARNING,
91
+ field: "name",
92
+ message: "Plugin name should be kebab-case (lowercase letters, numbers, hyphens) for best compatibility with Kimi."
93
+ });
94
+ }
95
+ if (!manifest.version || manifest.version.trim().length === 0) {
96
+ issues.push({
97
+ severity: import_core.Severity.ERROR,
98
+ field: "version",
99
+ message: "Plugin 'version' is required."
100
+ });
101
+ }
102
+ if (!manifest.description || manifest.description.trim().length === 0) {
103
+ issues.push({
104
+ severity: import_core.Severity.WARNING,
105
+ field: "description",
106
+ message: "Plugin 'description' is recommended for Kimi interface metadata."
107
+ });
108
+ }
109
+ if (manifest.hooks) {
110
+ for (const [hookName, hook] of Object.entries(manifest.hooks)) {
111
+ if (!hook) continue;
112
+ if (UNSUPPORTED_HOOKS.includes(hookName)) {
113
+ issues.push({
114
+ severity: import_core.Severity.ERROR,
115
+ field: `hooks.${hookName}`,
116
+ message: `Hook "${hookName}" is not supported by Kimi. Supported hooks: ${SUPPORTED_HOOKS.join(", ")}. Consider refactoring to use a supported hook or removing it.`
117
+ });
118
+ continue;
119
+ }
120
+ if (!SUPPORTED_HOOKS.includes(hookName)) {
121
+ issues.push({
122
+ severity: import_core.Severity.ERROR,
123
+ field: `hooks.${hookName}`,
124
+ message: `Unknown hook "${hookName}". Kimi supports: ${SUPPORTED_HOOKS.join(", ")}.`
125
+ });
126
+ continue;
127
+ }
128
+ if (hook.handler) {
129
+ if (hook.handler.type === "inline") {
130
+ issues.push({
131
+ severity: import_core.Severity.ERROR,
132
+ field: `hooks.${hookName}.handler`,
133
+ message: `Kimi does not support inline/function handlers for "${hookName}". Wrap the logic in a CLI command and set handler.type to "command" (e.g., "node ./hooks/${hookName}.js").`
134
+ });
135
+ } else if (hook.handler.type === "command") {
136
+ if (!hook.handler.command || hook.handler.command.trim().length === 0) {
137
+ issues.push({
138
+ severity: import_core.Severity.ERROR,
139
+ field: `hooks.${hookName}.handler.command`,
140
+ message: `Command handler for "${hookName}" has an empty command string.`
141
+ });
142
+ }
143
+ const securityKeywords = ["security", "block", "deny", "prevent", "guard"];
144
+ const lowerHookName = hookName.toLowerCase();
145
+ if (securityKeywords.some((k) => lowerHookName.includes(k))) {
146
+ issues.push({
147
+ severity: import_core.Severity.WARNING,
148
+ field: `hooks.${hookName}`,
149
+ message: `Hook "${hookName}" appears security-oriented. Kimi hooks are FAIL-OPEN (not a sole security barrier). Do not rely on this hook for access control.`
150
+ });
151
+ }
152
+ } else if (hook.handler.type !== "http") {
153
+ issues.push({
154
+ severity: import_core.Severity.ERROR,
155
+ field: `hooks.${hookName}.handler.type`,
156
+ message: `Kimi does not support handler type "${hook.handler.type}". Use "command" instead.`
157
+ });
158
+ }
159
+ }
160
+ if (hook.blocking && hookName !== "preToolUse") {
161
+ issues.push({
162
+ severity: import_core.Severity.WARNING,
163
+ field: `hooks.${hookName}.blocking`,
164
+ message: `Only "preToolUse" supports blocking semantics in Kimi. Hook "${hookName}" marked blocking=true but will run non-blocking.`
165
+ });
166
+ }
167
+ }
168
+ }
169
+ if (manifest.skills && manifest.skills.length > 0) {
170
+ for (let i = 0; i < manifest.skills.length; i++) {
171
+ const skill = manifest.skills[i];
172
+ if (!skill.name || skill.name.trim().length === 0) {
173
+ issues.push({
174
+ severity: import_core.Severity.ERROR,
175
+ field: `skills[${i}].name`,
176
+ message: `Skill at index ${i} is missing a name.`
177
+ });
178
+ }
179
+ if (!skill.description || skill.description.trim().length === 0) {
180
+ issues.push({
181
+ severity: import_core.Severity.WARNING,
182
+ field: `skills[${i}].description`,
183
+ message: `Skill "${skill.name || `#${i}`}" is missing a description.`
184
+ });
185
+ }
186
+ }
187
+ }
188
+ return issues;
189
+ }
190
+ function compileForKimi(manifest) {
191
+ const files = [];
192
+ const pluginJson = {
193
+ name: manifest.name,
194
+ skills: "./skills",
195
+ interface: {
196
+ displayName: manifest.displayName || manifest.name,
197
+ description: manifest.description || ""
198
+ }
199
+ };
200
+ const sessionStartHook = manifest.hooks?.sessionStart;
201
+ if (sessionStartHook?.handler?.type === "command") {
202
+ pluginJson.sessionStart = sessionStartHook.handler.command;
203
+ }
204
+ if (manifest.mcpServers && Object.keys(manifest.mcpServers).length > 0) {
205
+ pluginJson.mcpServers = "./mcp.json";
206
+ }
207
+ files.push({
208
+ path: MANIFEST_FILENAME,
209
+ content: JSON.stringify(pluginJson, null, 2)
210
+ });
211
+ const hooksJson = buildHooksJson(manifest.hooks || {});
212
+ if (Object.keys(hooksJson.hooks).length > 0) {
213
+ files.push({
214
+ path: "kimi-hooks.json",
215
+ content: JSON.stringify(hooksJson, null, 2)
216
+ });
217
+ }
218
+ if (manifest.skills && manifest.skills.length > 0) {
219
+ for (const skill of manifest.skills) {
220
+ const skillFile = compileSkillToMarkdown(skill);
221
+ files.push(skillFile);
222
+ }
223
+ }
224
+ files.push({
225
+ path: "KIMI_INSTALL.md",
226
+ content: generateInstallInstructions(manifest)
227
+ });
228
+ return {
229
+ files,
230
+ manifest: {},
231
+ warnings: [],
232
+ issues: []
233
+ };
234
+ }
235
+ function buildHooksJson(hooks) {
236
+ const hooksConfig = { hooks: {} };
237
+ for (const [hookName, hook] of Object.entries(hooks)) {
238
+ if (!hook) continue;
239
+ const universalName = hookName;
240
+ if (!SUPPORTED_HOOKS.includes(universalName)) {
241
+ continue;
242
+ }
243
+ if (universalName === "sessionStart") {
244
+ continue;
245
+ }
246
+ const kimiEventName = HOOK_NAME_MAP[universalName];
247
+ if (!kimiEventName) {
248
+ continue;
249
+ }
250
+ const command = extractCommand(hook, universalName);
251
+ if (!command) {
252
+ continue;
253
+ }
254
+ const statusMessage = buildStatusMessage(hook, universalName);
255
+ if (!hooksConfig.hooks[kimiEventName]) {
256
+ hooksConfig.hooks[kimiEventName] = [];
257
+ }
258
+ hooksConfig.hooks[kimiEventName].push({
259
+ matcher: hook.matcher || "*",
260
+ hooks: [
261
+ {
262
+ type: "command",
263
+ command,
264
+ statusMessage
265
+ }
266
+ ]
267
+ });
268
+ }
269
+ return hooksConfig;
270
+ }
271
+ function extractCommand(hook, hookName) {
272
+ if (!hook.handler) {
273
+ return null;
274
+ }
275
+ if (hook.handler.type === "command") {
276
+ return hook.handler.command || null;
277
+ }
278
+ if (hook.handler.type === "inline") {
279
+ return `node ./hooks/${hookName}.js`;
280
+ }
281
+ return null;
282
+ }
283
+ function buildStatusMessage(hook, universalName) {
284
+ if (hook.handler.type === "command" && hook.handler.statusMessage) {
285
+ return hook.handler.statusMessage;
286
+ }
287
+ const defaultMessages = {
288
+ preToolUse: "Running pre-tool check",
289
+ userPromptSubmit: "Processing user prompt",
290
+ sessionStart: "Initializing plugin session",
291
+ notification: "Handling notification",
292
+ permissionRequest: "Requesting permission",
293
+ sessionEnd: "Cleaning up session",
294
+ userPromptExpansion: "Expanding prompt context",
295
+ postToolUse: "Processing tool result",
296
+ postToolUseFailure: "Handling tool failure",
297
+ permissionDenied: "Processing permission denial",
298
+ subagentStart: "Subagent starting",
299
+ subagentStop: "Subagent stopping",
300
+ preCompact: "Pre-compacting session",
301
+ postCompact: "Post-compacting session",
302
+ stop: "Stopping",
303
+ stopFailure: "Handling stop failure",
304
+ fileChanged: "Processing file change",
305
+ cwdChanged: "Processing directory change",
306
+ setup: "Running setup"
307
+ };
308
+ return defaultMessages[universalName];
309
+ }
310
+ function compileSkillToMarkdown(skill) {
311
+ const frontmatter = {
312
+ name: skill.name,
313
+ description: skill.description
314
+ };
315
+ const frontmatterYaml = Object.entries(frontmatter).map(([key, value]) => {
316
+ if (Array.isArray(value)) {
317
+ return `${key}:
318
+ ${value.map((v) => ` - ${v}`).join("\n")}`;
319
+ }
320
+ return `${key}: ${value}`;
321
+ }).join("\n");
322
+ const body = skill.content || skill.description || "";
323
+ const content = `---
324
+ ${frontmatterYaml}
325
+ ---
326
+
327
+ ${body}
328
+ `;
329
+ const safeName = skill.name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
330
+ return {
331
+ path: `skills/SKILL__${safeName}.md`,
332
+ content
333
+ };
334
+ }
335
+ function generateInstallInstructions(manifest) {
336
+ const displayName = manifest.displayName || manifest.name;
337
+ return `# Installing ${displayName} for Kimi
338
+
339
+ > Generated by AgentPlugins \u2014 Kimi Platform Adapter
340
+
341
+ ## Quick Install
342
+
343
+ In any Kimi chat, run:
344
+
345
+ \`\`\`
346
+ /plugins install <github-url|local-path>
347
+ \`\`\`
348
+
349
+ Replace \`<github-url|local-path>\` with the repository URL or local directory
350
+ path containing this plugin.
351
+
352
+ ## Post-Install
353
+
354
+ Kimi plugins are **user-level** \u2014 they apply to all your sessions, not just the
355
+ current project.
356
+
357
+ After installing (or updating) this plugin, start a **new session** with:
358
+
359
+ \`\`\`
360
+ /new
361
+ \`\`\`
362
+
363
+ Plugin changes do **not** take effect in existing sessions.
364
+
365
+ ## Important Notes
366
+
367
+ - **Fail-open hooks**: Kimi hooks are designed to fail open. If a hook process
368
+ crashes or times out, Kimi continues execution. Do not rely on hooks as a
369
+ sole security mechanism.
370
+
371
+ - **Trust badges**: Kimi shows trust indicators for plugins installed from
372
+ GitHub. Install only plugins from sources you trust.
373
+
374
+ - **No project scope**: Kimi does not support project-level plugin scoping.
375
+ All plugins are installed at the user level.
376
+
377
+ ## Supported Features
378
+
379
+ This plugin uses the following Kimi features:
380
+
381
+ ${manifest.hooks && Object.keys(manifest.hooks).length > 0 ? `**Hooks**: ${Object.entries(manifest.hooks).filter(([name]) => SUPPORTED_HOOKS.includes(name)).map(([name]) => HOOK_NAME_MAP[name] || name).join(", ")}` : "**Hooks**: (none)"}
382
+
383
+ ${manifest.skills && manifest.skills.length > 0 ? `**Skills**: ${manifest.skills.map((s) => s.name).join(", ")}` : "**Skills**: (none)"}
384
+
385
+ ## Troubleshooting
386
+
387
+ | Problem | Solution |
388
+ |---------|----------|
389
+ | Plugin not active | Run \`/new\` to start a fresh session |
390
+ | Hook not firing | Check that the command in \`kimi-hooks.json\` is executable |
391
+ | Skill not recognized | Verify \`kimi.plugin.json\` has correct \`skills\` path |
392
+ | Changes not applied | Remember: **every change requires \`/new\`** |
393
+ `;
394
+ }
395
+ var KimiAdapter = class {
396
+ constructor() {
397
+ /** @inheritDoc */
398
+ this.name = PLATFORM_NAME;
399
+ /** @inheritDoc */
400
+ this.displayName = PLATFORM_DISPLAY_NAME;
401
+ /** @inheritDoc */
402
+ this.supportedHooks = SUPPORTED_HOOKS;
403
+ /** @inheritDoc */
404
+ this.supportedHandlers = SUPPORTED_HANDLERS;
405
+ /** @inheritDoc */
406
+ this.manifestPath = MANIFEST_FILENAME;
407
+ /** @inheritDoc */
408
+ this.manifestFormat = MANIFEST_FORMAT;
409
+ }
410
+ /**
411
+ * Validates a universal plugin manifest for Kimi compatibility.
412
+ *
413
+ * @param manifest — The plugin manifest to validate.
414
+ * @returns Array of validation issues (empty if fully valid).
415
+ */
416
+ validate(manifest) {
417
+ return validateForKimi(manifest);
418
+ }
419
+ /**
420
+ * Compiles a universal plugin manifest into Kimi-native artifacts.
421
+ *
422
+ * @param manifest — The plugin manifest to compile.
423
+ * @returns AdapterOutput containing all files to write.
424
+ */
425
+ compile(manifest) {
426
+ return compileForKimi(manifest);
427
+ }
428
+ };
429
+ var kimiAdapter = new KimiAdapter();
430
+ function createKimiAdapter() {
431
+ return new KimiAdapter();
432
+ }
433
+ var index_default = KimiAdapter;
434
+ // Annotate the CommonJS export names for ESM import in node:
435
+ 0 && (module.exports = {
436
+ KimiAdapter,
437
+ createKimiAdapter,
438
+ kimiAdapter
439
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,412 @@
1
+ // src/index.ts
2
+ import { Severity } from "@agentplugins/core";
3
+ var PLATFORM_NAME = "kimi";
4
+ var PLATFORM_DISPLAY_NAME = "Kimi (Moonshot AI)";
5
+ var MANIFEST_FILENAME = "kimi.plugin.json";
6
+ var MANIFEST_FORMAT = "json";
7
+ var SUPPORTED_HOOKS = [
8
+ "preToolUse",
9
+ "userPromptSubmit",
10
+ "sessionStart",
11
+ "notification",
12
+ "permissionRequest"
13
+ ];
14
+ var SUPPORTED_HANDLERS = ["command"];
15
+ var HOOK_NAME_MAP = {
16
+ preToolUse: "PreToolUse",
17
+ userPromptSubmit: "UserPromptSubmit",
18
+ sessionStart: "SessionStart",
19
+ notification: "Notification",
20
+ permissionRequest: "PermissionRequest",
21
+ // — unsupported mappings (not present in SUPPORTED_HOOKS) —
22
+ sessionEnd: "SessionEnd",
23
+ userPromptExpansion: "UserPromptExpansion",
24
+ postToolUse: "PostToolUse",
25
+ postToolUseFailure: "PostToolUseFailure",
26
+ permissionDenied: "PermissionDenied",
27
+ subagentStart: "SubagentStart",
28
+ subagentStop: "SubagentStop",
29
+ preCompact: "PreCompact",
30
+ postCompact: "PostCompact",
31
+ stop: "Stop",
32
+ stopFailure: "StopFailure",
33
+ fileChanged: "FileChanged",
34
+ cwdChanged: "CwdChanged",
35
+ setup: "Setup"
36
+ };
37
+ var UNSUPPORTED_HOOKS = [
38
+ "sessionEnd",
39
+ "userPromptExpansion",
40
+ "postToolUse",
41
+ "postToolUseFailure",
42
+ "permissionDenied",
43
+ "subagentStart",
44
+ "subagentStop",
45
+ "preCompact",
46
+ "postCompact",
47
+ "stop",
48
+ "stopFailure",
49
+ "fileChanged",
50
+ "cwdChanged",
51
+ "setup"
52
+ ];
53
+ function validateForKimi(manifest) {
54
+ const issues = [];
55
+ if (!manifest.name || manifest.name.trim().length === 0) {
56
+ issues.push({
57
+ severity: Severity.ERROR,
58
+ field: "name",
59
+ message: "Plugin 'name' is required for kimi.plugin.json."
60
+ });
61
+ } else if (!/^[a-z0-9-]+$/.test(manifest.name)) {
62
+ issues.push({
63
+ severity: Severity.WARNING,
64
+ field: "name",
65
+ message: "Plugin name should be kebab-case (lowercase letters, numbers, hyphens) for best compatibility with Kimi."
66
+ });
67
+ }
68
+ if (!manifest.version || manifest.version.trim().length === 0) {
69
+ issues.push({
70
+ severity: Severity.ERROR,
71
+ field: "version",
72
+ message: "Plugin 'version' is required."
73
+ });
74
+ }
75
+ if (!manifest.description || manifest.description.trim().length === 0) {
76
+ issues.push({
77
+ severity: Severity.WARNING,
78
+ field: "description",
79
+ message: "Plugin 'description' is recommended for Kimi interface metadata."
80
+ });
81
+ }
82
+ if (manifest.hooks) {
83
+ for (const [hookName, hook] of Object.entries(manifest.hooks)) {
84
+ if (!hook) continue;
85
+ if (UNSUPPORTED_HOOKS.includes(hookName)) {
86
+ issues.push({
87
+ severity: Severity.ERROR,
88
+ field: `hooks.${hookName}`,
89
+ message: `Hook "${hookName}" is not supported by Kimi. Supported hooks: ${SUPPORTED_HOOKS.join(", ")}. Consider refactoring to use a supported hook or removing it.`
90
+ });
91
+ continue;
92
+ }
93
+ if (!SUPPORTED_HOOKS.includes(hookName)) {
94
+ issues.push({
95
+ severity: Severity.ERROR,
96
+ field: `hooks.${hookName}`,
97
+ message: `Unknown hook "${hookName}". Kimi supports: ${SUPPORTED_HOOKS.join(", ")}.`
98
+ });
99
+ continue;
100
+ }
101
+ if (hook.handler) {
102
+ if (hook.handler.type === "inline") {
103
+ issues.push({
104
+ severity: Severity.ERROR,
105
+ field: `hooks.${hookName}.handler`,
106
+ message: `Kimi does not support inline/function handlers for "${hookName}". Wrap the logic in a CLI command and set handler.type to "command" (e.g., "node ./hooks/${hookName}.js").`
107
+ });
108
+ } else if (hook.handler.type === "command") {
109
+ if (!hook.handler.command || hook.handler.command.trim().length === 0) {
110
+ issues.push({
111
+ severity: Severity.ERROR,
112
+ field: `hooks.${hookName}.handler.command`,
113
+ message: `Command handler for "${hookName}" has an empty command string.`
114
+ });
115
+ }
116
+ const securityKeywords = ["security", "block", "deny", "prevent", "guard"];
117
+ const lowerHookName = hookName.toLowerCase();
118
+ if (securityKeywords.some((k) => lowerHookName.includes(k))) {
119
+ issues.push({
120
+ severity: Severity.WARNING,
121
+ field: `hooks.${hookName}`,
122
+ message: `Hook "${hookName}" appears security-oriented. Kimi hooks are FAIL-OPEN (not a sole security barrier). Do not rely on this hook for access control.`
123
+ });
124
+ }
125
+ } else if (hook.handler.type !== "http") {
126
+ issues.push({
127
+ severity: Severity.ERROR,
128
+ field: `hooks.${hookName}.handler.type`,
129
+ message: `Kimi does not support handler type "${hook.handler.type}". Use "command" instead.`
130
+ });
131
+ }
132
+ }
133
+ if (hook.blocking && hookName !== "preToolUse") {
134
+ issues.push({
135
+ severity: Severity.WARNING,
136
+ field: `hooks.${hookName}.blocking`,
137
+ message: `Only "preToolUse" supports blocking semantics in Kimi. Hook "${hookName}" marked blocking=true but will run non-blocking.`
138
+ });
139
+ }
140
+ }
141
+ }
142
+ if (manifest.skills && manifest.skills.length > 0) {
143
+ for (let i = 0; i < manifest.skills.length; i++) {
144
+ const skill = manifest.skills[i];
145
+ if (!skill.name || skill.name.trim().length === 0) {
146
+ issues.push({
147
+ severity: Severity.ERROR,
148
+ field: `skills[${i}].name`,
149
+ message: `Skill at index ${i} is missing a name.`
150
+ });
151
+ }
152
+ if (!skill.description || skill.description.trim().length === 0) {
153
+ issues.push({
154
+ severity: Severity.WARNING,
155
+ field: `skills[${i}].description`,
156
+ message: `Skill "${skill.name || `#${i}`}" is missing a description.`
157
+ });
158
+ }
159
+ }
160
+ }
161
+ return issues;
162
+ }
163
+ function compileForKimi(manifest) {
164
+ const files = [];
165
+ const pluginJson = {
166
+ name: manifest.name,
167
+ skills: "./skills",
168
+ interface: {
169
+ displayName: manifest.displayName || manifest.name,
170
+ description: manifest.description || ""
171
+ }
172
+ };
173
+ const sessionStartHook = manifest.hooks?.sessionStart;
174
+ if (sessionStartHook?.handler?.type === "command") {
175
+ pluginJson.sessionStart = sessionStartHook.handler.command;
176
+ }
177
+ if (manifest.mcpServers && Object.keys(manifest.mcpServers).length > 0) {
178
+ pluginJson.mcpServers = "./mcp.json";
179
+ }
180
+ files.push({
181
+ path: MANIFEST_FILENAME,
182
+ content: JSON.stringify(pluginJson, null, 2)
183
+ });
184
+ const hooksJson = buildHooksJson(manifest.hooks || {});
185
+ if (Object.keys(hooksJson.hooks).length > 0) {
186
+ files.push({
187
+ path: "kimi-hooks.json",
188
+ content: JSON.stringify(hooksJson, null, 2)
189
+ });
190
+ }
191
+ if (manifest.skills && manifest.skills.length > 0) {
192
+ for (const skill of manifest.skills) {
193
+ const skillFile = compileSkillToMarkdown(skill);
194
+ files.push(skillFile);
195
+ }
196
+ }
197
+ files.push({
198
+ path: "KIMI_INSTALL.md",
199
+ content: generateInstallInstructions(manifest)
200
+ });
201
+ return {
202
+ files,
203
+ manifest: {},
204
+ warnings: [],
205
+ issues: []
206
+ };
207
+ }
208
+ function buildHooksJson(hooks) {
209
+ const hooksConfig = { hooks: {} };
210
+ for (const [hookName, hook] of Object.entries(hooks)) {
211
+ if (!hook) continue;
212
+ const universalName = hookName;
213
+ if (!SUPPORTED_HOOKS.includes(universalName)) {
214
+ continue;
215
+ }
216
+ if (universalName === "sessionStart") {
217
+ continue;
218
+ }
219
+ const kimiEventName = HOOK_NAME_MAP[universalName];
220
+ if (!kimiEventName) {
221
+ continue;
222
+ }
223
+ const command = extractCommand(hook, universalName);
224
+ if (!command) {
225
+ continue;
226
+ }
227
+ const statusMessage = buildStatusMessage(hook, universalName);
228
+ if (!hooksConfig.hooks[kimiEventName]) {
229
+ hooksConfig.hooks[kimiEventName] = [];
230
+ }
231
+ hooksConfig.hooks[kimiEventName].push({
232
+ matcher: hook.matcher || "*",
233
+ hooks: [
234
+ {
235
+ type: "command",
236
+ command,
237
+ statusMessage
238
+ }
239
+ ]
240
+ });
241
+ }
242
+ return hooksConfig;
243
+ }
244
+ function extractCommand(hook, hookName) {
245
+ if (!hook.handler) {
246
+ return null;
247
+ }
248
+ if (hook.handler.type === "command") {
249
+ return hook.handler.command || null;
250
+ }
251
+ if (hook.handler.type === "inline") {
252
+ return `node ./hooks/${hookName}.js`;
253
+ }
254
+ return null;
255
+ }
256
+ function buildStatusMessage(hook, universalName) {
257
+ if (hook.handler.type === "command" && hook.handler.statusMessage) {
258
+ return hook.handler.statusMessage;
259
+ }
260
+ const defaultMessages = {
261
+ preToolUse: "Running pre-tool check",
262
+ userPromptSubmit: "Processing user prompt",
263
+ sessionStart: "Initializing plugin session",
264
+ notification: "Handling notification",
265
+ permissionRequest: "Requesting permission",
266
+ sessionEnd: "Cleaning up session",
267
+ userPromptExpansion: "Expanding prompt context",
268
+ postToolUse: "Processing tool result",
269
+ postToolUseFailure: "Handling tool failure",
270
+ permissionDenied: "Processing permission denial",
271
+ subagentStart: "Subagent starting",
272
+ subagentStop: "Subagent stopping",
273
+ preCompact: "Pre-compacting session",
274
+ postCompact: "Post-compacting session",
275
+ stop: "Stopping",
276
+ stopFailure: "Handling stop failure",
277
+ fileChanged: "Processing file change",
278
+ cwdChanged: "Processing directory change",
279
+ setup: "Running setup"
280
+ };
281
+ return defaultMessages[universalName];
282
+ }
283
+ function compileSkillToMarkdown(skill) {
284
+ const frontmatter = {
285
+ name: skill.name,
286
+ description: skill.description
287
+ };
288
+ const frontmatterYaml = Object.entries(frontmatter).map(([key, value]) => {
289
+ if (Array.isArray(value)) {
290
+ return `${key}:
291
+ ${value.map((v) => ` - ${v}`).join("\n")}`;
292
+ }
293
+ return `${key}: ${value}`;
294
+ }).join("\n");
295
+ const body = skill.content || skill.description || "";
296
+ const content = `---
297
+ ${frontmatterYaml}
298
+ ---
299
+
300
+ ${body}
301
+ `;
302
+ const safeName = skill.name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
303
+ return {
304
+ path: `skills/SKILL__${safeName}.md`,
305
+ content
306
+ };
307
+ }
308
+ function generateInstallInstructions(manifest) {
309
+ const displayName = manifest.displayName || manifest.name;
310
+ return `# Installing ${displayName} for Kimi
311
+
312
+ > Generated by AgentPlugins \u2014 Kimi Platform Adapter
313
+
314
+ ## Quick Install
315
+
316
+ In any Kimi chat, run:
317
+
318
+ \`\`\`
319
+ /plugins install <github-url|local-path>
320
+ \`\`\`
321
+
322
+ Replace \`<github-url|local-path>\` with the repository URL or local directory
323
+ path containing this plugin.
324
+
325
+ ## Post-Install
326
+
327
+ Kimi plugins are **user-level** \u2014 they apply to all your sessions, not just the
328
+ current project.
329
+
330
+ After installing (or updating) this plugin, start a **new session** with:
331
+
332
+ \`\`\`
333
+ /new
334
+ \`\`\`
335
+
336
+ Plugin changes do **not** take effect in existing sessions.
337
+
338
+ ## Important Notes
339
+
340
+ - **Fail-open hooks**: Kimi hooks are designed to fail open. If a hook process
341
+ crashes or times out, Kimi continues execution. Do not rely on hooks as a
342
+ sole security mechanism.
343
+
344
+ - **Trust badges**: Kimi shows trust indicators for plugins installed from
345
+ GitHub. Install only plugins from sources you trust.
346
+
347
+ - **No project scope**: Kimi does not support project-level plugin scoping.
348
+ All plugins are installed at the user level.
349
+
350
+ ## Supported Features
351
+
352
+ This plugin uses the following Kimi features:
353
+
354
+ ${manifest.hooks && Object.keys(manifest.hooks).length > 0 ? `**Hooks**: ${Object.entries(manifest.hooks).filter(([name]) => SUPPORTED_HOOKS.includes(name)).map(([name]) => HOOK_NAME_MAP[name] || name).join(", ")}` : "**Hooks**: (none)"}
355
+
356
+ ${manifest.skills && manifest.skills.length > 0 ? `**Skills**: ${manifest.skills.map((s) => s.name).join(", ")}` : "**Skills**: (none)"}
357
+
358
+ ## Troubleshooting
359
+
360
+ | Problem | Solution |
361
+ |---------|----------|
362
+ | Plugin not active | Run \`/new\` to start a fresh session |
363
+ | Hook not firing | Check that the command in \`kimi-hooks.json\` is executable |
364
+ | Skill not recognized | Verify \`kimi.plugin.json\` has correct \`skills\` path |
365
+ | Changes not applied | Remember: **every change requires \`/new\`** |
366
+ `;
367
+ }
368
+ var KimiAdapter = class {
369
+ constructor() {
370
+ /** @inheritDoc */
371
+ this.name = PLATFORM_NAME;
372
+ /** @inheritDoc */
373
+ this.displayName = PLATFORM_DISPLAY_NAME;
374
+ /** @inheritDoc */
375
+ this.supportedHooks = SUPPORTED_HOOKS;
376
+ /** @inheritDoc */
377
+ this.supportedHandlers = SUPPORTED_HANDLERS;
378
+ /** @inheritDoc */
379
+ this.manifestPath = MANIFEST_FILENAME;
380
+ /** @inheritDoc */
381
+ this.manifestFormat = MANIFEST_FORMAT;
382
+ }
383
+ /**
384
+ * Validates a universal plugin manifest for Kimi compatibility.
385
+ *
386
+ * @param manifest — The plugin manifest to validate.
387
+ * @returns Array of validation issues (empty if fully valid).
388
+ */
389
+ validate(manifest) {
390
+ return validateForKimi(manifest);
391
+ }
392
+ /**
393
+ * Compiles a universal plugin manifest into Kimi-native artifacts.
394
+ *
395
+ * @param manifest — The plugin manifest to compile.
396
+ * @returns AdapterOutput containing all files to write.
397
+ */
398
+ compile(manifest) {
399
+ return compileForKimi(manifest);
400
+ }
401
+ };
402
+ var kimiAdapter = new KimiAdapter();
403
+ function createKimiAdapter() {
404
+ return new KimiAdapter();
405
+ }
406
+ var index_default = KimiAdapter;
407
+ export {
408
+ KimiAdapter,
409
+ createKimiAdapter,
410
+ index_default as default,
411
+ kimiAdapter
412
+ };
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@agentplugins/adapter-kimi",
3
+ "version": "0.1.0",
4
+ "description": "AgentPlugins platform adapter for Kimi (Moonshot AI)",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.mjs",
10
+ "require": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "scripts": {
22
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
23
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
24
+ "lint": "eslint src/**/*.ts",
25
+ "typecheck": "tsc --noEmit"
26
+ },
27
+ "dependencies": {
28
+ "@agentplugins/core": "workspace:*"
29
+ },
30
+ "devDependencies": {
31
+ "tsup": "^8.0.0",
32
+ "typescript": "^5.3.0"
33
+ },
34
+ "peerDependencies": {
35
+ "@agentplugins/core": "^0.1.0"
36
+ },
37
+ "keywords": [
38
+ "agentplugins",
39
+ "kimi",
40
+ "moonshot",
41
+ "plugin",
42
+ "adapter"
43
+ ],
44
+ "license": "MIT",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/espetro/agentplugins.git",
48
+ "directory": "packages/adapter-kimi"
49
+ }
50
+ }