Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions Docs~/UnityCliPluginSync_zh.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,48 @@
# unity-cli-plugin 协议同步记录

## 2026-07-24:`editor/console.get` 有界诊断读取

新增只读内置命令 `editor/console.get`。接口只包含一个可选参数:

```json
{
"afterMarkerId": "editor/console.mark 返回的 32 位十六进制 id"
}
```

- 省略参数时读取 Unity 2022 `Editor.log` 的最近有界窗口;
- 传入 marker id 时只返回该 marker 记录结束后的日志;
- marker 格式非法时返回 `validation_error`;格式正确但在最近 8 MiB 日志快照内
找不到时返回 `system_error`,不会退化为当前日志尾部,也不能据此重跑结果未明的
原操作;
- 调用开始时固定文件长度,调用期间新增的日志不进入本次结果;
- 不读取或修改 Unity Console 的搜索、级别、折叠、清理选项;
- `resultJson` 的 UTF-8 大小硬限制为 16 KiB。

为了让 marker 边界不可被 label 伪造,`editor/console.mark` 的 `label` 现在限制为
单行、最多 200 个字符,并拒绝保留的 marker 前缀。

成功结果固定为:

```json
{
"text": "按原顺序返回并统一为 LF 的日志文本",
"truncated": false
}
```

`truncated=true` 表示历史尾部或 marker 后内容因固定预算被省略。调用方不能在
该状态下声称窗口内不存在其他诊断。推荐的复杂工作流是:

```text
editor/console.mark → 执行操作 → wait-ready / diagnose
→ editor/console.get(afterMarkerId=<mark id>)
```

该命令刻意不提供分页、正则、任意日志路径、source 选择或可调输出上限,避免把
日志查询复杂度和无界 token 成本暴露给 Agent。`console.mark` 的 marker 格式和
编辑器日志路径解析也已收拢到同一个内部模块。

## 2026-07-24:HTTP protocol v2 invocation 去重与诊断字段

本次将 `ConsoleServiceConfig.ProtocolVersion` 从 1 升为 2,package 版本不变。
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Tab completion works for both command names and argument names.

## 📋 Built-in Actions

59 built-in commands across 13 namespaces, covering editor control, scene manipulation, asset management, and more.
60 built-in commands across 13 namespaces, covering editor control, scene manipulation, asset management, and more.

| Namespace | Action | Description |
|-----------|--------|-------------|
Expand Down Expand Up @@ -244,6 +244,7 @@ Tab completion works for both command names and argument names.
| | `window.open` | Open an editor window by type name |
| | `console.clear` | Clear the editor console |
| | `console.mark` | Write a searchable marker into the editor log and return the log file path |
| | `console.get` | Read bounded Editor log output, optionally after a console marker |
| **project** | `scene.list` | List all scenes in the project |
| | `scene.open` | Open a scene by path |
| | `scene.save` | Save the current scene |
Expand Down
3 changes: 2 additions & 1 deletion README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Tab 补全支持命令名和参数名。

## 📋 内置 Action

13 个命名空间,59 个内置命令,覆盖编辑器控制、场景操作、资产管理等常见场景。
13 个命名空间,60 个内置命令,覆盖编辑器控制、场景操作、资产管理等常见场景。

| 命名空间 | Action | 说明 |
|----------|--------|------|
Expand Down Expand Up @@ -244,6 +244,7 @@ Tab 补全支持命令名和参数名。
| | `window.open` | 通过类型名打开编辑器窗口 |
| | `console.clear` | 清空编辑器控制台 |
| | `console.mark` | 向编辑器日志写入可搜索标记并返回日志文件路径 |
| | `console.get` | 读取有界的编辑器日志,可选从控制台标记之后开始 |
| **project** | `scene.list` | 列出项目中所有场景 |
| | `scene.open` | 通过路径打开场景 |
| | `scene.save` | 保存当前场景 |
Expand Down
88 changes: 5 additions & 83 deletions Runtime/Service/Commands/Handlers/EditorCommandActions.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
#if UNITY_EDITOR
using System.Globalization;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEngine;
Expand Down Expand Up @@ -46,16 +44,6 @@ private sealed class PlaymodeStatusResult
public bool isCompiling;
}

[Serializable]
private sealed class ConsoleMarkResult
{
public string logPath = "";
public string id = "";
public string label = "";
public string timestampUtc = "";
public string markerText = "";
}

private enum PlaymodeLifecycleState
{
EditMode = 0,
Expand Down Expand Up @@ -173,28 +161,12 @@ private static CommandResponse ClearConsole()
}

[CommandAction("editor", "console.mark", editorOnly: true, summary: "Write a searchable marker into the editor log and return the log file path")]
private static CommandResponse MarkConsole(string label = "")
{
var markerId = Guid.NewGuid().ToString("N");
var timestampUtc = DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture);
var trimmedLabel = (label ?? "").Trim();
var markerText = string.IsNullOrEmpty(trimmedLabel)
? $"[C#Console][ConsoleMark] id={markerId} utc={timestampUtc}"
: $"[C#Console][ConsoleMark] id={markerId} utc={timestampUtc} label={trimmedLabel}";
private static CommandResponse MarkConsole(string label = "") =>
EditorConsoleDiagnostics.Mark(label);

UnityEngine.Debug.Log(markerText);

var result = new ConsoleMarkResult
{
logPath = ResolveEditorLogPath(),
id = markerId,
label = trimmedLabel,
timestampUtc = timestampUtc,
markerText = markerText
};

return CommandResponseFactory.Ok($"Wrote console marker '{markerId}'", JsonUtility.ToJson(result));
}
[CommandAction("editor", "console.get", editorOnly: true, summary: "Read a bounded Unity Editor log window, optionally after a console marker")]
private static CommandResponse GetConsole(string afterMarkerId = "") =>
EditorConsoleDiagnostics.Get(afterMarkerId);

private static string ValidatePlaymodeTransition(bool enter)
{
Expand Down Expand Up @@ -339,56 +311,6 @@ private static bool ClearConsoleEntries()
return true;
}

private static string ResolveEditorLogPath()
{
try
{
if (!string.IsNullOrEmpty(Application.consoleLogPath))
{
return Application.consoleLogPath;
}
}
catch
{
// Fall back to Unity's default editor log locations below.
}

try
{
if (Application.platform == RuntimePlatform.WindowsEditor)
{
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
if (!string.IsNullOrEmpty(localAppData))
{
return Path.Combine(localAppData, "Unity", "Editor", "Editor.log");
}
}

if (Application.platform == RuntimePlatform.OSXEditor)
{
var home = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
if (!string.IsNullOrEmpty(home))
{
return Path.Combine(home, "Library", "Logs", "Unity", "Editor.log");
}
}

if (Application.platform == RuntimePlatform.LinuxEditor)
{
var home = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
if (!string.IsNullOrEmpty(home))
{
return Path.Combine(home, ".config", "unity3d", "Editor.log");
}
}
}
catch
{
// Ignore fallback resolution failures and return empty below.
}

return "";
}
#endif
}
}
Loading