vite-plugin-opencode-assistant 1.0.15 → 1.0.16

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.
Files changed (79) hide show
  1. package/es/client/App.vue.d.ts +6 -0
  2. package/es/client/App.vue.js +300 -0
  3. package/es/client/components/ChromeWarmupError-sfc.css +1 -0
  4. package/es/client/components/ChromeWarmupError.vue.d.ts +11 -0
  5. package/es/client/components/ChromeWarmupError.vue.js +196 -0
  6. package/es/client/components/LoadingContent.vue.d.ts +5 -0
  7. package/es/client/components/LoadingContent.vue.js +39 -0
  8. package/es/client/composables/useContext.d.ts +8 -0
  9. package/es/client/composables/useContext.js +63 -0
  10. package/es/client/composables/useHotkey.d.ts +12 -0
  11. package/es/client/composables/useHotkey.js +41 -0
  12. package/es/client/composables/useSSE.d.ts +20 -0
  13. package/es/client/composables/useSSE.js +61 -0
  14. package/es/client/composables/useSelectedElements.d.ts +19 -0
  15. package/es/client/composables/useSelectedElements.js +43 -0
  16. package/es/client/composables/useServiceStatus.d.ts +13 -0
  17. package/es/client/composables/useServiceStatus.js +53 -0
  18. package/es/client/composables/useSessions.d.ts +26 -0
  19. package/es/client/composables/useSessions.js +127 -0
  20. package/es/client/composables/useTheme.d.ts +12 -0
  21. package/es/client/composables/useTheme.js +42 -0
  22. package/es/client/index.d.ts +1 -1
  23. package/es/client/index.js +5 -675
  24. package/es/client/styles.css +1 -0
  25. package/es/core/api.d.ts +18 -6
  26. package/es/core/api.js +324 -69
  27. package/es/core/proxy-server.js +127 -2
  28. package/es/core/service.d.ts +9 -2
  29. package/es/core/service.js +35 -31
  30. package/es/endpoints/index.js +1 -1
  31. package/es/endpoints/sse.js +0 -3
  32. package/es/endpoints/start.d.ts +1 -2
  33. package/es/endpoints/start.js +2 -2
  34. package/es/endpoints/types.d.ts +5 -2
  35. package/es/endpoints/warmup.js +15 -3
  36. package/es/index.js +8 -12
  37. package/es/utils/system.d.ts +1 -0
  38. package/es/utils/system.js +28 -0
  39. package/lib/client/App.vue.d.ts +6 -0
  40. package/lib/client/App.vue.js +329 -0
  41. package/lib/client/components/ChromeWarmupError-sfc.css +1 -0
  42. package/lib/client/components/ChromeWarmupError.vue.d.ts +11 -0
  43. package/lib/client/components/ChromeWarmupError.vue.js +215 -0
  44. package/lib/client/components/LoadingContent.vue.d.ts +5 -0
  45. package/lib/client/components/LoadingContent.vue.js +58 -0
  46. package/lib/client/composables/useContext.d.ts +8 -0
  47. package/lib/client/composables/useContext.js +86 -0
  48. package/lib/client/composables/useHotkey.d.ts +12 -0
  49. package/lib/client/composables/useHotkey.js +66 -0
  50. package/lib/client/composables/useSSE.d.ts +20 -0
  51. package/lib/client/composables/useSSE.js +84 -0
  52. package/lib/client/composables/useSelectedElements.d.ts +19 -0
  53. package/lib/client/composables/useSelectedElements.js +66 -0
  54. package/lib/client/composables/useServiceStatus.d.ts +13 -0
  55. package/lib/client/composables/useServiceStatus.js +76 -0
  56. package/lib/client/composables/useSessions.d.ts +26 -0
  57. package/lib/client/composables/useSessions.js +148 -0
  58. package/lib/client/composables/useTheme.d.ts +12 -0
  59. package/lib/client/composables/useTheme.js +65 -0
  60. package/lib/client/index.d.ts +1 -1
  61. package/lib/client/index.js +22 -667
  62. package/lib/client/styles.css +1 -0
  63. package/lib/client.js +2988 -2973
  64. package/lib/core/api.d.ts +18 -6
  65. package/lib/core/api.js +321 -74
  66. package/lib/core/proxy-server.js +127 -2
  67. package/lib/core/service.d.ts +9 -2
  68. package/lib/core/service.js +31 -30
  69. package/lib/endpoints/index.js +1 -1
  70. package/lib/endpoints/sse.js +0 -3
  71. package/lib/endpoints/start.d.ts +1 -2
  72. package/lib/endpoints/start.js +2 -2
  73. package/lib/endpoints/types.d.ts +5 -2
  74. package/lib/endpoints/warmup.js +15 -3
  75. package/lib/index.js +8 -12
  76. package/lib/style.css +1 -1
  77. package/lib/utils/system.d.ts +1 -0
  78. package/lib/utils/system.js +29 -0
  79. package/package.json +4 -4
