vite-plugin-opencode-assistant 1.0.27 → 1.0.28

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 (37) hide show
  1. package/es/client/App.vue.js +64 -36
  2. package/es/client/composables/index.d.ts +10 -0
  3. package/es/client/composables/index.js +22 -0
  4. package/es/client/composables/useOpencodeSSE.d.ts +64 -0
  5. package/es/client/composables/useOpencodeSSE.js +29 -0
  6. package/es/client/composables/useOpencodeSessionSSE.d.ts +66 -0
  7. package/es/client/composables/useOpencodeSessionSSE.js +168 -0
  8. package/es/client/composables/useSSE.d.ts +85 -18
  9. package/es/client/composables/useSSE.js +101 -44
  10. package/es/client/composables/useServerSSE.d.ts +53 -0
  11. package/es/client/composables/useServerSSE.js +36 -0
  12. package/es/client/composables/useServiceStatus.d.ts +0 -2
  13. package/es/client/composables/useServiceStatus.js +1 -7
  14. package/es/client/composables/useSessions.d.ts +24 -5
  15. package/es/client/composables/useSessions.js +16 -2
  16. package/es/core/proxy-server.js +38 -148
  17. package/es/index.js +3 -1
  18. package/lib/client/App.vue.js +63 -35
  19. package/lib/client/composables/index.d.ts +10 -0
  20. package/lib/client/composables/index.js +54 -0
  21. package/lib/client/composables/useOpencodeSSE.d.ts +64 -0
  22. package/lib/client/composables/useOpencodeSSE.js +52 -0
  23. package/lib/client/composables/useOpencodeSessionSSE.d.ts +66 -0
  24. package/lib/client/composables/useOpencodeSessionSSE.js +187 -0
  25. package/lib/client/composables/useSSE.d.ts +85 -18
  26. package/lib/client/composables/useSSE.js +100 -43
  27. package/lib/client/composables/useServerSSE.d.ts +53 -0
  28. package/lib/client/composables/useServerSSE.js +59 -0
  29. package/lib/client/composables/useServiceStatus.d.ts +0 -2
  30. package/lib/client/composables/useServiceStatus.js +1 -7
  31. package/lib/client/composables/useSessions.d.ts +24 -5
  32. package/lib/client/composables/useSessions.js +16 -2
  33. package/lib/client.js +2823 -2566
  34. package/lib/core/proxy-server.js +38 -148
  35. package/lib/index.js +3 -1
  36. package/lib/style.css +1 -1
  37. package/package.json +4 -4
package/es/index.js CHANGED
@@ -175,7 +175,9 @@ function createOpenCodePlugin(options = {}) {
175
175
  const widget = injectWidget({
176
176
  theme: config.theme,
177
177
  open: config.open,
178
- hotkey: config.hotkey
178
+ hotkey: config.hotkey,
179
+ proxyPort: actualProxyPort,
180
+ proxyHost: config.hostname
179
181
  });
180
182
  timer.end();
181
183
  return html.replace("</body>", `${widget}</body>`);
@@ -71,7 +71,8 @@ var import_vue = require("vue");
71
71
  var import_vue2 = require("vue");
72
72
  var import_components = require("@vite-plugin-opencode-assistant/components");
73
73
  var import_useHotkey = require("./composables/useHotkey");
74
- var import_useSSE = require("./composables/useSSE");
74
+ var import_useServerSSE = require("./composables/useServerSSE");
75
+ var import_useOpencodeSessionSSE = require("./composables/useOpencodeSessionSSE");
75
76
  var import_useSessions = require("./composables/useSessions");
76
77
  var import_useTheme = require("./composables/useTheme");
77
78
  var import_useSelectedElements = require("./composables/useSelectedElements");
@@ -97,9 +98,14 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
97
98
  const {
98
99
  theme: initialTheme = "auto",
99
100
  open: autoOpen = false,
100
- hotkey = "ctrl+k"
101
+ hotkey = "ctrl+k",
102
+ proxyPort = 4098,
103
+ proxyHost = "localhost"
101
104
  } = props.config;
102
105
  const widgetTheme = initialTheme;
106
+ const proxyBaseUrl = (0, import_vue2.computed)(() => {
107
+ return `http://${proxyHost}:${proxyPort}`;
108
+ });
103
109
  const showNotification = (msg, options) => {
104
110
  var _a, _b;
105
111
  (_b = (_a = widgetRef.value) == null ? void 0 : _a.showNotification) == null ? void 0 : _b.call(_a, msg, options);
@@ -109,11 +115,9 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
109
115
  chromeMcpFailed,
110
116
  chromeMcpErrorType,
111
117
  chromeMcpErrorMessage,
112
- thinking,
113
118
  loadingText,
114
119
  updateStatusFromTask,
115
- setStarting,
116
- setThinking
120
+ setStarting
117
121
  } = (0, import_useServiceStatus.useServiceStatus)();
118
122
  const {
119
123
  selectedElements,
@@ -133,13 +137,50 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
133
137
  loadSessions,
134
138
  createSession,
135
139
  deleteSession,
136
- selectSession
137
- } = (0, import_useSessions.useSessions)(showNotification);
140
+ selectSession,
141
+ updateSessionInfo
142
+ } = (0, import_useSessions.useSessions)({ showNotification });
138
143
  const { updateContext } = (0, import_useContext.useContext)(serviceStatus, selectedElements);
