vite-plugin-opencode-assistant 1.0.3 → 1.0.5
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/client/index.d.ts +1 -0
- package/es/client/index.js +328 -0
- package/es/core/api.d.ts +14 -0
- package/es/core/api.js +294 -0
- package/es/core/injector.d.ts +2 -0
- package/es/core/injector.js +11 -0
- package/es/core/service.d.ts +18 -0
- package/es/core/service.js +163 -0
- package/es/endpoints/context.d.ts +3 -0
- package/es/endpoints/context.js +114 -0
- package/es/endpoints/index.d.ts +4 -0
- package/es/endpoints/index.js +16 -0
- package/es/endpoints/sessions.d.ts +3 -0
- package/es/endpoints/sessions.js +79 -0
- package/es/endpoints/sse.d.ts +3 -0
- package/es/endpoints/sse.js +56 -0
- package/es/endpoints/start.d.ts +3 -0
- package/es/endpoints/start.js +35 -0
- package/es/endpoints/types.d.ts +13 -0
- package/es/endpoints/widget.d.ts +3 -0
- package/es/endpoints/widget.js +57 -0
- package/es/index.d.ts +3 -0
- package/es/index.js +168 -0
- package/es/utils/paths.d.ts +3 -0
- package/es/utils/paths.js +38 -0
- package/es/utils/system.js +241 -0
- package/lib/client/index.d.ts +1 -0
- package/lib/client/index.js +328 -0
- package/lib/client.js +5597 -0
- package/lib/core/api.d.ts +14 -0
- package/lib/core/api.js +321 -0
- package/lib/core/injector.d.ts +2 -0
- package/lib/core/injector.js +34 -0
- package/lib/core/service.d.ts +18 -0
- package/lib/core/service.js +180 -0
- package/lib/endpoints/context.d.ts +3 -0
- package/lib/endpoints/context.js +137 -0
- package/lib/endpoints/index.d.ts +4 -0
- package/lib/endpoints/index.js +41 -0
- package/lib/endpoints/sessions.d.ts +3 -0
- package/lib/endpoints/sessions.js +102 -0
- package/lib/endpoints/sse.d.ts +3 -0
- package/lib/endpoints/sse.js +79 -0
- package/lib/endpoints/start.d.ts +3 -0
- package/lib/endpoints/start.js +58 -0
- package/lib/endpoints/types.d.ts +13 -0
- package/lib/endpoints/types.js +15 -0
- package/lib/endpoints/widget.d.ts +3 -0
- package/lib/endpoints/widget.js +90 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +190 -0
- package/lib/style.css +1 -0
- package/lib/utils/paths.d.ts +3 -0
- package/lib/utils/paths.js +73 -0
- package/lib/utils/system.d.ts +5 -0
- package/lib/utils/system.js +274 -0
- package/package.json +29 -31
- package/README.md +0 -282
- package/dist/constants.d.ts +0 -73
- package/dist/constants.js +0 -74
- package/dist/constants.js.map +0 -1
- package/dist/logger.d.ts +0 -64
- package/dist/logger.js +0 -311
- package/dist/logger.js.map +0 -1
- package/dist/opencode/plugins/page-context.d.ts +0 -7
- package/dist/opencode/plugins/page-context.js +0 -345
- package/dist/opencode/plugins/page-context.js.map +0 -1
- package/dist/opencode/web.d.ts +0 -3
- package/dist/opencode/web.js +0 -81
- package/dist/opencode/web.js.map +0 -1
- package/dist/types.d.ts +0 -124
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/vite/client.js +0 -2288
- package/dist/vite/client.js.map +0 -1
- package/dist/vite/index.d.ts +0 -3
- package/dist/vite/index.js +0 -520
- package/dist/vite/index.js.map +0 -1
- package/dist/vite/injector.d.ts +0 -2
- package/dist/vite/injector.js +0 -6
- package/dist/vite/injector.js.map +0 -1
- package/dist/vite/utils.js +0 -206
- package/dist/vite/utils.js.map +0 -1
- /package/{dist/vite/client.d.ts → es/endpoints/types.js} +0 -0
- /package/{dist/vite/utils.d.ts → es/utils/system.d.ts} +0 -0
package/lib/index.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
9
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __spreadValues = (a, b) => {
|
|
11
|
+
for (var prop in b || (b = {}))
|
|
12
|
+
if (__hasOwnProp.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
if (__getOwnPropSymbols)
|
|
15
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
16
|
+
if (__propIsEnum.call(b, prop))
|
|
17
|
+
__defNormalProp(a, prop, b[prop]);
|
|
18
|
+
}
|
|
19
|
+
return a;
|
|
20
|
+
};
|
|
21
|
+
var __export = (target, all) => {
|
|
22
|
+
for (var name in all)
|
|
23
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
24
|
+
};
|
|
25
|
+
var __copyProps = (to, from, except, desc) => {
|
|
26
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
27
|
+
for (let key of __getOwnPropNames(from))
|
|
28
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
29
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
30
|
+
}
|
|
31
|
+
return to;
|
|
32
|
+
};
|
|
33
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
34
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
35
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
36
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
37
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
38
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
39
|
+
mod
|
|
40
|
+
));
|
|
41
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
42
|
+
var __async = (__this, __arguments, generator) => {
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
var fulfilled = (value) => {
|
|
45
|
+
try {
|
|
46
|
+
step(generator.next(value));
|
|
47
|
+
} catch (e) {
|
|
48
|
+
reject(e);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var rejected = (value) => {
|
|
52
|
+
try {
|
|
53
|
+
step(generator.throw(value));
|
|
54
|
+
} catch (e) {
|
|
55
|
+
reject(e);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
59
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
var lib_exports = {};
|
|
63
|
+
__export(lib_exports, {
|
|
64
|
+
default: () => opencodePlugin
|
|
65
|
+
});
|
|
66
|
+
module.exports = __toCommonJS(lib_exports);
|
|
67
|
+
var import_vite = __toESM(require("unplugin-vue-inspector/vite"));
|
|
68
|
+
var import_shared = require("@vite-plugin-opencode-assistant/shared");
|
|
69
|
+
var import_endpoints = require("./endpoints/index.js");
|
|
70
|
+
var import_injector = require("./core/injector.js");
|
|
71
|
+
var import_api = require("./core/api.js");
|
|
72
|
+
var import_service = require("./core/service.js");
|
|
73
|
+
var import_paths = require("./utils/paths.js");
|
|
74
|
+
function opencodePlugin(options = {}) {
|
|
75
|
+
const plugins = [];
|
|
76
|
+
plugins.push(
|
|
77
|
+
...(0, import_vite.default)({
|
|
78
|
+
enabled: false,
|
|
79
|
+
toggleButtonVisibility: "never",
|
|
80
|
+
toggleComboKey: false
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
plugins.push(createOpenCodePlugin(options));
|
|
84
|
+
return plugins;
|
|
85
|
+
}
|
|
86
|
+
function createOpenCodePlugin(options = {}) {
|
|
87
|
+
const config = __spreadValues(__spreadValues({}, import_shared.DEFAULT_CONFIG), options);
|
|
88
|
+
(0, import_shared.setVerbose)(config.verbose);
|
|
89
|
+
const log = (0, import_shared.createLogger)("Plugin");
|
|
90
|
+
let actualWebPort = config.webPort;
|
|
91
|
+
let pageContext = { url: "", title: "" };
|
|
92
|
+
const sseClients = /* @__PURE__ */ new Set();
|
|
93
|
+
const api = new import_api.OpenCodeAPI(config.hostname, () => actualWebPort, config.warmupChromeMcp);
|
|
94
|
+
const service = new import_service.OpenCodeService(config, api, sseClients, (port) => {
|
|
95
|
+
actualWebPort = port;
|
|
96
|
+
});
|
|
97
|
+
return {
|
|
98
|
+
name: "vite-plugin-opencode",
|
|
99
|
+
apply(_viteConfig, env) {
|
|
100
|
+
if (!config.enabled) return false;
|
|
101
|
+
return env.command === "serve" && process.env.NODE_ENV !== "test";
|
|
102
|
+
},
|
|
103
|
+
configureServer(server) {
|
|
104
|
+
return __async(this, null, function* () {
|
|
105
|
+
var _a2, _b;
|
|
106
|
+
const timer = log.timer("configureServer");
|
|
107
|
+
(0, import_endpoints.setupMiddlewares)(server, {
|
|
108
|
+
get sessionUrl() {
|
|
109
|
+
return service.sessionUrl;
|
|
110
|
+
},
|
|
111
|
+
get sseClients() {
|
|
112
|
+
return sseClients;
|
|
113
|
+
},
|
|
114
|
+
get pageContext() {
|
|
115
|
+
return pageContext;
|
|
116
|
+
},
|
|
117
|
+
set pageContext(ctx) {
|
|
118
|
+
pageContext = ctx;
|
|
119
|
+
},
|
|
120
|
+
getSessions: () => api.getSessions(),
|
|
121
|
+
createSession: () => api.createSession(),
|
|
122
|
+
deleteSession: (id) => api.deleteSession(id),
|
|
123
|
+
resolveWidgetPath: import_paths.resolveWidgetPath,
|
|
124
|
+
resolveWidgetStylePath: import_paths.resolveWidgetStylePath
|
|
125
|
+
});
|
|
126
|
+
(_a2 = server.httpServer) == null ? void 0 : _a2.on("listening", () => __async(null, null, function* () {
|
|
127
|
+
var _a3;
|
|
128
|
+
log.debug("Vite server listening event fired");
|
|
129
|
+
const address = (_a3 = server.httpServer) == null ? void 0 : _a3.address();
|
|
130
|
+
let vitePort;
|
|
131
|
+
let viteHost;
|
|
132
|
+
if (address && typeof address === "object") {
|
|
133
|
+
vitePort = address.port;
|
|
134
|
+
const addr = address.address;
|
|
135
|
+
if (addr === "::" || addr === "::1" || addr === "0.0.0.0" || !addr) {
|
|
136
|
+
viteHost = "localhost";
|
|
137
|
+
} else {
|
|
138
|
+
viteHost = addr;
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
const host = server.config.server.host;
|
|
142
|
+
vitePort = server.config.server.port || 5173;
|
|
143
|
+
viteHost = typeof host === "string" && host !== "0.0.0.0" && host !== "::" && host !== "::1" ? host : "localhost";
|
|
144
|
+
}
|
|
145
|
+
const viteOrigin = `http://${viteHost}:${vitePort}`;
|
|
146
|
+
const contextApiUrl = `http://${viteHost}:${vitePort}${import_shared.CONTEXT_API_PATH}`;
|
|
147
|
+
log.debug("Vite server ready", {
|
|
148
|
+
vitePort,
|
|
149
|
+
viteHost,
|
|
150
|
+
viteOrigin,
|
|
151
|
+
contextApiUrl
|
|
152
|
+
});
|
|
153
|
+
try {
|
|
154
|
+
yield service.start([viteOrigin], contextApiUrl, viteOrigin);
|
|
155
|
+
} catch (e) {
|
|
156
|
+
log.error("Failed to start services", { error: e });
|
|
157
|
+
}
|
|
158
|
+
}));
|
|
159
|
+
(_b = server.httpServer) == null ? void 0 : _b.on("close", () => {
|
|
160
|
+
log.debug("HTTP server closing");
|
|
161
|
+
service.stop();
|
|
162
|
+
});
|
|
163
|
+
const cleanup = () => __async(null, null, function* () {
|
|
164
|
+
log.debug("Process cleanup triggered");
|
|
165
|
+
yield service.stop();
|
|
166
|
+
process.exit(0);
|
|
167
|
+
});
|
|
168
|
+
process.on("SIGINT", cleanup);
|
|
169
|
+
process.on("SIGTERM", cleanup);
|
|
170
|
+
timer.end("\u2713 Server configured");
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
transformIndexHtml(html) {
|
|
174
|
+
const timer = log.timer("transformIndexHtml");
|
|
175
|
+
const widget = (0, import_injector.injectWidget)({
|
|
176
|
+
webUrl: `http://${config.hostname}:${actualWebPort}`,
|
|
177
|
+
serverUrl: `http://${config.hostname}:${actualWebPort}`,
|
|
178
|
+
position: config.position,
|
|
179
|
+
theme: config.theme,
|
|
180
|
+
open: config.open,
|
|
181
|
+
autoReload: config.autoReload,
|
|
182
|
+
cwd: process.cwd(),
|
|
183
|
+
sessionUrl: service.sessionUrl || void 0,
|
|
184
|
+
hotkey: config.hotkey
|
|
185
|
+
});
|
|
186
|
+
timer.end();
|
|
187
|
+
return html.replace("</body>", `${widget}</body>`);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
}
|
package/lib/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.opencode-widget{--oc-bg-main: #ffffff;--oc-bg-secondary: #f8f9fa;--oc-bg-tertiary: #f3f4f6;--oc-overlay-bg: rgba(255, 255, 255, .9);--oc-bg-inverse: #1e1e1e;--oc-text-primary: #282828;--oc-text-secondary: #4b5563;--oc-text-tertiary: #6b7280;--oc-text-placeholder: #9ca3af;--oc-text-inverse: #ffffff;--oc-border-primary: #e5e7eb;--oc-border-secondary: #d1d5db;--oc-primary: #3b82f6;--oc-primary-hover: #2563eb;--oc-primary-bg: rgba(59, 130, 246, .1);--oc-danger: #ef4444;--oc-danger-hover: #dc2626;--oc-danger-active: #b91c1c;--oc-success: #10b981;--oc-overlay: rgba(0, 0, 0, .5);--oc-tooltip-bg: #1e1e1e;--oc-dialog-overlay: rgba(0, 0, 0, .5);--oc-skeleton-bg: #e5e7eb;--oc-skeleton-gradient: linear-gradient(90deg, #e5e7eb 25%, #f3f4f6 50%, #e5e7eb 75%);--oc-shadow-sm: 0 2px 4px rgba(0, 0, 0, .1);--oc-shadow-md: 0 4px 12px rgba(0, 0, 0, .15);--oc-shadow-lg: 0 8px 32px rgba(0, 0, 0, .12);--oc-shadow-xl: 0 20px 60px rgba(0, 0, 0, .3);--oc-shadow-primary: 0 2px 4px rgba(59, 130, 246, .2);--oc-shadow-primary-hover: 0 4px 6px rgba(59, 130, 246, .3);--oc-shadow-danger: 0 4px 12px rgba(239, 68, 68, .3);--oc-trigger-bg: linear-gradient(135deg, #667eea 0%, #764ba2 100%);--oc-trigger-bg-hover: linear-gradient(135deg, #764ba2 0%, #667eea 100%);--oc-trigger-bg-active: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);--oc-trigger-shadow: 0 4px 15px rgba(102, 126, 234, .4);--oc-trigger-shadow-hover: 0 6px 20px rgba(102, 126, 234, .6);--oc-trigger-shadow-active: 0 6px 20px rgba(240, 147, 251, .4);position:fixed;z-index:999999;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.opencode-widget.opencode-theme-dark{--oc-bg-main: #1a1a1a;--oc-bg-secondary: #1e1e1e;--oc-bg-tertiary: #282828;--oc-overlay-bg: rgba(26, 26, 26, .9);--oc-bg-inverse: #ffffff;--oc-text-primary: #f3f4f6;--oc-text-secondary: #d1d5db;--oc-text-tertiary: #9ca3af;--oc-text-placeholder: #6b7280;--oc-text-inverse: #282828;--oc-border-primary: #282828;--oc-border-secondary: #4b5563;--oc-primary: #3b82f6;--oc-primary-hover: #2563eb;--oc-primary-bg: rgba(59, 130, 246, .15);--oc-danger: #ef4444;--oc-danger-hover: #dc2626;--oc-danger-active: #b91c1c;--oc-success: #10b981;--oc-overlay: rgba(26, 26, 26, .9);--oc-tooltip-bg: #282828;--oc-dialog-overlay: rgba(0, 0, 0, .7);--oc-skeleton-bg: #151515;--oc-skeleton-gradient: linear-gradient(90deg, #282828 25%, #4b5563 50%, #282828 75%);--oc-shadow-sm: 0 2px 4px rgba(0, 0, 0, .3);--oc-shadow-md: 0 4px 12px rgba(0, 0, 0, .4);--oc-shadow-lg: 0 8px 32px rgba(0, 0, 0, .4);--oc-shadow-xl: 0 20px 60px rgba(0, 0, 0, .6);--oc-shadow-primary: 0 2px 4px rgba(59, 130, 246, .3);--oc-shadow-primary-hover: 0 4px 6px rgba(59, 130, 246, .4);--oc-shadow-danger: 0 4px 12px rgba(239, 68, 68, .4);--oc-trigger-bg: linear-gradient(135deg, #667eea 0%, #764ba2 100%);--oc-trigger-bg-hover: linear-gradient(135deg, #764ba2 0%, #667eea 100%);--oc-trigger-bg-active: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);--oc-trigger-shadow: 0 4px 15px rgba(102, 126, 234, .5);--oc-trigger-shadow-hover: 0 6px 20px rgba(102, 126, 234, .7);--oc-trigger-shadow-active: 0 6px 20px rgba(240, 147, 251, .5)}.opencode-widget.bottom-right{bottom:20px;right:20px}.opencode-widget.bottom-left{bottom:20px;left:20px}.opencode-widget.top-right{top:20px;right:20px}.opencode-widget.top-left{top:20px;left:20px}.opencode-chat{position:absolute;width:700px;height:86vh;background:var(--oc-bg-main);border-radius:16px;box-shadow:var(--oc-shadow-lg);overflow:hidden;opacity:0;visibility:hidden;transform:translateY(20px) scale(.95);transition:all .3s ease;display:flex;flex-direction:column}.opencode-chat-content{display:flex;flex:1;overflow:hidden}.opencode-widget.bottom-right .opencode-chat{bottom:56px;right:0}.opencode-widget.bottom-left .opencode-chat{bottom:56px;left:0}.opencode-widget.top-right .opencode-chat{top:56px;right:0}.opencode-widget.top-left .opencode-chat{top:56px;left:0}.opencode-widget.bottom-right .opencode-selected-bubbles{bottom:56px;right:0}.opencode-widget.bottom-left .opencode-selected-bubbles{bottom:56px;left:0}.opencode-widget.top-right .opencode-selected-bubbles{top:56px;bottom:auto;right:0}.opencode-widget.top-left .opencode-selected-bubbles{top:56px;bottom:auto;left:0}.opencode-chat.open{opacity:1;visibility:visible;transform:translateY(0) scale(1)}.opencode-notification{position:absolute;top:20px;left:50%;transform:translate(-50%);padding:12px 20px;background:var(--oc-bg-main);color:var(--oc-text-primary);border:1px solid var(--oc-border-primary);border-radius:8px;font-size:14px;box-shadow:var(--oc-shadow-lg);animation:slideDown .3s ease;z-index:10000000}.opencode-dialog-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:var(--oc-dialog-overlay);display:flex;align-items:center;justify-content:center;z-index:9999999;animation:fadeIn .2s ease}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.opencode-dialog{background:var(--oc-bg-main);border-radius:12px;padding:24px;min-width:320px;max-width:400px;box-shadow:var(--oc-shadow-xl);animation:scaleIn .2s ease}@keyframes scaleIn{0%{transform:scale(.9);opacity:0}to{transform:scale(1);opacity:1}}.opencode-dialog-content{margin-bottom:20px}.opencode-dialog-message{font-size:15px;color:var(--oc-text-primary);line-height:1.5}.opencode-dialog-actions{display:flex;gap:12px;justify-content:flex-end}.opencode-dialog-btn{padding:10px 20px;border-radius:8px;border:none;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s}.opencode-dialog-btn.cancel{background:var(--oc-bg-tertiary);color:var(--oc-text-primary)}.opencode-dialog-btn.cancel:hover{background:var(--oc-text-primary);color:var(--oc-bg-main)}.opencode-dialog-btn.confirm{background:var(--oc-danger);color:#fff}.opencode-dialog-btn.confirm:hover{background:var(--oc-danger-hover)}@keyframes slideDown{0%{transform:translate(-50%) translateY(-100%);opacity:0}to{transform:translate(-50%) translateY(0);opacity:1}}.opencode-element-highlight{position:fixed;pointer-events:none;z-index:999998;display:none;transition:all .1s ease;border-radius:4px}#vue-inspector-container{display:none!important}.opencode-element-tooltip{position:fixed;background:var(--oc-tooltip-bg);color:#fff;padding:8px 12px;border-radius:6px;font-size:12px;z-index:9999998;display:none;box-shadow:var(--oc-shadow-md);max-width:300px;pointer-events:none}.opencode-tooltip-tag{font-weight:500;margin-bottom:4px;word-break:break-all}.opencode-tooltip-file{font-size:11px;color:var(--oc-text-placeholder);word-break:break-all}.opencode-element-highlight-temp{position:absolute;pointer-events:none;z-index:999998;border-radius:4px;animation:highlight-pulse 2s ease-out forwards}@keyframes highlight-pulse{0%{opacity:1;transform:scale(1)}50%{opacity:.8;transform:scale(1.02)}to{opacity:0;transform:scale(1)}}@media (max-width:768px){.opencode-chat{width:calc(100vw - 40px);height:calc(100vh - 100px)}}.opencode-iframe-container{flex:1;position:relative;overflow:hidden;display:flex;flex-direction:column;margin-top:-42px}.opencode-loading-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background:var(--oc-overlay-bg);display:none;flex-direction:column;align-items:center;justify-content:center;z-index:10;transition:opacity .3s ease}.opencode-loading-overlay.visible{display:flex}.opencode-loading-spinner{width:40px;height:40px;border:3px solid var(--oc-border-primary);border-top-color:var(--oc-primary);border-radius:50%;animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.opencode-loading-text{margin-top:12px;font-size:14px;color:var(--oc-text-placeholder)}.opencode-empty-state-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background:var(--oc-bg-secondary);display:none;flex-direction:column;align-items:center;justify-content:center;z-index:5;transition:opacity .3s ease;margin-top:42px}.opencode-empty-state-overlay.visible{display:flex}.opencode-empty-state-icon{color:var(--oc-text-placeholder);margin-bottom:16px}.opencode-empty-state-text{color:var(--oc-text-primary);font-size:16px;font-weight:500;margin-bottom:24px}.opencode-empty-state-btn{padding:10px 24px;border-radius:8px;border:none;background:var(--oc-primary);color:#fff;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s;box-shadow:var(--oc-shadow-primary)}.opencode-empty-state-btn:hover{background:var(--oc-primary-hover);transform:translateY(-1px);box-shadow:var(--oc-shadow-primary-hover)}.opencode-empty-state-btn:active{transform:translateY(0)}.opencode-iframe{width:100%;height:100%;border:none}.opencode-chat-header{position:relative;flex-shrink:0;display:flex;align-items:center;justify-content:space-between;padding:0 12px;height:40px;background:var(--oc-bg-secondary);border-bottom:1px solid var(--oc-border-primary);z-index:5}.opencode-chat-header-left{display:flex;align-items:center;gap:4px}.opencode-chat-header-title{font-size:14px;font-weight:600;color:var(--oc-text-primary);position:absolute;left:50%;transform:translate(-50%)}.opencode-chat-header-actions{display:flex;gap:4px}.opencode-header-btn{width:28px;height:28px;border-radius:6px;border:none;background:transparent;color:var(--oc-text-placeholder);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s}.opencode-header-btn:hover{background:var(--oc-bg-tertiary);color:var(--oc-text-primary)}.opencode-header-btn.close:hover{background:var(--oc-danger);color:#fff}.opencode-header-btn.select-btn.active{background:var(--oc-primary);color:#fff}.opencode-select-mode-hint{position:fixed;top:20px;left:50%;transform:translate(-50%);padding:10px 16px;background:var(--oc-danger);color:#fff;border-radius:8px;font-size:13px;box-shadow:var(--oc-shadow-danger);z-index:9999999;display:none;align-items:center;gap:12px}.opencode-select-mode-hint.visible{display:flex;animation:slideDown .3s ease}.opencode-hint-shortcut{padding:2px 6px;background:#fff3;border-radius:4px;font-size:12px}.opencode-selected-bubbles{position:absolute;display:none;flex-direction:column;gap:6px;max-width:220px;max-height:300px;overflow-y:auto}.opencode-selected-bubbles.visible{display:flex}.opencode-selected-bubble{display:flex;flex-direction:column;gap:2px;padding:8px 24px 8px 10px;background:var(--oc-bg-main);border:1px solid var(--oc-border-primary);border-radius:8px;font-size:12px;box-shadow:var(--oc-shadow-sm);position:relative;cursor:pointer;transition:all .2s}.opencode-selected-bubble:hover{border-color:var(--oc-primary);box-shadow:var(--oc-shadow-primary)}.opencode-bubble-text{color:var(--oc-text-primary);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.opencode-bubble-file{color:var(--oc-text-placeholder);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.opencode-bubble-remove{position:absolute;top:8px;right:6px;width:16px;height:16px;border-radius:50%;border:none;background:transparent;color:var(--oc-text-placeholder);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:12px;transition:all .2s}.opencode-bubble-remove:hover{background:var(--oc-danger);color:#fff}.opencode-bubble-empty{padding:8px 12px;background:var(--oc-bg-main);border:1px dashed var(--oc-border-secondary);border-radius:8px;color:var(--oc-text-placeholder);font-size:12px;text-align:center}.opencode-right-toolbar{width:140px;background:var(--oc-bg-secondary);border-left:1px solid var(--oc-border-primary);display:flex;flex-direction:column;flex-shrink:0;transition:width .2s ease;overflow:hidden}.opencode-right-toolbar.collapsed{width:0;overflow:hidden}.opencode-right-toolbar.collapsed .opencode-selected-nodes-header,.opencode-right-toolbar.collapsed .opencode-selected-nodes,.opencode-right-toolbar.collapsed .opencode-clear-all-btn{display:none}.opencode-selected-nodes-header{padding:12px 8px 8px;border-bottom:1px solid var(--oc-border-primary)}.opencode-selected-nodes-title{font-size:14px;font-weight:600;color:var(--oc-text-primary);margin-bottom:4px}.opencode-selected-nodes-desc{font-size:11px;color:var(--oc-text-placeholder);line-height:1.4}.opencode-selected-nodes{flex:1;display:flex;flex-direction:column;padding:8px;gap:6px;overflow-y:auto;overflow-x:hidden}.opencode-selected-nodes:empty:before{content:"暂无选中元素";color:var(--oc-text-placeholder);font-size:12px;text-align:center;padding:20px 10px}.opencode-selected-node{display:flex;align-items:center;gap:8px;padding:8px 10px;background:var(--oc-bg-main);border:1px solid var(--oc-border-primary);border-radius:6px;font-size:12px;transition:all .2s}.opencode-selected-node:hover{border-color:var(--oc-primary);box-shadow:var(--oc-shadow-primary)}.opencode-node-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.opencode-node-text{color:var(--oc-text-primary);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.opencode-node-file{color:var(--oc-text-placeholder);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.opencode-node-remove{width:18px;height:18px;border-radius:4px;border:none;background:transparent;color:var(--oc-text-placeholder);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;transition:all .2s;flex-shrink:0}.opencode-node-remove:hover{background:var(--oc-danger);color:#fff}.opencode-clear-all-btn{width:calc(100% - 16px);margin:8px;padding:8px 12px;border-radius:6px;border:none;background:var(--oc-danger);color:#fff;font-size:12px;font-weight:500;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:4px;transition:all .2s}.opencode-clear-all-btn:hover{background:var(--oc-danger-hover);transform:scale(1.02)}.opencode-session-list{width:240px;background:var(--oc-bg-secondary);border-right:1px solid var(--oc-border-primary);display:flex;flex-direction:column;flex-shrink:0;transition:width .2s ease}.opencode-session-list.collapsed{width:0;overflow:hidden}.opencode-session-list.collapsed .opencode-session-list-header,.opencode-session-list.collapsed .opencode-session-list-content{display:none}.opencode-session-list-header{padding:16px;border-bottom:1px solid var(--oc-border-primary);display:flex;justify-content:space-between;align-items:center;font-weight:600;font-size:14px;color:var(--oc-text-primary)}.opencode-new-session-btn{width:28px;height:28px;border-radius:6px;border:none;background:var(--oc-primary);color:#fff;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s}.opencode-new-session-btn:hover{background:var(--oc-primary-hover);transform:scale(1.05)}.opencode-session-list-content{flex:1;overflow-y:auto;padding:8px;position:relative}.opencode-session-list-loading-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background:var(--oc-overlay-bg);display:flex;align-items:center;justify-content:center;z-index:10;border-radius:8px}.opencode-loading-spinner.small{width:24px;height:24px;border-width:2px}.opencode-session-item{padding:12px;border-radius:8px;cursor:pointer;transition:all .2s;margin-bottom:4px;color:var(--oc-text-primary)}.opencode-session-item:hover{background:var(--oc-bg-tertiary)}.opencode-session-item.active{background:var(--oc-primary);color:#fff}.opencode-session-title{font-size:14px;font-weight:500;margin-bottom:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.opencode-session-meta{font-size:12px;opacity:.6}.opencode-session-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px}.opencode-session-delete-btn{width:20px;height:20px;border-radius:4px;border:none;background:transparent;color:var(--oc-text-placeholder);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;opacity:0;flex-shrink:0}.opencode-session-item:hover .opencode-session-delete-btn{opacity:1}.opencode-session-delete-btn:hover{background:var(--oc-danger);color:#fff}.opencode-session-item.active .opencode-session-delete-btn{color:#ffffffb3}.opencode-session-item.active .opencode-session-delete-btn:hover{background:#fff3;color:#fff}.opencode-session-header-skeleton{padding:16px;border-bottom:1px solid var(--oc-border-primary);display:none;justify-content:space-between;align-items:center}.opencode-session-header-skeleton.visible{display:flex}.opencode-skeleton-header-title{height:18px;width:80px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px}.opencode-skeleton-header-btn{width:28px;height:28px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:6px}.opencode-session-skeleton{flex:1;overflow-y:auto;padding:8px;display:none}.opencode-session-skeleton.visible{display:block}.opencode-skeleton-item{padding:12px;border-radius:8px;margin-bottom:4px;background:var(--oc-skeleton-bg)}.opencode-skeleton-title{height:16px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px;margin-bottom:8px;width:70%}.opencode-skeleton-meta{height:12px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px;width:50%}.opencode-session-empty{padding:32px 16px;text-align:center;color:var(--oc-text-placeholder);font-size:13px}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}.opencode-button{width:44px;height:44px;border-radius:50%;background:var(--oc-trigger-bg);border:none;cursor:pointer;box-shadow:var(--oc-trigger-shadow);transition:all .3s ease;display:flex;align-items:center;justify-content:center;color:#fff;padding:0;position:relative}.opencode-button:before{content:"";position:absolute;top:-8px;left:-8px;right:-8px;bottom:-8px;border-radius:50%}.opencode-button:hover{transform:scale(1.1);box-shadow:var(--oc-trigger-shadow-hover);background:var(--oc-trigger-bg-hover)}.opencode-button.active{background:var(--oc-trigger-bg-active);box-shadow:var(--oc-trigger-shadow-active)}.opencode-button.active svg{transform:rotate(180deg)}.opencode-button svg{transition:transform .3s ease}.opencode-button.loading{animation:pulse 1s infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var paths_exports = {};
|
|
29
|
+
__export(paths_exports, {
|
|
30
|
+
resolvePackageDir: () => resolvePackageDir,
|
|
31
|
+
resolveWidgetPath: () => resolveWidgetPath,
|
|
32
|
+
resolveWidgetStylePath: () => resolveWidgetStylePath
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(paths_exports);
|
|
35
|
+
var import_fs = __toESM(require("fs"));
|
|
36
|
+
var import_path = __toESM(require("path"));
|
|
37
|
+
var import_module = require("module");
|
|
38
|
+
const require2 = (0, import_module.createRequire)(import_path.default.join(process.cwd(), "package.json"));
|
|
39
|
+
const packageDir = resolvePackageDir();
|
|
40
|
+
function resolvePackageDir() {
|
|
41
|
+
const entryPath = require2.resolve("vite-plugin-opencode-assistant");
|
|
42
|
+
return import_path.default.resolve(import_path.default.dirname(entryPath), "..");
|
|
43
|
+
}
|
|
44
|
+
function resolveWidgetPath() {
|
|
45
|
+
const candidatePaths = [
|
|
46
|
+
import_path.default.join(packageDir, "es", "client.js"),
|
|
47
|
+
import_path.default.join(packageDir, "lib", "client.js")
|
|
48
|
+
];
|
|
49
|
+
for (const candidatePath of candidatePaths) {
|
|
50
|
+
if (import_fs.default.existsSync(candidatePath)) {
|
|
51
|
+
return candidatePath;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return candidatePaths[0];
|
|
55
|
+
}
|
|
56
|
+
function resolveWidgetStylePath() {
|
|
57
|
+
const candidatePaths = [
|
|
58
|
+
import_path.default.join(packageDir, "es", "style.css"),
|
|
59
|
+
import_path.default.join(packageDir, "lib", "style.css")
|
|
60
|
+
];
|
|
61
|
+
for (const candidatePath of candidatePaths) {
|
|
62
|
+
if (import_fs.default.existsSync(candidatePath)) {
|
|
63
|
+
return candidatePath;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return candidatePaths[0];
|
|
67
|
+
}
|
|
68
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
69
|
+
0 && (module.exports = {
|
|
70
|
+
resolvePackageDir,
|
|
71
|
+
resolveWidgetPath,
|
|
72
|
+
resolveWidgetStylePath
|
|
73
|
+
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function waitForServer(url: string, timeout?: number): Promise<void>;
|
|
2
|
+
export declare function checkOpenCodeInstalled(): Promise<boolean>;
|
|
3
|
+
export declare function isPortAvailable(port: number, hostname?: string): Promise<boolean>;
|
|
4
|
+
export declare function findAvailablePort(startPort: number, hostname?: string, maxTries?: number): Promise<number>;
|
|
5
|
+
export declare function killOrphanOpenCodeProcesses(): Promise<number>;
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var __async = (__this, __arguments, generator) => {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
var fulfilled = (value) => {
|
|
31
|
+
try {
|
|
32
|
+
step(generator.next(value));
|
|
33
|
+
} catch (e) {
|
|
34
|
+
reject(e);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var rejected = (value) => {
|
|
38
|
+
try {
|
|
39
|
+
step(generator.throw(value));
|
|
40
|
+
} catch (e) {
|
|
41
|
+
reject(e);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
45
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
var system_exports = {};
|
|
49
|
+
__export(system_exports, {
|
|
50
|
+
checkOpenCodeInstalled: () => checkOpenCodeInstalled,
|
|
51
|
+
findAvailablePort: () => findAvailablePort,
|
|
52
|
+
isPortAvailable: () => isPortAvailable,
|
|
53
|
+
killOrphanOpenCodeProcesses: () => killOrphanOpenCodeProcesses,
|
|
54
|
+
waitForServer: () => waitForServer
|
|
55
|
+
});
|
|
56
|
+
module.exports = __toCommonJS(system_exports);
|
|
57
|
+
var import_child_process = require("child_process");
|
|
58
|
+
var import_http = __toESM(require("http"));
|
|
59
|
+
var import_net = __toESM(require("net"));
|
|
60
|
+
var import_shared = require("@vite-plugin-opencode-assistant/shared");
|
|
61
|
+
var import_shared2 = require("@vite-plugin-opencode-assistant/shared");
|
|
62
|
+
const log = (0, import_shared2.createLogger)("Utils");
|
|
63
|
+
function waitForServer(url, timeout = 1e4) {
|
|
64
|
+
const timer = new import_shared2.PerformanceTimer("waitForServer", { url, timeout });
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
const startTime = Date.now();
|
|
67
|
+
let attempts = 0;
|
|
68
|
+
const check = () => {
|
|
69
|
+
attempts++;
|
|
70
|
+
log.debug(`Checking server availability (attempt ${attempts})`, { url });
|
|
71
|
+
const req = import_http.default.get(url, (res) => {
|
|
72
|
+
if (res.statusCode && res.statusCode < 500) {
|
|
73
|
+
timer.end(`\u2713 Server ready after ${attempts} attempts`);
|
|
74
|
+
resolve();
|
|
75
|
+
} else {
|
|
76
|
+
log.debug(`Server returned status ${res.statusCode}, retrying...`);
|
|
77
|
+
retryOrReject();
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
req.on("error", (err) => {
|
|
81
|
+
log.debug(`Server check failed: ${err.message}`);
|
|
82
|
+
retryOrReject();
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
const retryOrReject = () => {
|
|
86
|
+
const elapsed = Date.now() - startTime;
|
|
87
|
+
if (elapsed < timeout) {
|
|
88
|
+
setTimeout(check, import_shared.SERVER_CHECK_INTERVAL);
|
|
89
|
+
} else {
|
|
90
|
+
timer.end("\u274C Timeout");
|
|
91
|
+
reject(new Error(`Server not ready after ${timeout}ms (${attempts} attempts)`));
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
check();
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function checkOpenCodeInstalled() {
|
|
98
|
+
return __async(this, null, function* () {
|
|
99
|
+
const timer = log.timer("checkOpenCodeInstalled");
|
|
100
|
+
return new Promise((resolve) => {
|
|
101
|
+
log.debug("Checking if OpenCode is installed...");
|
|
102
|
+
const proc = (0, import_child_process.spawn)("opencode", ["--version"], { stdio: "ignore" });
|
|
103
|
+
proc.on("close", (code) => {
|
|
104
|
+
const installed = code === 0;
|
|
105
|
+
timer.end(installed ? "\u2713 OpenCode is installed" : "\u274C OpenCode not found");
|
|
106
|
+
resolve(installed);
|
|
107
|
+
});
|
|
108
|
+
proc.on("error", (err) => {
|
|
109
|
+
log.debug("Failed to check OpenCode installation", { error: err.message });
|
|
110
|
+
timer.end("\u274C Check failed");
|
|
111
|
+
resolve(false);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function isPortAvailable(_0) {
|
|
117
|
+
return __async(this, arguments, function* (port, hostname = import_shared.DEFAULT_HOSTNAME) {
|
|
118
|
+
return new Promise((resolve) => {
|
|
119
|
+
const server = import_net.default.createServer();
|
|
120
|
+
server.once("error", (err) => {
|
|
121
|
+
log.debug(`Port ${port} is not available`, { error: err.message });
|
|
122
|
+
resolve(false);
|
|
123
|
+
});
|
|
124
|
+
server.once("listening", () => {
|
|
125
|
+
server.close();
|
|
126
|
+
log.debug(`Port ${port} is available`);
|
|
127
|
+
resolve(true);
|
|
128
|
+
});
|
|
129
|
+
server.listen(port, hostname);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function findAvailablePort(_0) {
|
|
134
|
+
return __async(this, arguments, function* (startPort, hostname = import_shared.DEFAULT_HOSTNAME, maxTries = import_shared.MAX_PORT_TRIES) {
|
|
135
|
+
const timer = log.timer("findAvailablePort", { startPort, hostname, maxTries });
|
|
136
|
+
log.debug(`Looking for available port starting from ${startPort}`);
|
|
137
|
+
for (let port = startPort; port < startPort + maxTries; port++) {
|
|
138
|
+
if (yield isPortAvailable(port, hostname)) {
|
|
139
|
+
timer.end(`\u2713 Found available port: ${port}`);
|
|
140
|
+
return port;
|
|
141
|
+
}
|
|
142
|
+
log.debug(`Port ${port} is in use, trying next...`);
|
|
143
|
+
}
|
|
144
|
+
timer.end("\u274C No available port found");
|
|
145
|
+
throw new Error(`No available port found after ${maxTries} tries starting from ${startPort}`);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function killOrphanOpenCodeProcesses() {
|
|
149
|
+
return __async(this, null, function* () {
|
|
150
|
+
const timer = log.timer("killOrphanOpenCodeProcesses");
|
|
151
|
+
log.debug("Looking for orphan OpenCode processes (PPID=1)");
|
|
152
|
+
return new Promise((resolve) => {
|
|
153
|
+
if (process.platform === "win32") {
|
|
154
|
+
killOrphanProcessesOnWindows(resolve, timer);
|
|
155
|
+
} else {
|
|
156
|
+
killOrphanProcessesOnUnix(resolve, timer);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
function killOrphanProcessesOnWindows(resolve, timer) {
|
|
162
|
+
var _a;
|
|
163
|
+
log.debug("Using Windows method to find orphan processes");
|
|
164
|
+
const proc = (0, import_child_process.spawn)(
|
|
165
|
+
"wmic",
|
|
166
|
+
["process", "where", 'name="opencode.exe"', "get", "processid,parentprocessid"],
|
|
167
|
+
{ stdio: "pipe" }
|
|
168
|
+
);
|
|
169
|
+
let output = "";
|
|
170
|
+
(_a = proc.stdout) == null ? void 0 : _a.on("data", (data) => {
|
|
171
|
+
output += data.toString();
|
|
172
|
+
});
|
|
173
|
+
proc.on("close", () => {
|
|
174
|
+
const lines = output.split("\n").filter((line) => line.trim());
|
|
175
|
+
const pidsToKill = [];
|
|
176
|
+
lines.forEach((line) => {
|
|
177
|
+
const parts = line.trim().split(/\s+/);
|
|
178
|
+
if (parts.length >= 2) {
|
|
179
|
+
const ppid = parts[0];
|
|
180
|
+
const pid = parts[1];
|
|
181
|
+
if (ppid === "1" && pid && !isNaN(Number(pid))) {
|
|
182
|
+
pidsToKill.push(pid);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
if (pidsToKill.length > 0) {
|
|
187
|
+
log.debug(`Found ${pidsToKill.length} orphan processes`, { pids: pidsToKill });
|
|
188
|
+
let killedCount = 0;
|
|
189
|
+
let completedCount = 0;
|
|
190
|
+
pidsToKill.forEach((pid) => {
|
|
191
|
+
const killProc = (0, import_child_process.spawn)("taskkill", ["/F", "/PID", pid], { stdio: "ignore" });
|
|
192
|
+
killProc.on("close", (code) => {
|
|
193
|
+
completedCount++;
|
|
194
|
+
if (code === 0) {
|
|
195
|
+
killedCount++;
|
|
196
|
+
log.debug(`Killed orphan process ${pid}`);
|
|
197
|
+
}
|
|
198
|
+
if (completedCount === pidsToKill.length) {
|
|
199
|
+
timer.end(`\u2713 Killed ${killedCount} orphan processes`);
|
|
200
|
+
resolve(killedCount);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
} else {
|
|
205
|
+
log.debug("No orphan processes found");
|
|
206
|
+
timer.end("No orphan processes found");
|
|
207
|
+
resolve(0);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
proc.on("error", (err) => {
|
|
211
|
+
log.debug("Failed to find orphan processes", { error: err.message });
|
|
212
|
+
timer.end("\u274C Failed to find orphan processes");
|
|
213
|
+
resolve(0);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function killOrphanProcessesOnUnix(resolve, timer) {
|
|
217
|
+
var _a;
|
|
218
|
+
log.debug("Using Unix method to find orphan processes");
|
|
219
|
+
const proc = (0, import_child_process.spawn)("ps", ["-e", "-o", "pid,ppid,comm"], { stdio: "pipe" });
|
|
220
|
+
let output = "";
|
|
221
|
+
(_a = proc.stdout) == null ? void 0 : _a.on("data", (data) => {
|
|
222
|
+
output += data.toString();
|
|
223
|
+
});
|
|
224
|
+
proc.on("close", () => {
|
|
225
|
+
const lines = output.split("\n");
|
|
226
|
+
const pidsToKill = [];
|
|
227
|
+
lines.forEach((line) => {
|
|
228
|
+
const trimmed = line.trim();
|
|
229
|
+
if (trimmed.includes("opencode")) {
|
|
230
|
+
const parts = trimmed.split(/\s+/);
|
|
231
|
+
if (parts.length >= 3) {
|
|
232
|
+
const pid = parts[0];
|
|
233
|
+
const ppid = parts[1];
|
|
234
|
+
const comm = parts.slice(2).join(" ");
|
|
235
|
+
if (ppid === "1" && comm.includes("opencode")) {
|
|
236
|
+
pidsToKill.push(pid);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
if (pidsToKill.length > 0) {
|
|
242
|
+
log.debug(`Found ${pidsToKill.length} orphan processes`, { pids: pidsToKill });
|
|
243
|
+
const killProc = (0, import_child_process.spawn)("kill", ["-9", ...pidsToKill], { stdio: "ignore" });
|
|
244
|
+
killProc.on("close", (code) => {
|
|
245
|
+
const killedCount = code === 0 ? pidsToKill.length : 0;
|
|
246
|
+
timer.end(
|
|
247
|
+
killedCount > 0 ? `\u2713 Killed ${killedCount} orphan processes` : "\u274C Failed to kill processes"
|
|
248
|
+
);
|
|
249
|
+
resolve(killedCount);
|
|
250
|
+
});
|
|
251
|
+
killProc.on("error", () => {
|
|
252
|
+
timer.end("\u274C Failed to kill processes");
|
|
253
|
+
resolve(0);
|
|
254
|
+
});
|
|
255
|
+
} else {
|
|
256
|
+
log.debug("No orphan processes found");
|
|
257
|
+
timer.end("No orphan processes found");
|
|
258
|
+
resolve(0);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
proc.on("error", (err) => {
|
|
262
|
+
log.debug("Failed to find orphan processes", { error: err.message });
|
|
263
|
+
timer.end("\u274C Failed to find orphan processes");
|
|
264
|
+
resolve(0);
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
268
|
+
0 && (module.exports = {
|
|
269
|
+
checkOpenCodeInstalled,
|
|
270
|
+
findAvailablePort,
|
|
271
|
+
isPortAvailable,
|
|
272
|
+
killOrphanOpenCodeProcesses,
|
|
273
|
+
waitForServer
|
|
274
|
+
});
|
package/package.json
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-opencode-assistant",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Embed OpenCode Web UI in your Vite dev server for real-time code modification and preview",
|
|
5
|
-
"main": "dist/vite/index.js",
|
|
6
|
-
"types": "dist/vite/index.d.ts",
|
|
7
5
|
"type": "module",
|
|
8
|
-
"
|
|
9
|
-
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"module": "es/index.js",
|
|
8
|
+
"types": "es/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"es",
|
|
11
|
+
"lib"
|
|
10
12
|
],
|
|
11
13
|
"exports": {
|
|
12
14
|
".": {
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
+
"types": "./es/index.d.ts",
|
|
16
|
+
"import": "./es/index.js",
|
|
17
|
+
"require": "./lib/index.js"
|
|
15
18
|
}
|
|
16
19
|
},
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
"scripts": {
|
|
21
|
-
"build": "rm -rf dist && tsc && npm run build:plugins",
|
|
22
|
-
"build:plugins": "vite build --config vite.plugins.config.ts",
|
|
23
|
-
"dev": "tsc --watch",
|
|
24
|
-
"test": "vitest",
|
|
25
|
-
"prepublishOnly": "npm run build"
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public",
|
|
22
|
+
"registry": "https://registry.npmjs.org/"
|
|
26
23
|
},
|
|
27
24
|
"keywords": [
|
|
28
25
|
"vite",
|
|
@@ -38,25 +35,26 @@
|
|
|
38
35
|
"author": "",
|
|
39
36
|
"license": "MIT",
|
|
40
37
|
"dependencies": {
|
|
41
|
-
"
|
|
42
|
-
"
|
|
38
|
+
"unplugin-vue-inspector": "^2.4.0",
|
|
39
|
+
"@vite-plugin-opencode-assistant/opencode": "1.0.4",
|
|
40
|
+
"@vite-plugin-opencode-assistant/shared": "1.0.5",
|
|
41
|
+
"@vite-plugin-opencode-assistant/components": "1.0.5"
|
|
43
42
|
},
|
|
44
43
|
"peerDependencies": {
|
|
45
44
|
"vite": ">=4.0.0"
|
|
46
45
|
},
|
|
47
46
|
"devDependencies": {
|
|
48
|
-
"@
|
|
49
|
-
"
|
|
50
|
-
"typescript": "^5.
|
|
47
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
48
|
+
"execa": "^9.6.1",
|
|
49
|
+
"typescript": "^5.9.3",
|
|
51
50
|
"vite": "^5.0.0",
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
"repository": {
|
|
55
|
-
"type": "git",
|
|
56
|
-
"url": "https://github.com/your-username/vite-plugin-opencode.git"
|
|
51
|
+
"vue": "^3.5.32",
|
|
52
|
+
"vue-tsc": "^2.2.12"
|
|
57
53
|
},
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "pagoda-cli build && vite build -c vite.client.config.ts",
|
|
56
|
+
"dev": "pagoda-cli dev",
|
|
57
|
+
"test": "vitest run",
|
|
58
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
59
|
+
}
|
|
60
|
+
}
|