@unity-china/codely-cli 1.0.0-beta.35 → 1.0.0-beta.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -321,6 +321,7 @@ Remove an MCP server with the specified name.
321
321
  ## Troubleshooting
322
322
 
323
323
  If you encounter issues, please check the error messages and ensure:
324
+
324
325
  - Node.js version is 20 or higher
325
326
  - All dependencies are properly installed
326
327
  - API keys are correctly configured in settings
package/README.zh-CN.md CHANGED
@@ -321,15 +321,16 @@ codely mcp add my-server python /path/to/server.py --scope user
321
321
  ## 故障排除
322
322
 
323
323
  如果您遇到问题,请检查错误消息并确保:
324
+
324
325
  - Node.js 版本为 20 或更高
325
326
  - 所有依赖项已正确安装
326
327
  - API 密钥在设置中正确配置
327
328
 
328
329
  如需更多帮助,请访问:
330
+
329
331
  - 🌐 [官方网站](https://codely.tuanjie.cn/)
330
332
  - 📖 [使用手册](https://yousandi.feishu.cn/wiki/Sqmlw31sYiTm8qkh7s1cSlbenmb)
331
333
 
332
334
  ## 许可证
333
335
 
334
336
  [LICENSE](./LICENSE)
335
-
package/bundle/gemini.js CHANGED
@@ -417144,7 +417144,7 @@ async function getPackageJson2() {
417144
417144
  // packages/cli/src/utils/version.ts
417145
417145
  async function getCliVersion() {
417146
417146
  const pkgJson = await getPackageJson2();
417147
- return "1.0.0-beta.35";
417147
+ return "1.0.0-beta.37";
417148
417148
  }
417149
417149
 
417150
417150
  // packages/cli/src/ui/commands/types.ts
@@ -417636,7 +417636,7 @@ import process30 from "node:process";
417636
417636
 
417637
417637
  // packages/cli/src/generated/git-commit.ts
417638
417638
  init_esbuild_polyfill();
417639
- var GIT_COMMIT_INFO = "193365d8";
417639
+ var GIT_COMMIT_INFO = "8dcb2033";
417640
417640
 
417641
417641
  // packages/cli/src/ui/commands/bugCommand.ts
417642
417642
  var bugCommand = {
@@ -421906,6 +421906,7 @@ var UnityTcpClient = class extends EventEmitter10 {
421906
421906
  this.ioLock = false;
421907
421907
  this.connLock = false;
421908
421908
  this.debugMode = false;
421909
+ this.lastConnectFailureHintAtMs = 0;
421909
421910
  this.host = host;
421910
421911
  this.port = port;
421911
421912
  this.debugMode = debugMode;
@@ -421924,6 +421925,31 @@ var UnityTcpClient = class extends EventEmitter10 {
421924
421925
  console.log(message);
421925
421926
  }
421926
421927
  }
421928
+ formatConnectError(error2) {
421929
+ try {
421930
+ if (error2 instanceof AggregateError) {
421931
+ const parts = (error2.errors || []).map((e3) => e3 instanceof Error ? e3.message : String(e3)).filter(Boolean);
421932
+ const detail = parts.length > 0 ? parts.join(" | ") : error2.message || String(error2);
421933
+ return `AggregateError: ${detail}`;
421934
+ }
421935
+ if (error2 instanceof Error) {
421936
+ return error2.message || error2.name;
421937
+ }
421938
+ return String(error2);
421939
+ } catch {
421940
+ return "Unknown connect error";
421941
+ }
421942
+ }
421943
+ maybeLogConnectFailureHint(error2) {
421944
+ const now = Date.now();
421945
+ const minIntervalMs = 2e3;
421946
+ if (now - this.lastConnectFailureHintAtMs < minIntervalMs) {
421947
+ return;
421948
+ }
421949
+ this.lastConnectFailureHintAtMs = now;
421950
+ const brief = this.formatConnectError(error2);
421951
+ console.log(`\u{1F504} Unity TCP not reachable at ${this.host}:${this.port} (${brief}). This is often normal during Unity compilation/domain reload; retrying...`);
421952
+ }
421927
421953
  /**
421928
421954
  * Establish connection to Unity Editor with handshake
421929
421955
  */
@@ -421959,7 +421985,11 @@ var UnityTcpClient = class extends EventEmitter10 {
421959
421985
  this.emit("connected");
421960
421986
  return true;
421961
421987
  } catch (error2) {
421962
- console.error(`\u274C Failed to connect to Unity: ${error2}`);
421988
+ if (this.debugMode) {
421989
+ this.debugLog(`\u26A0\uFE0F Unity connect failed (${this.host}:${this.port}): ${this.formatConnectError(error2)}`);
421990
+ } else {
421991
+ this.maybeLogConnectFailureHint(error2);
421992
+ }
421963
421993
  if (this.socket) {
421964
421994
  this.socket.destroy();
421965
421995
  this.socket = null;
@@ -457817,7 +457847,9 @@ var UnityConnectionManager = class extends EventEmitter12 {
457817
457847
  // -1 means unlimited
457818
457848
  debugMode: config3.debugMode ?? false,
457819
457849
  projectPath: config3.projectPath,
457820
- unityConfigPath: void 0
457850
+ unityConfigPath: void 0,
457851
+ expectedProjectRoot: void 0,
457852
+ unityLastHeartbeat: void 0
457821
457853
  };
457822
457854
  UnityTcpClientManager.setDebugMode(this.config.debugMode);
457823
457855
  if (this.config.projectPath) {
@@ -457906,6 +457938,8 @@ var UnityConnectionManager = class extends EventEmitter12 {
457906
457938
  const { config: config3, configPath } = this.readUnityConfigFromProjectPath();
457907
457939
  const host = config3.unity_host && config3.unity_host.trim().length > 0 ? config3.unity_host : "localhost";
457908
457940
  const port = config3.unity_port;
457941
+ const expectedProjectRoot = path70.dirname(configPath);
457942
+ const unityLastHeartbeat = config3.last_heartbeat;
457909
457943
  const configChanged = host !== previousHost || port !== previousPort || configPath !== previousConfigPath;
457910
457944
  if (configChanged) {
457911
457945
  this.debugLog(
@@ -457927,6 +457961,77 @@ var UnityConnectionManager = class extends EventEmitter12 {
457927
457961
  this.config.host = host;
457928
457962
  this.config.port = port;
457929
457963
  this.config.unityConfigPath = configPath;
457964
+ this.config.expectedProjectRoot = expectedProjectRoot;
457965
+ this.config.unityLastHeartbeat = unityLastHeartbeat;
457966
+ }
457967
+ normalizeProjectRootPath(input) {
457968
+ let normalized2 = input.replace(/\\/g, "/").replace(/\/+$/, "");
457969
+ if (process.platform === "win32") {
457970
+ normalized2 = normalized2.toLowerCase();
457971
+ }
457972
+ return normalized2;
457973
+ }
457974
+ formatHeartbeatAge(lastHeartbeat) {
457975
+ if (!lastHeartbeat || typeof lastHeartbeat !== "string") {
457976
+ return null;
457977
+ }
457978
+ const parsed = Date.parse(lastHeartbeat);
457979
+ if (Number.isNaN(parsed)) {
457980
+ return null;
457981
+ }
457982
+ const ageMs = Date.now() - parsed;
457983
+ if (ageMs < 0) {
457984
+ return null;
457985
+ }
457986
+ const ageSec = Math.round(ageMs / 100) / 10;
457987
+ return `${ageSec}s`;
457988
+ }
457989
+ async verifyConnectedUnityProjectRoot() {
457990
+ if (!this.tcpClient) {
457991
+ throw new Error("Cannot verify Unity project root: no TCP client");
457992
+ }
457993
+ const expectedRoot = this.config.expectedProjectRoot;
457994
+ if (!expectedRoot) {
457995
+ this.debugLog(
457996
+ "Skipping Unity project root verification: expectedProjectRoot unavailable"
457997
+ );
457998
+ return;
457999
+ }
458000
+ let response;
458001
+ try {
458002
+ response = await this.tcpClient.sendCommand("manage_editor", {
458003
+ action: "get_project_root"
458004
+ });
458005
+ } catch (error2) {
458006
+ const message = error2 instanceof Error ? error2.message : String(error2);
458007
+ throw new Error(`Failed to verify Unity project root: ${message}`);
458008
+ }
458009
+ const inner = response?.data ?? response;
458010
+ const reportedRoot = inner?.data?.projectRoot ?? inner?.projectRoot ?? response?.data?.projectRoot;
458011
+ if (typeof reportedRoot !== "string" || reportedRoot.trim().length === 0) {
458012
+ throw new Error(
458013
+ `Unity project root verification returned invalid response: ${JSON.stringify(
458014
+ response
458015
+ )}`
458016
+ );
458017
+ }
458018
+ const expectedNorm = this.normalizeProjectRootPath(expectedRoot);
458019
+ const reportedNorm = this.normalizeProjectRootPath(reportedRoot);
458020
+ if (expectedNorm !== reportedNorm) {
458021
+ const heartbeatAge = this.formatHeartbeatAge(
458022
+ this.config.unityLastHeartbeat
458023
+ );
458024
+ const heartbeatHint = this.config.unityLastHeartbeat ? ` (last_heartbeat: ${this.config.unityLastHeartbeat}${heartbeatAge ? `, age: ${heartbeatAge}` : ""})` : "";
458025
+ throw new Error(
458026
+ [
458027
+ `Connected Unity Bridge appears to belong to a different Unity project.`,
458028
+ `Target: ${this.config.host}:${this.config.port}`,
458029
+ `Expected project root (from ${this.config.unityConfigPath ?? ".com-unity-codely.json"}): ${expectedRoot}${heartbeatHint}`,
458030
+ `Unity reports project root: ${reportedRoot}`,
458031
+ `Hint: You may have another Unity project open on the same port, or the config heartbeat is stale. Open the correct Unity project (or regenerate .com-unity-codely.json) and retry.`
458032
+ ].join("\n")
458033
+ );
458034
+ }
457930
458035
  }
457931
458036
  /**
457932
458037
  * Start the connection manager and attempt to connect with retry logic
@@ -458029,6 +458134,24 @@ var UnityConnectionManager = class extends EventEmitter12 {
458029
458134
  this.setupEventHandlers();
458030
458135
  const connected = await this.tcpClient.connect();
458031
458136
  if (connected) {
458137
+ try {
458138
+ await this.verifyConnectedUnityProjectRoot();
458139
+ } catch (error2) {
458140
+ const message = error2 instanceof Error ? error2.message : String(error2);
458141
+ console.error(`
458142
+ \u274C ${message}`);
458143
+ this.emit("error", { message });
458144
+ if (this.tcpClient) {
458145
+ try {
458146
+ this.tcpClient.removeAllListeners();
458147
+ this.tcpClient.disconnect();
458148
+ } catch {
458149
+ }
458150
+ }
458151
+ this.tcpClient = null;
458152
+ UnityTcpClientManager.resetInstance();
458153
+ return false;
458154
+ }
458032
458155
  console.log(`\u2705 Connected to Unity Bridge at ${host}:${port}`);
458033
458156
  this.emit("connected", { host, port });
458034
458157
  return true;
@@ -459525,7 +459648,108 @@ var BuiltinUpmManager = class _BuiltinUpmManager {
459525
459648
  console.log(...args);
459526
459649
  }
459527
459650
  }
459528
- async connect(port = 25916, host = "localhost") {
459651
+ normalizeProjectRootPath(input) {
459652
+ let normalizedInput = input;
459653
+ try {
459654
+ normalizedInput = fs73.realpathSync(normalizedInput);
459655
+ } catch {
459656
+ }
459657
+ let normalized2 = normalizedInput.replace(/\\/g, "/").replace(/\/+$/, "");
459658
+ if (process.platform === "win32") {
459659
+ normalized2 = normalized2.toLowerCase();
459660
+ }
459661
+ return normalized2;
459662
+ }
459663
+ formatHeartbeatAge(lastHeartbeat) {
459664
+ if (!lastHeartbeat || typeof lastHeartbeat !== "string") {
459665
+ return null;
459666
+ }
459667
+ const parsed = Date.parse(lastHeartbeat);
459668
+ if (Number.isNaN(parsed)) {
459669
+ return null;
459670
+ }
459671
+ const ageMs = Date.now() - parsed;
459672
+ if (ageMs < 0) {
459673
+ return null;
459674
+ }
459675
+ const ageSec = Math.round(ageMs / 100) / 10;
459676
+ return `${ageSec}s`;
459677
+ }
459678
+ getHeartbeatAgeSeconds(lastHeartbeat) {
459679
+ if (!lastHeartbeat || typeof lastHeartbeat !== "string") {
459680
+ return null;
459681
+ }
459682
+ const parsed = Date.parse(lastHeartbeat);
459683
+ if (Number.isNaN(parsed)) {
459684
+ return null;
459685
+ }
459686
+ const ageMs = Date.now() - parsed;
459687
+ if (ageMs < 0) {
459688
+ return 0;
459689
+ }
459690
+ return ageMs / 1e3;
459691
+ }
459692
+ deriveExpectedProjectRoot(unityConfig) {
459693
+ const unityConfigPath = path73.join(process.cwd(), ".com-unity-codely.json");
459694
+ const expectedProjectRoot = (() => {
459695
+ const projectPathRaw = typeof unityConfig?.project_path === "string" ? unityConfig.project_path : void 0;
459696
+ if (projectPathRaw && projectPathRaw.trim().length > 0) {
459697
+ const trimmed2 = projectPathRaw.replace(/[\\/]+$/, "");
459698
+ return path73.dirname(trimmed2);
459699
+ }
459700
+ return path73.dirname(unityConfigPath);
459701
+ })();
459702
+ return {
459703
+ expectedProjectRoot,
459704
+ unityConfigPath,
459705
+ unityLastHeartbeat: typeof unityConfig?.last_heartbeat === "string" ? unityConfig.last_heartbeat : void 0
459706
+ };
459707
+ }
459708
+ async verifyConnectedUnityProjectRootOrThrow(expectedProjectRoot, unityConfigPath, unityLastHeartbeat) {
459709
+ if (!expectedProjectRoot) {
459710
+ this.debugLog(
459711
+ "Skipping Unity project root verification: expectedProjectRoot unavailable"
459712
+ );
459713
+ return;
459714
+ }
459715
+ if (!this.tcpClient) {
459716
+ throw new Error("Cannot verify Unity project root: no TCP client");
459717
+ }
459718
+ let response;
459719
+ try {
459720
+ response = await this.tcpClient.sendCommand("manage_editor", {
459721
+ action: "get_project_root"
459722
+ });
459723
+ } catch (error2) {
459724
+ const message = error2 instanceof Error ? error2.message : String(error2);
459725
+ throw new Error(`Failed to verify Unity project root: ${message}`);
459726
+ }
459727
+ const inner = response?.data ?? response;
459728
+ const reportedRoot = inner?.data?.projectRoot ?? inner?.projectRoot ?? response?.data?.projectRoot;
459729
+ if (typeof reportedRoot !== "string" || reportedRoot.trim().length === 0) {
459730
+ throw new Error(
459731
+ `Unity project root verification returned invalid response: ${JSON.stringify(
459732
+ response
459733
+ )}`
459734
+ );
459735
+ }
459736
+ const expectedNorm = this.normalizeProjectRootPath(expectedProjectRoot);
459737
+ const reportedNorm = this.normalizeProjectRootPath(reportedRoot);
459738
+ if (expectedNorm !== reportedNorm) {
459739
+ const heartbeatAge = this.formatHeartbeatAge(unityLastHeartbeat);
459740
+ const heartbeatHint = unityLastHeartbeat ? ` (last_heartbeat: ${unityLastHeartbeat}${heartbeatAge ? `, age: ${heartbeatAge}` : ""})` : "";
459741
+ throw new Error(
459742
+ [
459743
+ `Connected Unity Bridge appears to belong to a different Unity project.`,
459744
+ `Target: ${this.status.host ?? "localhost"}:${this.status.port ?? "unknown"}`,
459745
+ `Expected project root (from ${unityConfigPath}): ${expectedProjectRoot}${heartbeatHint}`,
459746
+ `Unity reports project root: ${reportedRoot}`,
459747
+ `Hint: The config heartbeat may be stale, or you have another Unity project open on the same port. Open the correct Unity project (or regenerate .com-unity-codely.json) and retry.`
459748
+ ].join("\n")
459749
+ );
459750
+ }
459751
+ }
459752
+ async connect(port = 25916, host = "localhost", options2) {
459529
459753
  if (this.status.status === "connecting") {
459530
459754
  throw new Error("Already connecting to Unity server");
459531
459755
  }
@@ -459549,6 +459773,20 @@ var BuiltinUpmManager = class _BuiltinUpmManager {
459549
459773
  if (!connected) {
459550
459774
  throw new Error("Failed to establish TCP connection");
459551
459775
  }
459776
+ await this.verifyConnectedUnityProjectRootOrThrow(
459777
+ options2?.expectedProjectRoot ?? null,
459778
+ options2?.unityConfigPath ?? path73.join(process.cwd(), ".com-unity-codely.json"),
459779
+ options2?.unityLastHeartbeat
459780
+ );
459781
+ this.status = {
459782
+ status: "connected",
459783
+ host,
459784
+ port,
459785
+ lastConnected: /* @__PURE__ */ new Date(),
459786
+ toolsAvailable: 10
459787
+ };
459788
+ this.debugLog(`\u2705 Connected to Unity TCP server on ${host}:${port}`);
459789
+ await this.notifyConnectionEstablished();
459552
459790
  } catch (error2) {
459553
459791
  this.status = {
459554
459792
  status: "error",
@@ -459573,27 +459811,38 @@ var BuiltinUpmManager = class _BuiltinUpmManager {
459573
459811
  }
459574
459812
  const host = unityConfig.unity_host || "localhost";
459575
459813
  const port = unityConfig.unity_port;
459814
+ const { expectedProjectRoot, unityConfigPath, unityLastHeartbeat } = this.deriveExpectedProjectRoot(unityConfig);
459815
+ const envMaxAgeRaw = process.env.CODELY_UNITY_HEARTBEAT_MAX_AGE_S;
459816
+ const envMaxAge = envMaxAgeRaw ? Number.parseInt(envMaxAgeRaw, 10) : Number.NaN;
459817
+ const maxAgeS = Number.isFinite(envMaxAge) && envMaxAge >= 0 ? envMaxAge : 60;
459818
+ const heartbeatAgeS = this.getHeartbeatAgeSeconds(unityLastHeartbeat);
459819
+ if (maxAgeS > 0 && heartbeatAgeS !== null && heartbeatAgeS > maxAgeS) {
459820
+ const ageRounded = Math.floor(heartbeatAgeS);
459821
+ const ageHint = this.formatHeartbeatAge(unityLastHeartbeat);
459822
+ throw new Error(
459823
+ [
459824
+ `Unity heartbeat is stale; refusing to connect.`,
459825
+ `Config: ${unityConfigPath}`,
459826
+ `last_heartbeat: ${unityLastHeartbeat ?? "n/a"}${ageHint ? ` (age: ${ageHint})` : ""}`,
459827
+ `age_seconds: ${ageRounded}, max_allowed_seconds: ${maxAgeS}`,
459828
+ `Hint: Open the correct Unity project to refresh heartbeat (or set CODELY_UNITY_HEARTBEAT_MAX_AGE_S=0 to disable fail-fast).`
459829
+ ].join("\n")
459830
+ );
459831
+ }
459576
459832
  this.debugLog(
459577
459833
  `\u{1F4D6} Unity config: ${host}:${port} (reason: ${unityConfig.reason}, reloading: ${unityConfig.reloading})`
459578
459834
  );
459579
- await this.connect(port, host);
459835
+ await this.connect(port, host, {
459836
+ expectedProjectRoot,
459837
+ unityConfigPath,
459838
+ unityLastHeartbeat
459839
+ });
459580
459840
  }
459581
459841
  /**
459582
459842
  * Setup TCP client event handlers
459583
459843
  */
459584
459844
  setupEventHandlers(host, port) {
459585
459845
  if (!this.tcpClient) return;
459586
- this.tcpClient.on("connected", async () => {
459587
- this.status = {
459588
- status: "connected",
459589
- host,
459590
- port,
459591
- lastConnected: /* @__PURE__ */ new Date(),
459592
- toolsAvailable: 10
459593
- };
459594
- this.debugLog(`\u2705 Connected to Unity TCP server on ${host}:${port}`);
459595
- await this.notifyConnectionEstablished();
459596
- });
459597
459846
  this.tcpClient.on("error", (error2) => {
459598
459847
  this.status = {
459599
459848
  status: "error",
@@ -484292,6 +484541,7 @@ var RenderThinkBlockInternal = ({
484292
484541
  terminalWidth: _terminalWidth
484293
484542
  }) => {
484294
484543
  const MAX_VISIBLE_THINK_LINES = 10;
484544
+ const MAX_VISIBLE_THINK_CHARS_WHEN_COLLAPSED = 500;
484295
484545
  const shouldCollapse = isPending && isStreaming;
484296
484546
  const filteredContent = content.filter((line) => line.trim().length > 0);
484297
484547
  if (filteredContent.length === 0) {
@@ -484303,8 +484553,41 @@ var RenderThinkBlockInternal = ({
484303
484553
  if (cleanedContent.length === 0) {
484304
484554
  return null;
484305
484555
  }
484306
- const hiddenLineCount = shouldCollapse ? Math.max(0, cleanedContent.length - MAX_VISIBLE_THINK_LINES) : 0;
484307
- const visibleContent = shouldCollapse && hiddenLineCount > 0 ? cleanedContent.slice(-MAX_VISIBLE_THINK_LINES) : cleanedContent;
484556
+ let visibleContent = cleanedContent;
484557
+ let hiddenLineCount = 0;
484558
+ if (shouldCollapse) {
484559
+ const lastIndex = cleanedContent.length - 1;
484560
+ const lastLine = cleanedContent[lastIndex] ?? "";
484561
+ let lastOverlongIndex = -1;
484562
+ for (let i3 = lastIndex; i3 >= 0; i3--) {
484563
+ if (cleanedContent[i3].length > MAX_VISIBLE_THINK_CHARS_WHEN_COLLAPSED) {
484564
+ lastOverlongIndex = i3;
484565
+ break;
484566
+ }
484567
+ }
484568
+ if (lastLine.length > MAX_VISIBLE_THINK_CHARS_WHEN_COLLAPSED) {
484569
+ visibleContent = [lastLine];
484570
+ hiddenLineCount = Math.max(0, cleanedContent.length - 1);
484571
+ } else {
484572
+ const resetStartIndex = lastOverlongIndex === -1 ? 0 : lastOverlongIndex + 1;
484573
+ const candidate = cleanedContent.slice(resetStartIndex);
484574
+ const selectedReversed = [];
484575
+ let totalChars = 0;
484576
+ for (let i3 = candidate.length - 1; i3 >= 0; i3--) {
484577
+ if (selectedReversed.length >= MAX_VISIBLE_THINK_LINES) break;
484578
+ const line = candidate[i3];
484579
+ const nextTotal = totalChars + line.length;
484580
+ if (nextTotal > MAX_VISIBLE_THINK_CHARS_WHEN_COLLAPSED) break;
484581
+ selectedReversed.push(line);
484582
+ totalChars = nextTotal;
484583
+ }
484584
+ if (selectedReversed.length === 0 && candidate.length > 0) {
484585
+ selectedReversed.push(candidate[candidate.length - 1]);
484586
+ }
484587
+ visibleContent = selectedReversed.reverse();
484588
+ hiddenLineCount = resetStartIndex + Math.max(0, candidate.length - visibleContent.length);
484589
+ }
484590
+ }
484308
484591
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
484309
484592
  Box_default,
484310
484593
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unity-china/codely-cli",
3
- "version": "1.0.0-beta.35",
3
+ "version": "1.0.0-beta.37",
4
4
  "engines": {
5
5
  "node": ">=20.0.0"
6
6
  },