@alpsckr/unitycli 0.4.0 → 0.4.2

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 (98) hide show
  1. package/README.md +111 -299
  2. package/contracts/init-contract.json +64 -0
  3. package/contracts/instances-contract.json +49 -0
  4. package/contracts/package-assembly-closure.json +33 -0
  5. package/contracts/package-files.json +1953 -0
  6. package/dist/bridge/session-supervisor.d.ts +2 -0
  7. package/dist/bridge/session-supervisor.js +52 -19
  8. package/dist/bridge/session-supervisor.js.map +1 -1
  9. package/dist/cli-commands/command.js +33 -15
  10. package/dist/cli-commands/command.js.map +1 -1
  11. package/dist/cli-commands/init-discovery.d.ts +11 -0
  12. package/dist/cli-commands/init-discovery.js +185 -0
  13. package/dist/cli-commands/init-discovery.js.map +1 -0
  14. package/dist/cli-commands/init-help.d.ts +3 -0
  15. package/dist/cli-commands/init-help.js +41 -0
  16. package/dist/cli-commands/init-help.js.map +1 -0
  17. package/dist/cli-commands/init-skill.d.ts +10 -0
  18. package/dist/cli-commands/init-skill.js +171 -0
  19. package/dist/cli-commands/init-skill.js.map +1 -0
  20. package/dist/cli-commands/instances.d.ts +4 -0
  21. package/dist/cli-commands/instances.js +90 -0
  22. package/dist/cli-commands/instances.js.map +1 -0
  23. package/dist/cli-commands/package.d.ts +2 -2
  24. package/dist/cli-commands/package.js +97 -130
  25. package/dist/cli-commands/package.js.map +1 -1
  26. package/dist/cli-commands/skill-installer.d.ts +29 -13
  27. package/dist/cli-commands/skill-installer.js +127 -88
  28. package/dist/cli-commands/skill-installer.js.map +1 -1
  29. package/dist/cli-commands/types.d.ts +4 -0
  30. package/dist/cli.d.ts +1 -1
  31. package/dist/cli.js +46 -37
  32. package/dist/cli.js.map +1 -1
  33. package/dist/contracts/command-contract.js +1 -0
  34. package/dist/contracts/command-contract.js.map +1 -1
  35. package/dist/doctor.js +1 -1
  36. package/dist/doctor.js.map +1 -1
  37. package/dist/instances.d.ts +1 -1
  38. package/dist/instances.js +63 -38
  39. package/dist/instances.js.map +1 -1
  40. package/dist/output.d.ts +4 -4
  41. package/dist/output.js +3 -4
  42. package/dist/output.js.map +1 -1
  43. package/dist/package-manager.d.ts +47 -2
  44. package/dist/package-manager.js +267 -16
  45. package/dist/package-manager.js.map +1 -1
  46. package/dist/tools/.generated-schemas.js +2 -2
  47. package/dist/tools/.generated-schemas.js.map +1 -1
  48. package/dist/tools/commands.js +11 -4
  49. package/dist/tools/commands.js.map +1 -1
  50. package/dist/tools/dispatcher.js +1 -1
  51. package/dist/tools/dispatcher.js.map +1 -1
  52. package/dist/tools/tools/group-list.d.ts +4 -8
  53. package/dist/tools/tools/group-list.js +12 -13
  54. package/dist/tools/tools/group-list.js.map +1 -1
  55. package/dist/tools/tools/pagination.d.ts +17 -0
  56. package/dist/tools/tools/pagination.js +28 -0
  57. package/dist/tools/tools/pagination.js.map +1 -0
  58. package/dist/tools/tools/search.d.ts +3 -5
  59. package/dist/tools/tools/search.js +12 -12
  60. package/dist/tools/tools/search.js.map +1 -1
  61. package/dist/unity-project-processes.d.ts +7 -0
  62. package/dist/unity-project-processes.js +54 -0
  63. package/dist/unity-project-processes.js.map +1 -1
  64. package/docs/README.md +7 -4
  65. package/docs/architecture.md +103 -0
  66. package/docs/availability-differences.md +1 -1
  67. package/docs/command-execution.md +6 -1
  68. package/docs/development.md +91 -0
  69. package/docs/error-codes.md +21 -5
  70. package/docs/extensions.md +13 -13
  71. package/docs/target-and-instance.md +6 -4
  72. package/docs/tool-discovery.md +12 -10
  73. package/docs/tool-execution.md +3 -2
  74. package/package.json +10 -4
  75. package/schemas/init.schema.json +209 -0
  76. package/schemas/instances.schema.json +104 -0
  77. package/skills/unitycli/SKILL.md +18 -6
  78. package/skills/unitycli/manifest.json +2 -2
  79. package/skills/unitycli/references/custom-tools.md +3 -3
  80. package/skills/unitycli/references/operation-protocol.md +6 -4
  81. package/skills/unitycli/reports/output_quality_scorecard.md +1 -1
  82. package/skills/unitycli/reports/trust-report.md +1 -1
  83. package/unitypkg/Editor/Bridge/BridgeCommandRegistry.cs +1 -0
  84. package/unitypkg/Editor/Bridge/BridgeWorkQueue.cs +18 -6
  85. package/unitypkg/Editor/Infrastructure/CodeExecSupport.cs +8 -77
  86. package/unitypkg/Editor/Infrastructure/UnityCliInstanceCleanup.cs +295 -0
  87. package/unitypkg/Editor/Infrastructure/UnityCliInstanceRegistry.cs +166 -10
  88. package/unitypkg/Editor/Infrastructure/UnityCliOperationCoordinator.cs +1 -0
  89. package/unitypkg/Editor/UnityCliBridge.cs +5 -1
  90. package/unitypkg/Tests/Editor/UnityCliInstanceCleanupTests.cs +232 -0
  91. package/unitypkg/Tests/Editor/UnityCliInstancePublicationRetryTests.cs +143 -0
  92. package/unitypkg/UnityCli.Editor.asmdef +1 -5
  93. package/unitypkg/package.json +1 -1
  94. package/unitypkg/Editor/Roslyn/LICENSE.txt +0 -23
  95. package/unitypkg/Editor/Roslyn/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  96. package/unitypkg/Editor/Roslyn/Microsoft.CodeAnalysis.dll +0 -0
  97. package/unitypkg/Editor/Roslyn/System.Collections.Immutable.dll +0 -0
  98. package/unitypkg/Editor/Roslyn/System.Reflection.Metadata.dll +0 -0
