linkshell-cli 0.3.28 → 0.4.0
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/setup.js +20 -2
- package/dist/cli/src/commands/setup.js.map +1 -1
- package/dist/cli/src/commands/upgrade.js +9 -24
- package/dist/cli/src/commands/upgrade.js.map +1 -1
- package/dist/cli/src/index.js +28 -26
- package/dist/cli/src/index.js.map +1 -1
- package/dist/cli/src/providers.d.ts +3 -7
- package/dist/cli/src/providers.js +76 -19
- package/dist/cli/src/providers.js.map +1 -1
- package/dist/cli/src/runtime/acp/acp-client.d.ts +0 -10
- package/dist/cli/src/runtime/acp/acp-client.js +20 -146
- package/dist/cli/src/runtime/acp/acp-client.js.map +1 -1
- package/dist/cli/src/runtime/acp/agent-session.d.ts +62 -0
- package/dist/cli/src/runtime/acp/agent-session.js +1075 -0
- package/dist/cli/src/runtime/acp/agent-session.js.map +1 -0
- package/dist/cli/src/runtime/acp/agent-workspace.d.ts +2 -27
- package/dist/cli/src/runtime/acp/agent-workspace.js +224 -1008
- package/dist/cli/src/runtime/acp/agent-workspace.js.map +1 -1
- package/dist/cli/src/runtime/acp/claude-sdk-client.d.ts +1 -3
- package/dist/cli/src/runtime/acp/claude-sdk-client.js +50 -82
- package/dist/cli/src/runtime/acp/claude-sdk-client.js.map +1 -1
- package/dist/cli/src/runtime/acp/claude-stream-json-client.d.ts +1 -2
- package/dist/cli/src/runtime/acp/claude-stream-json-client.js +36 -54
- package/dist/cli/src/runtime/acp/claude-stream-json-client.js.map +1 -1
- package/dist/cli/src/runtime/acp/json-rpc.d.ts +1 -34
- package/dist/cli/src/runtime/acp/json-rpc.js +8 -32
- package/dist/cli/src/runtime/acp/json-rpc.js.map +1 -1
- package/dist/cli/src/runtime/acp/provider-resolver.d.ts +0 -3
- package/dist/cli/src/runtime/acp/provider-resolver.js +6 -26
- package/dist/cli/src/runtime/acp/provider-resolver.js.map +1 -1
- package/dist/cli/src/runtime/bridge-session.d.ts +31 -1
- package/dist/cli/src/runtime/bridge-session.js +991 -81
- package/dist/cli/src/runtime/bridge-session.js.map +1 -1
- package/dist/cli/src/runtime/screen-fallback.d.ts +1 -1
- package/dist/cli/src/runtime/screen-fallback.js +4 -4
- package/dist/cli/src/runtime/screen-fallback.js.map +1 -1
- package/dist/cli/src/runtime/screen-share.d.ts +1 -1
- package/dist/cli/src/runtime/screen-share.js +7 -7
- package/dist/cli/src/runtime/screen-share.js.map +1 -1
- package/dist/cli/tsconfig.tsbuildinfo +1 -1
- package/dist/shared-protocol/src/index.d.ts +11978 -3423
- package/dist/shared-protocol/src/index.js +114 -163
- package/dist/shared-protocol/src/index.js.map +1 -1
- package/package.json +13 -13
- package/src/commands/setup.ts +31 -5
- package/src/commands/upgrade.ts +8 -28
- package/src/index.ts +34 -29
- package/src/providers.ts +108 -26
- package/src/runtime/acp/acp-client.ts +22 -159
- package/src/runtime/acp/agent-session.ts +1180 -0
- package/src/runtime/acp/agent-workspace.ts +246 -1094
- package/src/runtime/acp/claude-sdk-client.ts +51 -86
- package/src/runtime/acp/claude-stream-json-client.ts +42 -59
- package/src/runtime/acp/json-rpc.ts +14 -46
- package/src/runtime/acp/provider-resolver.ts +6 -29
- package/src/runtime/bridge-session.ts +1092 -84
- package/src/runtime/screen-fallback.ts +5 -5
- package/src/runtime/screen-share.ts +8 -8
- package/src/runtime/acp/claude-sessions.ts +0 -563
- package/src/runtime/acp/codex-rpc-bridge.ts +0 -233
- package/src/runtime/acp/codex-sessions.ts +0 -802
- package/src/types/linkshell-gateway.d.ts +0 -18
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
import { createEnvelope } from "@linkshell/protocol";
|
|
2
|
-
import type { Envelope } from "@linkshell/protocol";
|
|
3
|
-
import { JsonRpcStdioTransport, type JsonRpcMessage } from "./json-rpc.js";
|
|
4
|
-
import { resolveCodexAppServerCommands, type AgentCommandConfig } from "./provider-resolver.js";
|
|
5
|
-
|
|
6
|
-
const CODEX_PROXY_STARTUP_GRACE_MS = 250;
|
|
7
|
-
|
|
8
|
-
type JsonRpcId = string | number;
|
|
9
|
-
|
|
10
|
-
export class CodexRpcBridge {
|
|
11
|
-
private transport: JsonRpcStdioTransport | undefined;
|
|
12
|
-
private transportReady = false;
|
|
13
|
-
private starting = false;
|
|
14
|
-
private stopping = false;
|
|
15
|
-
private candidateIndex = 0;
|
|
16
|
-
private startupTimer: ReturnType<typeof setTimeout> | undefined;
|
|
17
|
-
private queuedMessages: JsonRpcMessage[] = [];
|
|
18
|
-
private inFlightRequests = new Map<JsonRpcId, JsonRpcMessage>();
|
|
19
|
-
|
|
20
|
-
constructor(
|
|
21
|
-
private readonly input: {
|
|
22
|
-
command?: string;
|
|
23
|
-
commandCandidates?: AgentCommandConfig[];
|
|
24
|
-
cwd: string;
|
|
25
|
-
hostDeviceId: string;
|
|
26
|
-
send: (envelope: Envelope) => void;
|
|
27
|
-
verbose?: boolean;
|
|
28
|
-
},
|
|
29
|
-
) {}
|
|
30
|
-
|
|
31
|
-
send(message: unknown): void {
|
|
32
|
-
const jsonMessage = message as JsonRpcMessage;
|
|
33
|
-
if (isJsonRpcNotification(jsonMessage) && jsonMessage.method === "initialized") {
|
|
34
|
-
if (this.input.verbose) {
|
|
35
|
-
process.stderr.write("[agent:codex-rpc] dropped initialized notification for Codex app-server\n");
|
|
36
|
-
}
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
this.ensureTransport();
|
|
40
|
-
if (!this.transportReady) {
|
|
41
|
-
this.queuedMessages.push(jsonMessage);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
this.rememberRequest(jsonMessage);
|
|
45
|
-
this.transport?.send(jsonMessage);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
stop(): void {
|
|
49
|
-
this.stopping = true;
|
|
50
|
-
if (this.startupTimer) {
|
|
51
|
-
clearTimeout(this.startupTimer);
|
|
52
|
-
this.startupTimer = undefined;
|
|
53
|
-
}
|
|
54
|
-
this.transport?.stop();
|
|
55
|
-
this.transport = undefined;
|
|
56
|
-
this.transportReady = false;
|
|
57
|
-
this.starting = false;
|
|
58
|
-
this.queuedMessages = [];
|
|
59
|
-
this.inFlightRequests.clear();
|
|
60
|
-
this.stopping = false;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
private ensureTransport(): void {
|
|
64
|
-
if (this.transport || this.starting) return;
|
|
65
|
-
const candidates = this.commandCandidates();
|
|
66
|
-
if (candidates.length === 0) {
|
|
67
|
-
throw new Error("Codex app-server command is unavailable.");
|
|
68
|
-
}
|
|
69
|
-
this.startCandidate(this.candidateIndex);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
private commandCandidates(): AgentCommandConfig[] {
|
|
73
|
-
return this.input.commandCandidates ?? resolveCodexAppServerCommands({
|
|
74
|
-
command: this.input.command,
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
private startCandidate(index: number): void {
|
|
79
|
-
const config = this.commandCandidates()[index];
|
|
80
|
-
if (!config) {
|
|
81
|
-
this.failQueued("Codex app-server command is unavailable.");
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
this.candidateIndex = index;
|
|
85
|
-
this.starting = true;
|
|
86
|
-
this.transportReady = false;
|
|
87
|
-
this.transport = new JsonRpcStdioTransport(
|
|
88
|
-
config.command,
|
|
89
|
-
config.framing,
|
|
90
|
-
() => {},
|
|
91
|
-
() => ({}),
|
|
92
|
-
(message) => this.handleTransportExit(message),
|
|
93
|
-
(message) => {
|
|
94
|
-
this.forgetRequest(message);
|
|
95
|
-
this.input.send(createEnvelope({
|
|
96
|
-
type: "agent.codex.rpc",
|
|
97
|
-
hostDeviceId: this.input.hostDeviceId,
|
|
98
|
-
payload: message,
|
|
99
|
-
}));
|
|
100
|
-
return true;
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
includeJsonrpc: false,
|
|
104
|
-
verbose: this.input.verbose,
|
|
105
|
-
onStderrData: (message) => this.handleTransportStderr(message),
|
|
106
|
-
},
|
|
107
|
-
);
|
|
108
|
-
this.transport.start(this.input.cwd);
|
|
109
|
-
if (this.input.verbose) {
|
|
110
|
-
process.stderr.write(`[agent:codex-rpc] started ${config.command}\n`);
|
|
111
|
-
}
|
|
112
|
-
this.startupTimer = setTimeout(() => {
|
|
113
|
-
this.startupTimer = undefined;
|
|
114
|
-
this.transportReady = true;
|
|
115
|
-
this.starting = false;
|
|
116
|
-
this.flushQueued();
|
|
117
|
-
}, CODEX_PROXY_STARTUP_GRACE_MS);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private handleTransportExit(message: string): void {
|
|
121
|
-
if (this.stopping) return;
|
|
122
|
-
if (this.startupTimer) {
|
|
123
|
-
clearTimeout(this.startupTimer);
|
|
124
|
-
this.startupTimer = undefined;
|
|
125
|
-
}
|
|
126
|
-
const wasReady = this.transportReady;
|
|
127
|
-
this.transport = undefined;
|
|
128
|
-
this.transportReady = false;
|
|
129
|
-
this.starting = false;
|
|
130
|
-
const nextIndex = this.candidateIndex + 1;
|
|
131
|
-
if (!wasReady && nextIndex < this.commandCandidates().length) {
|
|
132
|
-
if (this.input.verbose) {
|
|
133
|
-
process.stderr.write(`[agent:codex-rpc] ${message}; falling back\n`);
|
|
134
|
-
}
|
|
135
|
-
this.startCandidate(nextIndex);
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
this.failQueued(message);
|
|
139
|
-
this.failInFlight(message);
|
|
140
|
-
this.emitError(message);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private flushQueued(): void {
|
|
144
|
-
const messages = this.queuedMessages.splice(0);
|
|
145
|
-
for (const message of messages) {
|
|
146
|
-
this.rememberRequest(message);
|
|
147
|
-
this.transport?.send(message);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
private failQueued(message: string): void {
|
|
152
|
-
const queued = this.queuedMessages.splice(0);
|
|
153
|
-
for (const item of queued) {
|
|
154
|
-
if (!("id" in item) || item.id === undefined || item.id === null) continue;
|
|
155
|
-
this.input.send(createEnvelope({
|
|
156
|
-
type: "agent.codex.rpc",
|
|
157
|
-
hostDeviceId: this.input.hostDeviceId,
|
|
158
|
-
payload: {
|
|
159
|
-
jsonrpc: "2.0",
|
|
160
|
-
id: item.id,
|
|
161
|
-
error: { code: -32000, message },
|
|
162
|
-
},
|
|
163
|
-
}));
|
|
164
|
-
}
|
|
165
|
-
if (this.input.verbose) {
|
|
166
|
-
process.stderr.write(`[agent:codex-rpc] ${message}\n`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
private emitError(message: string): void {
|
|
171
|
-
this.input.send(createEnvelope({
|
|
172
|
-
type: "agent.codex.rpc",
|
|
173
|
-
hostDeviceId: this.input.hostDeviceId,
|
|
174
|
-
payload: {
|
|
175
|
-
jsonrpc: "2.0",
|
|
176
|
-
id: "linkshell-codex-rpc-error",
|
|
177
|
-
error: { code: -32000, message },
|
|
178
|
-
},
|
|
179
|
-
}));
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
private handleTransportStderr(message: string): void {
|
|
183
|
-
if (this.input.verbose) {
|
|
184
|
-
process.stderr.write(`[agent:codex-rpc] stderr ignored while app-server is running: ${message}\n`);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
private rememberRequest(message: JsonRpcMessage): void {
|
|
189
|
-
if (!isJsonRpcRequest(message)) return;
|
|
190
|
-
this.inFlightRequests.set(message.id, message);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private forgetRequest(message: JsonRpcMessage): void {
|
|
194
|
-
if (!isJsonRpcResponse(message)) return;
|
|
195
|
-
this.inFlightRequests.delete(message.id);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
private failInFlight(message: string): void {
|
|
199
|
-
const requests = [...this.inFlightRequests.values()];
|
|
200
|
-
this.inFlightRequests.clear();
|
|
201
|
-
for (const item of requests) {
|
|
202
|
-
if (!isJsonRpcRequest(item)) continue;
|
|
203
|
-
this.input.send(createEnvelope({
|
|
204
|
-
type: "agent.codex.rpc",
|
|
205
|
-
hostDeviceId: this.input.hostDeviceId,
|
|
206
|
-
payload: {
|
|
207
|
-
jsonrpc: "2.0",
|
|
208
|
-
id: item.id,
|
|
209
|
-
error: { code: -32000, message },
|
|
210
|
-
},
|
|
211
|
-
}));
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function isJsonRpcRequest(message: JsonRpcMessage): message is JsonRpcMessage & { id: JsonRpcId; method: string } {
|
|
217
|
-
return "id" in message &&
|
|
218
|
-
"method" in message &&
|
|
219
|
-
(typeof message.id === "string" || typeof message.id === "number") &&
|
|
220
|
-
typeof message.method === "string";
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
function isJsonRpcResponse(message: JsonRpcMessage): message is JsonRpcMessage & { id: JsonRpcId } {
|
|
224
|
-
return "id" in message &&
|
|
225
|
-
(typeof message.id === "string" || typeof message.id === "number") &&
|
|
226
|
-
("result" in message || "error" in message);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function isJsonRpcNotification(message: JsonRpcMessage): message is JsonRpcMessage & { method: string } {
|
|
230
|
-
return !("id" in message) &&
|
|
231
|
-
"method" in message &&
|
|
232
|
-
typeof message.method === "string";
|
|
233
|
-
}
|