@vite-plugin-opencode-assistant/components 1.0.92 → 1.0.93

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 (31) hide show
  1. package/es/index.d.ts +1 -1
  2. package/es/index.mjs +1 -1
  3. package/es/open-code-widget/composables/use-persist-state.d.ts +2 -0
  4. package/es/open-code-widget/composables/use-persist-state.mjs +2 -0
  5. package/es/open-code-widget/src/components/ChatPanel.vue.d.ts +2 -2
  6. package/es/open-code-widget/src/components/Frame.vue.mjs +7 -13
  7. package/es/open-code-widget/src/components/Header-sfc.css +1 -1
  8. package/es/open-code-widget/src/components/Header.vue.mjs +55 -23
  9. package/es/open-code-widget/src/components/SelectHint-sfc.css +1 -1
  10. package/es/open-code-widget/src/components/SelectHint.vue.mjs +2 -8
  11. package/es/open-code-widget/src/context.d.ts +2 -0
  12. package/es/open-code-widget/src/index-sfc.css +1 -1
  13. package/es/open-code-widget/src/index.vue.mjs +13 -1
  14. package/lib/@vite-plugin-opencode-assistant/components.cjs.js +65 -30
  15. package/lib/@vite-plugin-opencode-assistant/components.es.js +65 -30
  16. package/lib/components.css +3 -3
  17. package/lib/index.cjs +1 -1
  18. package/lib/index.d.ts +1 -1
  19. package/lib/open-code-widget/composables/use-persist-state.cjs +2 -0
  20. package/lib/open-code-widget/composables/use-persist-state.d.ts +2 -0
  21. package/lib/open-code-widget/src/components/ChatPanel.vue.d.ts +2 -2
  22. package/lib/open-code-widget/src/components/Frame.vue.cjs +6 -12
  23. package/lib/open-code-widget/src/components/Header-sfc.css +1 -1
  24. package/lib/open-code-widget/src/components/Header.vue.cjs +55 -23
  25. package/lib/open-code-widget/src/components/SelectHint-sfc.css +1 -1
  26. package/lib/open-code-widget/src/components/SelectHint.vue.cjs +1 -7
  27. package/lib/open-code-widget/src/context.d.ts +2 -0
  28. package/lib/open-code-widget/src/index-sfc.css +1 -1
  29. package/lib/open-code-widget/src/index.vue.cjs +13 -1
  30. package/lib/web-types.json +1 -1
  31. package/package.json +2 -2
package/es/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import OpenCodeWidget from './open-code-widget';
2
2
  import type { App } from 'vue';
3
- declare const version = "1.0.92";
3
+ declare const version = "1.0.93";
4
4
  declare function install(app: App<any>, options?: any): void;
5
5
  export { install, version, OpenCodeWidget };
6
6
  export default install;
