linkshell-cli 0.10.42 → 0.10.45
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/dist/cli/src/commands/desktop-update.d.ts +4 -0
- package/dist/cli/src/commands/desktop-update.js +54 -0
- package/dist/cli/src/commands/desktop-update.js.map +1 -0
- package/dist/cli/src/commands/desktop.d.ts +273 -0
- package/dist/cli/src/commands/desktop.js +115 -0
- package/dist/cli/src/commands/desktop.js.map +1 -0
- package/dist/cli/src/commands/login.js +9 -3
- package/dist/cli/src/commands/login.js.map +1 -1
- package/dist/cli/src/commands/upgrade.js +8 -0
- package/dist/cli/src/commands/upgrade.js.map +1 -1
- package/dist/cli/src/index.js +12 -0
- package/dist/cli/src/index.js.map +1 -1
- package/dist/cli/src/utils/daemon.d.ts +2 -0
- package/dist/cli/src/utils/daemon.js +12 -2
- package/dist/cli/src/utils/daemon.js.map +1 -1
- package/dist/cli/src/utils/standalone.d.ts +2 -0
- package/dist/cli/src/utils/standalone.js +19 -0
- package/dist/cli/src/utils/standalone.js.map +1 -0
- package/dist/cli/tsconfig.tsbuildinfo +1 -1
- package/dist/host/src/drivers/acp/antigravity.js +9 -15
- package/dist/host/src/drivers/acp/antigravity.js.map +1 -1
- package/dist/host/src/drivers/acp/driver.d.ts +2 -0
- package/dist/host/src/drivers/acp/driver.js +18 -6
- package/dist/host/src/drivers/acp/driver.js.map +1 -1
- package/dist/host/src/drivers/claude/transcript.d.ts +6 -0
- package/dist/host/src/host.js +2 -0
- package/dist/host/src/host.js.map +1 -1
- package/dist/host/src/index.d.ts +1 -0
- package/dist/host/src/index.js +1 -0
- package/dist/host/src/index.js.map +1 -1
- package/dist/host/src/input.js +3 -0
- package/dist/host/src/input.js.map +1 -1
- package/dist/host/src/rpc/server.d.ts +2 -0
- package/dist/host/src/rpc/server.js +3 -0
- package/dist/host/src/rpc/server.js.map +1 -1
- package/dist/host/src/store.d.ts +4 -0
- package/dist/host/src/store.js +10 -0
- package/dist/host/src/store.js.map +1 -1
- package/dist/host/src/usage.d.ts +54 -0
- package/dist/host/src/usage.js +269 -0
- package/dist/host/src/usage.js.map +1 -0
- package/dist/wire/src/index.d.ts +1 -0
- package/dist/wire/src/index.js +1 -0
- package/dist/wire/src/index.js.map +1 -1
- package/dist/wire/src/rpc.d.ts +364 -0
- package/dist/wire/src/rpc.js +2 -0
- package/dist/wire/src/rpc.js.map +1 -1
- package/dist/wire/src/updates.d.ts +68 -0
- package/dist/wire/src/updates.js +2 -0
- package/dist/wire/src/updates.js.map +1 -1
- package/dist/wire/src/usage.d.ts +247 -0
- package/dist/wire/src/usage.js +21 -0
- package/dist/wire/src/usage.js.map +1 -0
- package/dist/wire/src/watch.d.ts +2 -2
- package/package.json +4 -4
- package/src/commands/desktop-update.ts +56 -0
- package/src/commands/desktop.ts +96 -0
- package/src/commands/login.ts +11 -3
- package/src/commands/upgrade.ts +9 -0
- package/src/index.ts +13 -0
- package/src/utils/daemon.ts +10 -2
- package/src/utils/standalone.ts +13 -0
package/src/commands/login.ts
CHANGED
|
@@ -42,14 +42,14 @@ export async function runLogin(): Promise<LoginResult | null> {
|
|
|
42
42
|
const hash = window.location.hash.substring(1);
|
|
43
43
|
if (hash) {
|
|
44
44
|
fetch('/token?' + hash, { method: 'POST' })
|
|
45
|
-
.then(
|
|
45
|
+
.then(response => { if (!response.ok) throw new Error('Login failed'); document.body.innerHTML = '<h2>Login successful! You can close this tab.</h2>'; })
|
|
46
46
|
.catch(() => { document.body.innerHTML = '<h2>Login failed. Please try again.</h2>'; });
|
|
47
47
|
} else {
|
|
48
48
|
// Try query params (iTool may pass tokens as query params)
|
|
49
49
|
const params = window.location.search.substring(1);
|
|
50
50
|
if (params) {
|
|
51
51
|
fetch('/token?' + params, { method: 'POST' })
|
|
52
|
-
.then(
|
|
52
|
+
.then(response => { if (!response.ok) throw new Error('Login failed'); document.body.innerHTML = '<h2>Login successful! You can close this tab.</h2>'; })
|
|
53
53
|
.catch(() => { document.body.innerHTML = '<h2>Login failed. Please try again.</h2>'; });
|
|
54
54
|
} else {
|
|
55
55
|
document.body.innerHTML = '<h2>No auth data received. Please try again.</h2>';
|
|
@@ -120,10 +120,16 @@ export async function runLogin(): Promise<LoginResult | null> {
|
|
|
120
120
|
}
|
|
121
121
|
} catch {}
|
|
122
122
|
|
|
123
|
+
if (!userId) {
|
|
124
|
+
res.writeHead(401);
|
|
125
|
+
res.end("无法验证账号,请重新登录。");
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
123
129
|
const tokens: AuthTokens = {
|
|
124
130
|
accessToken,
|
|
125
131
|
refreshToken,
|
|
126
|
-
expiresAt: Date.now() + expiresIn * 1000,
|
|
132
|
+
expiresAt: Date.now() + (Number.isFinite(expiresIn) && expiresIn > 0 ? expiresIn : 3600) * 1000,
|
|
127
133
|
userId,
|
|
128
134
|
email,
|
|
129
135
|
};
|
|
@@ -156,6 +162,8 @@ export async function runLogin(): Promise<LoginResult | null> {
|
|
|
156
162
|
res.end("Not found");
|
|
157
163
|
});
|
|
158
164
|
|
|
165
|
+
server.on("error", () => { clearTimeout(timeout); resolve(null); });
|
|
166
|
+
|
|
159
167
|
server.listen(0, "127.0.0.1", () => {
|
|
160
168
|
const addr = server.address();
|
|
161
169
|
if (!addr || typeof addr === "string") {
|
package/src/commands/upgrade.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { execFileSync, type ExecFileSyncOptionsWithStringEncoding } from "node:child_process";
|
|
2
2
|
import { realpathSync } from "node:fs";
|
|
3
3
|
import { join, sep } from "node:path";
|
|
4
|
+
import { standaloneBundle } from "../utils/standalone.js";
|
|
5
|
+
import { linkshellDir } from "../utils/daemon.js";
|
|
4
6
|
import { runUpgradeWorker, type CliCommand } from "./upgrade-worker.js";
|
|
5
7
|
|
|
6
8
|
function isBrewInstall(): boolean {
|
|
@@ -34,6 +36,13 @@ async function fetchLatestVersion(): Promise<string | null> {
|
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
export async function runUpgrade(current: string): Promise<void> {
|
|
39
|
+
const app = standaloneBundle();
|
|
40
|
+
if (app) {
|
|
41
|
+
execFileSync("/usr/bin/open", ["-n", "-a", app, "--args", "--dashboard", "--check-updates", "--home", linkshellDir()]);
|
|
42
|
+
process.stderr.write(" 已打开 LinkShell 软件更新;App、内置 CLI 和 Host 将一起更新。\n");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
37
46
|
process.stderr.write(`\n Current version: ${current}\n Checking for updates...\n\n`);
|
|
38
47
|
const latest = await fetchLatestVersion();
|
|
39
48
|
if (!latest) {
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { standaloneBundle } from "./utils/standalone.js";
|
|
2
3
|
import { Command, Option } from "commander";
|
|
3
4
|
import { runDoctor } from "./commands/doctor.js";
|
|
4
5
|
import { runSetup } from "./commands/setup.js";
|
|
@@ -10,6 +11,10 @@ import { createRequire } from "node:module";
|
|
|
10
11
|
const require = createRequire(import.meta.url);
|
|
11
12
|
const pkg = require("../../../package.json") as { version: string };
|
|
12
13
|
|
|
14
|
+
const bundledApp = standaloneBundle();
|
|
15
|
+
if (bundledApp) process.env.LINKSHELL_APP_BUNDLE = bundledApp;
|
|
16
|
+
else delete process.env.LINKSHELL_APP_BUNDLE;
|
|
17
|
+
|
|
13
18
|
const program = new Command();
|
|
14
19
|
|
|
15
20
|
program
|
|
@@ -19,6 +24,14 @@ program
|
|
|
19
24
|
)
|
|
20
25
|
.version(pkg.version);
|
|
21
26
|
|
|
27
|
+
program.command("app")
|
|
28
|
+
.description("Open the native Mac status app (included with the CLI)")
|
|
29
|
+
.action(async () => { const { openDesktop } = await import("./commands/desktop.js"); await openDesktop(); });
|
|
30
|
+
|
|
31
|
+
program.command("desktop", { hidden: true })
|
|
32
|
+
.option("--action <action>", "snapshot, start, stop or restart", "snapshot")
|
|
33
|
+
.action(async (options) => { const { runDesktop } = await import("./commands/desktop.js"); await runDesktop(pkg.version, options.action); });
|
|
34
|
+
|
|
22
35
|
// ── host ────────────────────────────────────────────────────────────
|
|
23
36
|
|
|
24
37
|
const hostCmd = program
|
package/src/utils/daemon.ts
CHANGED
|
@@ -12,7 +12,7 @@ const hostLaunchFile = join(LINKSHELL_DIR, "host-launch.json");
|
|
|
12
12
|
export function saveHostLaunch(pid: number, tcpPort?: number): void {
|
|
13
13
|
const env = Object.fromEntries(HOST_ENV.flatMap((key) => process.env[key] === undefined ? [] : [[key, process.env[key]]]));
|
|
14
14
|
if (tcpPort !== undefined) env.LINKSHELL_DEV_PORT = String(tcpPort);
|
|
15
|
-
writeFileSync(hostLaunchFile, `${JSON.stringify({ pid, env })}\n`, { mode: 0o600 });
|
|
15
|
+
writeFileSync(hostLaunchFile, `${JSON.stringify({ pid, env, executable: process.execPath, entry: process.argv[1], appBundle: process.env.LINKSHELL_APP_BUNDLE })}\n`, { mode: 0o600 });
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export function readHostLaunch(pid: number): NodeJS.ProcessEnv {
|
|
@@ -26,6 +26,14 @@ export function readHostLaunch(pid: number): NodeJS.ProcessEnv {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/** Ownership is recorded by the host itself, and is valid only for that live PID. */
|
|
30
|
+
export function readHostOwner(pid: number): string | undefined {
|
|
31
|
+
try {
|
|
32
|
+
const saved = JSON.parse(readFileSync(hostLaunchFile, "utf8")) as { pid?: number; appBundle?: string };
|
|
33
|
+
return saved.pid === pid && typeof saved.appBundle === "string" ? saved.appBundle : undefined;
|
|
34
|
+
} catch { return undefined; }
|
|
35
|
+
}
|
|
36
|
+
|
|
29
37
|
// "bridge" is the 1.x daemon: nothing starts one any more, but `linkshell stop` still ends one left running.
|
|
30
38
|
type ServiceName = "gateway" | "bridge" | "host";
|
|
31
39
|
|
|
@@ -110,7 +118,7 @@ export function spawnDaemon(service: ServiceName, args: string[], env: NodeJS.Pr
|
|
|
110
118
|
detached: true,
|
|
111
119
|
stdio: ["ignore", out, err],
|
|
112
120
|
// The launching terminal's environment is the most faithful one agents can get.
|
|
113
|
-
env: { ...env, LINKSHELL_ENV_FROM_TERMINAL: "1" },
|
|
121
|
+
env: { ...env, LINKSHELL_ENV_FROM_TERMINAL: env.LINKSHELL_APP_BUNDLE ? "0" : "1" },
|
|
114
122
|
},
|
|
115
123
|
);
|
|
116
124
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
/** Only an entry point physically inside a complete app may claim app-managed updates. */
|
|
5
|
+
export function standaloneBundle(entry = process.argv[1] ?? ""): string | undefined {
|
|
6
|
+
let path: string;
|
|
7
|
+
try { path = realpathSync(entry); } catch { return undefined; }
|
|
8
|
+
const marker = ".app/Contents/Resources/runtime/cli/";
|
|
9
|
+
const index = path.lastIndexOf(marker);
|
|
10
|
+
if (index < 0) return undefined;
|
|
11
|
+
const app = path.slice(0, index + 4);
|
|
12
|
+
return existsSync(join(app, "Contents/Resources/standalone.json")) && existsSync(join(app, "Contents/MacOS/node")) ? app : undefined;
|
|
13
|
+
}
|