144
+ const serverSSE = (0, import_useServerSSE.useServerSSE)({
145
+ onStatusSync: (data) => {
146
+ if (data.isStarted !== void 0 && data.isStarted && serviceStatus.value === "idle") {
147
+ setStarting();
148
+ }
149
+ if (data.task) {
150
+ updateStatusFromTask(data.task, data.errorType, data.errorMessage);
151
+ }
152
+ if (serviceStatus.value !== "idle") {
153
+ loadSessions();
154
+ }
155
+ },
156
+ onTaskUpdate: (data) => {
157
+ updateStatusFromTask(data.task, data.errorType, data.errorMessage);
158
+ },
159
+ onClearElements: () => clearElements(),
160
+ onConnected: () => updateContext(true)
161
+ });
162
+ const opencodeSSE = (0, import_useOpencodeSessionSSE.useOpencodeSessionSSE)({
163
+ proxyBaseUrl: proxyBaseUrl.value,
164
+ currentSessionId,
165
+ onConnected: () => {
166
+ console.log("[OpenCode] Session SSE connected");
167
+ },
168
+ onSessionUpdate: (session) => {
169
+ updateSessionInfo(session);
170
+ }
171
+ });
172
+ const thinking = opencodeSSE.hasAnyThinking;
173
+ const sessionStates = opencodeSSE.sessionStates;
139
174
  const showSessionListSkeleton = (0, import_vue2.computed)(() => serviceStatus.value === "starting");
140
175
  const computedLoading = (0, import_vue2.computed)(() => {
141
176
  return serviceStatus.value === "starting" || iframeLoading.value;
142
177
  });
178
+ const displayLoadingText = (0, import_vue2.computed)(() => {
179
+ if (serviceStatus.value === "starting") {
180
+ return loadingText.value;
181
+ }
182
+ return "\u52A0\u8F7D\u4F1A\u8BDD...";
183
+ });
143
184
  const retryWarmup = () => __async(null, null, function* () {
144
185
  retryingWarmup.value = true;
145
186
  try {
@@ -167,24 +208,6 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
167
208
  retryingWarmup.value = false;
168
209
  }
169
210
  });
170
- const { setupSSE } = (0, import_useSSE.useSSE)(
171
- (data) => {
172
- if (data.isStarted !== void 0 && data.isStarted && serviceStatus.value === "idle") {
173
- setStarting();
174
- }
175
- if (data.task) {
176
- updateStatusFromTask(data.task, data.errorType, data.errorMessage);
177
- }
178
- if (serviceStatus.value !== "idle") {
179
- loadSessions();
180
- }
181
- },
182
- (data) => {
183
- updateStatusFromTask(data.task, data.errorType, data.errorMessage);
184
- },
185
- () => clearElements(),
186
- () => updateContext(true)
187
- );
188
211
  const ensureServicesStarted = () => __async(null, null, function* () {
189
212
  if (serviceStatus.value !== "idle") return true;
190
213
  try {
@@ -192,7 +215,7 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
192
215
  const data = yield res.json();
193
216
  if (data.success) {
194
217
  setStarting();
195
- setupSSE();
218
+ serverSSE.connect();
196
219
  return true;
197
220
  }
198
221
  } catch (e) {
@@ -212,10 +235,17 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
212
235
  showNotification("Vue Inspector \u672A\u52A0\u8F7D\uFF0C\u65E0\u6CD5\u4F7F\u7528\u5143\u7D20\u9009\u62E9\u529F\u80FD");
213
236
  }
214
237
  });