@@ -0,0 +1,41 @@
1
+ import { onMounted, onUnmounted } from "vue";
2
+ function parseHotkey(hotkeyStr) {
3
+ if (!hotkeyStr) return { ctrl: true, shift: false, alt: false, key: "k" };
4
+ const parts = hotkeyStr.toLowerCase().split("+");
5
+ const key = parts.pop();
6
+ return {
7
+ ctrl: parts.includes("ctrl") || parts.includes("cmd") || parts.includes("meta"),
8
+ shift: parts.includes("shift"),
9
+ alt: parts.includes("alt"),
10
+ key: key || "k"
11
+ };
12
+ }
13
+ function matchHotkey(e, hotkeyConfig) {
14
+ const ctrlMatch = hotkeyConfig.ctrl ? e.ctrlKey || e.metaKey : !(e.ctrlKey || e.metaKey);
15
+ const shiftMatch = hotkeyConfig.shift ? e.shiftKey : !e.shiftKey;
16
+ const altMatch = hotkeyConfig.alt ? e.altKey : !e.altKey;
17
+ const keyMatch = e.key.toLowerCase() === hotkeyConfig.key.toLowerCase();
18
+ return ctrlMatch && shiftMatch && altMatch && keyMatch;
19
+ }
20
+ function useHotkey(hotkeyStr, callback) {
21
+ const hotkeyConfig = parseHotkey(hotkeyStr);
22
+ const handleKeydown = (e) => {
23
+ if (matchHotkey(e, hotkeyConfig)) {
24
+ callback(e);
25
+ }
26
+ };
27
+ onMounted(() => {
28
+ document.addEventListener("keydown", handleKeydown);
29
+ });
30
+ onUnmounted(() => {
31
+ document.removeEventListener("keydown", handleKeydown);
32
+ });
33
+ return {
34
+ hotkeyConfig
35
+ };
36
+ }
37
+ export {
38
+ matchHotkey,
39
+ parseHotkey,
40
+ useHotkey
41
+ };
@@ -0,0 +1,20 @@
1
+ import { ServiceStartupTask } from "@vite-plugin-opencode-assistant/shared";
2
+ interface SSEStatusSyncData {
3
+ type: "STATUS_SYNC";
4
+ isStarted?: boolean;
5
+ task: ServiceStartupTask;
6
+ errorType?: string;
7
+ errorMessage?: string;
8
+ }
9
+ interface SSETaskUpdateData {
10
+ type: "TASK_UPDATE";
11
+ task: ServiceStartupTask;
12
+ errorType?: string;
13
+ errorMessage?: string;
14
+ }
15
+ export declare function useSSE(onStatusSync: (data: SSEStatusSyncData) => void, onTaskUpdate: (data: SSETaskUpdateData) => void, onClearElements: () => void, onConnected: () => void): {
16
+ setupSSE: () => void;
17
+ closeSSE: () => void;
18
+ sseRetryCount: import("vue").Ref<number, number>;
19
+ };
20
+ export {};
@@ -0,0 +1,61 @@
1
+ import { ref, onUnmounted } from "vue";
2
+ const MAX_SSE_RETRIES = 10;
3
+ const SSE_RETRY_DELAY = 1e3;
4
+ function useSSE(onStatusSync, onTaskUpdate, onClearElements, onConnected) {
5
+ const sseConnection = ref(null);
6
+ const sseRetryCount = ref(0);
7
+ const setupSSE = () => {
8
+ if (sseConnection.value) return;
9
+ try {
10
+ sseConnection.value = new EventSource("/__opencode_events__");
11
+ sseConnection.value.onmessage = (event) => {
12
+ try {
13
+ const data = JSON.parse(event.data);
14
+ if (data.type === "CONNECTED") {
15
+ onConnected();
16
+ sseRetryCount.value = 0;
17
+ } else if (data.type === "STATUS_SYNC") {
18
+ onStatusSync(data);
19
+ } else if (data.type === "TASK_UPDATE") {
20
+ onTaskUpdate(data);
21
+ } else if (data.type === "CLEAR_ELEMENTS") {
22
+ onClearElements();
23
+ }
24
+ } catch (e) {
25
+ }
26
+ };
27
+ sseConnection.value.onerror = () => {
28
+ var _a;
29
+ (_a = sseConnection.value) == null ? void 0 : _a.close();
30
+ sseConnection.value = null;
31
+ if (sseRetryCount.value < MAX_SSE_RETRIES) {
32
+ sseRetryCount.value++;
33
+ setTimeout(setupSSE, SSE_RETRY_DELAY * sseRetryCount.value);
34
+ }
35
+ };
36
+ } catch (e) {
37
+ sseConnection.value = null;
38
+ if (sseRetryCount.value < MAX_SSE_RETRIES) {
39
+ sseRetryCount.value++;
40
+ setTimeout(setupSSE, SSE_RETRY_DELAY * sseRetryCount.value);
41
+ }
42
+ }
43
+ };
44
+ const closeSSE = () => {
45
+ if (sseConnection.value) {
46
+ sseConnection.value.close();
47
+ sseConnection.value = null;
48
+ }
49
+ };
50
+ onUnmounted(() => {
51
+ closeSSE();
52
+ });
53
+ return {
54
+ setupSSE,
55
+ closeSSE,
56
+ sseRetryCount
57
+ };
58
+ }
59
+ export {
60
+ useSSE
61
+ };
@@ -0,0 +1,19 @@
1
+ import type { OpenCodeSelectedElement } from "@vite-plugin-opencode-assistant/shared";
2
+ export declare function useSelectedElements(): {
3
+ selectedElements: import("vue").Ref<{
4
+ filePath: string | null;
5
+ line: number | null;
6
+ column: number | null;
7
+ innerText: string;
8
+ description?: string | undefined;
9
+ }[], OpenCodeSelectedElement[] | {
10
+ filePath: string | null;
11
+ line: number | null;
12
+ column: number | null;
13
+ innerText: string;
14
+ description?: string | undefined;
15
+ }[]>;
16
+ addElement: (element: OpenCodeSelectedElement) => boolean;
17
+ removeElement: (index: number) => void;
18
+ clearElements: () => void;
19
+ };
@@ -0,0 +1,43 @@
1
+ import { ref, watch } from "vue";
2
+ function useSelectedElements() {
3
+ const selectedElements = ref([]);
4
+ try {
5
+ const stored = sessionStorage.getItem("__opencode_selected_elements__");
6
+ if (stored) {
7
+ selectedElements.value = JSON.parse(stored);
8
+ }
9
+ } catch (e) {
10
+ }
11
+ watch(
12
+ selectedElements,
13
+ (val) => {
14
+ sessionStorage.setItem("__opencode_selected_elements__", JSON.stringify(val));
15
+ },
16
+ { deep: true }
17
+ );
18
+ const addElement = (element) => {
19
+ const exists = selectedElements.value.some(
20
+ (el) => el.filePath === element.filePath && el.line === element.line
21
+ );
22
+ if (!exists) {
23
+ selectedElements.value.push(element);
24
+ return true;
25
+ }
26
+ return false;
27
+ };
28
+ const removeElement = (index) => {
29
+ selectedElements.value.splice(index, 1);
30
+ };
31
+ const clearElements = () => {
32
+ selectedElements.value = [];
33
+ };
34
+ return {
35
+ selectedElements,
36
+ addElement,
37
+ removeElement,
38
+ clearElements
39
+ };
40
+ }
41
+ export {
42
+ useSelectedElements
43
+ };
@@ -0,0 +1,13 @@
1
+ import type { ServiceStartupTask, ServiceStatus } from "@vite-plugin-opencode-assistant/shared";
2
+ export declare function useServiceStatus(): {
3
+ currentTask: import("vue").Ref<"" | ServiceStartupTask, "" | ServiceStartupTask>;
4
+ serviceStatus: import("vue").Ref<ServiceStatus, ServiceStatus>;
5
+ chromeMcpFailed: import("vue").Ref<boolean, boolean>;
6
+ chromeMcpErrorType: import("vue").Ref<string | undefined, string | undefined>;
7
+ chromeMcpErrorMessage: import("vue").Ref<string | undefined, string | undefined>;
8
+ thinking: import("vue").Ref<boolean, boolean>;
9
+ loadingText: import("vue").ComputedRef<string>;
10
+ updateStatusFromTask: (task: ServiceStartupTask | "", errorType?: string, errorMessage?: string) => void;
11
+ setStarting: () => void;
12
+ setThinking: (value: boolean) => void;
13
+ };
@@ -0,0 +1,53 @@
1
+ import { ref, computed } from "vue";
2
+ import { SERVICE_STARTUP_TASKS } from "@vite-plugin-opencode-assistant/shared";
3
+ function useServiceStatus() {
4
+ const currentTask = ref("");
5
+ const serviceStatus = ref("idle");
6
+ const chromeMcpFailed = ref(false);
7
+ const chromeMcpErrorType = ref(void 0);
8
+ const chromeMcpErrorMessage = ref(void 0);
9
+ const thinking = ref(false);
10
+ const loadingText = computed(() => {
11
+ if (!currentTask.value) return "\u52A0\u8F7D\u4E2D...";
12
+ return SERVICE_STARTUP_TASKS[currentTask.value] || "\u52A0\u8F7D\u4E2D...";
13
+ });
14
+ const updateStatusFromTask = (task, errorType, errorMessage) => {
15
+ currentTask.value = task;
16
+ if (task === "ready") {
17
+ serviceStatus.value = "ready";
18
+ chromeMcpFailed.value = false;
19
+ chromeMcpErrorType.value = void 0;
20
+ chromeMcpErrorMessage.value = void 0;
21
+ } else if (task === "chrome_mcp_failed") {
22
+ serviceStatus.value = "partial";
23
+ chromeMcpFailed.value = true;
24
+ chromeMcpErrorType.value = errorType;
25
+ chromeMcpErrorMessage.value = errorMessage;
26
+ } else if (task === "session_creation_failed" || task === "opencode_not_installed" || task === "web_start_timeout") {
27
+ serviceStatus.value = "failed";
28
+ } else if (serviceStatus.value === "idle" && task) {
29
+ serviceStatus.value = "starting";
30
+ }
31
+ };
32
+ const setStarting = () => {
33
+ serviceStatus.value = "starting";
34
+ };
35
+ const setThinking = (value) => {
36
+ thinking.value = value;
37
+ };
38
+ return {
39
+ currentTask,
40
+ serviceStatus,
41
+ chromeMcpFailed,
42
+ chromeMcpErrorType,
43
+ chromeMcpErrorMessage,
44
+ thinking,
45
+ loadingText,
46
+ updateStatusFromTask,
47
+ setStarting,
48
+ setThinking
49
+ };
50
+ }
51
+ export {
52
+ useServiceStatus
53
+ };
@@ -0,0 +1,26 @@
1
+ import type { OpenCodeWidgetSession } from "@vite-plugin-opencode-assistant/shared";
2
+ export declare function useSessions(showNotification: (msg: string) => void): {
3
+ sessions: import("vue").Ref<{
4
+ id: string;
5
+ title?: string | undefined;
6
+ updatedAt?: (string | number | Date) | undefined;
7
+ meta?: string | undefined;
8
+ directory?: string | undefined;
9
+ url?: string | undefined;
10
+ }[], OpenCodeWidgetSession[] | {
11
+ id: string;
12
+ title?: string | undefined;
13
+ updatedAt?: (string | number | Date) | undefined;
14
+ meta?: string | undefined;
15
+ directory?: string | undefined;
16
+ url?: string | undefined;
17
+ }[]>;
18
+ loadingSessionList: import("vue").Ref<boolean | undefined, boolean | undefined>;
19
+ currentSessionId: import("vue").Ref<string | null, string | null>;
20
+ iframeSrc: import("vue").ComputedRef<string>;
21
+ iframeLoading: import("vue").Ref<boolean, boolean>;
22
+ loadSessions: () => Promise<void>;
23
+ createSession: () => Promise<void>;
24
+ deleteSession: (session: OpenCodeWidgetSession) => Promise<void>;
25
+ selectSession: (session: OpenCodeWidgetSession) => void;
26
+ };
@@ -0,0 +1,127 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __async = (__this, __arguments, generator) => {
21
+ return new Promise((resolve, reject) => {
22
+ var fulfilled = (value) => {
23
+ try {
24
+ step(generator.next(value));
25
+ } catch (e) {
26
+ reject(e);
27
+ }
28
+ };
29
+ var rejected = (value) => {
30
+ try {
31
+ step(generator.throw(value));
32
+ } catch (e) {
33
+ reject(e);
34
+ }
35
+ };
36
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
+ step((generator = generator.apply(__this, __arguments)).next());
38
+ });
39
+ };
40
+ import { ref, computed } from "vue";
41
+ import { SESSIONS_API_PATH } from "@vite-plugin-opencode-assistant/shared";
42
+ function useSessions(showNotification) {
43
+ const sessions = ref([]);
44
+ const loadingSessionList = ref(void 0);
45
+ const currentSessionId = ref(null);
46
+ const iframeLoading = ref(false);
47
+ const iframeSrc = computed(() => {
48
+ var _a;
49
+ return currentSessionId.value ? ((_a = sessions.value.find((s) => s.id === currentSessionId.value)) == null ? void 0 : _a.url) || "" : "";
50
+ });
51
+ const loadSessions = () => __async(null, null, function* () {
52
+ var _a;
53
+ loadingSessionList.value = true;
54
+ try {
55
+ const response = yield fetch(SESSIONS_API_PATH);
56
+ const data = yield response.json();
57
+ sessions.value = data.filter((s) => s.title !== "__chrome_mcp_warmup__").map((s) => {
58
+ var _a2;
59
+ return __spreadProps(__spreadValues({}, s), {
60
+ updatedAt: ((_a2 = s.time) == null ? void 0 : _a2.updated) || Date.now()
61
+ });
62
+ });
63
+ if (!sessions.value.length) {
64
+ createSession();
65
+ }
66
+ currentSessionId.value = ((_a = sessions.value[0]) == null ? void 0 : _a.id) || null;
67
+ } catch (e) {
68
+ console.error("[OpenCode] Failed to load sessions:", e);
69
+ } finally {
70
+ loadingSessionList.value = false;
71
+ }
72
+ });
73
+ const createSession = () => __async(null, null, function* () {
74
+ try {
75
+ const response = yield fetch(SESSIONS_API_PATH, { method: "POST" });
76
+ const newSession = yield response.json();
77
+ sessions.value.unshift({
78
+ id: newSession.id,
79
+ title: "\u65B0\u4F1A\u8BDD",
80
+ updatedAt: Date.now(),
81
+ url: newSession.url
82
+ });
83
+ currentSessionId.value = newSession.id;
84
+ iframeLoading.value = true;
85
+ loadSessions();
86
+ } catch (e) {
87
+ showNotification("\u521B\u5EFA\u4F1A\u8BDD\u5931\u8D25");
88
+ }
89
+ });
90
+ const deleteSession = (session) => __async(null, null, function* () {
91
+ try {
92
+ yield fetch(`${SESSIONS_API_PATH}?id=${session.id}`, { method: "DELETE" });
93
+ yield loadSessions();
94
+ showNotification("\u4F1A\u8BDD\u5DF2\u5220\u9664");
95
+ if (currentSessionId.value === session.id) {
96
+ if (sessions.value.length > 0) {
97
+ const nextSession = sessions.value[0];
98
+ currentSessionId.value = nextSession.id;
99
+ iframeLoading.value = true;
100
+ } else {
101
+ currentSessionId.value = null;
102
+ }
103
+ }
104
+ } catch (e) {
105
+ showNotification("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25");
106
+ }
107
+ });
108
+ const selectSession = (session) => {
109
+ if (currentSessionId.value === session.id) return;
110
+ currentSessionId.value = session.id;
111
+ iframeLoading.value = true;
112
+ };
113
+ return {
114
+ sessions,
115
+ loadingSessionList,
116
+ currentSessionId,
117
+ iframeSrc,
118
+ iframeLoading,
119
+ loadSessions,
120
+ createSession,
121
+ deleteSession,
122
+ selectSession
123
+ };
124
+ }
125
+ export {
126
+ useSessions
127
+ };
@@ -0,0 +1,12 @@
1
+ import type { OpenCodeWidgetTheme } from "@vite-plugin-opencode-assistant/shared";
2
+ interface WidgetRef {
3
+ sendMessageToIframe: (type: string, data?: Record<string, unknown>) => void;
4
+ }
5
+ export declare function useTheme(initialTheme: OpenCodeWidgetTheme, widgetRef: {
6
+ value: WidgetRef | null;
7
+ }): {
8
+ theme: import("vue").Ref<OpenCodeWidgetTheme, OpenCodeWidgetTheme>;
9
+ resolvedTheme: import("vue").ComputedRef<"light" | "dark">;
10
+ sendThemeToIframe: () => void;
11
+ };
12
+ export {};
@@ -0,0 +1,42 @@
1
+ import { ref, computed, watch, onMounted, onUnmounted } from "vue";
2
+ function useTheme(initialTheme, widgetRef) {
3
+ const theme = ref(initialTheme);
4
+ const resolvedTheme = computed(() => {
5
+ if (theme.value === "auto") {
6
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
7
+ }
8
+ return theme.value;
9
+ });
10
+ const sendThemeToIframe = () => {
11
+ var _a;
12
+ (_a = widgetRef.value) == null ? void 0 : _a.sendMessageToIframe("OPENCODE_SET_THEME", {
13
+ theme: resolvedTheme.value
14
+ });
15
+ };
16
+ let mediaQuery = null;
17
+ const handleSystemThemeChange = () => {
18
+ if (theme.value === "auto") {
19
+ sendThemeToIframe();
20
+ }
21
+ };
22
+ onMounted(() => {
23
+ mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
24
+ mediaQuery.addEventListener("change", handleSystemThemeChange);
25
+ watch(resolvedTheme, () => {
26
+ sendThemeToIframe();
27
+ });
28
+ });
29
+ onUnmounted(() => {
30
+ if (mediaQuery) {
31
+ mediaQuery.removeEventListener("change", handleSystemThemeChange);
32
+ }
33
+ });
34
+ return {
35
+ theme,
36
+ resolvedTheme,
37
+ sendThemeToIframe
38
+ };
39
+ }
40
+ export {
41
+ useTheme
42
+ };
@@ -1 +1 @@
1
- import "@vite-plugin-opencode-assistant/components/style.css";
1
+ import "./styles.css";