@ycodium-ai/agent-kimi 0.2.3208 → 0.2.3212

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 (2) hide show
  1. package/dist/index.js +151 -44
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -91,8 +91,8 @@ var KIMI_CARD = {
91
91
  };
92
92
 
93
93
  // src/kimiInstance.ts
94
- import * as NodeOS4 from "node:os";
95
- import * as NodePath6 from "node:path";
94
+ import * as NodeOS5 from "node:os";
95
+ import * as NodePath7 from "node:path";
96
96
  import { mergeLaunchEnv, modelSelectionStringOption } from "@ycodium-ai/plugin-api/executor";
97
97
  import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
98
98
 
@@ -26943,6 +26943,92 @@ function readOpenToolCalls(toolCalls, turnId) {
26943
26943
  return running;
26944
26944
  }
26945
26945
 
26946
+ // ../../packages/ycodium-acp-executor/src/protocol-log.ts
26947
+ import * as NodeFS from "node:fs";
26948
+ import * as NodeOS from "node:os";
26949
+ import * as NodePath2 from "node:path";
26950
+ var DEFAULT_MAX_BYTES = 8 * 1024 * 1024;
26951
+ var UNSAFE_FILE_CHARS = /[^A-Za-z0-9._-]+/gu;
26952
+ function safeFileName(value) {
26953
+ return value.replaceAll(UNSAFE_FILE_CHARS, "_");
26954
+ }
26955
+ function createAcpProtocolLogFile(input2) {
26956
+ const maxBytes = input2.maxBytes ?? DEFAULT_MAX_BYTES;
26957
+ NodeFS.mkdirSync(input2.directory, { recursive: true });
26958
+ const filePath = NodePath2.join(
26959
+ input2.directory,
26960
+ `${safeFileName(input2.provider)}-${safeFileName(input2.threadId)}-${Date.now().toString(36)}.ndjson`
26961
+ );
26962
+ const stream = (input2.openStream ?? ((path) => NodeFS.createWriteStream(path, { flags: "a" })))(
26963
+ filePath
26964
+ );
26965
+ let bytes = 0;
26966
+ let stopped = false;
26967
+ const closed = Promise.withResolvers();
26968
+ let closing = false;
26969
+ stream.once("close", () => closed.resolve());
26970
+ stream.on("error", () => {
26971
+ stopped = true;
26972
+ stream.destroy();
26973
+ });
26974
+ const writeTruncated = () => {
26975
+ stopped = true;
26976
+ const marker = `${JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), stage: "truncated" })}
26977
+ `;
26978
+ if (bytes + Buffer.byteLength(marker) <= maxBytes) stream.write(marker);
26979
+ stream.end();
26980
+ };
26981
+ const writeLine = (value) => {
26982
+ if (stopped) return;
26983
+ const line = `${JSON.stringify(value)}
26984
+ `;
26985
+ const lineBytes = Buffer.byteLength(line);
26986
+ if (bytes + lineBytes > maxBytes) {
26987
+ writeTruncated();
26988
+ return;
26989
+ }
26990
+ bytes += lineBytes;
26991
+ stream.write(line);
26992
+ };
26993
+ return {
26994
+ path: filePath,
26995
+ write: (event) => writeLine({
26996
+ at: (/* @__PURE__ */ new Date()).toISOString(),
26997
+ direction: event.direction,
26998
+ stage: event.stage,
26999
+ payload: event.payload
27000
+ }),
27001
+ close: async () => {
27002
+ if (closing) return closed.promise;
27003
+ closing = true;
27004
+ stopped = true;
27005
+ stream.end();
27006
+ await closed.promise;
27007
+ }
27008
+ };
27009
+ }
27010
+ function createAcpProtocolLogFromEnv(input2) {
27011
+ const flag = process.env.YCODIUM_ACP_PROTOCOL_LOG;
27012
+ if (flag !== "1" && flag?.toLowerCase() !== "true") return void 0;
27013
+ const configured = process.env.YCODIUM_ACP_PROTOCOL_LOG_DIR?.trim();
27014
+ const directory = configured && configured.length > 0 ? configured : NodePath2.join(NodeOS.tmpdir(), "ycodium-acp-protocol");
27015
+ try {
27016
+ const sink = createAcpProtocolLogFile({
27017
+ directory,
27018
+ provider: input2.provider,
27019
+ threadId: input2.threadId
27020
+ });
27021
+ input2.log?.info("acp protocol frames are being recorded", { path: sink.path });
27022
+ return sink;
27023
+ } catch (error62) {
27024
+ input2.log?.warn?.("acp protocol frame log could not be opened", {
27025
+ directory,
27026
+ error: error62 instanceof Error ? error62.message : String(error62)
27027
+ });
27028
+ return void 0;
27029
+ }
27030
+ }
27031
+
26946
27032
  // ../../packages/ycodium-acp-executor/src/executor.ts