package/es/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import OpenCodeWidget from "./open-code-widget/index.mjs";
2
- const version = "1.0.92";
2
+ const version = "1.0.93";
3
3
  function install(app, options) {
4
4
  const components = [
5
5
  OpenCodeWidget
@@ -5,6 +5,7 @@ export interface WidgetPersistState {
5
5
  open: boolean;
6
6
  minimized: boolean;
7
7
  promptDockVisible: boolean;
8
+ reviewPanelVisible: boolean;
8
9
  bubbleOffset?: FloatingBubbleOffset;
9
10
  theme: OpenCodeWidgetTheme;
10
11
  sessionListCollapsed: boolean;
@@ -16,6 +17,7 @@ export interface UsePersistStateOptions {
16
17
  open: Ref<boolean>;
17
18
  minimized: Ref<boolean>;
18
19
  promptDockVisible: Ref<boolean>;
20
+ reviewPanelVisible: Ref<boolean>;
19
21
  bubbleOffset: Ref<FloatingBubbleOffset | undefined>;
20
22
  theme: Ref<OpenCodeWidgetTheme>;
21
23
  sessionListCollapsed: Ref<boolean>;
@@ -34,6 +34,7 @@ function usePersistState(options) {
34
34
  open: options.open.value,
35
35
  minimized: options.minimized.value,
36
36
  promptDockVisible: options.promptDockVisible.value,
37
+ reviewPanelVisible: options.reviewPanelVisible.value,
37
38
  bubbleOffset: options.bubbleOffset.value,
38
39
  theme: options.theme.value,
39
40
  sessionListCollapsed: options.sessionListCollapsed.value,
@@ -49,6 +50,7 @@ function usePersistState(options) {
49
50
  options.open,
50
51
  options.minimized,
51
52
  options.promptDockVisible,
53
+ options.reviewPanelVisible,
52
54
  options.bubbleOffset,
53
55
  options.theme,
54
56
  options.sessionListCollapsed
@@ -141,14 +141,14 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
141
141
  }) | null>;
142
142
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
143
143
  resize: (width: number) => any;
144
- toggle: () => any;
145
144
  "resize-start": () => any;
146
145
  "resize-end": () => any;
146
+ toggle: () => any;
147
147
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
148
148
  onResize?: ((width: number) => any) | undefined;
149
- onToggle?: (() => any) | undefined;
150
149
  "onResize-start"?: (() => any) | undefined;
151
150
  "onResize-end"?: (() => any) | undefined;
151
+ onToggle?: (() => any) | undefined;
152
152
  }>, {
153
153
  extension: boolean;
154
154
  resolvedTheme: "light" | "dark";
@@ -16,7 +16,7 @@ var __spreadValues = (a, b) => {
16
16
  };
17
17
  import "./Frame-sfc.css";
18
18
  import { defineComponent as _defineComponent } from "vue";
19
- import { ref, onMounted } from "vue";
19
+ import { ref } from "vue";
20
20
  import { useOpenCodeWidgetContext } from "../context.mjs";
21
21
  const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
22
22
  __name: "Frame",
@@ -37,13 +37,6 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
37
37
  if (!((_a = iframeRef.value) == null ? void 0 : _a.contentWindow)) return;
38
38
  iframeRef.value.contentWindow.postMessage(__spreadValues({ type }, data), "*");
39
39
  }
40
- onMounted(() => {
41
- if (iframeRef.value) {
42
- iframeRef.value.addEventListener("load", () => {
43
- handleFrameLoaded();
44
- });
45
- }
46
- });
47
40
  __expose({
48
41
  sendMessageToIframe
49
42
  });
@@ -65,7 +58,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
65
58
  },
66
59
  [
67
60
  _renderSlot(_ctx.$slots, "empty-state", {}, () => [
68
- _cache[1] || (_cache[1] = _createElementVNode(
61
+ _cache[2] || (_cache[2] = _createElementVNode(
69
62
  "div",
70
63
  { class: "opencode-empty-state-icon" },
71
64
  [
@@ -118,14 +111,14 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
118
111
  },
119
112
  [
120
113
  _renderSlot(_ctx.$slots, "loading", {}, () => [
121
- _cache[2] || (_cache[2] = _createElementVNode(
114
+ _cache[3] || (_cache[3] = _createElementVNode(
122
115
  "div",
123
116
  { class: "opencode-loading-spinner" },
124
117
  null,
125
118
  -1
126
119
  /* CACHED */
127
120
  )),
128
- _cache[3] || (_cache[3] = _createElementVNode(
121
+ _cache[4] || (_cache[4] = _createElementVNode(
129
122
  "div",
130
123
  { class: "opencode-loading-text" },
131
124
  "\u52A0\u8F7D\u4E2D...",
@@ -154,8 +147,9 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
154
147
  class: "opencode-iframe",
155
148
  src: $setup.iframeSrc,
156
149
  allow: "clipboard-write; clipboard-read",
157
- referrerpolicy: "origin"
158
- }, null, 8, _hoisted_3)
150
+ referrerpolicy: "origin",
151
+ onLoad: _cache[1] || (_cache[1] = (...args) => $setup.handleFrameLoaded && $setup.handleFrameLoaded(...args))
152
+ }, null, 40, _hoisted_3)
159
153
  ])
160
154
  ]);
161
155
  }
@@ -1 +1 @@
1
- .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,.opencode-header-btn.session-toggle.active{background:var(--oc-primary);color:#fff}
1
+ .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,.opencode-header-btn.session-toggle.active,.opencode-header-btn.review-panel.active{background:var(--oc-primary);color:#fff}
@@ -16,6 +16,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
16
16
  resolvedTheme,
17
17
  minimized,
18
18
  promptDockVisible,
19
+ reviewPanelVisible,
19
20
  mode,
20
21
  displayMode,
21
22
  splitPosition,
@@ -27,6 +28,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
27
28
  handleClose,
28
29
  handleToggleMinimize,
29
30
  handleTogglePromptDock,
31
+ handleToggleReviewPanel,
30
32
  handleRefresh
31
33
  } = useOpenCodeWidgetContext();
32
34
  const isSplitMode = computed(() => mode.value === "split");
@@ -80,7 +82,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
80
82
  const nextPosition = splitPosition.value === "right" ? "\u5DE6\u4FA7" : "\u53F3\u4FA7";
81
83
  return `\u5207\u6362\u5206\u680F\u4F4D\u7F6E - \u4E0B\u4E00\u4E2A: ${nextPosition}`;
82
84
  });
83
- const __returned__ = { title, sessionListTitle, sessionListCollapsed, selectMode, selectEnabled, theme, resolvedTheme, minimized, promptDockVisible, mode, displayMode, splitPosition, handleToggleSessionList, handleToggleSelectMode, handleToggleTheme, handleToggleDisplayMode, handleToggleSplitPosition, handleClose, handleToggleMinimize, handleTogglePromptDock, handleRefresh, isSplitMode, themeIconTitle, themeIconLabel, displayModeIconTitle, displayModeIconLabel, splitPositionIconTitle, splitPositionIconLabel };
85
+ const __returned__ = { title, sessionListTitle, sessionListCollapsed, selectMode, selectEnabled, theme, resolvedTheme, minimized, promptDockVisible, reviewPanelVisible, mode, displayMode, splitPosition, handleToggleSessionList, handleToggleSelectMode, handleToggleTheme, handleToggleDisplayMode, handleToggleSplitPosition, handleClose, handleToggleMinimize, handleTogglePromptDock, handleToggleReviewPanel, handleRefresh, isSplitMode, themeIconTitle, themeIconLabel, displayModeIconTitle, displayModeIconLabel, splitPositionIconTitle, splitPositionIconLabel };
84
86
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
85
87
  return __returned__;
86
88
  }
@@ -177,7 +179,8 @@ const _hoisted_17 = {
177
179
  };
178
180
  const _hoisted_18 = ["title", "aria-label", "aria-pressed"];
179
181
  const _hoisted_19 = ["title", "aria-label", "aria-pressed"];
180
- const _hoisted_20 = {
182
+ const _hoisted_20 = ["title", "aria-label", "aria-pressed"];
183
+ const _hoisted_21 = {
181
184
  key: 0,
182
185
  viewBox: "0 0 24 24",
183
186
  width: "14",
@@ -187,7 +190,7 @@ const _hoisted_20 = {
187
190
  "stroke-width": "2",
188
191
  "aria-hidden": "true"
189
192
  };
190
- const _hoisted_21 = {
193
+ const _hoisted_22 = {
191
194
  key: 1,
192
195
  viewBox: "0 0 24 24",
193
196
  width: "14",
@@ -209,7 +212,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
209
212
  onClick: _cache[0] || (_cache[0] = (...args) => $setup.handleToggleSessionList && $setup.handleToggleSessionList(...args))
210
213
  }, [
211
214
  _renderSlot(_ctx.$slots, "session-toggle-icon", {}, () => [
212
- _cache[9] || (_cache[9] = _createElementVNode(
215
+ _cache[10] || (_cache[10] = _createElementVNode(
213
216
  "svg",
214
217
  {
215
218
  viewBox: "0 0 24 24",
@@ -241,7 +244,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
241
244
  onClick: _cache[1] || (_cache[1] = (...args) => $setup.handleToggleSelectMode && $setup.handleToggleSelectMode(...args))
242
245
  }, [
243
246
  _renderSlot(_ctx.$slots, "select-icon", {}, () => [
244
- _cache[10] || (_cache[10] = _createElementVNode(
247
+ _cache[11] || (_cache[11] = _createElementVNode(
245
248
  "svg",
246
249
  {
247
250
  viewBox: "0 0 1024 1024",
@@ -272,9 +275,9 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
272
275
  onClick: _cache[2] || (_cache[2] = (...args) => $setup.handleToggleTheme && $setup.handleToggleTheme(...args))
273
276
  }, [
274
277
  _renderSlot(_ctx.$slots, "theme-icon", {}, () => [
275
- $setup.theme === "light" ? (_openBlock(), _createElementBlock("svg", _hoisted_6, [..._cache[11] || (_cache[11] = [
278
+ $setup.theme === "light" ? (_openBlock(), _createElementBlock("svg", _hoisted_6, [..._cache[12] || (_cache[12] = [
276
279
  _createStaticVNode('<circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>', 9)
277
- ])])) : $setup.theme === "dark" ? (_openBlock(), _createElementBlock("svg", _hoisted_7, [..._cache[12] || (_cache[12] = [
280
+ ])])) : $setup.theme === "dark" ? (_openBlock(), _createElementBlock("svg", _hoisted_7, [..._cache[13] || (_cache[13] = [
278
281
  _createElementVNode(
279
282
  "path",
280
283
  { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" },
@@ -282,7 +285,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
282
285
  -1
283
286
  /* CACHED */
284
287
  )
285
- ])])) : (_openBlock(), _createElementBlock("svg", _hoisted_8, [..._cache[13] || (_cache[13] = [
288
+ ])])) : (_openBlock(), _createElementBlock("svg", _hoisted_8, [..._cache[14] || (_cache[14] = [
286
289
  _createStaticVNode('<rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect><line x1="8" y1="21" x2="16" y2="21"></line><line x1="12" y1="17" x2="12" y2="21"></line><circle cx="12" cy="10" r="3"></circle><path d="M7 7l2 2M17 7l-2 2M7 13l2-2M17 13l-2-2"></path>', 5)
287
290
  ])]))
288
291
  ])
@@ -296,7 +299,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
296
299
  onClick: _cache[3] || (_cache[3] = (...args) => $setup.handleToggleDisplayMode && $setup.handleToggleDisplayMode(...args))
297
300
  }, [
298
301
  _renderSlot(_ctx.$slots, "display-mode-icon", {}, () => [
299
- $setup.displayMode === "bubble" ? (_openBlock(), _createElementBlock("svg", _hoisted_10, [..._cache[14] || (_cache[14] = [
302
+ $setup.displayMode === "bubble" ? (_openBlock(), _createElementBlock("svg", _hoisted_10, [..._cache[15] || (_cache[15] = [
300
303
  _createElementVNode(
301
304
  "circle",
302
305
  {
@@ -344,7 +347,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
344
347
  -1
345
348
  /* CACHED */
346
349
  )
347
- ])])) : $setup.displayMode === "split" ? (_openBlock(), _createElementBlock("svg", _hoisted_11, [..._cache[15] || (_cache[15] = [
350
+ ])])) : $setup.displayMode === "split" ? (_openBlock(), _createElementBlock("svg", _hoisted_11, [..._cache[16] || (_cache[16] = [
348
351
  _createElementVNode(
349
352
  "rect",
350
353
  {
@@ -370,7 +373,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
370
373
  -1
371
374
  /* CACHED */
372
375
  )
373
- ])])) : (_openBlock(), _createElementBlock("svg", _hoisted_12, [..._cache[16] || (_cache[16] = [
376
+ ])])) : (_openBlock(), _createElementBlock("svg", _hoisted_12, [..._cache[17] || (_cache[17] = [
374
377
  _createElementVNode(
375
378
  "rect",
376
379
  {
@@ -440,7 +443,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
440
443
  title: "\u5237\u65B0\u9762\u677F",
441
444
  "aria-label": "\u5237\u65B0\u9762\u677F",
442
445
  onClick: _cache[4] || (_cache[4] = (...args) => $setup.handleRefresh && $setup.handleRefresh(...args))
443
- }, [..._cache[17] || (_cache[17] = [
446
+ }, [..._cache[18] || (_cache[18] = [
444
447
  _createElementVNode(
445
448
  "svg",
446
449
  {
@@ -469,7 +472,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
469
472
  onClick: _cache[5] || (_cache[5] = (...args) => $setup.handleToggleSplitPosition && $setup.handleToggleSplitPosition(...args))
470
473
  }, [
471
474
  _renderSlot(_ctx.$slots, "split-position-icon", {}, () => [
472
- $setup.splitPosition === "right" ? (_openBlock(), _createElementBlock("svg", _hoisted_16, [..._cache[18] || (_cache[18] = [
475
+ $setup.splitPosition === "right" ? (_openBlock(), _createElementBlock("svg", _hoisted_16, [..._cache[19] || (_cache[19] = [
473
476
  _createElementVNode(
474
477
  "rect",
475
478
  {
@@ -495,7 +498,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
495
498
  -1
496
499
  /* CACHED */
497
500
  )
498
- ])])) : (_openBlock(), _createElementBlock("svg", _hoisted_17, [..._cache[19] || (_cache[19] = [
501
+ ])])) : (_openBlock(), _createElementBlock("svg", _hoisted_17, [..._cache[20] || (_cache[20] = [
499
502
  _createElementVNode(
500
503
  "rect",
501
504
  {
@@ -524,6 +527,35 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
524
527
  ])]))
525
528
  ])
526
529
  ], 8, _hoisted_15)) : _createCommentVNode("v-if", true),
530
+ _createElementVNode("button", {
531
+ class: _normalizeClass(["opencode-header-btn review-panel", { active: $setup.reviewPanelVisible }]),
532
+ type: "button",
533
+ title: $setup.reviewPanelVisible ? "\u6536\u8D77\u5BA1\u67E5\u9762\u677F" : "\u5C55\u5F00\u5BA1\u67E5\u9762\u677F",
534
+ "aria-label": $setup.reviewPanelVisible ? "\u6536\u8D77\u5BA1\u67E5\u9762\u677F" : "\u5C55\u5F00\u5BA1\u67E5\u9762\u677F",
535
+ "aria-pressed": $setup.reviewPanelVisible,
536
+ onClick: _cache[6] || (_cache[6] = (...args) => $setup.handleToggleReviewPanel && $setup.handleToggleReviewPanel(...args))
537
+ }, [..._cache[21] || (_cache[21] = [
538
+ _createElementVNode(
539
+ "svg",
540
+ {
541
+ viewBox: "0 0 24 24",
542
+ width: "15",
543
+ height: "15",
544
+ fill: "none",
545
+ stroke: "currentColor",
546
+ "stroke-width": "2",
547
+ "stroke-linecap": "round",
548
+ "stroke-linejoin": "round",
549
+ "aria-hidden": "true"
550
+ },
551
+ [
552
+ _createElementVNode("polyline", { points: "16 18 22 12 16 6" }),
553
+ _createElementVNode("polyline", { points: "8 6 2 12 8 18" })
554
+ ],
555
+ -1
556
+ /* CACHED */
557
+ )
558
+ ])], 10, _hoisted_18),
527
559
  !$setup.isSplitMode ? (_openBlock(), _createElementBlock("button", {
528
560
  key: 2,
529
561
  class: "opencode-header-btn prompt-dock",
@@ -531,10 +563,10 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
531
563
  title: $setup.promptDockVisible ? "\u9690\u85CF\u5BF9\u8BDD\u6846" : "\u663E\u793A\u5BF9\u8BDD\u6846",
532
564
  "aria-label": $setup.promptDockVisible ? "\u9690\u85CF\u5BF9\u8BDD\u6846" : "\u663E\u793A\u5BF9\u8BDD\u6846",
533
565
  "aria-pressed": $setup.promptDockVisible,
534
- onClick: _cache[6] || (_cache[6] = (...args) => $setup.handleTogglePromptDock && $setup.handleTogglePromptDock(...args))
566
+ onClick: _cache[7] || (_cache[7] = (...args) => $setup.handleTogglePromptDock && $setup.handleTogglePromptDock(...args))
535
567
  }, [
536
568
  _renderSlot(_ctx.$slots, "prompt-dock-icon", {}, () => [
537
- _cache[20] || (_cache[20] = _createElementVNode(
569
+ _cache[22] || (_cache[22] = _createElementVNode(
538
570
  "svg",
539
571
  {
540
572
  viewBox: "0 0 24 24",
@@ -552,7 +584,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
552
584
  /* CACHED */
553
585
  ))
554
586
  ])
555
- ], 8, _hoisted_18)) : _createCommentVNode("v-if", true),
587
+ ], 8, _hoisted_19)) : _createCommentVNode("v-if", true),
556
588
  !$setup.isSplitMode ? (_openBlock(), _createElementBlock("button", {
557
589
  key: 3,
558
590
  class: "opencode-header-btn minimize",
@@ -560,10 +592,10 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
560
592
  title: $setup.minimized ? "\u5C55\u5F00" : "\u6700\u5C0F\u5316",
561
593
  "aria-label": $setup.minimized ? "\u5C55\u5F00\u9762\u677F" : "\u6700\u5C0F\u5316\u9762\u677F",
562
594
  "aria-pressed": $setup.minimized,
563
- onClick: _cache[7] || (_cache[7] = (...args) => $setup.handleToggleMinimize && $setup.handleToggleMinimize(...args))
595
+ onClick: _cache[8] || (_cache[8] = (...args) => $setup.handleToggleMinimize && $setup.handleToggleMinimize(...args))
564
596
  }, [
565
597
  _renderSlot(_ctx.$slots, "minimize-icon", {}, () => [
566
- $setup.minimized ? (_openBlock(), _createElementBlock("svg", _hoisted_20, [..._cache[21] || (_cache[21] = [
598
+ $setup.minimized ? (_openBlock(), _createElementBlock("svg", _hoisted_21, [..._cache[23] || (_cache[23] = [
567
599
  _createElementVNode(
568
600
  "path",
569
601
  { d: "M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3" },
@@ -571,7 +603,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
571
603
  -1
572
604
  /* CACHED */
573
605
  )
574
- ])])) : (_openBlock(), _createElementBlock("svg", _hoisted_21, [..._cache[22] || (_cache[22] = [
606
+ ])])) : (_openBlock(), _createElementBlock("svg", _hoisted_22, [..._cache[24] || (_cache[24] = [
575
607
  _createElementVNode(
576
608
  "path",
577
609
  { d: "M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3" },
@@ -581,17 +613,17 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
581
613
  )
582
614
  ])]))
583
615
  ])
584
- ], 8, _hoisted_19)) : _createCommentVNode("v-if", true),
616
+ ], 8, _hoisted_20)) : _createCommentVNode("v-if", true),
585
617
  !$setup.isSplitMode ? (_openBlock(), _createElementBlock("button", {
586
618
  key: 4,
587
619
  class: "opencode-header-btn close",
588
620
  type: "button",
589
621
  title: "\u5173\u95ED",
590
622
  "aria-label": "\u5173\u95ED\u9762\u677F",
591
- onClick: _cache[8] || (_cache[8] = (...args) => $setup.handleClose && $setup.handleClose(...args))
623
+ onClick: _cache[9] || (_cache[9] = (...args) => $setup.handleClose && $setup.handleClose(...args))
592
624
  }, [
593
625
  _renderSlot(_ctx.$slots, "close-icon", {}, () => [
594
- _cache[23] || (_cache[23] = _createElementVNode(
626
+ _cache[25] || (_cache[25] = _createElementVNode(
595
627
  "svg",
596
628
  {
597
629
  viewBox: "0 0 24 24",
@@ -1 +1 @@
1
- .opencode-select-mode-hint{position:fixed;top:20px;left:50%;transform:translate(-50%);padding:10px;background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;border-radius:12px;font-size:14px;font-weight:500;box-shadow:0 6px 20px #ef444480,0 0 0 3px #ef44444d;z-index:9999999;display:none;align-items:center;gap:12px;border:1px solid rgba(255,255,255,.3)}.opencode-select-mode-hint.visible{display:flex;animation:slideDown .3s ease,pulseHint 2s ease-in-out infinite}.opencode-hint-shortcut{padding:4px 10px;background:#ffffff40;border-radius:6px;font-size:13px;font-weight:600;border:1px solid rgba(255,255,255,.4)}@keyframes pulseHint{0%,to{box-shadow:0 6px 20px #ef444480,0 0 0 3px #ef44444d}50%{box-shadow:0 6px 20px #ef444499,0 0 0 6px #ef444466}}
1
+ .opencode-select-mode-hint{position:fixed;top:16px;left:50%;transform:translate(-50%) translateY(-16px);width:280px;padding:8px 14px;background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;border-radius:18px;font-size:13px;font-weight:500;line-height:1.4;box-shadow:0 6px 20px #ef444480,0 0 0 3px #ef44444d;z-index:9999999;display:none;flex-direction:column;align-items:center;justify-content:center;gap:6px;border:1px solid rgba(255,255,255,.25);opacity:0;transition:opacity .2s ease,transform .25s cubic-bezier(.16,1,.3,1);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);box-sizing:border-box}.opencode-select-mode-hint.visible{display:flex;opacity:1;transform:translate(-50%) translateY(0);animation:hintSlideIn .3s cubic-bezier(.16,1,.3,1),pulseHint 2s ease-in-out .3s infinite}.opencode-hint-main{display:inline-flex;align-items:center;gap:8px;min-width:0}.opencode-hint-icon{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:50%;background:#fff3;color:#fff;flex-shrink:0}.opencode-hint-icon svg{display:block}.opencode-hint-text{font-size:13px;font-weight:500;letter-spacing:.2px;white-space:nowrap;text-shadow:0 1px 2px rgba(0,0,0,.15)}.opencode-hint-shortcut{display:inline-flex;align-items:center;padding:4px 10px;background:#0000002e;border-radius:999px;font-size:12px;font-weight:600;letter-spacing:.3px;border:1px solid rgba(255,255,255,.2);white-space:nowrap;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace}@keyframes hintSlideIn{0%{opacity:0;transform:translate(-50%) translateY(-16px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@keyframes pulseHint{0%,to{box-shadow:0 6px 20px #ef444480,0 0 0 3px #ef44444d}50%{box-shadow:0 6px 20px #ef444499,0 0 0 6px #ef444466}}
@@ -11,7 +11,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
11
11
  return __returned__;
12
12
  }
13
13
  });
14
- import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, normalizeClass as _normalizeClass, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue";
14
+ import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, normalizeClass as _normalizeClass, createStaticVNode as _createStaticVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue";
15
15
  const _hoisted_1 = { class: "opencode-hint-shortcut" };
16
16
  function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
17
17
  return _openBlock(), _createElementBlock(
@@ -20,13 +20,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
20
20
  class: _normalizeClass(["opencode-select-mode-hint", { visible: $setup.visible }])
21
21
  },
22
22
  [
23
- _cache[0] || (_cache[0] = _createElementVNode(
24
- "span",
25
- null,
26
- "\u{1F3AF} \u9009\u62E9\u6A21\u5F0F\u5DF2\u5F00\u542F - \u70B9\u51FB\u5143\u7D20\u8FDB\u884C\u9009\u62E9",
27
- -1
28
- /* CACHED */
29
- )),
23
+ _cache[0] || (_cache[0] = _createStaticVNode('<span class="opencode-hint-main"><span class="opencode-hint-icon" aria-hidden="true"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="8"></circle><circle cx="12" cy="12" r="2.5" fill="currentColor"></circle><line x1="12" y1="2" x2="12" y2="5"></line><line x1="12" y1="19" x2="12" y2="22"></line><line x1="2" y1="12" x2="5" y2="12"></line><line x1="19" y1="12" x2="22" y2="12"></line></svg></span><span class="opencode-hint-text">\u9009\u62E9\u6A21\u5F0F\u5DF2\u5F00\u542F \xB7 \u70B9\u51FB\u5143\u7D20\u8FDB\u884C\u9009\u62E9</span></span>', 1)),
30
24
  _createElementVNode(
31
25
  "span",
32
26
  _hoisted_1,
@@ -23,6 +23,7 @@ export interface OpenCodeWidgetContext {
23
23
  thinking: Ref<boolean>;
24
24
  minimized: Ref<boolean>;
25
25
  promptDockVisible: Ref<boolean>;
26
+ reviewPanelVisible: Ref<boolean>;
26
27
  bubbleOffset: Ref<FloatingBubbleOffset | undefined>;
27
28
  mode: Ref<"bubble" | "split">;
28
29
  displayMode: Ref<DisplayMode>;
@@ -39,6 +40,7 @@ export interface OpenCodeWidgetContext {
39
40
  handleClose: () => void;
40
41
  handleToggleMinimize: () => void;
41
42
  handleTogglePromptDock: () => void;
43
+ handleToggleReviewPanel: () => void;
42
44
  handleToggleSessionList: () => void;
43
45
  handleToggleTheme: () => void;
44
46
  handleToggleDisplayMode: () => void;
@@ -1 +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-thinking-gradient-1: #10b981;--oc-thinking-gradient-2: #059669;--oc-thinking-glow: rgba(16, 185, 129, .3);--oc-thinking-glow-strong: rgba(16, 185, 129, .6);--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: #3b82f6;--oc-trigger-bg-hover: #2563eb;--oc-trigger-bg-active: #1d4ed8;--oc-trigger-shadow: 0 2px 8px rgba(59, 130, 246, .3);--oc-trigger-shadow-hover: 0 4px 12px rgba(59, 130, 246, .4);--oc-trigger-shadow-active: 0 4px 12px rgba(59, 130, 246, .5);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-thinking-gradient-1: #34d399;--oc-thinking-gradient-2: #10b981;--oc-thinking-glow: rgba(52, 211, 153, .3);--oc-thinking-glow-strong: rgba(52, 211, 153, .6);--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: #60a5fa;--oc-trigger-bg-hover: #3b82f6;--oc-trigger-bg-active: #2563eb;--oc-trigger-shadow: 0 2px 8px rgba(96, 165, 250, .4);--oc-trigger-shadow-hover: 0 4px 12px rgba(96, 165, 250, .5);--oc-trigger-shadow-active: 0 4px 12px rgba(96, 165, 250, .6)}.opencode-chat{position:fixed;bottom:20px;width:700px;height:86vh;max-height:calc(100vh - 40px);background:var(--oc-bg-main);border-radius:16px;box-shadow:var(--oc-shadow-lg);overflow:hidden;opacity:0;visibility:hidden;transform:translate3d(var(---chatAnimationOrigin\.x),var(---chatAnimationOrigin\.y),0) scale(.95);transition:all .3s ease;display:flex;flex-direction:column;z-index:99999}.opencode-chat.open{opacity:1;visibility:visible;transform:translateZ(0) scale(1)}.opencode-chat.no-transition,.opencode-chat.no-transition.open{transition:none!important}.opencode-chat.minimized{width:320px;height:320px}.opencode-chat.minimized .opencode-iframe-container{margin-top:-146px}.opencode-chat-content{display:flex;flex:1;overflow:hidden}.opencode-notification{position:absolute;top:20px;left:50%;transform:translate(-50%);padding:12px 24px;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border-radius:10px;font-size:14px;font-weight:500;box-shadow:0 4px 16px #3b82f666,0 0 0 2px #3b82f633;animation:slideDown .3s ease;z-index:10000000;display:flex;align-items:center;gap:10px}.opencode-notification:before{content:"\1f4a1";font-size:16px}.opencode-dialog-overlay{position:fixed;inset: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-page-notification{position:fixed;top:20px;left:50%;transform:translate(-50%);padding:12px 24px;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border-radius:10px;font-size:14px;font-weight:500;box-shadow:0 4px 16px #3b82f666,0 0 0 2px #3b82f633;animation:slideDown .3s ease;z-index:2147483647;display:flex;align-items:center;gap:10px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.opencode-page-notification:before{content:"\1f4a1";font-size:16px}.opencode-element-highlight{position:fixed;pointer-events:none;z-index:999998;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;box-shadow:var(--oc-shadow-md);max-width:300px;pointer-events:none;line-height:1}.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)}}body.has-opencode-split{transition:padding .3s ease;min-width:auto}body.has-opencode-split-right{padding-right:var(--opencode-split-width, 500px)}body.has-opencode-split-left{padding-left:var(--opencode-split-width, 500px)}.opencode-widget.extension-mode{position:static;width:100%;height:100%;display:flex}.opencode-widget.extension-mode .opencode-select-mode-hint,.opencode-widget.extension-mode .opencode-dialog-overlay{position:absolute}
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-thinking-gradient-1: #10b981;--oc-thinking-gradient-2: #059669;--oc-thinking-glow: rgba(16, 185, 129, .3);--oc-thinking-glow-strong: rgba(16, 185, 129, .6);--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: #3b82f6;--oc-trigger-bg-hover: #2563eb;--oc-trigger-bg-active: #1d4ed8;--oc-trigger-shadow: 0 2px 8px rgba(59, 130, 246, .3);--oc-trigger-shadow-hover: 0 4px 12px rgba(59, 130, 246, .4);--oc-trigger-shadow-active: 0 4px 12px rgba(59, 130, 246, .5);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-thinking-gradient-1: #34d399;--oc-thinking-gradient-2: #10b981;--oc-thinking-glow: rgba(52, 211, 153, .3);--oc-thinking-glow-strong: rgba(52, 211, 153, .6);--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: #60a5fa;--oc-trigger-bg-hover: #3b82f6;--oc-trigger-bg-active: #2563eb;--oc-trigger-shadow: 0 2px 8px rgba(96, 165, 250, .4);--oc-trigger-shadow-hover: 0 4px 12px rgba(96, 165, 250, .5);--oc-trigger-shadow-active: 0 4px 12px rgba(96, 165, 250, .6)}.opencode-chat{position:fixed;bottom:20px;width:700px;height:86vh;max-height:calc(100vh - 40px);background:var(--oc-bg-main);border-radius:16px;box-shadow:var(--oc-shadow-lg);overflow:hidden;opacity:0;visibility:hidden;transform:translate3d(var(---chatAnimationOrigin\.x),var(---chatAnimationOrigin\.y),0) scale(.95);transition:all .3s ease;display:flex;flex-direction:column;z-index:99999}.opencode-chat.open{opacity:1;visibility:visible;transform:translateZ(0) scale(1)}.opencode-chat.no-transition,.opencode-chat.no-transition.open{transition:none!important}.opencode-chat.minimized{width:320px;height:320px}.opencode-chat.minimized .opencode-iframe-container{margin-top:-146px}.opencode-chat-content{display:flex;flex:1;overflow:hidden}.opencode-notification{position:absolute;top:20px;left:50%;transform:translate(-50%);padding:12px 24px;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border-radius:10px;font-size:14px;font-weight:500;box-shadow:0 4px 16px #3b82f666,0 0 0 2px #3b82f633;animation:slideDown .3s ease;z-index:10000000;display:flex;align-items:center;gap:10px}.opencode-notification:before{content:"\1f4a1";font-size:16px}.opencode-dialog-overlay{position:fixed;inset: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-page-notification{position:fixed;top:20px;left:50%;transform:translate(-50%);padding:12px 24px;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border-radius:10px;font-size:14px;font-weight:500;box-shadow:0 4px 16px #3b82f666,0 0 0 2px #3b82f633;animation:slideDown .3s ease;z-index:2147483647;display:flex;align-items:center;gap:10px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.opencode-page-notification:before{content:"\1f4a1";font-size:16px}.opencode-element-highlight{position:fixed;pointer-events:none;z-index:999998;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;box-shadow:var(--oc-shadow-md);max-width:300px;pointer-events:none;line-height:1}.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)}}body.has-opencode-split{transition:padding .3s ease;min-width:auto}body.has-opencode-split-right{padding-right:var(--opencode-split-width, 500px)}body.has-opencode-split-left{padding-left:var(--opencode-split-width, 500px)}.opencode-widget.extension-mode{position:relative;width:100%;height:100%;display:flex}.opencode-widget.extension-mode .opencode-select-mode-hint,.opencode-widget.extension-mode .opencode-dialog-overlay{position:absolute}
@@ -119,6 +119,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
119
119
  );
120
120
  const minimized = ref(false);
121
121
  const promptDockVisible = ref(true);
122
+ const reviewPanelVisible = ref(false);
122
123
  const isRestoring = ref(true);
123
124
  const iframeLoaded = ref(false);
124
125
  const splitPanelWidth = ref(props.splitPanelWidth);
@@ -126,6 +127,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
126
127
  if (!iframeLoaded.value) return;
127
128
  sendMessageToIframe(WIDGET_MSG.PROMPT_DOCK_VISIBILITY, { visible: promptDockVisible.value });
128
129
  sendMessageToIframe(WIDGET_MSG.MINIMIZE_STATE, { minimized: minimized.value });
130
+ sendMessageToIframe(WIDGET_MSG.REVIEW_PANEL_TOGGLE, { visible: reviewPanelVisible.value });
129
131
  };
130
132
  const handleFrameLoaded = () => {
131
133
  emit("frame-loaded");
@@ -280,6 +282,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
280
282
  open: toRef(props, "open"),
281
283
  minimized,
282
284
  promptDockVisible,
285
+ reviewPanelVisible,
283
286
  bubbleOffset,
284
287
  theme: toRef(props, "theme"),
285
288
  sessionListCollapsed: localSessionListCollapsed,
@@ -317,6 +320,9 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
317
320
  } else if (minimized.value) {
318
321
  promptDockVisible.value = false;
319
322
  }
323
+ if (state.reviewPanelVisible !== void 0) {
324
+ reviewPanelVisible.value = state.reviewPanelVisible;
325
+ }
320
326
  if (state.splitPanelWidth !== void 0 && state.splitPanelWidth !== props.splitPanelWidth) {
321
327
  handleResize(state.splitPanelWidth);
322
328
  }
@@ -344,6 +350,10 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
344
350
  promptDockVisible.value = !promptDockVisible.value;
345
351
  sendMessageToIframe(WIDGET_MSG.PROMPT_DOCK_VISIBILITY, { visible: promptDockVisible.value });
346
352
  };
353
+ const handleToggleReviewPanel = () => {
354
+ reviewPanelVisible.value = !reviewPanelVisible.value;
355
+ sendMessageToIframe(WIDGET_MSG.REVIEW_PANEL_TOGGLE, { visible: reviewPanelVisible.value });
356
+ };
347
357
  const handleRefresh = () => {
348
358
  window.location.reload();
349
359
  };
@@ -494,6 +504,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
494
504
  thinking: toRef(props, "thinking"),
495
505
  minimized,
496
506
  promptDockVisible,
507
+ reviewPanelVisible,
497
508
  bubbleOffset,
498
509
  mode: effectiveMode,
499
510
  displayMode: localDisplayMode,
@@ -513,6 +524,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
513
524
  handleClose,
514
525
  handleToggleMinimize,
515
526
  handleTogglePromptDock,
527
+ handleToggleReviewPanel,
516
528
  handleToggleSessionList,
517
529
  handleToggleTheme,
518
530
  handleToggleDisplayMode,
@@ -543,7 +555,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
543
555
  return dialogResolve;
544
556
  }, set dialogResolve(v) {
545
557
  dialogResolve = v;
546
- }, showConfirmDialog, handleDialogConfirm, handleDialogCancel, frameRef, triggerRef, sendMessageToIframe, localSessionListCollapsed, localDisplayMode, localSplitPosition, minimized, promptDockVisible, isRestoring, iframeLoaded, splitPanelWidth, syncStateToIframe, handleFrameLoaded, handleToggleDisplayMode, buttonActive, containerClasses, iframeSource, sessionListTitle, resolvedTheme, handleClose, handleEmptyAction, handleToggle, handleToggleSessionList, handleToggleTheme, sessionItems, handleCreateSession, handleDeleteSession, handleSelectSession, bubbleVisible, hasSelectedElements, selectedElementItems, handleClearSelectedNodes, handleClickSelectedNode, handleRemoveSelectedNode, handleToggleSelectMode, highlightVisible, highlightStyle, tooltipVisible, tooltipStyle, tooltipContent, bubbleOffset, effectiveMode, isSplitMode, isExtensionMode, panelWidth, splitConfig, splitPosition, handleResize, handleSplitToggle, handleTogglePosition, handleToggleMinimize, handleTogglePromptDock, handleRefresh, windowWidth, windowHeight, handleWindowResize, bubbleQuadrant, isBubbleOnRightSide, chatPositionStyle, handleBubbleOffsetChange, handleResizeStart, handleResizeEnd, chatAnimationOrigin, isDragging, get wasOpenBeforeDrag() {
558
+ }, showConfirmDialog, handleDialogConfirm, handleDialogCancel, frameRef, triggerRef, sendMessageToIframe, localSessionListCollapsed, localDisplayMode, localSplitPosition, minimized, promptDockVisible, reviewPanelVisible, isRestoring, iframeLoaded, splitPanelWidth, syncStateToIframe, handleFrameLoaded, handleToggleDisplayMode, buttonActive, containerClasses, iframeSource, sessionListTitle, resolvedTheme, handleClose, handleEmptyAction, handleToggle, handleToggleSessionList, handleToggleTheme, sessionItems, handleCreateSession, handleDeleteSession, handleSelectSession, bubbleVisible, hasSelectedElements, selectedElementItems, handleClearSelectedNodes, handleClickSelectedNode, handleRemoveSelectedNode, handleToggleSelectMode, highlightVisible, highlightStyle, tooltipVisible, tooltipStyle, tooltipContent, bubbleOffset, effectiveMode, isSplitMode, isExtensionMode, panelWidth, splitConfig, splitPosition, handleResize, handleSplitToggle, handleTogglePosition, handleToggleMinimize, handleTogglePromptDock, handleToggleReviewPanel, handleRefresh, windowWidth, windowHeight, handleWindowResize, bubbleQuadrant, isBubbleOnRightSide, chatPositionStyle, handleBubbleOffsetChange, handleResizeStart, handleResizeEnd, chatAnimationOrigin, isDragging, get wasOpenBeforeDrag() {
547
559
  return wasOpenBeforeDrag;
548
560
  }, set wasOpenBeforeDrag(v) {
549
561
  wasOpenBeforeDrag = v;