@limecloud/lime 1.144.1
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 +68 -0
- package/bin/lime.js +260 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# `@limecloud/lime`
|
|
2
|
+
|
|
3
|
+
Lime 的官方命令行入口。CLI、TUI 和 Desktop 共用 App Server JSON-RPC、RuntimeCore 与 canonical Thread/Turn/Item,不包含独立任务 runtime。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @limecloud/lime
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
根 npm 包只包含 launcher,并通过 optional dependency 安装当前平台的原生载荷;安装阶段不执行网络下载脚本。平台载荷原子包含 `lime`、`app-server`、`code-mode-host`、Windows sandbox helpers 和所需动态库,保证默认 TUI 与 `exec` 都进入同一 App Server 产品链。
|
|
12
|
+
|
|
13
|
+
当前发布目标为 macOS arm64/x64、Windows x64 与 Linux x64 GNU。尚无真实构建和运行证据的平台会明确拒绝启动,不发布空壳 optional package。
|
|
14
|
+
|
|
15
|
+
## 命令
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# 默认启动交互式 TUI
|
|
19
|
+
lime
|
|
20
|
+
|
|
21
|
+
# 显式启动 TUI
|
|
22
|
+
lime tui
|
|
23
|
+
|
|
24
|
+
# 非交互运行
|
|
25
|
+
lime exec "review this diff"
|
|
26
|
+
lime exec --json "review this diff"
|
|
27
|
+
lime exec --jsonl "review this diff"
|
|
28
|
+
|
|
29
|
+
# 只读检查 execpolicy prefix rules
|
|
30
|
+
lime execpolicy check --rules ./rules/policy.rules --pretty git push origin main
|
|
31
|
+
|
|
32
|
+
# 生成 shell completion
|
|
33
|
+
lime completion zsh > "${fpath[1]}/_lime"
|
|
34
|
+
|
|
35
|
+
# 恢复 canonical Thread
|
|
36
|
+
lime resume
|
|
37
|
+
lime resume <thread-id>
|
|
38
|
+
|
|
39
|
+
# App Server read/control surfaces
|
|
40
|
+
lime thread list
|
|
41
|
+
lime thread show <thread-id> --include-turns
|
|
42
|
+
lime mcp list
|
|
43
|
+
lime skills list
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`--json` 输出可读的稳定 JSON;`--jsonl` 输出单行 JSON envelope,二者互斥。`completion` 从同一命令树生成 bash、zsh、fish、PowerShell 和 elvish 脚本。
|
|
47
|
+
|
|
48
|
+
交互式 TUI 支持 `zh-CN`、`zh-TW`、`en-US`、`ja-JP`、`ko-KR`。可通过默认 `lime`、`lime tui` 或 `lime resume` 的 `--locale <LOCALE>` 指定;未指定时按 `LIME_LOCALE`、`LC_ALL`、`LANG` 解析,未知语言回退到 `en-US`。`exec` 与管理命令的 JSON 合同保持语言无关。
|
|
49
|
+
|
|
50
|
+
本地连接默认启动同目录或 `PATH` 中的 `app-server`。可用 `LIME_APP_SERVER_BIN` 或 `--app-server <PATH>` 覆盖。需要连接远端 App Server 时使用 Codex 形状的参数:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
lime exec --remote wss://cloud.example/rpc --remote-auth-token-env LIME_REMOTE_TOKEN "review this diff"
|
|
54
|
+
lime tui --remote ws://127.0.0.1:4500
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
远端 token 只从环境变量读取;token 连接要求 `wss://` 或 loopback `ws://`。当前仅提供 transport foundation,不代表生产 Cloud endpoint、租户或账号能力已启用。
|
|
58
|
+
|
|
59
|
+
## 发布
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python3 scripts/build_npm_package.py \
|
|
63
|
+
--package lime \
|
|
64
|
+
--release-version 1.140.0 \
|
|
65
|
+
--pack-output dist/lime-npm-1.140.0.tgz
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
平台包使用 `--package lime-<platform>-<arch> --vendor-src <vendor-root>` staging。`vendor-root` 必须使用 `vendor/<target-triple>/bin` 布局并包含完整 runtime payload。发布工作流先串行发布四个平台版本,最后发布 `@limecloud/lime` 根版本。
|
package/bin/lime.js
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Unified entry point for the Lime CLI.
|
|
3
|
+
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = path.dirname(__filename);
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const limePackageRoot = realpathSync(path.join(__dirname, ".."));
|
|
14
|
+
|
|
15
|
+
const PLATFORM_PACKAGE_BY_TARGET = {
|
|
16
|
+
"x86_64-unknown-linux-gnu": "@limecloud/lime-linux-x64",
|
|
17
|
+
"x86_64-apple-darwin": "@limecloud/lime-darwin-x64",
|
|
18
|
+
"aarch64-apple-darwin": "@limecloud/lime-darwin-arm64",
|
|
19
|
+
"x86_64-pc-windows-msvc": "@limecloud/lime-win32-x64",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const { platform, arch } = process;
|
|
23
|
+
|
|
24
|
+
let targetTriple = null;
|
|
25
|
+
switch (platform) {
|
|
26
|
+
case "linux":
|
|
27
|
+
if (arch === "x64") {
|
|
28
|
+
targetTriple = "x86_64-unknown-linux-gnu";
|
|
29
|
+
}
|
|
30
|
+
break;
|
|
31
|
+
case "darwin":
|
|
32
|
+
if (arch === "x64") {
|
|
33
|
+
targetTriple = "x86_64-apple-darwin";
|
|
34
|
+
} else if (arch === "arm64") {
|
|
35
|
+
targetTriple = "aarch64-apple-darwin";
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
38
|
+
case "win32":
|
|
39
|
+
if (arch === "x64") {
|
|
40
|
+
targetTriple = "x86_64-pc-windows-msvc";
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
default:
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!targetTriple) {
|
|
48
|
+
throw new Error(`Unsupported platform: ${platform} (${arch})`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const platformPackage = PLATFORM_PACKAGE_BY_TARGET[targetTriple];
|
|
52
|
+
if (!platformPackage) {
|
|
53
|
+
throw new Error(`Unsupported target triple: ${targetTriple}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function findLimeExecutable() {
|
|
57
|
+
let vendorRoot;
|
|
58
|
+
try {
|
|
59
|
+
const packageJsonPath = require.resolve(`${platformPackage}/package.json`);
|
|
60
|
+
vendorRoot = path.join(path.dirname(packageJsonPath), "vendor");
|
|
61
|
+
} catch {
|
|
62
|
+
vendorRoot = path.join(__dirname, "..", "vendor");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const limeExecutable = path.join(
|
|
66
|
+
vendorRoot,
|
|
67
|
+
targetTriple,
|
|
68
|
+
"bin",
|
|
69
|
+
process.platform === "win32" ? "lime.exe" : "lime",
|
|
70
|
+
);
|
|
71
|
+
if (existsSync(limeExecutable)) {
|
|
72
|
+
return limeExecutable;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const packageManager = detectPackageManager();
|
|
76
|
+
const updateCommand =
|
|
77
|
+
packageManager === "bun"
|
|
78
|
+
? "bun install -g @limecloud/lime@latest"
|
|
79
|
+
: packageManager === "pnpm"
|
|
80
|
+
? "pnpm add -g @limecloud/lime@latest"
|
|
81
|
+
: packageManager === "vite-plus"
|
|
82
|
+
? "vp install -g @limecloud/lime@latest"
|
|
83
|
+
: "npm install -g @limecloud/lime@latest";
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Missing optional dependency ${platformPackage}. Reinstall Lime: ${updateCommand}`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function isPnpmOwnedLimeInstall(nodeModulesDir) {
|
|
90
|
+
if (!existsSync(path.join(nodeModulesDir, ".modules.yaml"))) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
return (
|
|
96
|
+
realpathSync(path.join(nodeModulesDir, "@limecloud", "lime")) ===
|
|
97
|
+
limePackageRoot
|
|
98
|
+
);
|
|
99
|
+
} catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function isVitePlusOwnedLimeInstall(packagesDir) {
|
|
105
|
+
if (path.basename(packagesDir) !== "packages") {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
const metadata = JSON.parse(
|
|
111
|
+
readFileSync(path.join(packagesDir, "@limecloud", "lime.json"), "utf8"),
|
|
112
|
+
);
|
|
113
|
+
if (metadata.name !== "@limecloud/lime") {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const installId = metadata.installId || "";
|
|
118
|
+
const installDir = installId.startsWith("#")
|
|
119
|
+
? path.join(packagesDir, `@limecloud/lime${installId}`)
|
|
120
|
+
: path.join(packagesDir, "@limecloud/lime", installId);
|
|
121
|
+
for (const nodeModulesDir of [
|
|
122
|
+
path.join(installDir, "lib", "node_modules"),
|
|
123
|
+
path.join(installDir, "node_modules"),
|
|
124
|
+
]) {
|
|
125
|
+
const packageRoot = path.join(nodeModulesDir, "@limecloud", "lime");
|
|
126
|
+
if (
|
|
127
|
+
existsSync(packageRoot) &&
|
|
128
|
+
realpathSync(packageRoot) === limePackageRoot
|
|
129
|
+
) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
} catch {
|
|
134
|
+
// Missing ownership metadata must not prevent Lime from starting.
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function detectPackageManager() {
|
|
140
|
+
const entrypointDir = path.dirname(path.resolve(process.argv[1]));
|
|
141
|
+
for (const startDir of new Set([limePackageRoot, entrypointDir])) {
|
|
142
|
+
const filesystemRoot = path.parse(startDir).root;
|
|
143
|
+
for (
|
|
144
|
+
let currentDir = startDir;
|
|
145
|
+
currentDir !== filesystemRoot;
|
|
146
|
+
currentDir = path.dirname(currentDir)
|
|
147
|
+
) {
|
|
148
|
+
if (isVitePlusOwnedLimeInstall(currentDir)) {
|
|
149
|
+
return "vite-plus";
|
|
150
|
+
}
|
|
151
|
+
if (isPnpmOwnedLimeInstall(path.join(currentDir, "node_modules"))) {
|
|
152
|
+
return "pnpm";
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (isPnpmOwnedLimeInstall(path.join(filesystemRoot, "node_modules"))) {
|
|
157
|
+
return "pnpm";
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
162
|
+
if (/\bbun\//u.test(userAgent)) {
|
|
163
|
+
return "bun";
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const execPath = process.env.npm_execpath || "";
|
|
167
|
+
if (execPath.includes("bun")) {
|
|
168
|
+
return "bun";
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (
|
|
172
|
+
__dirname.includes(".bun/install/global") ||
|
|
173
|
+
__dirname.includes(".bun\\install\\global")
|
|
174
|
+
) {
|
|
175
|
+
return "bun";
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return userAgent ? "npm" : null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const binaryPath = findLimeExecutable();
|
|
182
|
+
const packageManager = detectPackageManager();
|
|
183
|
+
const packageManagerEnvVar =
|
|
184
|
+
packageManager === "bun"
|
|
185
|
+
? "LIME_MANAGED_BY_BUN"
|
|
186
|
+
: packageManager === "pnpm"
|
|
187
|
+
? "LIME_MANAGED_BY_PNPM"
|
|
188
|
+
: packageManager === "vite-plus"
|
|
189
|
+
? "LIME_MANAGED_BY_VITE_PLUS"
|
|
190
|
+
: "LIME_MANAGED_BY_NPM";
|
|
191
|
+
const env = {
|
|
192
|
+
...process.env,
|
|
193
|
+
LIME_MANAGED_PACKAGE_ROOT: limePackageRoot,
|
|
194
|
+
};
|
|
195
|
+
delete env.LIME_MANAGED_BY_NPM;
|
|
196
|
+
delete env.LIME_MANAGED_BY_BUN;
|
|
197
|
+
delete env.LIME_MANAGED_BY_PNPM;
|
|
198
|
+
delete env.LIME_MANAGED_BY_VITE_PLUS;
|
|
199
|
+
env[packageManagerEnvVar] = "1";
|
|
200
|
+
|
|
201
|
+
// macOS strips DYLD_* variables when Node launches the native child. The
|
|
202
|
+
// bundled App Server loads its @rpath libraries from this directory, so pass
|
|
203
|
+
// the package-local runtime directory explicitly to the native process.
|
|
204
|
+
const nativeRuntimeDir = path.dirname(binaryPath);
|
|
205
|
+
if (process.platform === "darwin") {
|
|
206
|
+
env.DYLD_LIBRARY_PATH = [nativeRuntimeDir, env.DYLD_LIBRARY_PATH]
|
|
207
|
+
.filter(Boolean)
|
|
208
|
+
.join(path.delimiter);
|
|
209
|
+
} else if (process.platform === "linux") {
|
|
210
|
+
env.LD_LIBRARY_PATH = [nativeRuntimeDir, env.LD_LIBRARY_PATH]
|
|
211
|
+
.filter(Boolean)
|
|
212
|
+
.join(path.delimiter);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
216
|
+
stdio: "inherit",
|
|
217
|
+
env,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
child.on("error", (error) => {
|
|
221
|
+
console.error(error);
|
|
222
|
+
process.exit(1);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const forwardSignal = (signal) => {
|
|
226
|
+
if (child.killed) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
try {
|
|
230
|
+
child.kill(signal);
|
|
231
|
+
} catch {
|
|
232
|
+
// The exit handler below remains the single parent termination owner.
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const signalHandlers = new Map();
|
|
237
|
+
for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
238
|
+
const handler = () => forwardSignal(signal);
|
|
239
|
+
signalHandlers.set(signal, handler);
|
|
240
|
+
process.on(signal, handler);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const childResult = await new Promise((resolve) => {
|
|
244
|
+
child.on("exit", (code, signal) => {
|
|
245
|
+
if (signal) {
|
|
246
|
+
resolve({ type: "signal", signal });
|
|
247
|
+
} else {
|
|
248
|
+
resolve({ type: "code", exitCode: code ?? 1 });
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
if (childResult.type === "signal") {
|
|
254
|
+
for (const [signal, handler] of signalHandlers) {
|
|
255
|
+
process.removeListener(signal, handler);
|
|
256
|
+
}
|
|
257
|
+
process.kill(process.pid, childResult.signal);
|
|
258
|
+
} else {
|
|
259
|
+
process.exit(childResult.exitCode);
|
|
260
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@limecloud/lime",
|
|
3
|
+
"version": "1.144.1",
|
|
4
|
+
"packageManager": "pnpm@9.15.9",
|
|
5
|
+
"description": "Lime CLI is an agent that runs in your terminal.",
|
|
6
|
+
"bin": {
|
|
7
|
+
"lime": "bin/lime.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/limecloud/lime.git",
|
|
16
|
+
"directory": "packages/cli"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"files": [
|
|
20
|
+
"bin/lime.js"
|
|
21
|
+
],
|
|
22
|
+
"optionalDependencies": {
|
|
23
|
+
"@limecloud/lime-linux-x64": "1.144.1-linux-x64",
|
|
24
|
+
"@limecloud/lime-darwin-x64": "1.144.1-darwin-x64",
|
|
25
|
+
"@limecloud/lime-darwin-arm64": "1.144.1-darwin-arm64",
|
|
26
|
+
"@limecloud/lime-win32-x64": "1.144.1-win32-x64"
|
|
27
|
+
}
|
|
28
|
+
}
|