26947
27033
  var DEFAULT_CANCEL_GRACE_MS = 5e3;
26948
27034
  function defaultNowIso() {
@@ -27051,9 +27137,16 @@ function createAcpExecutor(options) {
27051
27137
  });
27052
27138
  const { rememberSettledPromptKey, abortPendingSettlement, settleFromNotification } = createExecutorSettlement({ hooks, shared });
27053
27139
  const promptResults = createPromptResults({ options, shared });
27140
+ const protocolLogSink = options.protocolLog === void 0 ? createAcpProtocolLogFromEnv({
27141
+ provider: options.provider,
27142
+ threadId: options.threadId,
27143
+ ...options.log === void 0 ? {} : { log: options.log }
27144
+ }) : void 0;
27145
+ const protocolLog = options.protocolLog ?? protocolLogSink?.write;
27054
27146
  const connection = createAcpConnection({
27055
27147
  readable: options.readable,
27056
27148
  writable: options.writable,
27149
+ ...protocolLog === void 0 ? {} : { logger: protocolLog },
27057
27150
  onInboundFailure: (error62) => {
27058
27151
  options.log?.warn?.("acp connection closed: an inbound request could not be answered", {
27059
27152
  threadId: options.threadId,
@@ -27150,7 +27243,11 @@ function createAcpExecutor(options) {
27150
27243
  notifyPromptSettled,
27151
27244
  shared
27152
27245
  });
27153
- const { cancel, compact, dispose } = createExecutorLifecycle({
27246
+ const {
27247
+ cancel,
27248
+ compact,
27249
+ dispose: disposeLifecycle
27250
+ } = createExecutorLifecycle({
27154
27251
  promptResults,
27155
27252
  failIfDisposed,
27156
27253
  requireStarted,
@@ -27177,6 +27274,7 @@ function createAcpExecutor(options) {
27177
27274
  onInputDead,
27178
27275
  shared
27179
27276
  });
27277
+ let disposeOnce;
27180
27278
  return {
27181
27279
  get generation() {
27182
27280
  return shared.generation;
@@ -27199,7 +27297,16 @@ function createAcpExecutor(options) {
27199
27297
  setNativeMode,
27200
27298
  compact,
27201
27299
  openToolCalls: () => readOpenToolCalls(toolCalls, shared.activeTurnId),
27202
- dispose
27300
+ dispose: () => {
27301
+ disposeOnce ??= (async () => {
27302
+ try {
27303
+ await disposeLifecycle();
27304
+ } finally {
27305
+ await protocolLogSink?.close();
27306
+ }
27307
+ })();
27308
+ return disposeOnce;
27309
+ }
27203
27310
  };
27204
27311
  }
27205
27312
 
@@ -27523,8 +27630,8 @@ function tokenizeLaunchArgs(value) {
27523
27630
  }
27524
27631
 
27525
27632
  // src/kimi.ts
27526
- import * as NodeFS from "node:fs";
27527
- import * as NodePath2 from "node:path";
27633
+ import * as NodeFS2 from "node:fs";
27634
+ import * as NodePath3 from "node:path";
27528
27635
  var KIMI_USER_INPUT_TITLES = /* @__PURE__ */ new Set(["AskUserQuestion", "ExitPlanMode"]);
27529
27636
  var KIMI_PLAN_ACTIONS = {
27530
27637
  plan_approve: "approve",
@@ -27606,40 +27713,40 @@ function parseKimiContextWindow(contents) {
27606
27713
  function readTail(filePath) {
27607
27714
  let handle;
27608
27715
  try {
27609
- const size = NodeFS.statSync(filePath).size;
27716
+ const size = NodeFS2.statSync(filePath).size;
27610
27717
  if (!Number.isFinite(size) || size <= 0) return void 0;
27611
27718
  const length = size > TAIL_SCAN_BYTES ? TAIL_SCAN_BYTES : size;
27612
27719
  const buffer = Buffer.alloc(length);
27613
- handle = NodeFS.openSync(filePath, "r");
27614
- NodeFS.readSync(handle, buffer, 0, length, size - length);
27720
+ handle = NodeFS2.openSync(filePath, "r");
27721
+ NodeFS2.readSync(handle, buffer, 0, length, size - length);
27615
27722
  return buffer.toString("utf8");
27616
27723
  } catch {
27617
27724
  return void 0;
27618
27725
  } finally {
27619
27726
  if (handle !== void 0) {
27620
27727
  try {
27621
- NodeFS.closeSync(handle);
27728
+ NodeFS2.closeSync(handle);
27622
27729
  } catch {
27623
27730
  }
27624
27731
  }
27625
27732
  }
27626
27733
  }
27627
27734
  function findKimiSessionWireLog(input2) {
27628
- const sessionsRoot = NodePath2.join(input2.homePath, SESSIONS_DIR);
27735
+ const sessionsRoot = NodePath3.join(input2.homePath, SESSIONS_DIR);
27629
27736
  let workspaces;
27630
27737
  try {
27631
- workspaces = NodeFS.readdirSync(sessionsRoot);
27738
+ workspaces = NodeFS2.readdirSync(sessionsRoot);
27632
27739
  } catch {
27633
27740
  return void 0;
27634
27741
  }
27635
27742
  for (const workspace of workspaces) {
27636
- const candidate = NodePath2.join(
27743
+ const candidate = NodePath3.join(
27637
27744
  sessionsRoot,
27638
27745
  workspace,
27639
27746
  input2.acpSessionId,
27640
27747
  ...WIRE_LOG_SEGMENTS
27641
27748
  );
27642
- if (NodeFS.existsSync(candidate)) return candidate;
27749
+ if (NodeFS2.existsSync(candidate)) return candidate;
27643
27750
  }
27644
27751
  return void 0;
27645
27752
  }
@@ -27652,26 +27759,26 @@ function readKimiContextWindow(input2) {
27652
27759
  }
27653
27760
 
27654
27761
  // src/kimiQuota.ts
27655
- import * as NodeFS3 from "node:fs";
27656
- import * as NodeOS2 from "node:os";
27657
- import * as NodePath4 from "node:path";
27762
+ import * as NodeFS4 from "node:fs";
27763
+ import * as NodeOS3 from "node:os";
27764
+ import * as NodePath5 from "node:path";
27658
27765
  import {
27659
27766
  parseRetryAfterMs
27660
27767
  } from "@ycodium-ai/plugin-api/usage";
27661
27768
 
27662
27769
  // src/kimiAccount.ts
27663
- import * as NodeFS2 from "node:fs";
27664
- import * as NodeOS from "node:os";
27665
- import * as NodePath3 from "node:path";
27770
+ import * as NodeFS3 from "node:fs";
27771
+ import * as NodeOS2 from "node:os";
27772
+ import * as NodePath4 from "node:path";
27666
27773
  function kimiCredentialsPath(resolvedHomePath) {
27667
- const home = resolvedHomePath.trim().length > 0 ? resolvedHomePath : NodePath3.join(NodeOS.homedir(), ".kimi-code");
27668
- return NodePath3.join(home, "credentials", "kimi-code.json");
27774
+ const home = resolvedHomePath.trim().length > 0 ? resolvedHomePath : NodePath4.join(NodeOS2.homedir(), ".kimi-code");
27775
+ return NodePath4.join(home, "credentials", "kimi-code.json");
27669
27776
  }
27670
27777
  var nonEmptyString = (value) => typeof value === "string" && value.length > 0;
27671
27778
  function readKimiAuthState(resolvedHomePath) {
27672
27779
  let raw;
27673
27780
  try {
27674
- raw = NodeFS2.readFileSync(kimiCredentialsPath(resolvedHomePath), "utf8");
27781
+ raw = NodeFS3.readFileSync(kimiCredentialsPath(resolvedHomePath), "utf8");
27675
27782
  } catch (error62) {
27676
27783
  return error62.code === "ENOENT" ? "signed-out" : "unreadable";
27677
27784
  }
@@ -27836,12 +27943,12 @@ var kimiEffectiveHome = (resolvedHomePath, processEnvHome) => {
27836
27943
  var createKimiUsage = (input2) => {
27837
27944
  const now = input2.now ?? Date.now;
27838
27945
  const processEnv = input2.processEnv ?? process.env;
27839
- const home = input2.homePath.trim().length > 0 ? input2.homePath : NodePath4.join(NodeOS2.homedir(), ".kimi-code");
27946
+ const home = input2.homePath.trim().length > 0 ? input2.homePath : NodePath5.join(NodeOS3.homedir(), ".kimi-code");
27840
27947
  const credentialsPath = kimiCredentialsPath(input2.homePath);
27841
27948
  const readQuota = async (request) => {
27842
27949
  let configToml = null;
27843
27950
  try {
27844
- configToml = NodeFS3.readFileSync(NodePath4.join(home, "config.toml"), "utf8");
27951
+ configToml = NodeFS4.readFileSync(NodePath5.join(home, "config.toml"), "utf8");
27845
27952
  } catch (error62) {
27846
27953
  if (error62.code !== "ENOENT") {
27847
27954
  return { status: "unavailable", reason: "unreachable" };
@@ -27854,7 +27961,7 @@ var createKimiUsage = (input2) => {
27854
27961
  if ("custom" in endpoint) return { status: "unavailable", reason: "customEndpoint" };
27855
27962
  let token = null;
27856
27963
  try {
27857
- token = extractKimiToken(parseJson(NodeFS3.readFileSync(credentialsPath, "utf8")), now());
27964
+ token = extractKimiToken(parseJson(NodeFS4.readFileSync(credentialsPath, "utf8")), now());
27858
27965
  } catch {
27859
27966
  token = null;
27860
27967
  }
@@ -27903,9 +28010,9 @@ var createKimiUsage = (input2) => {
27903
28010
  };
27904
28011
 
27905
28012
  // src/kimiTokens.ts
27906
- import * as NodeFS4 from "node:fs";
27907
- import * as NodeOS3 from "node:os";
27908
- import * as NodePath5 from "node:path";
28013
+ import * as NodeFS5 from "node:fs";
28014
+ import * as NodeOS4 from "node:os";
28015
+ import * as NodePath6 from "node:path";
27909
28016
  var MTIME_SLACK_MS = 36 * 60 * 60 * 1e3;
27910
28017
  var GUARD_LENGTH = 64;
27911
28018
  var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -27942,7 +28049,7 @@ var parseKimiUsageLine = (line) => {
27942
28049
  var hasTokens = (totals) => totals.uncachedInputTokens > 0 || totals.cachedInputTokens > 0 || totals.cacheCreationTokens > 0 || totals.outputTokens > 0;
27943
28050
  var readDirs = (dir) => {
27944
28051
  try {
27945
- return NodeFS4.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
28052
+ return NodeFS5.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
27946
28053
  } catch {
27947
28054
  return [];
27948
28055
  }
@@ -27950,10 +28057,10 @@ var readDirs = (dir) => {
27950
28057
  var listWireLogs = (sessionsRoot) => {
27951
28058
  const found = [];
27952
28059
  for (const workspace of readDirs(sessionsRoot)) {
27953
- for (const session of readDirs(NodePath5.join(sessionsRoot, workspace))) {
27954
- const agentsDir = NodePath5.join(sessionsRoot, workspace, session, "agents");
28060
+ for (const session of readDirs(NodePath6.join(sessionsRoot, workspace))) {
28061
+ const agentsDir = NodePath6.join(sessionsRoot, workspace, session, "agents");
27955
28062
  for (const agent of readDirs(agentsDir)) {
27956
- found.push({ file: NodePath5.join(agentsDir, agent, "wire.jsonl"), sessionId: session });
28063
+ found.push({ file: NodePath6.join(agentsDir, agent, "wire.jsonl"), sessionId: session });
27957
28064
  }
27958
28065
  }
27959
28066
  }
@@ -27962,23 +28069,23 @@ var listWireLogs = (sessionsRoot) => {
27962
28069
  var readRange = (file2, from, to) => {
27963
28070
  const length = Math.max(0, to - from);
27964
28071
  const buffer = Buffer.alloc(length);
27965
- const fd = NodeFS4.openSync(file2, "r");
28072
+ const fd = NodeFS5.openSync(file2, "r");
27966
28073
  try {
27967
28074
  let read = 0;
27968
28075
  while (read < length) {
27969
- const n = NodeFS4.readSync(fd, buffer, read, length - read, from + read);
28076
+ const n = NodeFS5.readSync(fd, buffer, read, length - read, from + read);
27970
28077
  if (n === 0) break;
27971
28078
  read += n;
27972
28079
  }
27973
28080
  return read === length ? buffer : buffer.subarray(0, read);
27974
28081
  } finally {
27975
- NodeFS4.closeSync(fd);
28082
+ NodeFS5.closeSync(fd);
27976
28083
  }
27977
28084
  };
27978
28085
  var guardOf = (file2, size) => readRange(file2, 0, Math.min(size, GUARD_LENGTH)).toString("base64");
27979
28086
  var createKimiTokenReader = (input2) => {
27980
- const home = input2.homePath.trim().length > 0 ? NodePath5.resolve(input2.homePath) : NodePath5.join(NodeOS3.homedir(), ".kimi-code");
27981
- const sessionsRoot = NodePath5.join(home, "sessions");
28087
+ const home = input2.homePath.trim().length > 0 ? NodePath6.resolve(input2.homePath) : NodePath6.join(NodeOS4.homedir(), ".kimi-code");
28088
+ const sessionsRoot = NodePath6.join(home, "sessions");
27982
28089
  const memos = /* @__PURE__ */ new Map();
27983
28090
  const refresh = (file2, size) => {
27984
28091
  const guard = guardOf(file2, size);
@@ -28003,7 +28110,7 @@ var createKimiTokenReader = (input2) => {
28003
28110
  const readTokenUsage = async (request) => {
28004
28111
  const sinceMs = Date.parse(request.since);
28005
28112
  const untilMs = Date.parse(request.until);
28006
- if (!NodeFS4.existsSync(sessionsRoot)) {
28113
+ if (!NodeFS5.existsSync(sessionsRoot)) {
28007
28114
  return {
28008
28115
  records: [],
28009
28116
  source: {
@@ -28024,7 +28131,7 @@ var createKimiTokenReader = (input2) => {
28024
28131
  for (const { file: file2, sessionId } of listWireLogs(sessionsRoot)) {
28025
28132
  let size;
28026
28133
  try {
28027
- const stat = NodeFS4.statSync(file2);
28134
+ const stat = NodeFS5.statSync(file2);
28028
28135
  if (stat.mtimeMs < sinceMs - MTIME_SLACK_MS) {
28029
28136
  skippedFiles += 1;
28030
28137
  continue;
@@ -28304,9 +28411,9 @@ var EventBus = class {
28304
28411
  }
28305
28412
  };
28306
28413
  function expandHomePath(value) {
28307
- if (value === "~") return NodeOS4.homedir();
28414
+ if (value === "~") return NodeOS5.homedir();
28308
28415
  if (value.startsWith("~/") || value.startsWith("~\\")) {
28309
- return NodePath6.join(NodeOS4.homedir(), value.slice(2));
28416
+ return NodePath7.join(NodeOS5.homedir(), value.slice(2));
28310
28417
  }
28311
28418
  return value;
28312
28419
  }
@@ -28331,7 +28438,7 @@ function nowIso() {
28331
28438
  }
28332
28439
  function kimiContinuationKey(recipe) {
28333
28440
  const homePath = recipe.homePath.trim();
28334
- const resolvedHomePath = homePath.length > 0 ? NodePath6.resolve(expandHomePath(homePath)) : "";
28441
+ const resolvedHomePath = homePath.length > 0 ? NodePath7.resolve(expandHomePath(homePath)) : "";
28335
28442
  return `kimiCode:home:${recipe.binaryPath.trim()}\0${resolvedHomePath}`;
28336
28443
  }
28337
28444
  function resolveHomePath(recipe) {
@@ -28671,7 +28778,7 @@ var executors = [
28671
28778
  ];
28672
28779
  var index_default = definePlugin({
28673
28780
  id: "agent-kimi",
28674
- apiVersion: 19,
28781
+ apiVersion: 20,
28675
28782
  executors,
28676
28783
  activate(ctx) {
28677
28784
  ctx.log.info("Kimi Code executor ready");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-kimi",
3
- "version": "0.2.3208",
3
+ "version": "0.2.3212",
4
4
  "description": "Kimi Code executor: runs `kimi acp` over Agent Client Protocol stdio.",
5
5
  "keywords": [
6
6
  "ycodium",
@@ -21,9 +21,9 @@
21
21
  "@types/node": "24.12.4",
22
22
  "esbuild": "0.28.1",
23
23
  "vite-plus": "0.2.2",
24
- "ycodium-executor-testing": "0.0.0",
25
- "@ycodium-ai/plugin-api": "0.2.3208",
26
- "ycodium-acp-executor": "0.2.3208"
24
+ "ycodium-acp-executor": "0.2.3212",
25
+ "@ycodium-ai/plugin-api": "0.2.0",
26
+ "ycodium-executor-testing": "0.0.0"
27
27
  },
28
28
  "ycodium": {
29
29
  "plugin": "./dist/index.js",