@tickernelz/paperclip-pro-adapter-kimi-local 2026.925.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.
Files changed (86) hide show
  1. package/LICENSE +22 -0
  2. package/dist/cli/format-event.d.ts +2 -0
  3. package/dist/cli/format-event.d.ts.map +1 -0
  4. package/dist/cli/format-event.js +95 -0
  5. package/dist/cli/format-event.js.map +1 -0
  6. package/dist/cli/index.d.ts +2 -0
  7. package/dist/cli/index.d.ts.map +1 -0
  8. package/dist/cli/index.js +2 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/index.d.ts +30 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +82 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/server/acp.d.ts +19 -0
  15. package/dist/server/acp.d.ts.map +1 -0
  16. package/dist/server/acp.js +316 -0
  17. package/dist/server/acp.js.map +1 -0
  18. package/dist/server/acp.test.d.ts +2 -0
  19. package/dist/server/acp.test.d.ts.map +1 -0
  20. package/dist/server/acp.test.js +57 -0
  21. package/dist/server/acp.test.js.map +1 -0
  22. package/dist/server/engine-availability.test.d.ts +2 -0
  23. package/dist/server/engine-availability.test.d.ts.map +1 -0
  24. package/dist/server/engine-availability.test.js +41 -0
  25. package/dist/server/engine-availability.test.js.map +1 -0
  26. package/dist/server/execute.acp-failure.test.d.ts +2 -0
  27. package/dist/server/execute.acp-failure.test.d.ts.map +1 -0
  28. package/dist/server/execute.acp-failure.test.js +22 -0
  29. package/dist/server/execute.acp-failure.test.js.map +1 -0
  30. package/dist/server/execute.d.ts +3 -0
  31. package/dist/server/execute.d.ts.map +1 -0
  32. package/dist/server/execute.js +630 -0
  33. package/dist/server/execute.js.map +1 -0
  34. package/dist/server/execute.test.d.ts +2 -0
  35. package/dist/server/execute.test.d.ts.map +1 -0
  36. package/dist/server/execute.test.js +354 -0
  37. package/dist/server/execute.test.js.map +1 -0
  38. package/dist/server/index.d.ts +8 -0
  39. package/dist/server/index.d.ts.map +1 -0
  40. package/dist/server/index.js +66 -0
  41. package/dist/server/index.js.map +1 -0
  42. package/dist/server/parse.d.ts +66 -0
  43. package/dist/server/parse.d.ts.map +1 -0
  44. package/dist/server/parse.js +194 -0
  45. package/dist/server/parse.js.map +1 -0
  46. package/dist/server/parse.test.d.ts +2 -0
  47. package/dist/server/parse.test.d.ts.map +1 -0
  48. package/dist/server/parse.test.js +155 -0
  49. package/dist/server/parse.test.js.map +1 -0
  50. package/dist/server/skills.d.ts +4 -0
  51. package/dist/server/skills.d.ts.map +1 -0
  52. package/dist/server/skills.js +73 -0
  53. package/dist/server/skills.js.map +1 -0
  54. package/dist/server/test.d.ts +3 -0
  55. package/dist/server/test.d.ts.map +1 -0
  56. package/dist/server/test.js +306 -0
  57. package/dist/server/test.js.map +1 -0
  58. package/dist/server/test.test.d.ts +2 -0
  59. package/dist/server/test.test.d.ts.map +1 -0
  60. package/dist/server/test.test.js +126 -0
  61. package/dist/server/test.test.js.map +1 -0
  62. package/dist/server/utils.d.ts +2 -0
  63. package/dist/server/utils.d.ts.map +1 -0
  64. package/dist/server/utils.js +7 -0
  65. package/dist/server/utils.js.map +1 -0
  66. package/dist/ui/build-config.d.ts +3 -0
  67. package/dist/ui/build-config.d.ts.map +1 -0
  68. package/dist/ui/build-config.js +79 -0
  69. package/dist/ui/build-config.js.map +1 -0
  70. package/dist/ui/build-config.test.d.ts +2 -0
  71. package/dist/ui/build-config.test.d.ts.map +1 -0
  72. package/dist/ui/build-config.test.js +73 -0
  73. package/dist/ui/build-config.test.js.map +1 -0
  74. package/dist/ui/index.d.ts +3 -0
  75. package/dist/ui/index.d.ts.map +1 -0
  76. package/dist/ui/index.js +3 -0
  77. package/dist/ui/index.js.map +1 -0
  78. package/dist/ui/parse-stdout.d.ts +9 -0
  79. package/dist/ui/parse-stdout.d.ts.map +1 -0
  80. package/dist/ui/parse-stdout.js +110 -0
  81. package/dist/ui/parse-stdout.js.map +1 -0
  82. package/dist/ui/parse-stdout.test.d.ts +2 -0
  83. package/dist/ui/parse-stdout.test.d.ts.map +1 -0
  84. package/dist/ui/parse-stdout.test.js +84 -0
  85. package/dist/ui/parse-stdout.test.js.map +1 -0
  86. package/package.json +57 -0
