linkshell-cli 0.5.34 → 0.5.36
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/runtime/acp/acp-client.d.ts +38 -0
- package/dist/cli/src/runtime/acp/acp-client.js +134 -20
- package/dist/cli/src/runtime/acp/acp-client.js.map +1 -1
- package/dist/cli/src/runtime/acp/agent-process-discovery.d.ts +48 -0
- package/dist/cli/src/runtime/acp/agent-process-discovery.js +267 -0
- package/dist/cli/src/runtime/acp/agent-process-discovery.js.map +1 -0
- package/dist/cli/src/runtime/acp/agent-workspace.d.ts +23 -0
- package/dist/cli/src/runtime/acp/agent-workspace.js +834 -90
- package/dist/cli/src/runtime/acp/agent-workspace.js.map +1 -1
- package/dist/cli/src/runtime/acp/provider-resolver.d.ts +3 -1
- package/dist/cli/src/runtime/acp/provider-resolver.js +13 -4
- package/dist/cli/src/runtime/acp/provider-resolver.js.map +1 -1
- package/dist/cli/src/runtime/bridge-session.d.ts +1 -0
- package/dist/cli/src/runtime/bridge-session.js +49 -18
- package/dist/cli/src/runtime/bridge-session.js.map +1 -1
- package/dist/cli/src/runtime/hook-command.d.ts +19 -0
- package/dist/cli/src/runtime/hook-command.js +31 -0
- package/dist/cli/src/runtime/hook-command.js.map +1 -0
- package/dist/cli/tsconfig.tsbuildinfo +1 -1
- package/dist/shared-protocol/src/index.d.ts +1161 -939
- package/dist/shared-protocol/src/index.js +43 -1
- package/dist/shared-protocol/src/index.js.map +1 -1
- package/package.json +3 -3
- package/src/runtime/acp/acp-client.ts +153 -22
- package/src/runtime/acp/agent-process-discovery.ts +301 -0
- package/src/runtime/acp/agent-workspace.ts +844 -96
- package/src/runtime/acp/provider-resolver.ts +18 -3
- package/src/runtime/bridge-session.ts +46 -18
- package/src/runtime/hook-command.ts +35 -0
- package/web/assets/{FileBrowser-9wRS6a0E.js → FileBrowser-Coy7Szjx.js} +1 -1
- package/web/assets/{PortPreview-yvXMn63g.js → PortPreview-D-XovbV1.js} +1 -1
- package/web/assets/{TerminalPanel-xtGQI_fv.js → TerminalPanel-Cah56AtC.js} +1 -1
- package/web/assets/{UsageDashboard-ByQ6mehF.js → UsageDashboard-DfkjJagC.js} +1 -1
- package/web/assets/index-BsnDaeCt.css +33 -0
- package/web/assets/index-ClZzQ4ba.js +35 -0
- package/web/assets/{vendor-highlight-Cus7zBI4.js → vendor-highlight-NXWAAyIv.js} +1 -1
- package/web/assets/{vendor-react-0zU5oKmd.js → vendor-react-M7xG3qiw.js} +8 -8
- package/web/index.html +4 -4
- package/web/assets/index-Vtyd7s5T.css +0 -33
- package/web/assets/index-pqslvKcS.js +0 -35
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import type { KnownAgentProvider } from "./agent-process-discovery.js";
|
|
2
|
+
export type AgentProvider = string;
|
|
3
|
+
export type { KnownAgentProvider };
|
|
2
4
|
export type AgentProtocol = "acp" | "codex-app-server" | "claude-agent-sdk" | "claude-stream-json";
|
|
3
5
|
export type AgentFraming = "content-length" | "newline";
|
|
4
6
|
export interface AgentCommandConfig {
|
|
@@ -86,12 +86,21 @@ function resolveBinary(bin) {
|
|
|
86
86
|
}
|
|
87
87
|
return null;
|
|
88
88
|
}
|
|
89
|
+
const INSTALL_BINARIES = [
|
|
90
|
+
{ provider: "claude", binaries: ["claude"] },
|
|
91
|
+
{ provider: "codex", binaries: ["codex"] },
|
|
92
|
+
{ provider: "gemini", binaries: ["gemini"] },
|
|
93
|
+
{ provider: "copilot", binaries: ["copilot"] },
|
|
94
|
+
{ provider: "opencode", binaries: ["opencode", "opencode-ai"] },
|
|
95
|
+
{ provider: "cursor", binaries: ["cursor-agent"] },
|
|
96
|
+
{ provider: "kimi", binaries: ["kimi"] },
|
|
97
|
+
];
|
|
89
98
|
export function detectAvailableProviders() {
|
|
90
99
|
const available = [];
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
for (const entry of INSTALL_BINARIES) {
|
|
101
|
+
if (entry.binaries.some((bin) => resolveBinary(bin)))
|
|
102
|
+
available.push(entry.provider);
|
|
103
|
+
}
|
|
95
104
|
return available;
|
|
96
105
|
}
|
|
97
106
|
//# sourceMappingURL=provider-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-resolver.js","sourceRoot":"","sources":["../../../../../src/runtime/acp/provider-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"provider-resolver.js","sourceRoot":"","sources":["../../../../../src/runtime/acp/provider-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@ import { getValidToken, refreshAccessToken } from "../auth.js";
|
|
|
16
16
|
import { AgentSessionProxy } from "./acp/agent-session.js";
|
|
17
17
|
import { AgentWorkspaceProxy, makeAgentV2RemoteConversationId } from "./acp/agent-workspace.js";
|
|
18
18
|
import { detectAvailableProviders } from "./acp/provider-resolver.js";
|
|
19
|
+
import { buildLinkShellHookCommand, shouldWriteProjectHooksJson } from "./hook-command.js";
|
|
19
20
|
const HEARTBEAT_INTERVAL = 15_000;
|
|
20
21
|
// Transport-layer WS keepalive: ping the gateway periodically; if a pong
|
|
21
22
|
// doesn't arrive before the next ping, the socket is half-open (network
|
|
@@ -41,6 +42,7 @@ const EXITED_TERMINAL_GRACE_MS = 30_000;
|
|
|
41
42
|
// allowlist is configured. Covers the common dev servers the app tunnels to.
|
|
42
43
|
const DEFAULT_TUNNEL_PORTS = [3000, 3001, 4321, 5173, 5174, 8080, 8000, 8081];
|
|
43
44
|
const PERMISSION_REQUEST_TIMEOUT_MS = Number(process.env.LINKSHELL_PERMISSION_TIMEOUT_MS ?? 5 * 60_000);
|
|
45
|
+
const HOOK_COMMAND_TIMEOUT_SEC = Math.ceil((PERMISSION_REQUEST_TIMEOUT_MS + 30_000) / 1000);
|
|
44
46
|
const LINKSHELL_PERMISSION_GUARD_MARKER = "LINKSHELL_PERMISSION_GUARD";
|
|
45
47
|
function isLinkShellHookEntry(entry, marker) {
|
|
46
48
|
let raw = "";
|
|
@@ -220,9 +222,8 @@ export function resolvePairingGateway(gatewayHttpUrl, pairingGateway) {
|
|
|
220
222
|
}
|
|
221
223
|
}
|
|
222
224
|
function normalizeAgentProvider(provider) {
|
|
223
|
-
if (provider === "
|
|
224
|
-
return provider;
|
|
225
|
-
}
|
|
225
|
+
if (typeof provider === "string" && provider.trim())
|
|
226
|
+
return provider.trim();
|
|
226
227
|
return "codex";
|
|
227
228
|
}
|
|
228
229
|
export function resolveAgentWorkspaceProviders(options) {
|
|
@@ -270,6 +271,7 @@ export class BridgeSession {
|
|
|
270
271
|
keepAwake;
|
|
271
272
|
agentSession;
|
|
272
273
|
agentWorkspace;
|
|
274
|
+
outboundAgentQueue = [];
|
|
273
275
|
machineIdentity;
|
|
274
276
|
// Default host workspace shown to clients and used by the initial PTY.
|
|
275
277
|
defaultCwd;
|
|
@@ -504,6 +506,11 @@ export class BridgeSession {
|
|
|
504
506
|
projectName: basename(this.defaultCwd),
|
|
505
507
|
},
|
|
506
508
|
}));
|
|
509
|
+
if (this.outboundAgentQueue.length > 0) {
|
|
510
|
+
const queued = this.outboundAgentQueue.splice(0);
|
|
511
|
+
for (const envelope of queued)
|
|
512
|
+
this.send(envelope);
|
|
513
|
+
}
|
|
507
514
|
this.startHeartbeat();
|
|
508
515
|
this.startWsPing();
|
|
509
516
|
});
|
|
@@ -1240,7 +1247,7 @@ export class BridgeSession {
|
|
|
1240
1247
|
hookPort = result.port;
|
|
1241
1248
|
hookConfigPaths.push(result.configPath);
|
|
1242
1249
|
// Also set up hooks for other providers (curlCmd already has marker from setupHookServer)
|
|
1243
|
-
const curlCmd =
|
|
1250
|
+
const curlCmd = buildLinkShellHookCommand(result.port, hookMarker, HOOK_COMMAND_TIMEOUT_SEC);
|
|
1244
1251
|
hookConfigPaths.push(this.setupCodexHooks(terminalId, curlCmd, hookMarker));
|
|
1245
1252
|
hookConfigPaths.push(this.setupGeminiHooks(terminalId, curlCmd, hookMarker));
|
|
1246
1253
|
hookConfigPaths.push(this.setupCopilotHooks(terminalId, curlCmd, hookMarker));
|
|
@@ -1346,8 +1353,8 @@ export class BridgeSession {
|
|
|
1346
1353
|
const reqLid = reqUrl.searchParams.get("lid") ?? "";
|
|
1347
1354
|
if (reqMarker !== marker || (reqLid !== "" && reqLid !== marker)) {
|
|
1348
1355
|
this.log(`ignoring hook event: m=${reqMarker} lid=${reqLid} (expected ${marker})`);
|
|
1349
|
-
res.writeHead(200);
|
|
1350
|
-
res.end("
|
|
1356
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1357
|
+
res.end("{}");
|
|
1351
1358
|
return;
|
|
1352
1359
|
}
|
|
1353
1360
|
let body = "";
|
|
@@ -1358,8 +1365,8 @@ export class BridgeSession {
|
|
|
1358
1365
|
body += chunk.toString();
|
|
1359
1366
|
if (Buffer.byteLength(body, "utf8") > HOOK_BODY_LIMIT) {
|
|
1360
1367
|
bodyTooLarge = true;
|
|
1361
|
-
res.writeHead(413);
|
|
1362
|
-
res.end("
|
|
1368
|
+
res.writeHead(413, { "Content-Type": "application/json" });
|
|
1369
|
+
res.end("{}");
|
|
1363
1370
|
req.destroy();
|
|
1364
1371
|
}
|
|
1365
1372
|
});
|
|
@@ -1403,15 +1410,16 @@ export class BridgeSession {
|
|
|
1403
1410
|
this.sendHookPermissionRequest(terminalId, event, requestId, provider);
|
|
1404
1411
|
}
|
|
1405
1412
|
else {
|
|
1406
|
-
// All other hooks: respond immediately
|
|
1407
|
-
|
|
1408
|
-
res.
|
|
1413
|
+
// All other hooks: respond immediately with valid JSON so clients
|
|
1414
|
+
// that parse stdout (Cursor) fail-open instead of blocking the tool.
|
|
1415
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1416
|
+
res.end("{}");
|
|
1409
1417
|
this.handleHookEvent(terminalId, event, provider);
|
|
1410
1418
|
}
|
|
1411
1419
|
}
|
|
1412
1420
|
catch (e) {
|
|
1413
|
-
res.writeHead(200);
|
|
1414
|
-
res.end("
|
|
1421
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
1422
|
+
res.end("{}");
|
|
1415
1423
|
this.log(`hook parse error: ${e}`);
|
|
1416
1424
|
}
|
|
1417
1425
|
});
|
|
@@ -1425,7 +1433,7 @@ export class BridgeSession {
|
|
|
1425
1433
|
server.on("error", reject);
|
|
1426
1434
|
});
|
|
1427
1435
|
this.log(`hook server for ${terminalId} (${provider}) listening on port ${port}, marker=${marker}`);
|
|
1428
|
-
const curlCmd =
|
|
1436
|
+
const curlCmd = buildLinkShellHookCommand(port, marker, HOOK_COMMAND_TIMEOUT_SEC);
|
|
1429
1437
|
let configPath;
|
|
1430
1438
|
if (provider === "codex") {
|
|
1431
1439
|
configPath = this.setupCodexHooks(terminalId, curlCmd, marker);
|
|
@@ -1447,7 +1455,7 @@ export class BridgeSession {
|
|
|
1447
1455
|
if (!term?.hookPort)
|
|
1448
1456
|
return;
|
|
1449
1457
|
const marker = term.hookMarker;
|
|
1450
|
-
const curlCmd =
|
|
1458
|
+
const curlCmd = buildLinkShellHookCommand(term.hookPort, marker, HOOK_COMMAND_TIMEOUT_SEC);
|
|
1451
1459
|
const providers = resolveAgentWorkspaceProviders(this.options);
|
|
1452
1460
|
try {
|
|
1453
1461
|
for (const provider of providers) {
|
|
@@ -1481,7 +1489,7 @@ export class BridgeSession {
|
|
|
1481
1489
|
hooks: [{
|
|
1482
1490
|
type: "command",
|
|
1483
1491
|
command: curlCmd,
|
|
1484
|
-
timeout:
|
|
1492
|
+
timeout: HOOK_COMMAND_TIMEOUT_SEC,
|
|
1485
1493
|
}],
|
|
1486
1494
|
};
|
|
1487
1495
|
const hookEvents = {
|
|
@@ -1540,7 +1548,7 @@ export class BridgeSession {
|
|
|
1540
1548
|
hooks: [{
|
|
1541
1549
|
type: "command",
|
|
1542
1550
|
command: curlCmd,
|
|
1543
|
-
timeout:
|
|
1551
|
+
timeout: HOOK_COMMAND_TIMEOUT_SEC,
|
|
1544
1552
|
}],
|
|
1545
1553
|
};
|
|
1546
1554
|
const hookEvents = {
|
|
@@ -1596,9 +1604,26 @@ export class BridgeSession {
|
|
|
1596
1604
|
return settingsPath;
|
|
1597
1605
|
}
|
|
1598
1606
|
setupCopilotHooks(terminalId, curlCmd, marker) {
|
|
1599
|
-
// Copilot loads hooks from CWD as hooks.json
|
|
1607
|
+
// Copilot loads hooks from CWD as hooks.json. Cursor's coding agent also
|
|
1608
|
+
// reads that file when the folder is a Cursor project — writing it here
|
|
1609
|
+
// freezes every IDE tool call the moment the hook server is down or
|
|
1610
|
+
// returns non-JSON.
|
|
1600
1611
|
const cwd = this.terminals.get(terminalId)?.cwd ?? this.defaultCwd;
|
|
1601
1612
|
const hooksPath = join(cwd, "hooks.json");
|
|
1613
|
+
if (!shouldWriteProjectHooksJson(cwd)) {
|
|
1614
|
+
this.sweepLinkShellHookEntries(hooksPath);
|
|
1615
|
+
try {
|
|
1616
|
+
if (existsSync(hooksPath)) {
|
|
1617
|
+
const raw = JSON.parse(readFileSync(hooksPath, "utf8"));
|
|
1618
|
+
if (!raw.hooks || (typeof raw.hooks === "object" && Object.keys(raw.hooks).length === 0)) {
|
|
1619
|
+
unlinkSync(hooksPath);
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
catch { /* leave whatever is on disk */ }
|
|
1624
|
+
this.log(`skip writing ${hooksPath}: Cursor project would inherit it and freeze the IDE agent`);
|
|
1625
|
+
return hooksPath;
|
|
1626
|
+
}
|
|
1602
1627
|
const mkHook = () => ({
|
|
1603
1628
|
type: "command",
|
|
1604
1629
|
bash: curlCmd,
|
|
@@ -2156,6 +2181,12 @@ export class BridgeSession {
|
|
|
2156
2181
|
}
|
|
2157
2182
|
send(message) {
|
|
2158
2183
|
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
|
|
2184
|
+
if (message.type.startsWith("agent.v2.")) {
|
|
2185
|
+
this.outboundAgentQueue.push(message);
|
|
2186
|
+
if (this.outboundAgentQueue.length > 40) {
|
|
2187
|
+
this.outboundAgentQueue.splice(0, this.outboundAgentQueue.length - 40);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2159
2190
|
return;
|
|
2160
2191
|
}
|
|
2161
2192
|
const machineId = this.machineIdentity?.machineId;
|