@aipanel/provider-opencode 1.2.0-beta.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/es/api.d.ts +16 -0
- package/es/api.js +225 -0
- package/es/bridge-script.d.ts +14 -0
- package/es/bridge-script.js +683 -0
- package/es/constants.d.ts +32 -0
- package/es/constants.js +29 -0
- package/es/index.d.ts +15 -0
- package/es/index.js +24 -0
- package/es/opencode-web.d.ts +4 -0
- package/es/opencode-web.js +276 -0
- package/es/provider.d.ts +49 -0
- package/es/provider.js +257 -0
- package/es/system.d.ts +3 -0
- package/es/system.js +175 -0
- package/es/types.d.ts +160 -0
- package/es/types.js +0 -0
- package/lib/api.cjs +251 -0
- package/lib/api.d.ts +16 -0
- package/lib/bridge-script.cjs +706 -0
- package/lib/bridge-script.d.ts +14 -0
- package/lib/constants.cjs +55 -0
- package/lib/constants.d.ts +32 -0
- package/lib/index.cjs +55 -0
- package/lib/index.d.ts +15 -0
- package/lib/opencode-web.cjs +302 -0
- package/lib/opencode-web.d.ts +4 -0
- package/lib/provider.cjs +289 -0
- package/lib/provider.d.ts +49 -0
- package/lib/system.cjs +200 -0
- package/lib/system.d.ts +3 -0
- package/lib/types.cjs +15 -0
- package/lib/types.d.ts +160 -0
- package/package.json +32 -0
package/es/api.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SessionInfo } from "./types";
|
|
2
|
+
export declare class OpenCodeAPI {
|
|
3
|
+
private hostname;
|
|
4
|
+
private getPort;
|
|
5
|
+
private getProxyPort;
|
|
6
|
+
private chromeDevtoolsPort;
|
|
7
|
+
constructor(hostname: string, getPort: () => number, getProxyPort: () => number, chromeDevtoolsPort?: number);
|
|
8
|
+
/** 构建代理 iframe URL(旧版格式:/{base64(projectDir)}/session/{id}) */
|
|
9
|
+
buildSessionProxyUrl(projectDir: string, sessionId: string): string;
|
|
10
|
+
private createHttpRequest;
|
|
11
|
+
getSessions(projectDir: string, retries?: number): Promise<SessionInfo[]>;
|
|
12
|
+
createSession(projectDir: string, retries?: number, title?: string): Promise<SessionInfo>;
|
|
13
|
+
deleteSession(sessionId: string, retries?: number): Promise<void>;
|
|
14
|
+
getToolIds(retries?: number): Promise<string[]>;
|
|
15
|
+
getOrCreateSession(projectDir: string): Promise<string>;
|
|
16
|
+
}
|
package/es/api.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import http from "http";
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_RETRIES,
|
|
7
|
+
RETRY_DELAY,
|
|
8
|
+
CHROME_DEVTOOLS_PORT,
|
|
9
|
+
sleep,
|
|
10
|
+
base64Encode
|
|
11
|
+
} from "@aipanel/core";
|
|
12
|
+
import { PerformanceTimer, createLogger } from "@aipanel/core/node";
|
|
13
|
+
const log = createLogger("API");
|
|
14
|
+
class OpenCodeAPI {
|
|
15
|
+
constructor(hostname, getPort, getProxyPort, chromeDevtoolsPort = CHROME_DEVTOOLS_PORT) {
|
|
16
|
+
__publicField(this, "hostname", hostname);
|
|
17
|
+
__publicField(this, "getPort", getPort);
|
|
18
|
+
__publicField(this, "getProxyPort", getProxyPort);
|
|
19
|
+
__publicField(this, "chromeDevtoolsPort", chromeDevtoolsPort);
|
|
20
|
+
}
|
|
21
|
+
/** 构建代理 iframe URL(旧版格式:/{base64(projectDir)}/session/{id}) */
|
|
22
|
+
buildSessionProxyUrl(projectDir, sessionId) {
|
|
23
|
+
return `http://${this.hostname}:${this.getProxyPort()}/${base64Encode(projectDir)}/session/${sessionId}`;
|
|
24
|
+
}
|
|
25
|
+
createHttpRequest(options, body, timeout) {
|
|
26
|
+
const timer = new PerformanceTimer("HTTP Request", {
|
|
27
|
+
operation: `${options.method || "GET"} ${options.path}`
|
|
28
|
+
});
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const req = http.request(options, (res) => {
|
|
31
|
+
let data = "";
|
|
32
|
+
res.on("data", (chunk) => data += chunk);
|
|
33
|
+
res.on("end", () => {
|
|
34
|
+
try {
|
|
35
|
+
const result = JSON.parse(data);
|
|
36
|
+
timer.end(`\u2713 Status: ${res.statusCode}`);
|
|
37
|
+
resolve(result);
|
|
38
|
+
} catch {
|
|
39
|
+
timer.end("\u274C JSON parse error");
|
|
40
|
+
reject(new Error(`JSON parse error: ${data.substring(0, 100)}`));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
req.on("error", (e) => {
|
|
45
|
+
timer.end("\u274C Request failed");
|
|
46
|
+
reject(e);
|
|
47
|
+
});
|
|
48
|
+
if (timeout) {
|
|
49
|
+
req.setTimeout(timeout, () => {
|
|
50
|
+
timer.end("\u274C Request timeout");
|
|
51
|
+
req.destroy();
|
|
52
|
+
reject(new Error(`Request timeout after ${timeout}ms`));
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (body) req.write(body);
|
|
56
|
+
req.end();
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async getSessions(projectDir, retries = DEFAULT_RETRIES) {
|
|
60
|
+
const timer = log.timer("getSessions", { retries, projectDir });
|
|
61
|
+
let lastError = null;
|
|
62
|
+
for (let i = 0; i < retries; i++) {
|
|
63
|
+
try {
|
|
64
|
+
log.debug(`Attempt ${i + 1}/${retries}`, { operation: "getSessions", projectDir });
|
|
65
|
+
const sessions = await this.createHttpRequest({
|
|
66
|
+
hostname: this.hostname,
|
|
67
|
+
port: this.getPort(),
|
|
68
|
+
path: `/session?directory=${encodeURIComponent(projectDir)}`
|
|
69
|
+
});
|
|
70
|
+
const sessionsWithUrl = sessions.map((s) => ({
|
|
71
|
+
...s,
|
|
72
|
+
url: s.directory && s.id ? this.buildSessionProxyUrl(s.directory, s.id) : ""
|
|
73
|
+
}));
|
|
74
|
+
timer.end(`Found ${sessions.length} sessions`);
|
|
75
|
+
return sessionsWithUrl;
|
|
76
|
+
} catch (e) {
|
|
77
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
78
|
+
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, {
|
|
79
|
+
operation: "getSessions"
|
|
80
|
+
});
|
|
81
|
+
if (i < retries - 1) {
|
|
82
|
+
log.debug(`Retrying in ${RETRY_DELAY}ms...`, {
|
|
83
|
+
operation: "getSessions"
|
|
84
|
+
});
|
|
85
|
+
await sleep(RETRY_DELAY);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
timer.end("\u274C All retries exhausted");
|
|
90
|
+
throw lastError;
|
|
91
|
+
}
|
|
92
|
+
async createSession(projectDir, retries = DEFAULT_RETRIES, title) {
|
|
93
|
+
const timer = log.timer("createSession", { retries, title, projectDir });
|
|
94
|
+
let lastError = null;
|
|
95
|
+
for (let i = 0; i < retries; i++) {
|
|
96
|
+
try {
|
|
97
|
+
log.debug(`Attempt ${i + 1}/${retries}`, {
|
|
98
|
+
operation: "createSession",
|
|
99
|
+
title,
|
|
100
|
+
projectDir
|
|
101
|
+
});
|
|
102
|
+
const requestBody = title ? JSON.stringify({ title }) : void 0;
|
|
103
|
+
const session = await this.createHttpRequest(
|
|
104
|
+
{
|
|
105
|
+
hostname: this.hostname,
|
|
106
|
+
port: this.getPort(),
|
|
107
|
+
path: "/session",
|
|
108
|
+
method: "POST",
|
|
109
|
+
headers: {
|
|
110
|
+
...requestBody ? { "Content-Type": "application/json" } : {}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
requestBody
|
|
114
|
+
);
|
|
115
|
+
const sessionWithUrl = {
|
|
116
|
+
...session,
|
|
117
|
+
url: this.buildSessionProxyUrl(projectDir, session.id)
|
|
118
|
+
};
|
|
119
|
+
timer.end(`Created session: ${session.id}`);
|
|
120
|
+
return sessionWithUrl;
|
|
121
|
+
} catch (e) {
|
|
122
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
123
|
+
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, {
|
|
124
|
+
operation: "createSession"
|
|
125
|
+
});
|
|
126
|
+
if (i < retries - 1) {
|
|
127
|
+
log.debug(`Retrying in ${RETRY_DELAY}ms...`, {
|
|
128
|
+
operation: "createSession"
|
|
129
|
+
});
|
|
130
|
+
await sleep(RETRY_DELAY);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
timer.end("\u274C All retries exhausted");
|
|
135
|
+
throw lastError;
|
|
136
|
+
}
|
|
137
|
+
async deleteSession(sessionId, retries = DEFAULT_RETRIES) {
|
|
138
|
+
const timer = log.timer("deleteSession", { sessionId, retries });
|
|
139
|
+
let lastError = null;
|
|
140
|
+
for (let i = 0; i < retries; i++) {
|
|
141
|
+
try {
|
|
142
|
+
log.debug(`Attempt ${i + 1}/${retries}`, {
|
|
143
|
+
operation: "deleteSession",
|
|
144
|
+
sessionId
|
|
145
|
+
});
|
|
146
|
+
await this.createHttpRequest({
|
|
147
|
+
hostname: this.hostname,
|
|
148
|
+
port: this.getPort(),
|
|
149
|
+
path: `/session/${sessionId}`,
|
|
150
|
+
method: "DELETE"
|
|
151
|
+
});
|
|
152
|
+
timer.end(`Deleted session: ${sessionId}`);
|
|
153
|
+
return;
|
|
154
|
+
} catch (e) {
|
|
155
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
156
|
+
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, {
|
|
157
|
+
operation: "deleteSession",
|
|
158
|
+
sessionId
|
|
159
|
+
});
|
|
160
|
+
if (i < retries - 1) {
|
|
161
|
+
log.debug(`Retrying in ${RETRY_DELAY}ms...`, {
|
|
162
|
+
operation: "deleteSession",
|
|
163
|
+
sessionId
|
|
164
|
+
});
|
|
165
|
+
await sleep(RETRY_DELAY);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
timer.end("\u274C All retries exhausted");
|
|
170
|
+
throw lastError;
|
|
171
|
+
}
|
|
172
|
+
async getToolIds(retries = DEFAULT_RETRIES) {
|
|
173
|
+
const timer = log.timer("getToolIds", { retries });
|
|
174
|
+
let lastError = null;
|
|
175
|
+
for (let i = 0; i < retries; i++) {
|
|
176
|
+
try {
|
|
177
|
+
log.debug(`Attempt ${i + 1}/${retries}`, {
|
|
178
|
+
operation: "getToolIds"
|
|
179
|
+
});
|
|
180
|
+
const toolIds = await this.createHttpRequest({
|
|
181
|
+
hostname: this.hostname,
|
|
182
|
+
port: this.getPort(),
|
|
183
|
+
path: "/experimental/tool/ids"
|
|
184
|
+
});
|
|
185
|
+
timer.end(`Found ${toolIds.length} tools`);
|
|
186
|
+
return toolIds;
|
|
187
|
+
} catch (e) {
|
|
188
|
+
lastError = e instanceof Error ? e : new Error(String(e));
|
|
189
|
+
log.debug(`Attempt ${i + 1} failed: ${lastError.message}`, {
|
|
190
|
+
operation: "getToolIds"
|
|
191
|
+
});
|
|
192
|
+
if (i < retries - 1) {
|
|
193
|
+
log.debug(`Retrying in ${RETRY_DELAY}ms...`, {
|
|
194
|
+
operation: "getToolIds"
|
|
195
|
+
});
|
|
196
|
+
await sleep(RETRY_DELAY);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
timer.end("\u274C All retries exhausted");
|
|
201
|
+
throw lastError;
|
|
202
|
+
}
|
|
203
|
+
async getOrCreateSession(projectDir) {
|
|
204
|
+
const timer = log.timer("getOrCreateSession", { projectDir });
|
|
205
|
+
log.debug("Getting sessions...", { projectDir });
|
|
206
|
+
const sessions = await this.getSessions(projectDir);
|
|
207
|
+
log.debug(`Found ${sessions.length} sessions`, {
|
|
208
|
+
sessions: sessions.map((s) => ({ id: s.id, directory: s.directory }))
|
|
209
|
+
});
|
|
210
|
+
const matchingSession = sessions.find((s) => s.directory === projectDir);
|
|
211
|
+
if (matchingSession) {
|
|
212
|
+
const url2 = this.buildSessionProxyUrl(projectDir, matchingSession.id);
|
|
213
|
+
timer.end(`Using existing session: ${matchingSession.id}`);
|
|
214
|
+
return url2;
|
|
215
|
+
}
|
|
216
|
+
log.debug("Creating new session...", { projectDir });
|
|
217
|
+
const newSession = await this.createSession(projectDir);
|
|
218
|
+
const url = this.buildSessionProxyUrl(projectDir, newSession.id);
|
|
219
|
+
timer.end(`Created new session: ${newSession.id}`);
|
|
220
|
+
return url;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
export {
|
|
224
|
+
OpenCodeAPI
|
|
225
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { OpenCodeLanguage, OpenCodeSettings } from "./types";
|
|
2
|
+
export interface BridgeScriptOptions {
|
|
3
|
+
/** 主题模式 */
|
|
4
|
+
theme?: "light" | "dark" | "auto";
|
|
5
|
+
/** 界面语言 */
|
|
6
|
+
language?: OpenCodeLanguage;
|
|
7
|
+
/** 内部设置 */
|
|
8
|
+
settings?: OpenCodeSettings;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 生成 PostMessage Bridge 脚本
|
|
12
|
+
* 只处理 DOM 操作和主题同步,SSE 监听已迁移到 client 层
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateBridgeScript(options?: BridgeScriptOptions): string;
|