@@ -0,0 +1,194 @@
1
+ import { asString, parseJson, parseObject } from "@tickernelz/paperclip-pro-adapter-utils/server-utils";
2
+ /**
3
+ * Kimi tool_call `function.arguments` is a JSON-encoded string. Parse it when
4
+ * possible so downstream consumers see structured input; fall back to the raw
5
+ * string when it is not valid JSON.
6
+ */
7
+ function parseToolCallArguments(value) {
8
+ if (typeof value !== "string")
9
+ return value ?? {};
10
+ const trimmed = value.trim();
11
+ if (!trimmed)
12
+ return {};
13
+ try {
14
+ return JSON.parse(trimmed);
15
+ }
16
+ catch {
17
+ return value;
18
+ }
19
+ }
20
+ function errorText(value) {
21
+ if (typeof value === "string")
22
+ return value;
23
+ const rec = parseObject(value);
24
+ const message = asString(rec.message, "").trim() ||
25
+ asString(rec.error, "").trim() ||
26
+ asString(rec.detail, "").trim() ||
27
+ asString(rec.code, "").trim();
28
+ if (message)
29
+ return message;
30
+ try {
31
+ return JSON.stringify(rec);
32
+ }
33
+ catch {
34
+ return "";
35
+ }
36
+ }
37
+ /**
38
+ * Build the run summary that Paperclip may auto-post as an issue comment.
39
+ *
40
+ * Kimi emits many intermediate assistant content lines during a multi-step
41
+ * agent loop ("Let me check…", tool plans, etc.). Joining all of them produced
42
+ * 50k+ character issue dumps. Prefer the last non-empty assistant content —
43
+ * typically the final board-facing wrap-up after the last tool turn.
44
+ */
45
+ export function buildKimiRunSummary(assistantContents) {
46
+ for (let i = assistantContents.length - 1; i >= 0; i -= 1) {
47
+ const text = (assistantContents[i] ?? "").trim();
48
+ if (text)
49
+ return text;
50
+ }
51
+ return "";
52
+ }
53
+ /**
54
+ * Parse `kimi -p ... --output-format stream-json` stdout.
55
+ *
56
+ * Verified event shapes (kimi 0.27.0):
57
+ * - {"role":"assistant","content":"..."}
58
+ * - {"role":"assistant","tool_calls":[{"type":"function","id":"...","function":{"name":"...","arguments":"{...}"}}]}
59
+ * - {"role":"tool","tool_call_id":"...","content":"..."}
60
+ * - {"role":"meta","type":"session.resume_hint","session_id":"...","command":"kimi -r ...","content":"..."}
61
+ */
62
+ export function parseKimiJsonl(stdout) {
63
+ let sessionId = null;
64
+ let errorMessage = null;
65
+ const textParts = [];
66
+ const toolCalls = [];
67
+ const toolResults = [];
68
+ for (const rawLine of stdout.split(/\r?\n/)) {
69
+ const line = rawLine.trim();
70
+ if (!line)
71
+ continue;
72
+ const event = parseJson(line);
73
+ if (!event)
74
+ continue;
75
+ const role = asString(event.role, "").trim().toLowerCase();
76
+ if (role === "assistant") {
77
+ const content = asString(event.content, "").trim();
78
+ if (content)
79
+ textParts.push(content);
80
+ const calls = Array.isArray(event.tool_calls) ? event.tool_calls : [];
81
+ for (const callRaw of calls) {
82
+ const call = parseObject(callRaw);
83
+ const fn = parseObject(call.function);
84
+ const name = asString(fn.name, asString(call.name, "")).trim();
85
+ if (!name)
86
+ continue;
87
+ toolCalls.push({
88
+ id: asString(call.id, "").trim() || null,
89
+ name,
90
+ arguments: parseToolCallArguments(fn.arguments ?? call.arguments),
91
+ });
92
+ }
93
+ continue;
94
+ }
95
+ if (role === "tool") {
96
+ toolResults.push({
97
+ toolCallId: asString(event.tool_call_id, "").trim() || null,
98
+ content: asString(event.content, ""),
99
+ });
100
+ continue;
101
+ }
102
+ if (role === "meta") {
103
+ const type = asString(event.type, "").trim();
104
+ if (type === "session.resume_hint") {
105
+ sessionId = asString(event.session_id, "").trim() || sessionId;
106
+ }
107
+ continue;
108
+ }
109
+ // Defensive: kimi has no dedicated error event in the verified schema, but
110
+ // tolerate {"role":"error"} / {"type":"error"} lines if they ever appear.
111
+ const type = asString(event.type, "").trim().toLowerCase();
112
+ if (role === "error" || type === "error") {
113
+ const text = errorText(event.error ?? event.message ?? event.content ?? event.detail).trim();
114
+ if (text)
115
+ errorMessage = text;
116
+ }
117
+ }
118
+ return {
119
+ sessionId,
120
+ summary: buildKimiRunSummary(textParts),
121
+ toolCalls,
122
+ toolResults,
123
+ errorMessage,
124
+ };
125
+ }
126
+ /**
127
+ * Map a single `kimi -p ... --output-format stream-json` line to live runtime
128
+ * events for `onEvent`, which drive the issue-thread activity indicator
129
+ * (`currentToolName` / `lastAssistantSnippet` / `lastEventAt`).
130
+ *
131
+ * Kimi emits complete messages in bursts with no token-level streaming, so
132
+ * without this the issue thread never sees a tool name or assistant snippet and
133
+ * sits on a stale "no output for N s" line while the model thinks. Tool results
134
+ * are intentionally omitted so the last meaningful "Using X" / assistant snippet
135
+ * is not overwritten by a generic label; the raw run-log stream keeps the
136
+ * activity timer fresh across tool execution.
137
+ */
138
+ export function extractKimiRuntimeEvents(line) {
139
+ const event = parseJson(line);
140
+ if (!event)
141
+ return [];
142
+ const role = asString(event.role, "").trim().toLowerCase();
143
+ if (role !== "assistant")
144
+ return [];
145
+ const events = [];
146
+ const content = asString(event.content, "").trim();
147
+ if (content) {
148
+ events.push({ eventType: "assistant", message: content, payload: { content } });
149
+ }
150
+ const calls = Array.isArray(event.tool_calls) ? event.tool_calls : [];
151
+ for (const callRaw of calls) {
152
+ const call = parseObject(callRaw);
153
+ const fn = parseObject(call.function);
154
+ const name = asString(fn.name, asString(call.name, "")).trim();
155
+ if (name) {
156
+ events.push({ eventType: "tool_call", payload: { toolName: name } });
157
+ }
158
+ }
159
+ return events;
160
+ }
161
+ function normalizedHaystack(stdout, stderr) {
162
+ return `${stdout}\n${stderr}`
163
+ .split(/\r?\n/)
164
+ .map((line) => line.trim())
165
+ .filter(Boolean)
166
+ .join("\n");
167
+ }
168
+ export function isKimiSessionUnrecoverableError(stdout, stderr) {
169
+ return /unknown\s+session|session(?:\s+.*)?\s+not\s+found|resume\s+.*\s+not\s+found|cannot\s+resume|failed\s+to\s+resume|invalid\s+session/i.test(normalizedHaystack(stdout, stderr));
170
+ }
171
+ export function isKimiTransientNetworkError(stdout, stderr) {
172
+ return /ENOTFOUND|EAI_AGAIN|ECONNRESET|ECONNREFUSED|ETIMEDOUT|fetch\s+failed|socket\s+hang\s+up/i.test(normalizedHaystack(stdout, stderr));
173
+ }
174
+ export function describeKimiFailure(input) {
175
+ const detail = (typeof input.errorMessage === "string" ? input.errorMessage.trim() : "") ||
176
+ (input.stderr ?? "")
177
+ .split(/\r?\n/)
178
+ .map((line) => line.trim())
179
+ .find(Boolean) ||
180
+ "";
181
+ if (!detail)
182
+ return null;
183
+ const clean = detail.replace(/\s+/g, " ").trim();
184
+ const max = 240;
185
+ return `Kimi run failed: ${clean.length > max ? `${clean.slice(0, max - 1)}…` : clean}`;
186
+ }
187
+ const KIMI_AUTH_REQUIRED_RE = /(?:\bkimi\s+login\b|\blogin\s+required\b|not\s+(?:logged\s+in|authenticated)|\b401\b|unauthorized|device\s+code|authentication\s+(?:required|failed)|invalid\s+api[_ ]?key)/i;
188
+ export function detectKimiAuthRequired(input) {
189
+ const requiresAuth = normalizedHaystack(input.stdout, input.stderr)
190
+ .split(/\r?\n/)
191
+ .some((line) => KIMI_AUTH_REQUIRED_RE.test(line));
192
+ return { requiresAuth };
193
+ }
194
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/server/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parse.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.test.d.ts","sourceRoot":"","sources":["../../src/server/parse.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,155 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildKimiRunSummary, detectKimiAuthRequired, extractKimiRuntimeEvents, isKimiSessionUnrecoverableError, isKimiTransientNetworkError, parseKimiJsonl, } from "./parse.js";
3
+ describe("extractKimiRuntimeEvents", () => {
4
+ it("maps assistant content to an assistant snippet event", () => {
5
+ const events = extractKimiRuntimeEvents('{"role":"assistant","content":"Here is my plan"}');
6
+ expect(events).toEqual([
7
+ { eventType: "assistant", message: "Here is my plan", payload: { content: "Here is my plan" } },
8
+ ]);
9
+ });
10
+ it("maps tool_calls to tool_call events carrying the tool name", () => {
11
+ const line = '{"role":"assistant","content":"running","tool_calls":[{"type":"function","id":"t1","function":{"name":"Bash","arguments":"{}"}}]}';
12
+ const events = extractKimiRuntimeEvents(line);
13
+ expect(events).toEqual([
14
+ { eventType: "assistant", message: "running", payload: { content: "running" } },
15
+ { eventType: "tool_call", payload: { toolName: "Bash" } },
16
+ ]);
17
+ });
18
+ it("emits nothing for tool results, meta, and malformed lines", () => {
19
+ expect(extractKimiRuntimeEvents('{"role":"tool","tool_call_id":"t1","content":"done"}')).toEqual([]);
20
+ expect(extractKimiRuntimeEvents('{"role":"meta","type":"session.resume_hint","session_id":"s"}')).toEqual([]);
21
+ expect(extractKimiRuntimeEvents("not json")).toEqual([]);
22
+ });
23
+ });
24
+ describe("parseKimiJsonl", () => {
25
+ it("collects assistant text from content events", () => {
26
+ const stdout = [
27
+ '{"role":"assistant","content":"PAPERCLIP_ADAPTER_TEST_OK"}',
28
+ '{"role":"meta","type":"session.resume_hint","session_id":"session_769ddab9-0a25-4edd-99f4-cdfebdc90879","command":"kimi -r session_769ddab9-0a25-4edd-99f4-cdfebdc90879","content":"To resume this session: kimi -r session_769ddab9-0a25-4edd-99f4-cdfebdc90879"}',
29
+ ].join("\n");
30
+ const parsed = parseKimiJsonl(stdout);
31
+ expect(parsed.summary).toBe("PAPERCLIP_ADAPTER_TEST_OK");
32
+ expect(parsed.sessionId).toBe("session_769ddab9-0a25-4edd-99f4-cdfebdc90879");
33
+ expect(parsed.errorMessage).toBeNull();
34
+ });
35
+ it("parses tool calls with JSON-encoded arguments strings", () => {
36
+ const stdout = [
37
+ '{"role":"assistant","tool_calls":[{"type":"function","id":"tool_8c1OWyRBe68OMTbWY6NqnkMm","function":{"name":"Read","arguments":"{\\"path\\":\\"probe.txt\\"}"}}]}',
38
+ ].join("\n");
39
+ const parsed = parseKimiJsonl(stdout);
40
+ expect(parsed.toolCalls).toEqual([
41
+ { id: "tool_8c1OWyRBe68OMTbWY6NqnkMm", name: "Read", arguments: { path: "probe.txt" } },
42
+ ]);
43
+ expect(parsed.summary).toBe("");
44
+ });
45
+ it("keeps raw arguments when the string is not valid JSON", () => {
46
+ const stdout = [
47
+ '{"role":"assistant","tool_calls":[{"type":"function","id":"tool_1","function":{"name":"Bash","arguments":"not json"}}]}',
48
+ ].join("\n");
49
+ const parsed = parseKimiJsonl(stdout);
50
+ expect(parsed.toolCalls).toEqual([
51
+ { id: "tool_1", name: "Bash", arguments: "not json" },
52
+ ]);
53
+ });
54
+ it("collects tool results keyed by tool_call_id", () => {
55
+ const stdout = [
56
+ '{"role":"assistant","tool_calls":[{"type":"function","id":"tool_8c1OWyRBe68OMTbWY6NqnkMm","function":{"name":"Read","arguments":"{\\"path\\":\\"probe.txt\\"}"}}]}',
57
+ '{"role":"tool","tool_call_id":"tool_8c1OWyRBe68OMTbWY6NqnkMm","content":"1\\thello paperclip"}',
58
+ ].join("\n");
59
+ const parsed = parseKimiJsonl(stdout);
60
+ expect(parsed.toolResults).toEqual([
61
+ { toolCallId: "tool_8c1OWyRBe68OMTbWY6NqnkMm", content: "1\thello paperclip" },
62
+ ]);
63
+ });
64
+ it("captures the session id from the trailing meta resume hint", () => {
65
+ const stdout = [
66
+ '{"role":"assistant","content":"done"}',
67
+ '{"role":"meta","type":"session.resume_hint","session_id":"session_abc","command":"kimi -r session_abc","content":"To resume this session: kimi -r session_abc"}',
68
+ ].join("\n");
69
+ expect(parseKimiJsonl(stdout).sessionId).toBe("session_abc");
70
+ });
71
+ it("uses only the last assistant content as the run summary", () => {
72
+ // Intermediate "thinking out loud" lines must not be auto-posted as issue comments.
73
+ const stdout = [
74
+ '{"role":"assistant","content":"Let me get oriented and check the PRs…"}',
75
+ '{"role":"assistant","tool_calls":[{"type":"function","id":"t1","function":{"name":"Bash","arguments":"{}"}}]}',
76
+ '{"role":"tool","tool_call_id":"t1","content":"ok"}',
77
+ '{"role":"assistant","content":"## Update\\n\\n- Merged PR #25\\n- Burn-in continues"}',
78
+ ].join("\n");
79
+ expect(parseKimiJsonl(stdout).summary).toBe("## Update\n\n- Merged PR #25\n- Burn-in continues");
80
+ });
81
+ it("buildKimiRunSummary picks the last non-empty message", () => {
82
+ expect(buildKimiRunSummary(["first", "second", ""])).toBe("second");
83
+ expect(buildKimiRunSummary([])).toBe("");
84
+ });
85
+ it("skips malformed lines without failing the parse", () => {
86
+ const stdout = [
87
+ "not json at all",
88
+ '{"role":"assistant","content":"visible"}',
89
+ "{broken json",
90
+ "",
91
+ ].join("\n");
92
+ const parsed = parseKimiJsonl(stdout);
93
+ expect(parsed.summary).toBe("visible");
94
+ expect(parsed.sessionId).toBeNull();
95
+ });
96
+ it("ignores meta events without a session id", () => {
97
+ const stdout = '{"role":"meta","type":"some.other_meta","content":"noise"}';
98
+ expect(parseKimiJsonl(stdout).sessionId).toBeNull();
99
+ });
100
+ });
101
+ describe("detectKimiAuthRequired", () => {
102
+ it("flags device-flow login hints", () => {
103
+ const result = detectKimiAuthRequired({
104
+ stdout: "",
105
+ stderr: "Not authenticated. Run `kimi login` to authenticate with a device code.",
106
+ });
107
+ expect(result.requiresAuth).toBe(true);
108
+ });
109
+ it("flags 401 unauthorized responses", () => {
110
+ const result = detectKimiAuthRequired({
111
+ stdout: "",
112
+ stderr: "Error: 401 Unauthorized",
113
+ });
114
+ expect(result.requiresAuth).toBe(true);
115
+ });
116
+ it("does not flag ordinary output", () => {
117
+ const result = detectKimiAuthRequired({
118
+ stdout: '{"role":"assistant","content":"hello"}',
119
+ stderr: "",
120
+ });
121
+ expect(result.requiresAuth).toBe(false);
122
+ });
123
+ });
124
+ describe("isKimiTransientNetworkError", () => {
125
+ it("matches DNS failures", () => {
126
+ expect(isKimiTransientNetworkError("", "Error: getaddrinfo ENOTFOUND api.moonshot.cn")).toBe(true);
127
+ });
128
+ it("matches EAI_AGAIN", () => {
129
+ expect(isKimiTransientNetworkError("", "getaddrinfo EAI_AGAIN api.moonshot.cn")).toBe(true);
130
+ });
131
+ it("matches fetch failed", () => {
132
+ expect(isKimiTransientNetworkError("", "TypeError: fetch failed")).toBe(true);
133
+ });
134
+ it("does not match unrelated stderr", () => {
135
+ expect(isKimiTransientNetworkError("", "Some other error")).toBe(false);
136
+ });
137
+ });
138
+ describe("isKimiSessionUnrecoverableError", () => {
139
+ it("matches unknown session", () => {
140
+ expect(isKimiSessionUnrecoverableError("", "Error: unknown session 'session_abc'")).toBe(true);
141
+ });
142
+ it("matches session not found", () => {
143
+ expect(isKimiSessionUnrecoverableError("", "session session_abc not found on disk")).toBe(true);
144
+ });
145
+ it("matches failed to resume", () => {
146
+ expect(isKimiSessionUnrecoverableError("", "failed to resume session session_abc")).toBe(true);
147
+ });
148
+ it("does not match unrelated stderr", () => {
149
+ expect(isKimiSessionUnrecoverableError("", "Some other error")).toBe(false);
150
+ });
151
+ it("does not match transient network errors (those go to isKimiTransientNetworkError)", () => {
152
+ expect(isKimiSessionUnrecoverableError("", "Error: getaddrinfo ENOTFOUND api.moonshot.cn")).toBe(false);
153
+ });
154
+ });
155
+ //# sourceMappingURL=parse.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.test.js","sourceRoot":"","sources":["../../src/server/parse.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AdapterSkillContext, AdapterSkillSnapshot } from "@tickernelz/paperclip-pro-adapter-utils";
2
+ export declare function listKimiSkills(ctx: AdapterSkillContext): Promise<AdapterSkillSnapshot>;
3
+ export declare function syncKimiSkills(ctx: AdapterSkillContext, desiredSkills: string[]): Promise<AdapterSkillSnapshot>;
4
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/server/skills.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,yCAAyC,CAAC;AAiDjD,wBAAsB,cAAc,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAE5F;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,mBAAmB,EACxB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,oBAAoB,CAAC,CA0B/B"}
@@ -0,0 +1,73 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { buildPersistentSkillSnapshot, ensurePaperclipSkillSymlink, readPaperclipRuntimeSkillEntries, readInstalledSkillTargets, resolveLegacyPaperclipDesiredSkillNames, } from "@tickernelz/paperclip-pro-adapter-utils/server-utils";
6
+ const __moduleDir = path.dirname(fileURLToPath(import.meta.url));
7
+ function asString(value) {
8
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
9
+ }
10
+ /**
11
+ * Resolve the Kimi skills home, honoring KIMI_CODE_HOME (adapter config env
12
+ * first, then the server process env) and falling back to ~/.kimi-code/skills.
13
+ */
14
+ function resolveKimiSkillsHome(config) {
15
+ const env = typeof config.env === "object" && config.env !== null && !Array.isArray(config.env)
16
+ ? config.env
17
+ : {};
18
+ const kimiCodeHome = asString(env.KIMI_CODE_HOME) ?? asString(process.env.KIMI_CODE_HOME);
19
+ if (kimiCodeHome)
20
+ return path.join(path.resolve(kimiCodeHome), "skills");
21
+ const configuredHome = asString(env.HOME);
22
+ const home = configuredHome ? path.resolve(configuredHome) : os.homedir();
23
+ return path.join(home, ".kimi-code", "skills");
24
+ }
25
+ async function buildKimiSkillSnapshot(config) {
26
+ const availableEntries = await readPaperclipRuntimeSkillEntries(config, __moduleDir);
27
+ const desiredSkills = resolveLegacyPaperclipDesiredSkillNames(config, availableEntries);
28
+ const skillsHome = resolveKimiSkillsHome(config);
29
+ const installed = await readInstalledSkillTargets(skillsHome);
30
+ return buildPersistentSkillSnapshot({
31
+ adapterType: "kimi_local",
32
+ availableEntries,
33
+ desiredSkills,
34
+ installed,
35
+ skillsHome,
36
+ locationLabel: "~/.kimi-code/skills",
37
+ missingDetail: "Configured but not currently linked into the Kimi skills home.",
38
+ externalConflictDetail: "Skill name is occupied by an external installation.",
39
+ externalDetail: "Installed outside Paperclip management.",
40
+ });
41
+ }
42
+ export async function listKimiSkills(ctx) {
43
+ return buildKimiSkillSnapshot(ctx.config);
44
+ }
45
+ export async function syncKimiSkills(ctx, desiredSkills) {
46
+ const availableEntries = await readPaperclipRuntimeSkillEntries(ctx.config, __moduleDir);
47
+ const desiredSet = new Set([
48
+ ...resolveLegacyPaperclipDesiredSkillNames({}, availableEntries),
49
+ ...desiredSkills,
50
+ ]);
51
+ const skillsHome = resolveKimiSkillsHome(ctx.config);
52
+ await fs.mkdir(skillsHome, { recursive: true });
53
+ const installed = await readInstalledSkillTargets(skillsHome);
54
+ const availableByRuntimeName = new Map(availableEntries.map((entry) => [entry.runtimeName, entry]));
55
+ for (const available of availableEntries) {
56
+ if (!desiredSet.has(available.key))
57
+ continue;
58
+ const target = path.join(skillsHome, available.runtimeName);
59
+ await ensurePaperclipSkillSymlink(available.source, target);
60
+ }
61
+ for (const [name, installedEntry] of installed.entries()) {
62
+ const available = availableByRuntimeName.get(name);
63
+ if (!available)
64
+ continue;
65
+ if (desiredSet.has(available.key))
66
+ continue;
67
+ if (installedEntry.targetPath !== available.source)
68
+ continue;
69
+ await fs.unlink(path.join(skillsHome, name)).catch(() => { });
70
+ }
71
+ return buildKimiSkillSnapshot(ctx.config);
72
+ }
73
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/server/skills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AdapterEnvironmentTestContext, AdapterEnvironmentTestResult } from "@tickernelz/paperclip-pro-adapter-utils";
2
+ export declare function testEnvironment(ctx: AdapterEnvironmentTestContext): Promise<AdapterEnvironmentTestResult>;
3
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/server/test.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,6BAA6B,EAC7B,4BAA4B,EAC7B,MAAM,yCAAyC,CAAC;AA+FjD,wBAAsB,eAAe,CACnC,GAAG,EAAE,6BAA6B,GACjC,OAAO,CAAC,4BAA4B,CAAC,CAgPvC"}