@jingyi0605/codingns 0.1.4 → 0.1.5

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 (209) hide show
  1. package/dist/public/assets/{TerminalPage-4ulgBhv9.js → TerminalPage-4p6EBqrR.js} +1 -1
  2. package/dist/public/assets/gemini-D4G1NbrE.png +0 -0
  3. package/dist/public/assets/index-CxeghocY.css +1 -0
  4. package/dist/public/assets/index-DXusStl0.js +108 -0
  5. package/dist/public/assets/kimi-BWNNSh7e.png +0 -0
  6. package/dist/public/index.html +2 -2
  7. package/dist/server/config/env.d.ts +6 -0
  8. package/dist/server/config/env.js +145 -0
  9. package/dist/server/config/env.js.map +1 -1
  10. package/dist/server/config/opencode-system-probe-helper-process.d.ts +24 -0
  11. package/dist/server/config/opencode-system-probe-helper-process.js +70 -5
  12. package/dist/server/config/opencode-system-probe-helper-process.js.map +1 -1
  13. package/dist/server/modules/butler/butler-action-context-service.d.ts +30 -0
  14. package/dist/server/modules/butler/butler-action-context-service.js +108 -0
  15. package/dist/server/modules/butler/butler-action-context-service.js.map +1 -0
  16. package/dist/server/modules/butler/butler-auth-service.d.ts +17 -0
  17. package/dist/server/modules/butler/butler-auth-service.js +91 -0
  18. package/dist/server/modules/butler/butler-auth-service.js.map +1 -0
  19. package/dist/server/modules/butler/butler-control-action-service.d.ts +65 -0
  20. package/dist/server/modules/butler/butler-control-action-service.js +296 -0
  21. package/dist/server/modules/butler/butler-control-action-service.js.map +1 -0
  22. package/dist/server/modules/butler/butler-control-session-service.d.ts +55 -0
  23. package/dist/server/modules/butler/butler-control-session-service.js +367 -0
  24. package/dist/server/modules/butler/butler-control-session-service.js.map +1 -0
  25. package/dist/server/modules/butler/butler-controller.d.ts +367 -0
  26. package/dist/server/modules/butler/butler-controller.js +475 -0
  27. package/dist/server/modules/butler/butler-controller.js.map +1 -0
  28. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.d.ts +34 -0
  29. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js +77 -0
  30. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js.map +1 -0
  31. package/dist/server/modules/butler/butler-follow-up-scheduler.d.ts +23 -0
  32. package/dist/server/modules/butler/butler-follow-up-scheduler.js +57 -0
  33. package/dist/server/modules/butler/butler-follow-up-scheduler.js.map +1 -0
  34. package/dist/server/modules/butler/butler-follow-up-service.d.ts +86 -0
  35. package/dist/server/modules/butler/butler-follow-up-service.js +948 -0
  36. package/dist/server/modules/butler/butler-follow-up-service.js.map +1 -0
  37. package/dist/server/modules/butler/butler-inbox-service.d.ts +35 -0
  38. package/dist/server/modules/butler/butler-inbox-service.js +136 -0
  39. package/dist/server/modules/butler/butler-inbox-service.js.map +1 -0
  40. package/dist/server/modules/butler/butler-notification-service.d.ts +12 -0
  41. package/dist/server/modules/butler/butler-notification-service.js +45 -0
  42. package/dist/server/modules/butler/butler-notification-service.js.map +1 -0
  43. package/dist/server/modules/butler/butler-profile-service.d.ts +26 -0
  44. package/dist/server/modules/butler/butler-profile-service.js +529 -0
  45. package/dist/server/modules/butler/butler-profile-service.js.map +1 -0
  46. package/dist/server/modules/butler/butler-project-service.d.ts +48 -0
  47. package/dist/server/modules/butler/butler-project-service.js +253 -0
  48. package/dist/server/modules/butler/butler-project-service.js.map +1 -0
  49. package/dist/server/modules/butler/butler-session-service.d.ts +79 -0
  50. package/dist/server/modules/butler/butler-session-service.js +503 -0
  51. package/dist/server/modules/butler/butler-session-service.js.map +1 -0
  52. package/dist/server/modules/butler/butler-session-summary-service.d.ts +55 -0
  53. package/dist/server/modules/butler/butler-session-summary-service.js +382 -0
  54. package/dist/server/modules/butler/butler-session-summary-service.js.map +1 -0
  55. package/dist/server/modules/butler/context-aggregator.d.ts +187 -0
  56. package/dist/server/modules/butler/context-aggregator.js +807 -0
  57. package/dist/server/modules/butler/context-aggregator.js.map +1 -0
  58. package/dist/server/modules/butler/instruction-adapter.d.ts +28 -0
  59. package/dist/server/modules/butler/instruction-adapter.js +101 -0
  60. package/dist/server/modules/butler/instruction-adapter.js.map +1 -0
  61. package/dist/server/modules/butler/patrol-execution-service.d.ts +47 -0
  62. package/dist/server/modules/butler/patrol-execution-service.js +347 -0
  63. package/dist/server/modules/butler/patrol-execution-service.js.map +1 -0
  64. package/dist/server/modules/butler/patrol-plan-service.d.ts +54 -0
  65. package/dist/server/modules/butler/patrol-plan-service.js +272 -0
  66. package/dist/server/modules/butler/patrol-plan-service.js.map +1 -0
  67. package/dist/server/modules/butler/patrol-run-service.d.ts +60 -0
  68. package/dist/server/modules/butler/patrol-run-service.js +185 -0
  69. package/dist/server/modules/butler/patrol-run-service.js.map +1 -0
  70. package/dist/server/modules/butler/patrol-scheduler.d.ts +36 -0
  71. package/dist/server/modules/butler/patrol-scheduler.js +99 -0
  72. package/dist/server/modules/butler/patrol-scheduler.js.map +1 -0
  73. package/dist/server/modules/butler/project-memory-service.d.ts +30 -0
  74. package/dist/server/modules/butler/project-memory-service.js +103 -0
  75. package/dist/server/modules/butler/project-memory-service.js.map +1 -0
  76. package/dist/server/modules/butler/provider-adapter-registry.d.ts +61 -0
  77. package/dist/server/modules/butler/provider-adapter-registry.js +430 -0
  78. package/dist/server/modules/butler/provider-adapter-registry.js.map +1 -0
  79. package/dist/server/modules/butler/session-summary-instruction-adapter.d.ts +28 -0
  80. package/dist/server/modules/butler/session-summary-instruction-adapter.js +79 -0
  81. package/dist/server/modules/butler/session-summary-instruction-adapter.js.map +1 -0
  82. package/dist/server/modules/butler/session-summary-scheduler.d.ts +23 -0
  83. package/dist/server/modules/butler/session-summary-scheduler.js +57 -0
  84. package/dist/server/modules/butler/session-summary-scheduler.js.map +1 -0
  85. package/dist/server/modules/butler/verification-run-service.d.ts +73 -0
  86. package/dist/server/modules/butler/verification-run-service.js +633 -0
  87. package/dist/server/modules/butler/verification-run-service.js.map +1 -0
  88. package/dist/server/modules/preferences/profile-service.js +8 -2
  89. package/dist/server/modules/preferences/profile-service.js.map +1 -1
  90. package/dist/server/modules/sessions/claude-runtime-helper-process.js +1 -1
  91. package/dist/server/modules/sessions/claude-runtime-helper-process.js.map +1 -1
  92. package/dist/server/modules/sessions/codex-app-server-helper-client.d.ts +5 -1
  93. package/dist/server/modules/sessions/codex-app-server-helper-client.js +10 -2
  94. package/dist/server/modules/sessions/codex-app-server-helper-client.js.map +1 -1
  95. package/dist/server/modules/sessions/session-controller.d.ts +3 -1
  96. package/dist/server/modules/sessions/session-controller.js +11 -2
  97. package/dist/server/modules/sessions/session-controller.js.map +1 -1
  98. package/dist/server/modules/sessions/session-history-service.d.ts +14 -1
  99. package/dist/server/modules/sessions/session-history-service.js +291 -30
  100. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  101. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +25 -2
  102. package/dist/server/modules/sessions/session-live-runtime-service.js +526 -158
  103. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  104. package/dist/server/modules/sessions/session-provider-error-mapper.js +28 -0
  105. package/dist/server/modules/sessions/session-provider-error-mapper.js.map +1 -1
  106. package/dist/server/modules/workbench/workbench-service.d.ts +7 -1
  107. package/dist/server/modules/workbench/workbench-service.js +31 -7
  108. package/dist/server/modules/workbench/workbench-service.js.map +1 -1
  109. package/dist/server/routes/butler.d.ts +3 -0
  110. package/dist/server/routes/butler.js +54 -0
  111. package/dist/server/routes/butler.js.map +1 -0
  112. package/dist/server/server/create-server.d.ts +61 -0
  113. package/dist/server/server/create-server.js +148 -4
  114. package/dist/server/server/create-server.js.map +1 -1
  115. package/dist/server/storage/repositories/butler-control-event-repository.d.ts +8 -0
  116. package/dist/server/storage/repositories/butler-control-event-repository.js +78 -0
  117. package/dist/server/storage/repositories/butler-control-event-repository.js.map +1 -0
  118. package/dist/server/storage/repositories/butler-control-session-repository.d.ts +11 -0
  119. package/dist/server/storage/repositories/butler-control-session-repository.js +86 -0
  120. package/dist/server/storage/repositories/butler-control-session-repository.js.map +1 -0
  121. package/dist/server/storage/repositories/butler-follow-up-task-repository.d.ts +16 -0
  122. package/dist/server/storage/repositories/butler-follow-up-task-repository.js +252 -0
  123. package/dist/server/storage/repositories/butler-follow-up-task-repository.js.map +1 -0
  124. package/dist/server/storage/repositories/butler-inbox-item-repository.d.ts +15 -0
  125. package/dist/server/storage/repositories/butler-inbox-item-repository.js +111 -0
  126. package/dist/server/storage/repositories/butler-inbox-item-repository.js.map +1 -0
  127. package/dist/server/storage/repositories/butler-notification-archive-repository.d.ts +9 -0
  128. package/dist/server/storage/repositories/butler-notification-archive-repository.js +48 -0
  129. package/dist/server/storage/repositories/butler-notification-archive-repository.js.map +1 -0
  130. package/dist/server/storage/repositories/butler-profile-repository.d.ts +9 -0
  131. package/dist/server/storage/repositories/butler-profile-repository.js +86 -0
  132. package/dist/server/storage/repositories/butler-profile-repository.js.map +1 -0
  133. package/dist/server/storage/repositories/butler-project-repository.d.ts +14 -0
  134. package/dist/server/storage/repositories/butler-project-repository.js +140 -0
  135. package/dist/server/storage/repositories/butler-project-repository.js.map +1 -0
  136. package/dist/server/storage/repositories/butler-session-repository.d.ts +11 -0
  137. package/dist/server/storage/repositories/butler-session-repository.js +106 -0
  138. package/dist/server/storage/repositories/butler-session-repository.js.map +1 -0
  139. package/dist/server/storage/repositories/butler-session-summary-state-repository.d.ts +8 -0
  140. package/dist/server/storage/repositories/butler-session-summary-state-repository.js +62 -0
  141. package/dist/server/storage/repositories/butler-session-summary-state-repository.js.map +1 -0
  142. package/dist/server/storage/repositories/patrol-plan-repository.d.ts +27 -0
  143. package/dist/server/storage/repositories/patrol-plan-repository.js +119 -0
  144. package/dist/server/storage/repositories/patrol-plan-repository.js.map +1 -0
  145. package/dist/server/storage/repositories/patrol-run-repository.d.ts +28 -0
  146. package/dist/server/storage/repositories/patrol-run-repository.js +121 -0
  147. package/dist/server/storage/repositories/patrol-run-repository.js.map +1 -0
  148. package/dist/server/storage/repositories/project-memory-repository.d.ts +15 -0
  149. package/dist/server/storage/repositories/project-memory-repository.js +150 -0
  150. package/dist/server/storage/repositories/project-memory-repository.js.map +1 -0
  151. package/dist/server/storage/repositories/session-checkpoint-repository.d.ts +9 -0
  152. package/dist/server/storage/repositories/session-checkpoint-repository.js +72 -0
  153. package/dist/server/storage/repositories/session-checkpoint-repository.js.map +1 -0
  154. package/dist/server/storage/repositories/session-message-origin-repository.d.ts +10 -0
  155. package/dist/server/storage/repositories/session-message-origin-repository.js +93 -0
  156. package/dist/server/storage/repositories/session-message-origin-repository.js.map +1 -0
  157. package/dist/server/storage/repositories/verification-run-repository.d.ts +29 -0
  158. package/dist/server/storage/repositories/verification-run-repository.js +125 -0
  159. package/dist/server/storage/repositories/verification-run-repository.js.map +1 -0
  160. package/dist/server/storage/sqlite/client.js +39 -0
  161. package/dist/server/storage/sqlite/client.js.map +1 -1
  162. package/dist/server/storage/sqlite/schema.sql +324 -0
  163. package/dist/server/types/domain.d.ts +261 -1
  164. package/dist/server/ws/ws-server.d.ts +2 -1
  165. package/dist/server/ws/ws-server.js +2 -1
  166. package/dist/server/ws/ws-server.js.map +1 -1
  167. package/node_modules/@codingns/session-sync-core/dist/index.d.ts +4 -0
  168. package/node_modules/@codingns/session-sync-core/dist/index.js +4 -0
  169. package/node_modules/@codingns/session-sync-core/dist/index.js.map +1 -1
  170. package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.d.ts +18 -0
  171. package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.js +659 -0
  172. package/node_modules/@codingns/session-sync-core/dist/kimi-message-normalizer.js.map +1 -0
  173. package/node_modules/@codingns/session-sync-core/dist/kimi-shared.d.ts +11 -0
  174. package/node_modules/@codingns/session-sync-core/dist/kimi-shared.js +72 -0
  175. package/node_modules/@codingns/session-sync-core/dist/kimi-shared.js.map +1 -0
  176. package/node_modules/@codingns/session-sync-core/dist/patch-builder.d.ts +8 -0
  177. package/node_modules/@codingns/session-sync-core/dist/patch-builder.js +89 -0
  178. package/node_modules/@codingns/session-sync-core/dist/patch-builder.js.map +1 -1
  179. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +4 -1
  180. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
  181. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.d.ts +41 -0
  182. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +1086 -0
  183. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +1 -0
  184. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.d.ts +29 -0
  185. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js +578 -0
  186. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js.map +1 -0
  187. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +2 -1
  188. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
  189. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js +30 -2
  190. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js.map +1 -1
  191. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.d.ts +2 -0
  192. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js +43 -5
  193. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js.map +1 -1
  194. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +2 -0
  195. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +320 -69
  196. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
  197. package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.d.ts +21 -0
  198. package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.js +537 -0
  199. package/node_modules/@codingns/session-sync-core/dist/runtime/gemini-runtime.js.map +1 -0
  200. package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.d.ts +38 -0
  201. package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.js +911 -0
  202. package/node_modules/@codingns/session-sync-core/dist/runtime/kimi-runtime.js.map +1 -0
  203. package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.d.ts +6 -0
  204. package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.js +9 -0
  205. package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.js.map +1 -0
  206. package/node_modules/@codingns/session-sync-core/package.json +8 -0
  207. package/package.json +1 -1
  208. package/dist/public/assets/index-C5lu52cQ.css +0 -1
  209. package/dist/public/assets/index-WpdUo_Vs.js +0 -108