@@ -0,0 +1,185 @@
1
+ import { lstat, readFile, readdir, realpath, stat } from "node:fs/promises";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { inspectPackageBridge } from "../package-manager.js";
5
+ import { resolveProjectIdentityAsync } from "../project-identity.js";
6
+ import { failure, success } from "../output.js";
7
+ import { findUnityProjectProcesses } from "../unity-project-processes.js";
8
+ import { findSkillSourcePath, inspectSkillTarget, resolveSkillTarget } from "./skill-installer.js";
9
+ const maxDescendantDepth = 4;
10
+ const maxScannedDirectories = 2000;
11
+ const maxUnityProjects = 100;
12
+ const ignoredDirectories = new Set([".git", "node_modules", "library", "temp", "logs", "obj"]);
13
+ async function directoryExists(path) { try {
14
+ return (await stat(path)).isDirectory();
15
+ }
16
+ catch {
17
+ return false;
18
+ } }
19
+ async function readUnityVersion(path) {
20
+ try {
21
+ return /^m_EditorVersion:\s*(.+?)\s*$/m.exec(await readFile(join(path, "ProjectSettings", "ProjectVersion.txt"), "utf8"))?.[1];
22
+ }
23
+ catch {
24
+ return undefined;
25
+ }
26
+ }
27
+ async function unityProjectCandidate(path, relation, depth) {
28
+ try {
29
+ const info = await lstat(path);
30
+ if (!info.isDirectory() || info.isSymbolicLink())
31
+ return undefined;
32
+ const [assets, manifest, unityVersion] = await Promise.all([
33
+ directoryExists(join(path, "Assets")),
34
+ readFile(join(path, "Packages", "manifest.json"), "utf8").then((text) => { JSON.parse(text); return true; }).catch(() => false),
35
+ readUnityVersion(path),
36
+ ]);
37
+ return assets && manifest && unityVersion ? { path: await realpath(path), unityVersion, relation, depth } : undefined;
38
+ }
39
+ catch {
40
+ return undefined;
41
+ }
42
+ }
43
+ function pathIdentity(path) { return process.platform === "win32" ? path.toLowerCase() : path; }
44
+ async function findRepositoryRoot(cwd) {
45
+ let current = cwd;
46
+ for (let depth = 0; depth < 64; depth += 1) {
47
+ try {
48
+ await lstat(join(current, ".git"));
49
+ return current;
50
+ }
51
+ catch { /* continue */ }
52
+ const parent = dirname(current);
53
+ if (parent === current)
54
+ break;
55
+ current = parent;
56
+ }
57
+ return undefined;
58
+ }
59
+ async function discoverUnityProjects(cwd) {
60
+ const projects = [];
61
+ const identities = new Set();
62
+ const add = (candidate) => {
63
+ if (!candidate || projects.length >= maxUnityProjects || identities.has(pathIdentity(candidate.path)))
64
+ return;
65
+ identities.add(pathIdentity(candidate.path));
66
+ projects.push(candidate);
67
+ };
68
+ let ancestor = cwd;
69
+ for (let depth = 0; depth < 64; depth += 1) {
70
+ const candidate = await unityProjectCandidate(ancestor, depth === 0 ? "cwd" : "ancestor", depth);
71
+ if (candidate)
72
+ return { projects: [candidate], scannedDirectories: 0, truncated: false };
73
+ const parent = dirname(ancestor);
74
+ if (parent === ancestor)
75
+ break;
76
+ ancestor = parent;
77
+ }
78
+ const queue = [{ path: cwd, depth: 0 }];
79
+ let scannedDirectories = 0;
80
+ let truncated = false;
81
+ for (let index = 0; index < queue.length; index += 1) {
82
+ const item = queue[index];
83
+ if (++scannedDirectories > maxScannedDirectories || projects.length >= maxUnityProjects) {
84
+ truncated = true;
85
+ break;
86
+ }
87
+ if (item.depth > 0)
88
+ add(await unityProjectCandidate(item.path, "descendant", item.depth));
89
+ if (item.depth >= maxDescendantDepth)
90
+ continue;
91
+ let entries;
92
+ try {
93
+ entries = await readdir(item.path, { withFileTypes: true });
94
+ }
95
+ catch {
96
+ continue;
97
+ }
98
+ for (const entry of entries.sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0)) {
99
+ if (!entry.isDirectory() || entry.isSymbolicLink() || ignoredDirectories.has(entry.name.toLowerCase()))
100
+ continue;
101
+ if (queue.length >= maxScannedDirectories) {
102
+ truncated = true;
103
+ break;
104
+ }
105
+ queue.push({ path: join(item.path, entry.name), depth: item.depth + 1 });
106
+ }
107
+ }
108
+ projects.sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
109
+ return { projects, scannedDirectories: Math.min(scannedDirectories, maxScannedDirectories), truncated };
110
+ }
111
+ /** 当前项目常见路径返回完整安装计划;多项目搜索只保留选择所需信息。 */
112
+ export async function discoverInitEnvironment(cwdInput, userHomeInput, runtime = {}) {
113
+ const cwd = await realpath(resolve(cwdInput));
114
+ await realpath(resolve(userHomeInput));
115
+ const repositoryRoot = await findRepositoryRoot(cwd);
116
+ const discovery = await discoverUnityProjects(cwd);
117
+ const inspectBridge = runtime.inspectPackageBridge ?? inspectPackageBridge;
118
+ const findEditors = runtime.findUnityProjectProcesses ?? findUnityProjectProcesses;
119
+ const inspectLiveState = discovery.projects.length === 1;
120
+ const unityProjects = [];
121
+ for (const project of discovery.projects) {
122
+ let bridge = { status: "not-inspected" };
123
+ let editor = { status: "not-inspected" };
124
+ if (inspectLiveState) {
125
+ try {
126
+ const inspection = await inspectBridge(project.path);
127
+ bridge = {
128
+ status: inspection.status,
129
+ availableVersion: inspection.availableVersion,
130
+ ...(inspection.installedVersion ? { installedVersion: inspection.installedVersion } : {}),
131
+ ...(inspection.reasonCode ? { reasonCode: inspection.reasonCode } : {}),
132
+ };
133
+ }
134
+ catch {
135
+ bridge = { status: "unverifiable", reasonCode: "INIT_BRIDGE_STATE_UNVERIFIABLE" };
136
+ }
137
+ try {
138
+ const identity = await resolveProjectIdentityAsync(project.path, { timeoutMs: 3_000 });
139
+ const processes = await findEditors(identity.instanceId, identity.canonicalProjectPath, 3_000);
140
+ editor = { status: processes.length ? "running" : "stopped", processCount: processes.length };
141
+ }
142
+ catch {
143
+ editor = { status: "unverifiable" };
144
+ }
145
+ }
146
+ unityProjects.push({ ...project, bridge, editor });
147
+ }
148
+ const sourcePath = await findSkillSourcePath();
149
+ const recommendedTarget = resolveSkillTarget(cwd, ".agents");
150
+ const recommendedSkill = await inspectSkillTarget(sourcePath, recommendedTarget);
151
+ const requiredDecisions = [];
152
+ if (unityProjects.length > 1) {
153
+ requiredDecisions.push({ id: "bridgeProjects", question: "Which discovered Unity projects should receive the UnityCLI Bridge?", choices: unityProjects.map((project) => project.path), multiple: true });
154
+ }
155
+ else if ((unityProjects[0]?.editor?.status) === "running") {
156
+ requiredDecisions.push({ id: "closeEditor", question: "May UnityCLI normally close the exact target Unity project before Bridge installation?", projectPath: unityProjects[0].path, multiple: false });
157
+ }
158
+ return {
159
+ action: "init_discover",
160
+ cwd,
161
+ repositoryRoot: repositoryRoot ?? null,
162
+ unityProjects,
163
+ skill: { workspace: cwd, recommendedTarget, explicitTargetSupported: true, ...recommendedSkill },
164
+ requiredDecisions,
165
+ ...(discovery.scannedDirectories > 0 || discovery.truncated ? { scan: { scannedDirectories: discovery.scannedDirectories, truncated: discovery.truncated, maxDescendantDepth, maxScannedDirectories, maxUnityProjects } } : {}),
166
+ nextActions: requiredDecisions.length
167
+ ? ["Ask only the returned required decisions; keep any target the user already specified."]
168
+ : ["Use the unique current project and the user's explicit Skill target, or the recommended workspace target when none was specified."],
169
+ };
170
+ }
171
+ /** 从当前工作目录有界发现安装现场,不修改文件或进程。 */
172
+ export async function handleInitDiscover(args, flags, runtime, requestId) {
173
+ if (args.length)
174
+ return failure(requestId, "E_INIT_ARGUMENT_UNEXPECTED", "init discover does not accept positional arguments.", ["Run `unitycli init discover` without additional arguments."]);
175
+ const unknown = Object.keys(flags).find((name) => name !== "pretty");
176
+ if (unknown)
177
+ return failure(requestId, "E_UNKNOWN_OPTION", `Unknown option for init discover: --${unknown}.`, ["Run `unitycli init discover` without options."], { option: `--${unknown}` });
178
+ try {
179
+ return success(requestId, await discoverInitEnvironment(process.cwd(), homedir(), { findUnityProjectProcesses: runtime.findUnityProjectProcesses }));
180
+ }
181
+ catch (error) {
182
+ return failure(requestId, "INIT_DISCOVERY_FAILED", error instanceof Error ? error.message : String(error), ["Run `unitycli init discover` from an existing readable working directory."]);
183
+ }
184
+ }
185
+ //# sourceMappingURL=init-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-discovery.js","sourceRoot":"","sources":["../../src/cli-commands/init-discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CliResult } from "../types.js";
2
+ /** 返回静态、自足、无现场读取的 AI 安装协议。 */
3
+ export declare function handleInitHelp(args: string[], flags: Record<string, string | boolean>, requestId: string): CliResult;
@@ -0,0 +1,41 @@
1
+ import { failure, success } from "../output.js";
2
+ const commands = {
3
+ discover: "unitycli init discover",
4
+ packageInstall: "unitycli init package --project <UnityProject>",
5
+ packageInstallAndCloseEditor: "unitycli init package --project <UnityProject> --close-editor",
6
+ packageCheck: "unitycli init package --project <UnityProject> --check",
7
+ explicitSkillInstall: "unitycli init skill --target <SkillDirectory>",
8
+ explicitSkillCheck: "unitycli init skill --target <SkillDirectory> --check",
9
+ workspaceSkillInstall: "unitycli init skill --agent <.agents|claude> --scope workspace --workspace <path>",
10
+ workspaceSkillCheck: "unitycli init skill --agent <.agents|claude> --scope workspace --workspace <path> --check",
11
+ userSkillInstall: "unitycli init skill --agent <.agents|claude> --scope user",
12
+ userSkillCheck: "unitycli init skill --agent <.agents|claude> --scope user --check",
13
+ };
14
+ /** 返回静态、自足、无现场读取的 AI 安装协议。 */
15
+ export function handleInitHelp(args, flags, requestId) {
16
+ if (args.length)
17
+ return failure(requestId, "E_INIT_ARGUMENT_UNEXPECTED", "init help does not accept positional arguments.", ["Run `unitycli init help` without additional arguments."]);
18
+ const unknown = Object.keys(flags).find((name) => name !== "pretty");
19
+ if (unknown)
20
+ return failure(requestId, "E_UNKNOWN_OPTION", `Unknown option for init help: --${unknown}.`, ["Run `unitycli init help` without options."], { option: `--${unknown}` });
21
+ return success(requestId, {
22
+ action: "init_help",
23
+ audience: "ai",
24
+ protocolVersion: 2,
25
+ aiInstructions: [
26
+ "Run `unitycli init discover` from the user's current working directory and use its compact current-project plan.",
27
+ "Treat every project, scope, host, or Skill directory the user already specified as final; never ask them to choose it again. Use `init skill --target` for an explicit directory such as `.pi/skills/unitycli`.",
28
+ "When discovery returns one current or ancestor Unity project, use it without another project-selection question. Ask only entries present in discovery.requiredDecisions.",
29
+ "If the exact target Unity project is running, ask once whether it may be closed normally. After approval use `init package --close-editor`; never force-terminate Unity or decide an unsaved-scene prompt for the user.",
30
+ "Bridge and Skill installation are independent authorized effects. A failure blocks only that effect and its check; continue other user-authorized independent installation effects and report every final status.",
31
+ "Run one corresponding `--check` after each successful package or Skill installation and verify its business status.",
32
+ "For a recoverable installation error, follow its exact nextActions after the required external state changes. Do not create unbounded retries or change the user's selected targets.",
33
+ "Do not start or restart Unity Editor during installation. Normal close is allowed only for the exact project and only through the explicitly authorized --close-editor package call.",
34
+ "The user's installation request authorizes the selected package and Skill effects; do not add confirmation gates except the separate close-Editor decision.",
35
+ ],
36
+ commands,
37
+ nextCommand: commands.discover,
38
+ nextActions: [commands.discover],
39
+ });
40
+ }
41
+ //# sourceMappingURL=init-help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-help.js","sourceRoot":"","sources":["../../src/cli-commands/init-help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,QAAQ,GAAG;IACf,QAAQ,EAAE,wBAAwB;IAClC,cAAc,EAAE,gDAAgD;IAChE,4BAA4B,EAAE,+DAA+D;IAC7F,YAAY,EAAE,wDAAwD;IACtE,oBAAoB,EAAE,+CAA+C;IACrE,kBAAkB,EAAE,uDAAuD;IAC3E,qBAAqB,EAAE,mFAAmF;IAC1G,mBAAmB,EAAE,2FAA2F;IAChH,gBAAgB,EAAE,2DAA2D;IAC7E,cAAc,EAAE,mEAAmE;CAC3E,CAAC;AAEX,8BAA8B;AAC9B,MAAM,UAAU,cAAc,CAAC,IAAc,EAAE,KAAuC,EAAE,SAAiB;IACvG,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC,SAAS,EAAE,4BAA4B,EAAE,iDAAiD,EAAE,CAAC,wDAAwD,CAAC,CAAC,CAAC;IACxL,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IACrE,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC,SAAS,EAAE,kBAAkB,EAAE,mCAAmC,OAAO,GAAG,EAAE,CAAC,2CAA2C,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,OAAO,EAAE,EAAE,CAAC,CAAC;IACrL,OAAO,OAAO,CAAC,SAAS,EAAE;QACxB,MAAM,EAAE,WAAW;QACnB,QAAQ,EAAE,IAAI;QACd,eAAe,EAAE,CAAC;QAClB,cAAc,EAAE;YACd,kHAAkH;YAClH,iNAAiN;YACjN,2KAA2K;YAC3K,yNAAyN;YACzN,mNAAmN;YACnN,qHAAqH;YACrH,sLAAsL;YACtL,sLAAsL;YACtL,6JAA6J;SAC9J;QACD,QAAQ;QACR,WAAW,EAAE,QAAQ,CAAC,QAAQ;QAC9B,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;KACjC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { CliResult } from "../types.js";
2
+ import { type AgentKind } from "./skill-installer.js";
3
+ import type { Runtime } from "./types.js";
4
+ export type SkillScope = "workspace" | "user";
5
+ export declare function resolveInitSkillTarget(agent: AgentKind, scope: SkillScope, workspace: string | undefined, userHome: string): {
6
+ basePath: string;
7
+ targetPath: string;
8
+ };
9
+ /** 安装或只读检查一个预设agent目标或用户明确给出的精确Skill目录。 */
10
+ export declare function handleInitSkill(args: string[], flags: Record<string, string | boolean>, runtime: Runtime, requestId: string): Promise<CliResult>;
@@ -0,0 +1,171 @@
1
+ import { lstat, realpath, rm } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
4
+ import { getBoolean, getString } from "../args.js";
5
+ import { failure, success } from "../output.js";
6
+ import { agentSkillInstaller, findSkillSourcePath, inspectSkillTarget, installSkillTarget, parseAgentList, resolveSkillTarget, SkillInstallerError } from "./skill-installer.js";
7
+ export function resolveInitSkillTarget(agent, scope, workspace, userHome) {
8
+ const basePath = scope === "user" ? resolve(userHome) : resolve(workspace);
9
+ return { basePath, targetPath: resolveSkillTarget(basePath, agent) };
10
+ }
11
+ async function assertRealDirectory(path, label) {
12
+ try {
13
+ const info = await lstat(path);
14
+ if (!info.isDirectory() || info.isSymbolicLink())
15
+ throw new Error("not a real directory");
16
+ return await realpath(path);
17
+ }
18
+ catch {
19
+ throw new SkillInstallerError("E_SKILL_ROOT_INVALID", `${label} must be an existing real directory: ${path}`, [`Pass an existing non-linked ${label.toLowerCase()} path.`]);
20
+ }
21
+ }
22
+ async function rejectLinkedTargetAncestors(basePath, agent) {
23
+ const agentRoot = join(basePath, agent === ".agents" ? ".agents" : ".claude");
24
+ for (const path of [agentRoot, join(agentRoot, "skills"), join(agentRoot, "skills", "unitycli")]) {
25
+ try {
26
+ const info = await lstat(path);
27
+ if (info.isSymbolicLink() || !info.isDirectory())
28
+ throw new SkillInstallerError("E_SKILL_TARGET_UNSAFE", `Skill target ancestor must be a real directory: ${path}`, ["Replace the linked or non-directory target ancestor before retrying."]);
29
+ }
30
+ catch (error) {
31
+ if (error.code === "ENOENT")
32
+ continue;
33
+ throw error;
34
+ }
35
+ }
36
+ }
37
+ function timeout(flags) {
38
+ const raw = getString(flags, "timeout-ms");
39
+ if (raw === undefined)
40
+ return 60_000;
41
+ const value = Number(raw);
42
+ return Number.isSafeInteger(value) && value > 0 ? value : undefined;
43
+ }
44
+ /** 明确目标允许尚未创建,但所有既有祖先必须是真实目录且入口名固定为unitycli。 */
45
+ async function resolveExplicitSkillTarget(raw) {
46
+ const targetPath = resolve(raw);
47
+ if (basename(targetPath).toLowerCase() !== "unitycli") {
48
+ throw new SkillInstallerError("E_INIT_SKILL_TARGET_INVALID", "init skill --target must name the exact unitycli Skill directory.", ["Pass a path ending in the `unitycli` directory, such as `.pi/skills/unitycli`."]);
49
+ }
50
+ if (process.platform === "win32" && !/^[a-z]:\\/i.test(targetPath)) {
51
+ throw new SkillInstallerError("E_INIT_SKILL_TARGET_INVALID", "init skill --target must resolve to a fixed local Windows path.", ["Use a local drive path for the exact UnityCLI Skill directory."]);
52
+ }
53
+ if (targetPath.split(/[\\/]/).some((segment) => segment === ".unitycli-install")) {
54
+ throw new SkillInstallerError("E_INIT_SKILL_TARGET_INVALID", "init skill --target cannot be inside the installer transaction directory.", ["Choose the final UnityCLI Skill directory outside `.unitycli-install`."]);
55
+ }
56
+ let current = targetPath;
57
+ while (true) {
58
+ try {
59
+ const info = await lstat(current);
60
+ if (info.isSymbolicLink() || !info.isDirectory()) {
61
+ throw new SkillInstallerError("E_SKILL_TARGET_UNSAFE", `Skill target ancestors must be real directories: ${current}`, ["Replace the linked or non-directory target ancestor before retrying."]);
62
+ }
63
+ }
64
+ catch (error) {
65
+ if (error.code !== "ENOENT")
66
+ throw error;
67
+ }
68
+ const parent = dirname(current);
69
+ if (parent === current)
70
+ break;
71
+ current = parent;
72
+ }
73
+ return targetPath;
74
+ }
75
+ function pathContains(parent, child) {
76
+ const fromParent = relative(parent, child);
77
+ return fromParent === "" || (!fromParent.startsWith("..") && !isAbsolute(fromParent));
78
+ }
79
+ /** bundled source与target不得互相包含,避免安装事务改写自己的准源。 */
80
+ function rejectSkillSourceOverlap(sourcePath, targetPath) {
81
+ const sourceRoot = resolve(dirname(sourcePath));
82
+ const targetRoot = resolve(targetPath);
83
+ const normalize = (value) => process.platform === "win32" ? value.toLowerCase() : value;
84
+ const sourceIdentity = normalize(sourceRoot);
85
+ const targetIdentity = normalize(targetRoot);
86
+ if (pathContains(sourceIdentity, targetIdentity) || pathContains(targetIdentity, sourceIdentity)) {
87
+ throw new SkillInstallerError("E_SKILL_TARGET_OVERLAPS_SOURCE", "The selected Skill target overlaps the bundled UnityCLI Skill source.", ["Choose a separate installed Skill directory."]);
88
+ }
89
+ }
90
+ /** 安装或只读检查一个预设agent目标或用户明确给出的精确Skill目录。 */
91
+ export async function handleInitSkill(args, flags, runtime, requestId) {
92
+ if (args.length)
93
+ return failure(requestId, "E_INIT_ARGUMENT_UNEXPECTED", "init skill does not accept positional arguments.", ["Run `unitycli init skill` using only documented options."]);
94
+ const agentRaw = getString(flags, "agent");
95
+ const scopeRaw = getString(flags, "scope");
96
+ const workspaceRaw = getString(flags, "workspace");
97
+ const explicitTargetRaw = getString(flags, "target");
98
+ if (explicitTargetRaw && (agentRaw || scopeRaw || workspaceRaw)) {
99
+ return failure(requestId, "E_INIT_SKILL_TARGET_CONFLICT", "init skill --target cannot be combined with --agent, --scope, or --workspace.", ["Use either one exact --target directory or one preset agent/scope target."], { option: "--target" });
100
+ }
101
+ if (!explicitTargetRaw && !agentRaw)
102
+ return failure(requestId, "E_INIT_SKILL_TARGET_REQUIRED", "init skill requires either --target <SkillDirectory> or --agent <.agents|claude> with --scope.", ["Use the user's explicit Skill directory when provided; otherwise choose one preset host."], { options: ["--target", "--agent"] });
103
+ const timeoutMs = timeout(flags);
104
+ if (timeoutMs === undefined)
105
+ return failure(requestId, "E_INIT_TIMEOUT_INVALID", "init skill --timeout-ms must be a positive integer.", ["Pass --timeout-ms <positive-integer>."], { option: "--timeout-ms" });
106
+ const deadlineMs = Date.now() + timeoutMs;
107
+ try {
108
+ const sourcePath = await findSkillSourcePath();
109
+ if (explicitTargetRaw) {
110
+ const targetPath = await resolveExplicitSkillTarget(explicitTargetRaw);
111
+ rejectSkillSourceOverlap(sourcePath, targetPath);
112
+ const installCommand = `unitycli init skill --target ${JSON.stringify(targetPath)}`;
113
+ if (getBoolean(flags, "check")) {
114
+ const inspection = await inspectSkillTarget(sourcePath, targetPath);
115
+ return success(requestId, { action: "init_skill_check", target: targetPath, skill: inspection, nextActions: inspection.status === "installed" ? [] : [installCommand] });
116
+ }
117
+ const installRoot = join(dirname(targetPath), ".unitycli-install");
118
+ const change = await installSkillTarget(sourcePath, targetPath, installRoot, deadlineMs);
119
+ const inspection = await inspectSkillTarget(sourcePath, targetPath);
120
+ if (inspection.status !== "installed")
121
+ throw new SkillInstallerError("E_SKILL_INSTALL_PROJECTION_INVALID", "Skill installation did not reach an installed readback state.", ["Inspect the reported target before retrying."]);
122
+ await rm(installRoot, { recursive: true, force: true });
123
+ return success(requestId, { action: "init_skill", target: targetPath, changes: [change], skill: inspection, nextActions: [`${installCommand} --check`] });
124
+ }
125
+ let agent;
126
+ try {
127
+ const agents = parseAgentList(agentRaw);
128
+ if (agents.length !== 1)
129
+ throw new SkillInstallerError("E_INIT_AGENT_INVALID", "init skill accepts exactly one preset agent target.", ["Pass either --agent .agents or --agent claude."]);
130
+ agent = agents[0];
131
+ }
132
+ catch (error) {
133
+ if (error instanceof SkillInstallerError)
134
+ return failure(requestId, error.code, error.message, error.nextActions);
135
+ throw error;
136
+ }
137
+ if (scopeRaw !== "workspace" && scopeRaw !== "user")
138
+ return failure(requestId, "E_INIT_SCOPE_INVALID", "Preset Skill installation requires --scope <workspace|user>.", ["Choose workspace for the current project or user for the current Windows account."], { option: "--scope", actual: scopeRaw ?? null });
139
+ const scope = scopeRaw;
140
+ if (scope === "workspace" && !workspaceRaw)
141
+ return failure(requestId, "E_INIT_WORKSPACE_REQUIRED", "Workspace Skill scope requires --workspace <path>.", ["Pass the user's normal AI working directory."], { option: "--workspace" });
142
+ if (scope === "user" && workspaceRaw)
143
+ return failure(requestId, "E_INIT_WORKSPACE_FORBIDDEN", "User Skill scope does not accept --workspace.", ["Remove --workspace or choose --scope workspace."], { option: "--workspace" });
144
+ const baseCandidate = scope === "user" ? resolve(runtime.userHome ?? homedir()) : resolve(workspaceRaw);
145
+ const basePath = await assertRealDirectory(baseCandidate, scope === "user" ? "User home" : "Workspace");
146
+ await rejectLinkedTargetAncestors(basePath, agent);
147
+ const targetPath = resolveSkillTarget(basePath, agent);
148
+ if (getBoolean(flags, "check")) {
149
+ const inspection = await inspectSkillTarget(sourcePath, targetPath);
150
+ const installCommand = scope === "workspace"
151
+ ? `unitycli init skill --agent ${agent} --scope workspace --workspace ${JSON.stringify(basePath)}`
152
+ : `unitycli init skill --agent ${agent} --scope user`;
153
+ return success(requestId, { action: "init_skill_check", agent, scope, ...(scope === "workspace" ? { workspace: basePath } : {}), skill: inspection, nextActions: inspection.status === "installed" ? [] : [installCommand] });
154
+ }
155
+ const installRoot = scope === "user"
156
+ ? join(runtime.dataDir, ".temp", "skill-install", agent === ".agents" ? "agents" : agent)
157
+ : join(basePath, agent === ".agents" ? ".agents" : ".claude", "skills", ".unitycli-install");
158
+ const changes = await agentSkillInstaller.installForAgents([agent], sourcePath, basePath, deadlineMs, installRoot);
159
+ const inspection = await inspectSkillTarget(sourcePath, targetPath);
160
+ if (inspection.status !== "installed")
161
+ throw new SkillInstallerError("E_SKILL_INSTALL_PROJECTION_INVALID", "Skill installation did not reach an installed readback state.", ["Inspect the reported target before retrying."]);
162
+ await rm(installRoot, { recursive: true, force: true });
163
+ return success(requestId, { action: "init_skill", agent, scope, ...(scope === "workspace" ? { workspace: basePath } : {}), changes, skill: inspection, nextActions: ["Run the same init skill command with --check."] });
164
+ }
165
+ catch (error) {
166
+ if (error instanceof SkillInstallerError)
167
+ return failure(requestId, error.code, error.message, error.nextActions);
168
+ return failure(requestId, "INIT_SKILL_FAILED", error instanceof Error ? error.message : String(error), ["Inspect the Skill source and selected target before retrying."]);
169
+ }
170
+ }
171
+ //# sourceMappingURL=init-skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-skill.js","sourceRoot":"","sources":["../../src/cli-commands/init-skill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { CliResult } from "../types.js";
2
+ import type { Runtime } from "./types.js";
3
+ /** 顶层instances控制面:list纯读取,prune只授权当前Unity writer执行同一清理函数。 */
4
+ export declare function handleInstances(command: string | undefined, flags: Record<string, string | boolean>, runtime: Runtime, requestId: string): Promise<CliResult>;
@@ -0,0 +1,90 @@
1
+ import { executeBridgePayload, SessionSupervisor, SessionSupervisorError } from "../bridge/index.js";
2
+ import { handleInstancesCommand, instanceSelectionFailure } from "../instances.js";
3
+ import { failure, success } from "../output.js";
4
+ const DEFAULT_PRUNE_TIMEOUT_MS = 30_000;
5
+ /** 顶层instances控制面:list纯读取,prune只授权当前Unity writer执行同一清理函数。 */
6
+ export async function handleInstances(command, flags, runtime, requestId) {
7
+ const subCommand = command ?? "list";
8
+ if (subCommand !== "prune")
9
+ return handleInstancesCommand(subCommand, flags, runtime.dataDir, requestId);
10
+ return runWriterOwnedPrune(flags, runtime, requestId);
11
+ }
12
+ async function runWriterOwnedPrune(flags, runtime, requestId) {
13
+ const rawTimeout = flags["timeout-ms"];
14
+ const timeoutMs = rawTimeout === undefined ? DEFAULT_PRUNE_TIMEOUT_MS : typeof rawTimeout === "string" ? Number(rawTimeout) : Number.NaN;
15
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1) {
16
+ return failure(requestId, "E_SCHEMA_INVALID", "instances prune --timeout-ms must be a positive integer.", ["Pass --timeout-ms <positive-integer>."]);
17
+ }
18
+ const startedAtMs = Date.now();
19
+ const supervisor = new SessionSupervisor(flags, runtime);
20
+ try {
21
+ const admission = await supervisor.acquireRootAdmission({
22
+ requestId,
23
+ command: "instances.prune",
24
+ input: {},
25
+ dryRun: false,
26
+ target: "editor",
27
+ completionContractIdentity: "instances-prune-v1",
28
+ timeoutMs,
29
+ admissionAbsoluteDeadlineMs: startedAtMs + timeoutMs,
30
+ });
31
+ const result = await executeBridgePayload(requestId, "internal.instances.prune", {}, { ...flags, instance: admission.instanceId }, { ...runtime, rootAdmission: admission }, undefined, {
32
+ mode: "execute",
33
+ mutation: true,
34
+ absoluteDeadlineMs: admission.executionAbsoluteDeadlineMs,
35
+ });
36
+ await supervisor.completeRootAdmission(admission);
37
+ if (!result.ok)
38
+ return result;
39
+ const normalized = pruneResult(result.data);
40
+ if (!normalized) {
41
+ return failure(requestId, "E_BRIDGE_RESPONSE_INVALID", "Unity returned an invalid instances prune result.", [
42
+ "Update the selected UnityCLI Package so it matches the current CLI, then retry instances prune.",
43
+ ]);
44
+ }
45
+ return success(requestId, normalized);
46
+ }
47
+ catch (error) {
48
+ const selection = instanceSelectionFailure(requestId, error);
49
+ if (selection)
50
+ return selection;
51
+ if (error instanceof SessionSupervisorError) {
52
+ return failure(requestId, error.code, error.message, error.nextActions, error.details, {
53
+ transient: error.transient,
54
+ retryAfterMs: error.retryAfterMs,
55
+ });
56
+ }
57
+ return failure(requestId, "BRIDGE_CONNECTION_FAILED", error instanceof Error ? error.message : String(error), [
58
+ "Open the target Unity project, then retry unitycli instances prune from that project or pass --instance <id|projectPath|alias>.",
59
+ ], undefined, { transient: true, retryAfterMs: 100 });
60
+ }
61
+ }
62
+ function pruneResult(value) {
63
+ if (!exactObject(value, ["removed", "remaining", "deferred", "scanned", "truncated", "retention"]))
64
+ return undefined;
65
+ const root = value;
66
+ if (![root.removed, root.remaining, root.deferred, root.scanned].every(nonnegativeInteger) || typeof root.truncated !== "boolean")
67
+ return undefined;
68
+ if (!exactObject(root.retention, ["offlineMax", "damagedMax", "maxAgeDays", "scanLimit", "deleteLimit"]))
69
+ return undefined;
70
+ const retention = root.retention;
71
+ if (retention.offlineMax !== 100 || retention.damagedMax !== 20 || retention.maxAgeDays !== 30
72
+ || retention.scanLimit !== 2000 || retention.deleteLimit !== 20)
73
+ return undefined;
74
+ return {
75
+ removed: root.removed,
76
+ remaining: root.remaining,
77
+ deferred: root.deferred,
78
+ scanned: root.scanned,
79
+ truncated: root.truncated,
80
+ retention: { offlineMax: 100, damagedMax: 20, maxAgeDays: 30, scanLimit: 2000, deleteLimit: 20 },
81
+ };
82
+ }
83
+ function exactObject(value, keys) {
84
+ return !!value && typeof value === "object" && !Array.isArray(value)
85
+ && Object.keys(value).length === keys.length && keys.every((key) => Object.prototype.hasOwnProperty.call(value, key));
86
+ }
87
+ function nonnegativeInteger(value) {
88
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
89
+ }
90
+ //# sourceMappingURL=instances.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instances.js","sourceRoot":"","sources":["../../src/cli-commands/instances.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import type { CliResult } from "../types.js";
2
2
  import type { Runtime } from "./types.js";
3
- /** 安装 Core package、Agent Skill 和自动检测 Extension,并只返回文件系统 readback。 */
4
- export declare function handleInit(flags: Record<string, string | boolean>, runtime: Runtime, requestId: string): Promise<CliResult>;
3
+ /** 唯一 init 控制面分发;不保留裸 init 或旧混装 flag。 */
4
+ export declare function handleInit(command: string | undefined, args: string[], flags: Record<string, string | boolean>, runtime: Runtime, requestId: string): Promise<CliResult>;