238
+ (0, import_vue2.watch)(serviceStatus, (status, oldStatus) => {
239
+ if (status !== "idle" && oldStatus === "idle") {
240
+ serverSSE.connect();
241
+ opencodeSSE.connect();
242
+ }
243
+ });
215
244
  (0, import_vue2.onMounted)(() => {
216
245
  if (serviceStatus.value !== "idle") {
217
246
  loadSessions();
218
- setupSSE();
247
+ serverSSE.connect();
248
+ opencodeSSE.connect();
219
249
  updateContext(true);
220
250
  }
221
251
  if (autoOpen && serviceStatus.value !== "idle") {
@@ -224,11 +254,8 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
224
254
  }, 1e3);
225
255
  }
226
256
  const handleIframeMessage = (event) => {
227
- var _a, _b;
228
- if (((_a = event.data) == null ? void 0 : _a.type) === "OPENCODE_THINKING_STATE") {
229
- setThinking(event.data.thinking);
230
- }
231
- if (((_b = event.data) == null ? void 0 : _b.type) === "OPENCODE_READY") {
257
+ var _a;
258
+ if (((_a = event.data) == null ? void 0 : _a.type) === "OPENCODE_READY") {
232
259
  sendThemeToIframe();
233
260
  }
234
261
  };
@@ -283,7 +310,7 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
283
310
  const handleFrameLoaded = () => {
284
311
  iframeLoading.value = false;
285
312
  };
286
- const __returned__ = { props, open, selectMode, sessionListCollapsed, loading, widgetRef, retryingWarmup, initialTheme, autoOpen, hotkey, widgetTheme, showNotification, serviceStatus, chromeMcpFailed, chromeMcpErrorType, chromeMcpErrorMessage, thinking, loadingText, updateStatusFromTask, setStarting, setThinking, selectedElements, removeElement, clearElements, theme, sendThemeToIframe, sessions, loadingSessionList, currentSessionId, iframeSrc, iframeLoading, loadSessions, createSession, deleteSession, selectSession, updateContext, showSessionListSkeleton, computedLoading, retryWarmup, setupSSE, ensureServicesStarted, handleToggle, handleSelectNode, handleClearSelected, handleSelectModeChange, handleSessionListCollapsedChange, handleThemeChange, handleRemoveSelectedNode, handleFrameLoaded, get OpenCodeWidget() {
313
+ const __returned__ = { props, open, selectMode, sessionListCollapsed, loading, widgetRef, retryingWarmup, initialTheme, autoOpen, hotkey, proxyPort, proxyHost, widgetTheme, proxyBaseUrl, showNotification, serviceStatus, chromeMcpFailed, chromeMcpErrorType, chromeMcpErrorMessage, loadingText, updateStatusFromTask, setStarting, selectedElements, removeElement, clearElements, theme, sendThemeToIframe, sessions, loadingSessionList, currentSessionId, iframeSrc, iframeLoading, loadSessions, createSession, deleteSession, selectSession, updateSessionInfo, updateContext, serverSSE, opencodeSSE, thinking, sessionStates, showSessionListSkeleton, computedLoading, displayLoadingText, retryWarmup, ensureServicesStarted, handleToggle, handleSelectNode, handleClearSelected, handleSelectModeChange, handleSessionListCollapsedChange, handleThemeChange, handleRemoveSelectedNode, handleFrameLoaded, get OpenCodeWidget() {
287
314
  return import_components.OpenCodeWidget;
288
315
  }, LoadingContent: import_LoadingContent_vue.default, ChromeWarmupError: import_ChromeWarmupError_vue.default };
289
316
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
@@ -304,6 +331,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
304
331
  "iframe-src": $setup.iframeSrc,
305
332
  "current-session-id": $setup.currentSessionId,
306
333
  sessions: $setup.sessions,
334
+ "session-states": $setup.sessionStates,
307
335
  "session-key": "id",
308
336
  "hotkey-label": $setup.hotkey,
309
337
  thinking: $setup.thinking,
@@ -322,7 +350,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
322
350
  onFrameLoaded: $setup.handleFrameLoaded
323
351
  }, {
324
352
  loading: (0, import_vue3.withCtx)(() => [
325
- (0, import_vue3.createVNode)($setup["LoadingContent"], { "loading-text": $setup.loadingText }, null, 8, ["loading-text"])
353
+ (0, import_vue3.createVNode)($setup["LoadingContent"], { "loading-text": $setup.displayLoadingText }, null, 8, ["loading-text"])
326
354
  ]),
327
355
  error: (0, import_vue3.withCtx)(() => [
328
356
  $setup.chromeMcpFailed ? ((0, import_vue3.openBlock)(), (0, import_vue3.createBlock)($setup["ChromeWarmupError"], {
@@ -335,7 +363,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
335
363
  ]),
336
364
  _: 1
337
365
  /* STABLE */
338
- }, 8, ["theme", "open", "select-mode", "session-list-collapsed", "frame-loading", "loading-session-list", "show-session-list-skeleton", "show-error", "iframe-src", "current-session-id", "sessions", "hotkey-label", "thinking", "onCreateSession", "onDeleteSession", "onSelectSession", "onEmptyAction"]);
366
+ }, 8, ["theme", "open", "select-mode", "session-list-collapsed", "frame-loading", "loading-session-list", "show-session-list-skeleton", "show-error", "iframe-src", "current-session-id", "sessions", "session-states", "hotkey-label", "thinking", "onCreateSession", "onDeleteSession", "onSelectSession", "onEmptyAction"]);
339
367
  }
340
368
  __vue_sfc__.render = __vue_render__;
341
369
  var App_vue_default = __vue_sfc__;
@@ -0,0 +1,10 @@
1
+ export { useSSE } from "./useSSE";
2
+ export { useServerSSE } from "./useServerSSE";
3
+ export { useOpencodeSSE } from "./useOpencodeSSE";
4
+ export { useOpencodeSessionSSE } from "./useOpencodeSessionSSE";
5
+ export { useHotkey } from "./useHotkey";
6
+ export { useSessions } from "./useSessions";
7
+ export { useTheme } from "./useTheme";
8
+ export { useSelectedElements } from "./useSelectedElements";
9
+ export { useServiceStatus } from "./useServiceStatus";
10
+ export { useContext } from "./useContext";
@@ -0,0 +1,54 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var composables_exports = {};
19
+ __export(composables_exports, {
20
+ useContext: () => import_useContext.useContext,
21
+ useHotkey: () => import_useHotkey.useHotkey,
22
+ useOpencodeSSE: () => import_useOpencodeSSE.useOpencodeSSE,
23
+ useOpencodeSessionSSE: () => import_useOpencodeSessionSSE.useOpencodeSessionSSE,
24
+ useSSE: () => import_useSSE.useSSE,
25
+ useSelectedElements: () => import_useSelectedElements.useSelectedElements,
26
+ useServerSSE: () => import_useServerSSE.useServerSSE,
27
+ useServiceStatus: () => import_useServiceStatus.useServiceStatus,
28
+ useSessions: () => import_useSessions.useSessions,
29
+ useTheme: () => import_useTheme.useTheme
30
+ });
31
+ module.exports = __toCommonJS(composables_exports);
32
+ var import_useSSE = require("./useSSE");
33
+ var import_useServerSSE = require("./useServerSSE");
34
+ var import_useOpencodeSSE = require("./useOpencodeSSE");
35
+ var import_useOpencodeSessionSSE = require("./useOpencodeSessionSSE");
36
+ var import_useHotkey = require("./useHotkey");
37
+ var import_useSessions = require("./useSessions");
38
+ var import_useTheme = require("./useTheme");
39
+ var import_useSelectedElements = require("./useSelectedElements");
40
+ var import_useServiceStatus = require("./useServiceStatus");
41
+ var import_useContext = require("./useContext");
42
+ // Annotate the CommonJS export names for ESM import in node:
43
+ 0 && (module.exports = {
44
+ useContext,
45
+ useHotkey,
46
+ useOpencodeSSE,
47
+ useOpencodeSessionSSE,
48
+ useSSE,
49
+ useSelectedElements,
50
+ useServerSSE,
51
+ useServiceStatus,
52
+ useSessions,
53
+ useTheme
54
+ });
@@ -0,0 +1,64 @@
1
+ import { type Ref } from "vue";
2
+ /**
3
+ * OpenCode SSE 事件 payload
4
+ */
5
+ export interface OpencodeSSEPayload {
6
+ type: string;
7
+ properties: {
8
+ sessionID?: string;
9
+ status?: {
10
+ type: string;
11
+ };
12
+ info?: {
13
+ sessionID?: string;
14
+ role?: string;
15
+ time?: {
16
+ completed?: number;
17
+ created?: number;
18
+ updated?: number;
19
+ archived?: number;
20
+ compacting?: number;
21
+ };
22
+ title?: string;
23
+ id?: string;
24
+ summary?: {
25
+ additions?: number;
26
+ deletions?: number;
27
+ files?: number;
28
+ };
29
+ };
30
+ [key: string]: unknown;
31
+ };
32
+ }
33
+ /**
34
+ * OpenCode SSE 消息结构
35
+ */
36
+ export interface OpencodeSSEMessage {
37
+ payload: OpencodeSSEPayload;
38
+ }
39
+ /**
40
+ * OpenCode SSE 配置选项
41
+ */
42
+ export interface OpencodeSSEOptions {
43
+ /** OpenCode proxy 基础 URL (例如: http://localhost:4098/xxx) */
44
+ proxyBaseUrl: string;
45
+ /** 是否启用 */
46
+ enabled?: Ref<boolean>;
47
+ /** 事件处理器 */
48
+ onEvent?: (payload: OpencodeSSEPayload) => void;
49
+ /** 连接成功回调 */
50
+ onConnected?: () => void;
51
+ /** 连接错误回调 */
52
+ onError?: (error: Error) => void;
53
+ }
54
+ /**
55
+ * 监听 OpenCode SSE 事件
56
+ * 端点: /global/event (通过 proxy server)
57
+ * 只负责连接管理和消息分发,不包含业务逻辑
58
+ */
59
+ export declare function useOpencodeSSE(options: OpencodeSSEOptions): {
60
+ status: Ref<import("./useSSE").SSEConnectionStatus, import("./useSSE").SSEConnectionStatus>;
61
+ isConnected: import("vue").ComputedRef<boolean>;
62
+ connect: () => void;
63
+ disconnect: () => void;
64
+ };
@@ -0,0 +1,52 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var useOpencodeSSE_exports = {};
19
+ __export(useOpencodeSSE_exports, {
20
+ useOpencodeSSE: () => useOpencodeSSE
21
+ });
22
+ module.exports = __toCommonJS(useOpencodeSSE_exports);
23
+ var import_useSSE = require("./useSSE");
24
+ function useOpencodeSSE(options) {
25
+ const { proxyBaseUrl, enabled, onEvent, onConnected, onError } = options;
26
+ const endpoint = `${proxyBaseUrl}/global/event`;
27
+ const { status, isConnected, connect, disconnect } = (0, import_useSSE.useSSE)({
28
+ endpoint,
29
+ autoConnect: false,
30
+ enabled,
31
+ onMessage: (data) => {
32
+ const message = data;
33
+ const payload = message.payload;
34
+ if (!payload) return;
35
+ onEvent == null ? void 0 : onEvent(payload);
36
+ },
37
+ onConnected,
38
+ onError
39
+ });
40
+ return {
41
+ // 状态
42
+ status,
43
+ isConnected,
44
+ // 方法
45
+ connect,
46
+ disconnect
47
+ };
48
+ }
49
+ // Annotate the CommonJS export names for ESM import in node:
50
+ 0 && (module.exports = {
51
+ useOpencodeSSE
52
+ });
@@ -0,0 +1,66 @@
1
+ import { type Ref, type ComputedRef } from "vue";
2
+ /**
3
+ * Session 状态类型
4
+ */
5
+ export type OpencodeSessionStatusType = "idle" | "running" | "streaming" | "completed";
6
+ /**
7
+ * Session 思考状态
8
+ */
9
+ export interface OpencodeSessionThinkingState {
10
+ thinking: boolean;
11
+ statusType: OpencodeSessionStatusType;
12
+ hasPending: boolean;
13
+ }
14
+ /**
15
+ * Session 更新事件数据
16
+ */
17
+ export interface OpencodeSessionUpdateData {
18
+ id: string;
19
+ title?: string;
20
+ time?: {
21
+ created?: number;
22
+ updated?: number;
23
+ archived?: number;
24
+ compacting?: number;
25
+ };
26
+ summary?: {
27
+ additions?: number;
28
+ deletions?: number;
29
+ files?: number;
30
+ };
31
+ }
32
+ /**
33
+ * OpenCode Session SSE 配置选项
34
+ */
35
+ export interface OpencodeSessionSSEOptions {
36
+ /** OpenCode proxy 基础 URL */
37
+ proxyBaseUrl: string;
38
+ /** 当前 session ID (响应式) */
39
+ currentSessionId: Ref<string | null>;
40
+ /** 是否启用 */
41
+ enabled?: Ref<boolean>;
42
+ /** 连接成功回调 */
43
+ onConnected?: () => void;
44
+ /** Session 更新回调 (包括标题变化) */
45
+ onSessionUpdate?: (session: OpencodeSessionUpdateData) => void;
46
+ }
47
+ /**
48
+ * 监听 OpenCode Session SSE 事件
49
+ * 专注于 session thinking 状态管理和标题更新
50
+ */
51
+ export declare function useOpencodeSessionSSE(options: OpencodeSessionSSEOptions): {
52
+ status: Ref<import("./useSSE").SSEConnectionStatus, import("./useSSE").SSEConnectionStatus>;
53
+ isConnected: ComputedRef<boolean>;
54
+ sessionStates: Ref<Record<string, OpencodeSessionThinkingState>, Record<string, OpencodeSessionThinkingState>>;
55
+ currentThinking: ComputedRef<boolean>;
56
+ currentSessionState: ComputedRef<OpencodeSessionThinkingState | null>;
57
+ hasAnyThinking: ComputedRef<boolean>;
58
+ thinkingSessionCount: ComputedRef<number>;
59
+ connect: () => void;
60
+ disconnect: () => void;
61
+ clearSessionState: (sessionID: string) => void;
62
+ clearAllSessionStates: () => void;
63
+ getSessionState: (sessionID: string) => OpencodeSessionThinkingState | undefined;
64
+ isSessionThinking: (sessionID: string) => boolean;
65
+ getSessionsThinking: (sessionIds: string[]) => Record<string, boolean>;
66
+ };
@@ -0,0 +1,187 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
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 __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
22
+ var __export = (target, all) => {
23
+ for (var name in all)
24
+ __defProp(target, name, { get: all[name], enumerable: true });
25
+ };
26
+ var __copyProps = (to, from, except, desc) => {
27
+ if (from && typeof from === "object" || typeof from === "function") {
28
+ for (let key of __getOwnPropNames(from))
29
+ if (!__hasOwnProp.call(to, key) && key !== except)
30
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
31
+ }
32
+ return to;
33
+ };
34
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
+ var useOpencodeSessionSSE_exports = {};
36
+ __export(useOpencodeSessionSSE_exports, {
37
+ useOpencodeSessionSSE: () => useOpencodeSessionSSE
38
+ });
39
+ module.exports = __toCommonJS(useOpencodeSessionSSE_exports);
40
+ var import_vue = require("vue");
41
+ var import_useOpencodeSSE = require("./useOpencodeSSE");
42
+ function useOpencodeSessionSSE(options) {
43
+ const { proxyBaseUrl, currentSessionId, enabled, onConnected, onSessionUpdate } = options;
44
+ const sessionStates = (0, import_vue.ref)({});
45
+ function isPendingMessage(info) {
46
+ var _a;
47
+ return (info == null ? void 0 : info.role) === "assistant" && typeof ((_a = info == null ? void 0 : info.time) == null ? void 0 : _a.completed) !== "number";
48
+ }
49
+ function updateThinkingState(sessionID) {
50
+ const state = sessionStates.value[sessionID];
51
+ const isThinking = (state == null ? void 0 : state.hasPending) || (state == null ? void 0 : state.statusType) !== "idle";
52
+ sessionStates.value[sessionID] = {
53
+ thinking: isThinking,
54
+ statusType: (state == null ? void 0 : state.statusType) || "idle",
55
+ hasPending: (state == null ? void 0 : state.hasPending) || false
56
+ };
57
+ }
58
+ function handleEvent(payload) {
59
+ var _a;
60
+ const type = payload.type;
61
+ const props = payload.properties;
62
+ switch (type) {
63
+ case "session.updated": {
64
+ const info = props.info;
65
+ if (!(info == null ? void 0 : info.id)) return;
66
+ onSessionUpdate == null ? void 0 : onSessionUpdate({
67
+ id: info.id,
68
+ title: info.title,
69
+ time: info.time,
70
+ summary: info.summary
71
+ });
72
+ break;
73
+ }
74
+ case "session.status": {
75
+ const sessionID = props.sessionID;
76
+ if (!sessionID) return;
77
+ const statusType = ((_a = props.status) == null ? void 0 : _a.type) || "idle";
78
+ sessionStates.value[sessionID] = {
79
+ thinking: statusType !== "idle",
80
+ statusType,
81
+ hasPending: false
82
+ };
83
+ updateThinkingState(sessionID);
84
+ break;
85
+ }
86
+ case "message.updated": {
87
+ const info = props.info;
88
+ if (!(info == null ? void 0 : info.sessionID)) return;
89
+ const sessionID = info.sessionID;
90
+ if (info.role === "assistant") {
91
+ const hasPending = isPendingMessage(info);
92
+ const current = sessionStates.value[sessionID] || {
93
+ thinking: false,
94
+ statusType: "idle",
95
+ hasPending: false
96
+ };
97
+ sessionStates.value[sessionID] = __spreadProps(__spreadValues({}, current), {
98
+ hasPending
99
+ });
100
+ updateThinkingState(sessionID);
101
+ }
102
+ break;
103
+ }
104
+ case "message.part.delta": {
105
+ const sessionID = props.sessionID;
106
+ if (!sessionID) return;
107
+ const current = sessionStates.value[sessionID];
108
+ if (!(current == null ? void 0 : current.hasPending)) {
109
+ sessionStates.value[sessionID] = {
110
+ thinking: true,
111
+ statusType: (current == null ? void 0 : current.statusType) || "idle",
112
+ hasPending: true
113
+ };
114
+ }
115
+ break;
116
+ }
117
+ }
118
+ }
119
+ const sse = (0, import_useOpencodeSSE.useOpencodeSSE)({
120
+ proxyBaseUrl,
121
+ enabled,
122
+ onEvent: handleEvent,
123
+ onConnected
124
+ });
125
+ const currentThinking = (0, import_vue.computed)(() => {
126
+ var _a, _b;
127
+ const id = currentSessionId.value;
128
+ if (!id) return false;
129
+ return (_b = (_a = sessionStates.value[id]) == null ? void 0 : _a.thinking) != null ? _b : false;
130
+ });
131
+ const currentSessionState = (0, import_vue.computed)(() => {
132
+ const id = currentSessionId.value;
133
+ if (!id) return null;
134
+ return sessionStates.value[id] || null;
135
+ });
136
+ const hasAnyThinking = (0, import_vue.computed)(() => {
137
+ return Object.values(sessionStates.value).some((state) => state.thinking);
138
+ });
139
+ const thinkingSessionCount = (0, import_vue.computed)(() => {
140
+ return Object.values(sessionStates.value).filter((state) => state.thinking).length;
141
+ });
142
+ function clearSessionState(sessionID) {
143
+ delete sessionStates.value[sessionID];
144
+ }
145
+ function clearAllSessionStates() {
146
+ sessionStates.value = {};
147
+ }
148
+ function getSessionState(sessionID) {
149
+ return sessionStates.value[sessionID];
150
+ }
151
+ function isSessionThinking(sessionID) {
152
+ var _a, _b;
153
+ return (_b = (_a = sessionStates.value[sessionID]) == null ? void 0 : _a.thinking) != null ? _b : false;
154
+ }
155
+ function getSessionsThinking(sessionIds) {
156
+ return sessionIds.reduce(
157
+ (acc, id) => {
158
+ acc[id] = isSessionThinking(id);
159
+ return acc;
160
+ },
161
+ {}
162
+ );
163
+ }
164
+ return {
165
+ // SSE 基础状态
166
+ status: sse.status,
167
+ isConnected: sse.isConnected,
168
+ // session 状态
169
+ sessionStates,
170
+ currentThinking,
171
+ currentSessionState,
172
+ hasAnyThinking,
173
+ thinkingSessionCount,
174
+ // 方法
175
+ connect: sse.connect,
176
+ disconnect: sse.disconnect,
177
+ clearSessionState,
178
+ clearAllSessionStates,
179
+ getSessionState,
180
+ isSessionThinking,
181
+ getSessionsThinking
182
+ };
183
+ }
184
+ // Annotate the CommonJS export names for ESM import in node:
185
+ 0 && (module.exports = {
186
+ useOpencodeSessionSSE
187
+ });