@@ -0,0 +1,911 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync, readdirSync, statSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { createInterface } from "node:readline";
5
+ import { buildKimiSessionRawStoreRef, findKimiWorkDirRecordByPath, readKimiWorkDirRecords } from "../kimi-shared.js";
6
+ import { extractTextBlocks, messageIdFromRawRef, nextTimestamp, safeDate } from "../providers/utils.js";
7
+ import { buildKimiMessageRawRef, extractKimiDisplayTextSegments, looksLikeKimiMessagePayload, normalizeKimiMessageRecord, readKimiFirstNonEmptyString, readKimiFirstPresentValue } from "../kimi-message-normalizer.js";
8
+ const INTERRUPT_KILL_TIMEOUT_MS = 1_500;
9
+ const READY_SIGNAL_TIMEOUT_MS = 700;
10
+ const KIMI_START_BINDING_RESOLVE_TIMEOUT_MS = 10_000;
11
+ const KIMI_START_BINDING_RESOLVE_POLL_MS = 100;
12
+ export class KimiRuntimeAdapter {
13
+ options;
14
+ providerId = "kimi";
15
+ commandPath;
16
+ baseArgs;
17
+ spawnFactory;
18
+ cliSyntax;
19
+ cliProbeTimeoutMs;
20
+ cliSyntaxPromise = null;
21
+ constructor(options) {
22
+ this.options = options;
23
+ this.commandPath = options.commandPath?.trim() || "kimi";
24
+ this.baseArgs = options.baseArgs ?? [];
25
+ this.spawnFactory = options.spawnFactory ?? spawn;
26
+ this.cliSyntax = options.cliSyntax ?? "auto";
27
+ this.cliProbeTimeoutMs = options.cliProbeTimeoutMs ?? 1_500;
28
+ }
29
+ async startSession(request, sink) {
30
+ const pendingBinding = buildPendingKimiBinding(request.sessionId);
31
+ const startBindingProbe = this.captureStartBindingProbe(request.workspacePath);
32
+ sink.updateSessionBinding(pendingBinding);
33
+ return this.launchWithFallback({
34
+ request,
35
+ sink,
36
+ mode: "start",
37
+ sessionId: pendingBinding.providerSessionId,
38
+ rawStoreRef: pendingBinding.rawStoreRef,
39
+ startBindingProbe
40
+ });
41
+ }
42
+ async continueSession(request, sink) {
43
+ const sessionId = request.providerSessionId?.trim();
44
+ if (!sessionId) {
45
+ throw new Error("PROVIDER_SESSION_ID_REQUIRED");
46
+ }
47
+ const rawStoreRef = request.rawStoreRef ?? buildKimiSessionRawStoreRef(sessionId);
48
+ sink.updateSessionBinding({
49
+ providerSessionId: sessionId,
50
+ rawStoreRef
51
+ });
52
+ return this.launchWithFallback({
53
+ request,
54
+ sink,
55
+ mode: "continue",
56
+ sessionId,
57
+ rawStoreRef,
58
+ startBindingProbe: null
59
+ });
60
+ }
61
+ async launchWithFallback(context) {
62
+ const cliSyntax = await this.resolveCliSyntax();
63
+ const commandAttempt = this.launchTransport(context, "command", cliSyntax);
64
+ try {
65
+ await commandAttempt.ready;
66
+ this.scheduleBindingResolution(context, commandAttempt);
67
+ return commandAttempt.launch;
68
+ }
69
+ catch (commandError) {
70
+ commandAttempt.launch.completed.catch(() => {
71
+ return;
72
+ });
73
+ const commandDetail = extractErrorDetail(await commandAttempt.launch.completed.then(() => null).catch((error) => error));
74
+ throw new Error(`KIMI_RUNTIME_FALLBACK_FAILED: wire=disabled; command=${commandDetail}; cause=${extractErrorDetail(commandError)}`);
75
+ }
76
+ }
77
+ launchTransport(context, transport, cliSyntax) {
78
+ const args = [
79
+ ...this.baseArgs,
80
+ ...buildKimiRuntimeArgs(transport, context.mode, context.sessionId, context.request, cliSyntax)
81
+ ];
82
+ const proc = this.spawnFactory(this.commandPath, args, {
83
+ cwd: context.request.workspacePath,
84
+ env: buildKimiSpawnEnv(),
85
+ shell: shouldSpawnViaShell(this.commandPath),
86
+ windowsHide: true,
87
+ stdio: ["pipe", "pipe", "pipe"]
88
+ });
89
+ let sequence = Math.max(0, context.request.sequenceBase ?? 0);
90
+ let lineNumber = 0;
91
+ let interrupted = false;
92
+ let settled = false;
93
+ let activeSessionId = context.sessionId;
94
+ let activeRawStoreRef = context.rawStoreRef;
95
+ let stderrBuffer = "";
96
+ let lineChain = Promise.resolve();
97
+ let stdinClosed = false;
98
+ let writeChain = Promise.resolve();
99
+ let sawStdoutEvent = false;
100
+ let readySettled = false;
101
+ let plainTextBuffer = [];
102
+ let plainTextStartLineNumber = 0;
103
+ const recentMessageSignatures = [];
104
+ let readyTimer = null;
105
+ let resolveReady = null;
106
+ let rejectReady = null;
107
+ const updateActiveBinding = (binding) => {
108
+ if (!binding.providerSessionId.trim()
109
+ || (binding.providerSessionId === activeSessionId
110
+ && binding.rawStoreRef === activeRawStoreRef)) {
111
+ return;
112
+ }
113
+ activeSessionId = binding.providerSessionId;
114
+ activeRawStoreRef = binding.rawStoreRef;
115
+ context.sink.updateSessionBinding(binding);
116
+ launch.providerSessionId = binding.providerSessionId;
117
+ launch.rawStoreRef = binding.rawStoreRef;
118
+ };
119
+ const enqueuePromptWrite = (options, closeAfterWrite = false) => {
120
+ writeChain = writeChain.then(() => this.writePromptPayload(proc, options, transport, closeAfterWrite));
121
+ return writeChain;
122
+ };
123
+ const canSubmitInRunInput = () => !interrupted &&
124
+ !settled &&
125
+ !proc.killed &&
126
+ !stdinClosed &&
127
+ !proc.stdin.destroyed &&
128
+ !proc.stdin.writableEnded &&
129
+ proc.stdin.writable;
130
+ const ready = new Promise((resolve, reject) => {
131
+ resolveReady = resolve;
132
+ rejectReady = (error) => reject(error);
133
+ });
134
+ const settleReady = (error) => {
135
+ if (readySettled) {
136
+ return;
137
+ }
138
+ readySettled = true;
139
+ if (readyTimer) {
140
+ clearTimeout(readyTimer);
141
+ }
142
+ if (error) {
143
+ rejectReady?.(error);
144
+ }
145
+ else {
146
+ resolveReady?.();
147
+ }
148
+ };
149
+ readyTimer = setTimeout(() => {
150
+ settleReady();
151
+ }, READY_SIGNAL_TIMEOUT_MS);
152
+ const completed = new Promise((resolve, reject) => {
153
+ const settle = (callback) => {
154
+ if (settled) {
155
+ return;
156
+ }
157
+ settled = true;
158
+ callback();
159
+ };
160
+ const onStructuredEvent = async (event) => {
161
+ if (event.providerSessionId?.trim() && event.providerSessionId !== activeSessionId) {
162
+ updateActiveBinding({
163
+ providerSessionId: event.providerSessionId,
164
+ rawStoreRef: event.rawStoreRef ?? buildKimiSessionRawStoreRef(event.providerSessionId)
165
+ });
166
+ }
167
+ await context.sink.emit({
168
+ ...event,
169
+ providerSessionId: activeSessionId,
170
+ rawStoreRef: activeRawStoreRef
171
+ });
172
+ };
173
+ const emitRuntimeEvent = async (event) => {
174
+ if (event.type === "message" && event.message) {
175
+ if (shouldSkipEquivalentRecentKimiRuntimeMessage(recentMessageSignatures, event.message)) {
176
+ return;
177
+ }
178
+ rememberKimiRuntimeMessage(recentMessageSignatures, event.message);
179
+ }
180
+ await onStructuredEvent(event);
181
+ };
182
+ const handleJsonPayload = async (payload) => {
183
+ const mapped = mapKimiWirePayload(payload, {
184
+ sessionId: activeSessionId,
185
+ rawStoreRef: activeRawStoreRef,
186
+ sequence,
187
+ lineNumber
188
+ });
189
+ if (mapped.providerSessionId && mapped.providerSessionId !== activeSessionId) {
190
+ updateActiveBinding({
191
+ providerSessionId: mapped.providerSessionId,
192
+ rawStoreRef: buildKimiSessionRawStoreRef(mapped.providerSessionId)
193
+ });
194
+ }
195
+ for (const event of mapped.events) {
196
+ if (event.type === "message" && event.message) {
197
+ sequence = event.message.sequence;
198
+ }
199
+ await emitRuntimeEvent(event);
200
+ }
201
+ };
202
+ const flushBufferedPlainText = async () => {
203
+ if (plainTextBuffer.length === 0) {
204
+ return;
205
+ }
206
+ const startLineNumber = plainTextStartLineNumber || lineNumber;
207
+ const contentBlocks = extractKimiDisplayTextSegments(plainTextBuffer.join("\n"));
208
+ plainTextBuffer = [];
209
+ plainTextStartLineNumber = 0;
210
+ for (const [contentIndex, content] of contentBlocks.entries()) {
211
+ const nextSequence = sequence + 1;
212
+ sequence = nextSequence;
213
+ const message = createTextMessage({
214
+ sessionId: activeSessionId,
215
+ rawStoreRef: activeRawStoreRef,
216
+ sequence: nextSequence,
217
+ lineNumber: startLineNumber,
218
+ role: "assistant",
219
+ kind: "text",
220
+ content,
221
+ timestamp: nextTimestamp(),
222
+ rawEventRef: buildKimiMessageRawRef(activeSessionId, "wire", startLineNumber, contentBlocks.length > 1 ? contentIndex : undefined)
223
+ });
224
+ await emitRuntimeEvent({
225
+ type: "message",
226
+ message,
227
+ status: "running",
228
+ detail: "wire line",
229
+ rawEventRef: message.rawRef
230
+ });
231
+ }
232
+ };
233
+ const handleStdoutLine = (line) => {
234
+ lineNumber += 1;
235
+ const trimmed = line.trim();
236
+ const payload = trimmed ? parseJsonObject(trimmed) : null;
237
+ if (payload) {
238
+ sawStdoutEvent = true;
239
+ settleReady();
240
+ return flushBufferedPlainText().then(() => handleJsonPayload(payload));
241
+ }
242
+ if (!trimmed) {
243
+ if (plainTextBuffer.length > 0) {
244
+ plainTextBuffer.push("");
245
+ }
246
+ return Promise.resolve();
247
+ }
248
+ sawStdoutEvent = true;
249
+ settleReady();
250
+ if (plainTextBuffer.length === 0) {
251
+ plainTextStartLineNumber = lineNumber;
252
+ }
253
+ plainTextBuffer.push(line);
254
+ if (trimmed.toLowerCase() === "turnend") {
255
+ return flushBufferedPlainText();
256
+ }
257
+ return Promise.resolve();
258
+ };
259
+ const stdoutReader = createInterface({ input: proc.stdout });
260
+ stdoutReader.on("line", (line) => {
261
+ lineChain = lineChain.then(() => handleStdoutLine(line));
262
+ });
263
+ proc.stderr.setEncoding("utf8");
264
+ proc.stderr.on("data", (chunk) => {
265
+ stderrBuffer = `${stderrBuffer}${chunk}`.trim();
266
+ });
267
+ proc.once("error", (error) => {
268
+ if (transport === "wire") {
269
+ settleReady(toWireUnavailableError(error));
270
+ }
271
+ else {
272
+ settleReady(error instanceof Error ? error : new Error("KIMI_RUNTIME_FAILED"));
273
+ }
274
+ settle(() => {
275
+ reject(error);
276
+ });
277
+ });
278
+ proc.once("close", (code, signal) => {
279
+ stdinClosed = true;
280
+ if (!sawStdoutEvent && !interrupted && code !== 0) {
281
+ if (transport === "wire") {
282
+ settleReady(toWireUnavailableError(new Error(stderrBuffer ||
283
+ `Kimi wire exited with code=${String(code ?? "null")} signal=${String(signal ?? "null")}`)));
284
+ }
285
+ else {
286
+ settleReady(new Error(stderrBuffer ||
287
+ `Kimi command exited with code=${String(code ?? "null")} signal=${String(signal ?? "null")}`));
288
+ }
289
+ }
290
+ else {
291
+ settleReady();
292
+ }
293
+ void lineChain
294
+ .then(async () => {
295
+ await flushBufferedPlainText();
296
+ if (interrupted) {
297
+ settle(() => {
298
+ resolve();
299
+ });
300
+ return;
301
+ }
302
+ if (code === 0) {
303
+ settle(() => {
304
+ resolve();
305
+ });
306
+ return;
307
+ }
308
+ const detail = stderrBuffer ||
309
+ `Kimi ${transport} exited with code=${String(code ?? "null")} signal=${String(signal ?? "null")}`;
310
+ settle(() => {
311
+ reject(new Error(detail));
312
+ });
313
+ })
314
+ .catch((error) => {
315
+ settle(() => {
316
+ reject(error instanceof Error ? error : new Error("KIMI_WIRE_RUNTIME_FAILED"));
317
+ });
318
+ });
319
+ });
320
+ enqueuePromptWrite(context.request.options, transport === "command").catch((error) => {
321
+ settle(() => {
322
+ reject(error);
323
+ });
324
+ });
325
+ });
326
+ const submitDuringRun = async (options) => {
327
+ if (transport === "command" || !canSubmitInRunInput()) {
328
+ throw new Error("IN_RUN_INPUT_NOT_SUPPORTED");
329
+ }
330
+ return enqueuePromptWrite(options).catch((error) => {
331
+ throw mapInRunSubmitError(error);
332
+ });
333
+ };
334
+ const launch = {
335
+ providerSessionId: context.sessionId,
336
+ rawStoreRef: context.rawStoreRef,
337
+ interrupt: async () => {
338
+ interrupted = true;
339
+ if (proc.killed) {
340
+ return;
341
+ }
342
+ proc.kill("SIGINT");
343
+ await new Promise((resolve) => {
344
+ const timeout = setTimeout(() => {
345
+ if (!proc.killed) {
346
+ proc.kill("SIGKILL");
347
+ }
348
+ resolve();
349
+ }, INTERRUPT_KILL_TIMEOUT_MS);
350
+ proc.once("close", () => {
351
+ clearTimeout(timeout);
352
+ resolve();
353
+ });
354
+ });
355
+ },
356
+ isAlive: () => !proc.killed,
357
+ submitDuringRun: transport === "command" ? undefined : submitDuringRun,
358
+ completed
359
+ };
360
+ return {
361
+ transport,
362
+ launch,
363
+ ready,
364
+ updateBinding: updateActiveBinding
365
+ };
366
+ }
367
+ scheduleBindingResolution(context, attempt) {
368
+ if (context.mode !== "start" || !isPendingKimiBinding(context.sessionId)) {
369
+ return;
370
+ }
371
+ void Promise.race([
372
+ this.resolveStartedSessionBinding(context.request.workspacePath, context.startBindingProbe),
373
+ attempt.launch.completed.then(() => null)
374
+ ])
375
+ .then(async (binding) => {
376
+ if (!binding) {
377
+ return;
378
+ }
379
+ attempt.updateBinding(binding);
380
+ await context.sink.emit({
381
+ type: "session_created",
382
+ status: "starting",
383
+ providerSessionId: binding.providerSessionId,
384
+ rawStoreRef: binding.rawStoreRef,
385
+ detail: "Kimi session binding resolved"
386
+ });
387
+ })
388
+ .catch(() => {
389
+ return;
390
+ });
391
+ }
392
+ async resolveCliSyntax() {
393
+ if (this.cliSyntax !== "auto") {
394
+ return this.cliSyntax;
395
+ }
396
+ if (!this.cliSyntaxPromise) {
397
+ // 先探测本地 CLI 的参数风格,避免新版/旧版参数互相打架。
398
+ this.cliSyntaxPromise = detectKimiCliSyntax({
399
+ commandPath: this.commandPath,
400
+ baseArgs: this.baseArgs,
401
+ spawnFactory: this.spawnFactory,
402
+ timeoutMs: this.cliProbeTimeoutMs
403
+ }).catch(() => "modern");
404
+ }
405
+ return this.cliSyntaxPromise;
406
+ }
407
+ async resolveStartedSessionBinding(workspacePath, startBindingProbe) {
408
+ const startedAtMs = Date.now();
409
+ const initialLastSessionId = startBindingProbe?.lastSessionId ?? null;
410
+ const workDirHash = startBindingProbe?.workDirHash ?? null;
411
+ while (Date.now() - startedAtMs < KIMI_START_BINDING_RESOLVE_TIMEOUT_MS) {
412
+ const workDirs = readKimiWorkDirRecords(this.options.homeDir);
413
+ const activeWorkDir = findKimiWorkDirRecordByPath(workDirs, workspacePath);
414
+ const candidateSessionId = this.findResolvedSessionIdFromWorkDir(activeWorkDir?.lastSessionId ?? null, initialLastSessionId)
415
+ ?? this.findLatestSessionIdForWorkspace(activeWorkDir?.hash ?? workDirHash, startedAtMs, initialLastSessionId);
416
+ if (candidateSessionId) {
417
+ return {
418
+ providerSessionId: candidateSessionId,
419
+ rawStoreRef: buildKimiSessionRawStoreRef(candidateSessionId)
420
+ };
421
+ }
422
+ await waitForKimiBindingResolvePoll();
423
+ }
424
+ return null;
425
+ }
426
+ captureStartBindingProbe(workspacePath) {
427
+ const workDirs = readKimiWorkDirRecords(this.options.homeDir);
428
+ const workDir = findKimiWorkDirRecordByPath(workDirs, workspacePath);
429
+ return {
430
+ workDirHash: workDir?.hash ?? null,
431
+ lastSessionId: workDir?.lastSessionId ?? null
432
+ };
433
+ }
434
+ findResolvedSessionIdFromWorkDir(candidateSessionId, initialLastSessionId) {
435
+ const normalizedCandidate = candidateSessionId?.trim();
436
+ if (!normalizedCandidate) {
437
+ return null;
438
+ }
439
+ if (initialLastSessionId && normalizedCandidate === initialLastSessionId) {
440
+ return null;
441
+ }
442
+ return normalizedCandidate;
443
+ }
444
+ findLatestSessionIdForWorkspace(workDirHash, startedAtMs, initialLastSessionId) {
445
+ if (!workDirHash?.trim()) {
446
+ return null;
447
+ }
448
+ const workspaceSessionsDir = join(this.options.homeDir, "sessions", workDirHash);
449
+ if (!existsSync(workspaceSessionsDir)) {
450
+ return null;
451
+ }
452
+ let bestCandidate = null;
453
+ const entries = readdirSync(workspaceSessionsDir, { withFileTypes: true });
454
+ for (const entry of entries) {
455
+ if (!entry.isDirectory()) {
456
+ continue;
457
+ }
458
+ if (initialLastSessionId && entry.name === initialLastSessionId) {
459
+ continue;
460
+ }
461
+ const sessionDir = join(workspaceSessionsDir, entry.name);
462
+ const mtimeMs = readKimiSessionDirectoryMtime(sessionDir);
463
+ if (mtimeMs < startedAtMs - 1_000) {
464
+ continue;
465
+ }
466
+ if (!bestCandidate || mtimeMs > bestCandidate.mtimeMs) {
467
+ bestCandidate = {
468
+ sessionId: entry.name,
469
+ mtimeMs
470
+ };
471
+ }
472
+ }
473
+ return bestCandidate?.sessionId ?? null;
474
+ }
475
+ async writePrompt(proc, request) {
476
+ return this.writePromptPayload(proc, request.options, "command");
477
+ }
478
+ async writePromptPayload(proc, options, transport, closeAfterWrite = false) {
479
+ const prompt = options.providerPrompt?.trim() || options.content.trim();
480
+ if (!prompt) {
481
+ if (transport === "command" && closeAfterWrite) {
482
+ await this.closeCommandInput(proc);
483
+ }
484
+ return;
485
+ }
486
+ const payload = transport === "command"
487
+ ? buildCommandInputPayloadFromOptions(prompt)
488
+ : buildPromptPayloadFromOptions(options, prompt);
489
+ await this.writeWirePayload(proc, payload);
490
+ if (transport === "command" && closeAfterWrite) {
491
+ await this.closeCommandInput(proc);
492
+ }
493
+ }
494
+ async writeWirePayload(proc, payload) {
495
+ await new Promise((resolve, reject) => {
496
+ proc.stdin.write(`${JSON.stringify(payload)}\n`, (error) => {
497
+ if (error) {
498
+ reject(error);
499
+ return;
500
+ }
501
+ resolve();
502
+ });
503
+ });
504
+ }
505
+ async closeCommandInput(proc) {
506
+ if (proc.stdin.destroyed || proc.stdin.writableEnded) {
507
+ return;
508
+ }
509
+ await new Promise((resolve, reject) => {
510
+ try {
511
+ proc.stdin.end();
512
+ resolve();
513
+ }
514
+ catch (error) {
515
+ reject(error);
516
+ }
517
+ });
518
+ }
519
+ }
520
+ function buildPromptPayloadFromOptions(options, prompt) {
521
+ return {
522
+ type: "prompt.submit",
523
+ content: prompt,
524
+ client_request_id: options.clientRequestId,
525
+ permission_mode: options.permissionMode,
526
+ model: options.model,
527
+ reasoning_level: options.reasoningLevel,
528
+ attachments: options.attachments.map((attachment) => ({
529
+ file_path: attachment.filePath,
530
+ file_name: attachment.fileName,
531
+ mime_type: attachment.mimeType,
532
+ file_size: attachment.fileSize
533
+ }))
534
+ };
535
+ }
536
+ function buildKimiRuntimeArgs(transport, mode, sessionId, request, cliSyntax) {
537
+ if (cliSyntax === "modern") {
538
+ return buildModernKimiRuntimeArgs(transport, mode, sessionId, request);
539
+ }
540
+ return buildLegacyKimiRuntimeArgs(transport, mode, sessionId, request);
541
+ }
542
+ function buildModernKimiRuntimeArgs(transport, mode, sessionId, request) {
543
+ if (transport === "wire") {
544
+ const args = ["--wire"];
545
+ if (mode === "continue") {
546
+ args.push("--session", sessionId);
547
+ }
548
+ args.push("--work-dir", request.workspacePath);
549
+ if (request.options.model) {
550
+ args.push("--model", request.options.model);
551
+ }
552
+ return args;
553
+ }
554
+ const args = ["--print", "--output-format", "stream-json", "--input-format", "stream-json"];
555
+ if (mode === "continue") {
556
+ args.push("--session", sessionId);
557
+ }
558
+ args.push("--work-dir", request.workspacePath);
559
+ if (request.options.model) {
560
+ args.push("--model", request.options.model);
561
+ }
562
+ return args;
563
+ }
564
+ function buildLegacyKimiRuntimeArgs(transport, mode, sessionId, request) {
565
+ if (transport === "wire") {
566
+ const args = ["wire", "--output-format", "stream-json"];
567
+ if (mode === "continue") {
568
+ args.push("--resume", sessionId);
569
+ }
570
+ else {
571
+ args.push("--new-session");
572
+ }
573
+ args.push("--cwd", request.workspacePath);
574
+ if (request.options.model) {
575
+ args.push("--model", request.options.model);
576
+ }
577
+ return args;
578
+ }
579
+ const args = ["--print", "--output-format", "stream-json", "--input-format", "stream-json"];
580
+ if (mode === "continue") {
581
+ args.push("--resume", sessionId);
582
+ }
583
+ args.push("--cwd", request.workspacePath);
584
+ if (request.options.model) {
585
+ args.push("--model", request.options.model);
586
+ }
587
+ return args;
588
+ }
589
+ function parseJsonObject(line) {
590
+ try {
591
+ const parsed = JSON.parse(line);
592
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
593
+ return null;
594
+ }
595
+ return parsed;
596
+ }
597
+ catch {
598
+ return null;
599
+ }
600
+ }
601
+ function mapKimiWirePayload(payload, context) {
602
+ const events = [];
603
+ const wireType = (readKimiFirstNonEmptyString(payload, [
604
+ ["type"],
605
+ ["event"],
606
+ ["kind"],
607
+ ["message", "type"],
608
+ ["message", "payload", "type"],
609
+ ["payload", "type"]
610
+ ]) ?? "").trim().toLowerCase();
611
+ const providerSessionId = readKimiFirstNonEmptyString(payload, [
612
+ ["sessionId"],
613
+ ["session_id"],
614
+ ["session", "id"]
615
+ ]) ?? null;
616
+ const timestamp = resolveEventTimestamp(payload);
617
+ const resolvedSessionId = providerSessionId ?? context.sessionId;
618
+ const resolvedRawStoreRef = providerSessionId
619
+ ? buildKimiSessionRawStoreRef(providerSessionId)
620
+ : context.rawStoreRef;
621
+ const rawEventRef = buildKimiMessageRawRef(resolvedSessionId, "wire", context.lineNumber);
622
+ if (wireType.includes("session") && wireType.includes("created")) {
623
+ events.push({
624
+ type: "session_created",
625
+ status: "starting",
626
+ timestamp,
627
+ detail: "Kimi wire session created",
628
+ rawEventRef,
629
+ providerSessionId: providerSessionId ?? undefined
630
+ });
631
+ }
632
+ if (wireType.includes("running") || wireType.includes("progress")) {
633
+ events.push({
634
+ type: "status",
635
+ status: "running",
636
+ timestamp,
637
+ detail: extractTextBlocks(payload).trim() || "Kimi wire running",
638
+ rawEventRef,
639
+ providerSessionId: providerSessionId ?? undefined
640
+ });
641
+ }
642
+ if (wireType.includes("question") || wireType.includes("prompt") || wireType.includes("request")) {
643
+ events.push({
644
+ type: "status",
645
+ status: "running",
646
+ timestamp,
647
+ detail: extractTextBlocks(payload).trim() || "Kimi wire awaiting runtime guidance",
648
+ rawEventRef,
649
+ providerSessionId: providerSessionId ?? undefined
650
+ });
651
+ }
652
+ const maybeError = readKimiFirstNonEmptyString(payload, [["error"], ["detail"], ["message"]]);
653
+ if (wireType.includes("error") || wireType.includes("failed")) {
654
+ events.push({
655
+ type: "error",
656
+ status: "failed",
657
+ timestamp,
658
+ detail: maybeError || "Kimi wire failed",
659
+ errorCode: normalizeErrorCode(payload),
660
+ rawEventRef,
661
+ providerSessionId: providerSessionId ?? undefined
662
+ });
663
+ return {
664
+ providerSessionId,
665
+ events
666
+ };
667
+ }
668
+ // Kimi 的 wire 完成标记经常早于本地历史真正落盘,这里不直接发 completed,
669
+ // 改由进程 completed Promise 作为终态来源,避免前端过早显示“已结束”。
670
+ const normalizedMessages = normalizeKimiWireMessages(payload, wireType, {
671
+ sessionId: resolvedSessionId,
672
+ rawStoreRef: resolvedRawStoreRef,
673
+ sequence: context.sequence,
674
+ lineNumber: context.lineNumber,
675
+ timestamp
676
+ });
677
+ for (const normalizedMessage of normalizedMessages) {
678
+ events.push({
679
+ type: "message",
680
+ message: normalizedMessage,
681
+ status: "running",
682
+ timestamp,
683
+ detail: null,
684
+ rawEventRef: normalizedMessage.rawRef,
685
+ providerSessionId: providerSessionId ?? undefined
686
+ });
687
+ }
688
+ return {
689
+ providerSessionId,
690
+ events
691
+ };
692
+ }
693
+ function normalizeKimiWireMessages(payload, wireType, input) {
694
+ if (!looksLikeKimiMessagePayload(payload, wireType)) {
695
+ return [];
696
+ }
697
+ const normalizedParts = normalizeKimiMessageRecord(payload);
698
+ return normalizedParts.map((part, index) => createTextMessage({
699
+ sessionId: input.sessionId,
700
+ rawStoreRef: input.rawStoreRef,
701
+ sequence: input.sequence + index + 1,
702
+ lineNumber: input.lineNumber,
703
+ role: part.role,
704
+ kind: part.kind,
705
+ content: part.content,
706
+ timestamp: input.timestamp,
707
+ rawEventRef: buildKimiMessageRawRef(input.sessionId, "wire", input.lineNumber, part.partIndex ?? undefined),
708
+ toolCall: part.toolCall
709
+ }));
710
+ }
711
+ function createTextMessage(input) {
712
+ return {
713
+ messageId: messageIdFromRawRef(input.rawEventRef),
714
+ provider: "kimi",
715
+ providerSessionId: input.sessionId,
716
+ role: input.role,
717
+ kind: input.kind,
718
+ content: input.content,
719
+ toolCall: input.toolCall ?? null,
720
+ timestamp: input.timestamp,
721
+ sequence: input.sequence,
722
+ rawRef: input.rawEventRef
723
+ };
724
+ }
725
+ function resolveEventTimestamp(payload) {
726
+ const raw = readKimiFirstPresentValue(payload, [
727
+ ["timestamp"],
728
+ ["created_at"],
729
+ ["createdAt"],
730
+ ["time"],
731
+ ["event", "timestamp"]
732
+ ]);
733
+ return safeDate(raw, nextTimestamp()) || nextTimestamp();
734
+ }
735
+ function normalizeErrorCode(payload) {
736
+ const code = readKimiFirstNonEmptyString(payload, [["error_code"], ["code"], ["error", "code"]]);
737
+ return code?.trim().toUpperCase().replace(/[^A-Z0-9_]+/g, "_") || "KIMI_WIRE_ERROR";
738
+ }
739
+ function toWireUnavailableError(error) {
740
+ return new Error(`KIMI_WIRE_MODE_UNAVAILABLE: ${extractErrorDetail(error)}`);
741
+ }
742
+ function isWireUnavailableError(error) {
743
+ return error instanceof Error && error.message.startsWith("KIMI_WIRE_MODE_UNAVAILABLE:");
744
+ }
745
+ function extractErrorDetail(error) {
746
+ if (error instanceof Error) {
747
+ return error.message.trim() || "unknown error";
748
+ }
749
+ if (typeof error === "string") {
750
+ return error.trim() || "unknown error";
751
+ }
752
+ return "unknown error";
753
+ }
754
+ function mapInRunSubmitError(error) {
755
+ if (error instanceof Error && error.message === "IN_RUN_INPUT_NOT_SUPPORTED") {
756
+ return error;
757
+ }
758
+ if (isClosedStdinError(error)) {
759
+ return new Error("IN_RUN_INPUT_NOT_SUPPORTED");
760
+ }
761
+ return error instanceof Error ? error : new Error("IN_RUN_INPUT_NOT_SUPPORTED");
762
+ }
763
+ function isClosedStdinError(error) {
764
+ if (!error || typeof error !== "object") {
765
+ return false;
766
+ }
767
+ const code = error.code;
768
+ return (code === "EPIPE" ||
769
+ code === "ECONNRESET" ||
770
+ code === "ERR_STREAM_DESTROYED" ||
771
+ code === "ERR_STREAM_WRITE_AFTER_END");
772
+ }
773
+ function shouldSkipEquivalentRecentKimiRuntimeMessage(recentMessages, message) {
774
+ if (message.kind !== "text" && message.kind !== "thinking") {
775
+ return false;
776
+ }
777
+ const comparableContent = normalizeComparableKimiRuntimeMessageContent(message.content);
778
+ if (!comparableContent) {
779
+ return false;
780
+ }
781
+ return recentMessages.some((item) => item.role === message.role
782
+ && item.kind === message.kind
783
+ && item.comparableContent === comparableContent);
784
+ }
785
+ function rememberKimiRuntimeMessage(recentMessages, message) {
786
+ const comparableContent = normalizeComparableKimiRuntimeMessageContent(message.content);
787
+ if (!comparableContent) {
788
+ return;
789
+ }
790
+ recentMessages.push({
791
+ role: message.role,
792
+ kind: message.kind,
793
+ comparableContent
794
+ });
795
+ if (recentMessages.length > 8) {
796
+ recentMessages.splice(0, recentMessages.length - 8);
797
+ }
798
+ }
799
+ function normalizeComparableKimiRuntimeMessageContent(content) {
800
+ const cleaned = extractKimiDisplayTextSegments(content).join("\n\n") || content;
801
+ return cleaned
802
+ .replace(/\r\n/g, "\n")
803
+ .trim()
804
+ .replace(/\s+/g, " ");
805
+ }
806
+ function shouldSpawnViaShell(commandPath) {
807
+ return /\.(cmd|bat|ps1)$/i.test(commandPath);
808
+ }
809
+ function buildKimiSpawnEnv() {
810
+ return {
811
+ ...process.env,
812
+ PYTHONIOENCODING: "utf-8",
813
+ PYTHONUTF8: "1"
814
+ };
815
+ }
816
+ function buildPendingKimiBinding(sessionId) {
817
+ const pendingValue = `pending://kimi/${sessionId}`;
818
+ return {
819
+ providerSessionId: pendingValue,
820
+ rawStoreRef: pendingValue
821
+ };
822
+ }
823
+ function buildCommandInputPayloadFromOptions(prompt) {
824
+ return {
825
+ role: "user",
826
+ content: [
827
+ {
828
+ type: "text",
829
+ text: prompt
830
+ }
831
+ ]
832
+ };
833
+ }
834
+ function isPendingKimiBinding(value) {
835
+ return value.trim().toLowerCase().startsWith("pending://kimi/");
836
+ }
837
+ function readKimiSessionDirectoryMtime(sessionDir) {
838
+ let mtimeMs = 0;
839
+ for (const fileName of ["state.json", "context.jsonl", "wire.jsonl"]) {
840
+ const filePath = join(sessionDir, fileName);
841
+ if (!existsSync(filePath)) {
842
+ continue;
843
+ }
844
+ mtimeMs = Math.max(mtimeMs, statSync(filePath).mtimeMs);
845
+ }
846
+ return mtimeMs;
847
+ }
848
+ function waitForKimiBindingResolvePoll() {
849
+ return new Promise((resolve) => {
850
+ setTimeout(resolve, KIMI_START_BINDING_RESOLVE_POLL_MS);
851
+ });
852
+ }
853
+ async function detectKimiCliSyntax(input) {
854
+ const helpOutput = await captureKimiCliOutput(input, ["--help"]);
855
+ if (looksLikeModernKimiHelp(helpOutput)) {
856
+ return "modern";
857
+ }
858
+ if (looksLikeLegacyKimiHelp(helpOutput)) {
859
+ return "legacy";
860
+ }
861
+ return "modern";
862
+ }
863
+ async function captureKimiCliOutput(input, probeArgs) {
864
+ return new Promise((resolve) => {
865
+ const proc = input.spawnFactory(input.commandPath, [...input.baseArgs, ...probeArgs], {
866
+ shell: shouldSpawnViaShell(input.commandPath),
867
+ windowsHide: true,
868
+ stdio: ["ignore", "pipe", "pipe"]
869
+ });
870
+ let settled = false;
871
+ let stdoutBuffer = "";
872
+ let stderrBuffer = "";
873
+ const finalize = (value) => {
874
+ if (settled) {
875
+ return;
876
+ }
877
+ settled = true;
878
+ clearTimeout(timeout);
879
+ resolve(value);
880
+ };
881
+ const timeout = setTimeout(() => {
882
+ if (!proc.killed) {
883
+ proc.kill("SIGTERM");
884
+ }
885
+ finalize(`${stdoutBuffer}\n${stderrBuffer}`.trim());
886
+ }, Math.max(200, input.timeoutMs));
887
+ proc.stdout.setEncoding("utf8");
888
+ proc.stdout.on("data", (chunk) => {
889
+ stdoutBuffer += chunk;
890
+ });
891
+ proc.stderr.setEncoding("utf8");
892
+ proc.stderr.on("data", (chunk) => {
893
+ stderrBuffer += chunk;
894
+ });
895
+ proc.once("error", () => {
896
+ finalize(`${stdoutBuffer}\n${stderrBuffer}`.trim());
897
+ });
898
+ proc.once("close", () => {
899
+ finalize(`${stdoutBuffer}\n${stderrBuffer}`.trim());
900
+ });
901
+ });
902
+ }
903
+ function looksLikeModernKimiHelp(output) {
904
+ const normalized = output.toLowerCase();
905
+ return normalized.includes("--wire") || normalized.includes("--work-dir");
906
+ }
907
+ function looksLikeLegacyKimiHelp(output) {
908
+ const normalized = output.toLowerCase();
909
+ return normalized.includes("--cwd") || normalized.includes("no such command 'wire'");
910
+ }
911
+ //# sourceMappingURL=kimi-runtime.js.map