@hotmail007/vue-admin-ai-assistant 0.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .assistant-widget{--assistant-primary: #409eff;--assistant-primary-soft: #ecf5ff;--assistant-primary-muted: #c6e2ff;--assistant-panel-bg: #fff;--assistant-panel-border: #f0f0f0;--assistant-panel-shadow: 0 8px 32px rgb(0 0 0 / 10%), 0 2px 8px rgb(0 0 0 / 4%);--assistant-assistant-bubble-bg: #f5f5f7;--assistant-assistant-bubble-color: #1a1a1a;--assistant-user-bubble-bg: #409eff;--assistant-user-bubble-color: #fff;--assistant-trigger-bg: #409eff;--assistant-trigger-active-bg: #e0e0e0;--assistant-trigger-active-color: #666;--assistant-right: 24px;--assistant-trigger-bottom: 24px;--assistant-panel-bottom: 84px;--assistant-panel-width: 400px;--assistant-panel-height: 70vh;--assistant-panel-min-height: 420px;--assistant-panel-max-height: 720px;--assistant-trigger-z-index: 2000;--assistant-panel-z-index: 1999}.msg[data-v-ec7104f7]{display:flex;gap:8px;margin-bottom:14px;padding:0 14px}.msg--user[data-v-ec7104f7]{flex-direction:row-reverse}.msg--user .msg__body[data-v-ec7104f7]{align-items:flex-end}.msg--user .msg__bubble[data-v-ec7104f7]{background:var(--assistant-user-bubble-bg, var(--assistant-primary, var(--el-color-primary, #409eff)));color:var(--assistant-user-bubble-color, #fff);border-radius:14px 4px 14px 14px}.msg--assistant .msg__bubble[data-v-ec7104f7]{background:var(--assistant-assistant-bubble-bg, #f5f5f7);color:var(--assistant-assistant-bubble-color, #1a1a1a);border-radius:4px 14px 14px}.msg__avatar[data-v-ec7104f7]{width:30px;height:30px;border-radius:50%;background:var(--assistant-primary-soft, #ecf5ff);color:var(--assistant-primary, var(--el-color-primary, #409eff));display:flex;align-items:center;justify-content:center;flex-shrink:0}.msg__body[data-v-ec7104f7]{display:flex;flex-direction:column;gap:6px;max-width:84%;min-width:0}.msg__bubble[data-v-ec7104f7]{padding:10px 14px;font-size:13.5px;line-height:1.6;word-break:break-word}.msg__bubble.is-error[data-v-ec7104f7]{background:#fff2f0;color:#cf1322}.msg__text[data-v-ec7104f7]{white-space:pre-wrap}.msg__md[data-v-ec7104f7] p,.msg__md[data-v-ec7104f7] ul,.msg__md[data-v-ec7104f7] ol,.msg__md[data-v-ec7104f7] pre,.msg__md[data-v-ec7104f7] blockquote,.msg__md[data-v-ec7104f7] table{margin:0 0 6px}.msg__md[data-v-ec7104f7] p:last-child,.msg__md[data-v-ec7104f7] ul:last-child,.msg__md[data-v-ec7104f7] ol:last-child,.msg__md[data-v-ec7104f7] pre:last-child,.msg__md[data-v-ec7104f7] blockquote:last-child,.msg__md[data-v-ec7104f7] table:last-child{margin-bottom:0}.msg__md[data-v-ec7104f7] code{padding:1px 5px;border-radius:4px;background:#0000000d;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:.88em}.msg__md[data-v-ec7104f7] pre{padding:10px 12px;border-radius:8px;background:#1e1e1e;color:#d4d4d4;overflow-x:auto;font-size:12px;line-height:1.5}.msg__md[data-v-ec7104f7] pre code{padding:0;background:none;color:inherit}.msg__md[data-v-ec7104f7] a{color:var(--assistant-primary, var(--el-color-primary, #409eff));text-decoration:none}.msg__md[data-v-ec7104f7] a:hover{text-decoration:underline}.msg__md[data-v-ec7104f7] table{width:100%;border-collapse:collapse;font-size:12px}.msg__md[data-v-ec7104f7] th,.msg__md[data-v-ec7104f7] td{padding:4px 8px;border:1px solid #eee;text-align:left}.msg__md[data-v-ec7104f7] img{max-width:100%;border-radius:6px}.msg__time[data-v-ec7104f7]{margin-top:2px;font-size:11px;color:#bbb}.thinking-card[data-v-ec7104f7],.step-card[data-v-ec7104f7],.approval-card[data-v-ec7104f7]{border-radius:10px;overflow:hidden}.thinking-card[data-v-ec7104f7]{border:1px solid #d8e6ff;background:#f4f8ff}.thinking-card__summary[data-v-ec7104f7]{width:100%;border:none;background:transparent;padding:8px 12px;display:flex;align-items:center;justify-content:space-between;cursor:pointer}.thinking-card__label[data-v-ec7104f7]{font-size:12px;font-weight:600;color:#31589a}.thinking-card__hint[data-v-ec7104f7],.thinking-card__preview[data-v-ec7104f7]{font-size:12px;color:#4f5f7f}.thinking-card__preview[data-v-ec7104f7],.thinking-card__content pre[data-v-ec7104f7]{padding:0 12px 10px}.thinking-card__content pre[data-v-ec7104f7]{margin:0;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;white-space:pre-wrap;word-break:break-word;background:#edf3ff;padding-top:10px}.step-card[data-v-ec7104f7]{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:7px 12px;font-size:12px;background:#f0f7ff;border:1px solid #d6e8fa}.step-card.is-done[data-v-ec7104f7]{background:#f6ffed;border-color:#b7eb8f}.step-card.is-fail[data-v-ec7104f7]{background:#fff2f0;border-color:#ffccc7}.step-card__name[data-v-ec7104f7]{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;color:#333}.step-card__status[data-v-ec7104f7]{color:#999;flex-shrink:0}.approval-card[data-v-ec7104f7]{border:1px solid #ffe58f;background:#fffbe6}.approval-card__header[data-v-ec7104f7],.approval-card__handled[data-v-ec7104f7]{padding:8px 12px;font-size:12.5px;color:#8c6d1f}.approval-card__item[data-v-ec7104f7]{padding:8px 12px;border-top:1px solid #fff1b8}.approval-card__tool[data-v-ec7104f7],.approval-card__args[data-v-ec7104f7]{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace}.approval-card__tool[data-v-ec7104f7]{font-size:12px;font-weight:600;color:#333;margin-bottom:4px}.approval-card__args[data-v-ec7104f7]{margin:0;padding:6px 8px;background:#00000008;border-radius:6px;font-size:11px;white-space:pre-wrap;word-break:break-all;max-height:120px;overflow-x:auto}.approval-card__risk[data-v-ec7104f7]{display:inline-block;margin-top:4px;padding:1px 6px;border-radius:4px;font-size:10px;font-weight:600}.approval-card__risk.write[data-v-ec7104f7]{background:#fff1f0;color:#cf1322}.approval-card__risk.read[data-v-ec7104f7]{background:#e6f7ff;color:#096dd9}.approval-card__actions[data-v-ec7104f7]{display:flex;gap:8px;padding:8px 12px;border-top:1px solid #fff1b8}.approval-btn[data-v-ec7104f7]{flex:1;padding:6px 0;border-radius:6px;font-size:12.5px;cursor:pointer;border:none}.approval-btn--ok[data-v-ec7104f7]{background:var(--assistant-primary, var(--el-color-primary, #409eff));color:#fff}.approval-btn--no[data-v-ec7104f7]{background:transparent;border:1px solid #d9d9d9;color:#666}.cursor-blink[data-v-ec7104f7]{animation:blink-ec7104f7 .7s step-end infinite;color:var(--assistant-primary, var(--el-color-primary, #409eff));font-weight:700}@keyframes blink-ec7104f7{0%,to{opacity:1}50%{opacity:0}}.loading-indicator[data-v-e87c9521]{display:flex;gap:8px;padding:0 14px;margin-bottom:14px}.loading-indicator__avatar[data-v-e87c9521]{width:30px;height:30px;border-radius:50%;background:var(--assistant-primary-soft, var(--el-color-primary-light-8, #ecf5ff));color:var(--assistant-primary, var(--el-color-primary, #409eff));display:flex;align-items:center;justify-content:center;flex-shrink:0}.loading-indicator__dots[data-v-e87c9521]{display:flex;align-items:center;gap:4px;padding:10px 14px;background:var(--assistant-assistant-bubble-bg, #f5f5f7);border-radius:4px 14px 14px}.loading-indicator__dots .dot[data-v-e87c9521]{width:6px;height:6px;border-radius:50%;background:#ccc;animation:bounce-e87c9521 1.4s ease-in-out infinite}.loading-indicator__dots .dot[data-v-e87c9521]:nth-child(1){animation-delay:0s}.loading-indicator__dots .dot[data-v-e87c9521]:nth-child(2){animation-delay:.2s}.loading-indicator__dots .dot[data-v-e87c9521]:nth-child(3){animation-delay:.4s}@keyframes bounce-e87c9521{0%,60%,to{transform:translateY(0);opacity:.4}30%{transform:translateY(-5px);opacity:1}}.history-panel[data-v-f9a48034]{display:flex;flex-direction:column;height:100%;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif}.history-header[data-v-f9a48034]{display:flex;align-items:center;gap:8px;padding:14px 14px 14px 12px;border-bottom:1px solid var(--assistant-panel-border, #f0f0f0);flex-shrink:0}.history-header__back[data-v-f9a48034]{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:6px;color:#666;cursor:pointer;transition:all .15s}.history-header__back[data-v-f9a48034]:hover{background:#f5f5f5;color:#333}.history-header__title[data-v-f9a48034]{font-size:15px;font-weight:600;color:#1a1a1a;letter-spacing:-.01em}.history-body[data-v-f9a48034]{flex:1;overflow-y:auto;scrollbar-width:thin;scrollbar-color:transparent transparent}.history-body[data-v-f9a48034]:hover{scrollbar-color:rgba(0,0,0,.12) transparent}.history-body[data-v-f9a48034]::-webkit-scrollbar{width:5px}.history-body[data-v-f9a48034]::-webkit-scrollbar-track{background:transparent}.history-body[data-v-f9a48034]::-webkit-scrollbar-thumb{background:transparent;border-radius:3px}.history-body[data-v-f9a48034]:hover::-webkit-scrollbar-thumb{background:#0000001f}.history-loading[data-v-f9a48034]{display:flex;flex-direction:column;align-items:center;gap:12px;padding:60px 20px;color:#999;font-size:13px}.history-spinner[data-v-f9a48034]{width:24px;height:24px;border:2px solid #e8e8e8;border-top-color:var(--assistant-primary, var(--el-color-primary, #409eff));border-radius:50%;animation:spin-f9a48034 .8s linear infinite}@keyframes spin-f9a48034{to{transform:rotate(360deg)}}.history-empty[data-v-f9a48034]{display:flex;flex-direction:column;align-items:center;gap:12px;padding:80px 20px;color:#bbb;font-size:13px}.history-list[data-v-f9a48034]{padding:8px}.session-item[data-v-f9a48034]{display:flex;align-items:center;gap:8px;padding:12px;border-radius:10px;border:1px solid #eee;cursor:pointer;transition:all .15s}.session-item[data-v-f9a48034]:hover{background:#f7f7f8;border-color:#ddd}.session-item.is-active[data-v-f9a48034]{background:var(--assistant-primary-soft, var(--el-color-primary-light-9, #ecf5ff));border-color:var(--assistant-primary-muted, var(--el-color-primary-light-7, #c6e2ff))}.session-item+.session-item[data-v-f9a48034]{margin-top:8px}.session-item__content[data-v-f9a48034]{flex:1;min-width:0}.session-item__title[data-v-f9a48034]{font-size:13.5px;font-weight:500;color:#1a1a1a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.4}.session-item__meta[data-v-f9a48034]{display:flex;align-items:center;gap:6px;margin-top:3px}.session-item__time[data-v-f9a48034]{font-size:11px;color:#bbb}.session-item__badge[data-v-f9a48034]{font-size:10px;padding:0 5px;border-radius:4px;background:var(--assistant-primary-soft, var(--el-color-primary-light-8, #d9ecff));color:var(--assistant-primary, var(--el-color-primary, #409eff));font-weight:500;line-height:1.6}.session-item__delete[data-v-f9a48034]{display:flex;align-items:center;justify-content:center;width:26px;height:26px;border:none;background:transparent;border-radius:6px;color:#ccc;cursor:pointer;opacity:0;transition:all .15s;flex-shrink:0}.session-item:hover .session-item__delete[data-v-f9a48034]{opacity:1}.session-item__delete[data-v-f9a48034]:hover{background:#fff1f0;color:#ff4d4f}.assistant-panel[data-v-1c632eb3]{position:fixed;right:var(--assistant-right, 24px);bottom:var(--assistant-panel-bottom, 84px);z-index:var(--assistant-panel-z-index, 1999);width:var(--assistant-panel-width, 400px);height:var(--assistant-panel-height, 70vh);min-height:var(--assistant-panel-min-height, 420px);max-height:var(--assistant-panel-max-height, 720px);display:flex;flex-direction:column;background:var(--assistant-panel-bg, #fff);border-radius:16px;box-shadow:var(--assistant-panel-shadow);overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,sans-serif}.panel-header[data-v-1c632eb3]{display:flex;align-items:center;justify-content:space-between;padding:14px 14px 14px 18px;border-bottom:1px solid var(--assistant-panel-border, #f0f0f0);flex-shrink:0}.panel-header__title[data-v-1c632eb3]{display:flex;align-items:center;gap:8px;font-size:15px;font-weight:600;color:#1a1a1a;letter-spacing:-.01em}.panel-header__title svg[data-v-1c632eb3]{color:var(--assistant-primary, var(--el-color-primary, #409eff))}.panel-header__actions[data-v-1c632eb3]{display:flex;align-items:center;gap:2px}.panel-header__btn[data-v-1c632eb3]{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;background:transparent;border-radius:6px;color:#999;cursor:pointer;transition:all .15s}.panel-header__btn[data-v-1c632eb3]:hover{background:#f5f5f5;color:#666}.panel-messages[data-v-1c632eb3]{flex:1;overflow-y:auto;padding:16px 0;scroll-behavior:smooth;scrollbar-width:thin;scrollbar-color:transparent transparent}.panel-messages[data-v-1c632eb3]:hover{scrollbar-color:rgba(0,0,0,.12) transparent}.panel-messages[data-v-1c632eb3]::-webkit-scrollbar{width:5px}.panel-messages[data-v-1c632eb3]::-webkit-scrollbar-track{background:transparent}.panel-messages[data-v-1c632eb3]::-webkit-scrollbar-thumb{background:transparent;border-radius:3px}.panel-messages[data-v-1c632eb3]:hover::-webkit-scrollbar-thumb{background:#0000001f}.panel-footer[data-v-1c632eb3]{padding:10px 14px 12px;border-top:1px solid var(--assistant-panel-border, #f0f0f0);flex-shrink:0}.panel-input-wrap[data-v-1c632eb3]{display:flex;align-items:flex-end;gap:8px;background:#f7f7f8;border-radius:12px;padding:8px 8px 8px 14px;transition:box-shadow .2s}.panel-input-wrap[data-v-1c632eb3]:focus-within{box-shadow:0 0 0 2px var(--assistant-primary-muted, #c6e2ff)}.panel-input[data-v-1c632eb3]{flex:1;border:none;background:transparent;outline:none;resize:none;font-size:13.5px;line-height:1.55;min-height:22px;max-height:120px;overflow-y:auto;color:#1a1a1a;font-family:inherit;scrollbar-width:none}.panel-input[data-v-1c632eb3]::-webkit-scrollbar{display:none}.panel-input[data-v-1c632eb3]::placeholder{color:#bbb}.panel-input[data-v-1c632eb3]:disabled{opacity:.45}.panel-send-btn[data-v-1c632eb3]{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;border-radius:8px;background:var(--assistant-primary, var(--el-color-primary, #409eff));color:#fff;cursor:pointer;flex-shrink:0;transition:all .15s}.panel-send-btn[data-v-1c632eb3]:hover:not(:disabled){opacity:.85}.panel-send-btn[data-v-1c632eb3]:disabled{opacity:.35;cursor:not-allowed}.panel-slide-enter-active[data-v-1c632eb3]{animation:panel-in-1c632eb3 .3s cubic-bezier(.16,1,.3,1)}.panel-slide-leave-active[data-v-1c632eb3]{animation:panel-in-1c632eb3 .2s cubic-bezier(.4,0,1,1) reverse}@keyframes panel-in-1c632eb3{0%{opacity:0;transform:translateY(16px) scale(.97)}to{opacity:1;transform:translateY(0) scale(1)}}.assistant-trigger[data-v-bcdc94dc]{position:fixed;right:var(--assistant-right, 24px);bottom:var(--assistant-trigger-bottom, 24px);z-index:var(--assistant-trigger-z-index, 2000);display:flex;align-items:center;justify-content:center;width:48px;height:48px;border:none;border-radius:50%;background:var(--assistant-trigger-bg, var(--assistant-primary, #409eff));color:#fff;cursor:pointer;box-shadow:0 4px 14px #00000026;transition:all .25s cubic-bezier(.4,0,.2,1);-webkit-user-select:none;user-select:none}.assistant-trigger[data-v-bcdc94dc]:hover{transform:scale(1.08);box-shadow:0 6px 20px #0003}.assistant-trigger[data-v-bcdc94dc]:active{transform:scale(.95)}.assistant-trigger.is-active[data-v-bcdc94dc]{background:var(--assistant-trigger-active-bg, #e0e0e0);color:var(--assistant-trigger-active-color, #666)}
@@ -0,0 +1,34 @@
1
+ import type { PanelView, ChatMessage, SessionItem } from "../types/assistant";
2
+ import type { AssistantLocale } from "../types/plugin";
3
+ type __VLS_Props = {
4
+ messages: ChatMessage[];
5
+ loading: boolean;
6
+ visible: boolean;
7
+ panelView: PanelView;
8
+ sessions: SessionItem[];
9
+ sessionsLoading: boolean;
10
+ currentSessionId?: string;
11
+ locale: AssistantLocale;
12
+ };
13
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
14
+ approve: () => any;
15
+ reject: () => any;
16
+ close: () => any;
17
+ send: (text: string) => any;
18
+ newConversation: () => any;
19
+ openHistory: () => any;
20
+ closeHistory: () => any;
21
+ selectSession: (session: SessionItem) => any;
22
+ deleteSession: (sessionId: string) => any;
23
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
24
+ onApprove?: () => any;
25
+ onReject?: () => any;
26
+ onClose?: () => any;
27
+ onSend?: (text: string) => any;
28
+ onNewConversation?: () => any;
29
+ onOpenHistory?: () => any;
30
+ onCloseHistory?: () => any;
31
+ onSelectSession?: (session: SessionItem) => any;
32
+ onDeleteSession?: (sessionId: string) => any;
33
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
34
+ export default _default;
@@ -0,0 +1,9 @@
1
+ type __VLS_Props = {
2
+ visible: boolean;
3
+ };
4
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
5
+ toggle: () => any;
6
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
7
+ onToggle?: () => any;
8
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,18 @@
1
+ import type { AssistantLocale } from "../types/plugin";
2
+ import type { SessionItem } from "../types/assistant";
3
+ type __VLS_Props = {
4
+ sessions: SessionItem[];
5
+ loading: boolean;
6
+ currentSessionId?: string;
7
+ locale: AssistantLocale;
8
+ };
9
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
10
+ delete: (sessionId: string) => any;
11
+ select: (session: SessionItem) => any;
12
+ back: () => any;
13
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
14
+ onDelete?: (sessionId: string) => any;
15
+ onSelect?: (session: SessionItem) => any;
16
+ onBack?: () => any;
17
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import type { ChatMessage } from "../types/assistant";
2
+ import type { AssistantLocale } from "../types/plugin";
3
+ type __VLS_Props = {
4
+ message: ChatMessage;
5
+ locale: AssistantLocale;
6
+ };
7
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
8
+ approve: () => any;
9
+ reject: () => any;
10
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
11
+ onApprove?: () => any;
12
+ onReject?: () => any;
13
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
14
+ export default _default;
@@ -0,0 +1,26 @@
1
+ import type { Ref } from "vue";
2
+ import type { ChatMessage, PanelView, SessionItem } from "../types/assistant";
3
+ import type { ResolvedAssistantPluginOptions } from "../types/plugin";
4
+ export interface AssistantController {
5
+ messages: ChatMessage[];
6
+ loading: Ref<boolean>;
7
+ sessionId: Ref<string | undefined>;
8
+ panelVisible: Ref<boolean>;
9
+ pendingTaskId: Ref<number | undefined>;
10
+ panelView: Ref<PanelView>;
11
+ sessions: SessionItem[];
12
+ sessionsLoading: Ref<boolean>;
13
+ send: (text: string) => Promise<void>;
14
+ submitApproval: (action: "APPROVE" | "REJECT") => Promise<void>;
15
+ recoverPendingTask: (taskId: number) => Promise<void>;
16
+ newConversation: () => void;
17
+ reset: () => void;
18
+ togglePanel: () => void;
19
+ openPanel: () => void;
20
+ closePanel: () => void;
21
+ openHistory: () => Promise<void>;
22
+ closeHistory: () => void;
23
+ selectSession: (item: SessionItem) => Promise<void>;
24
+ deleteSession: (sessionId: string) => Promise<void>;
25
+ }
26
+ export declare function createAssistantController(options: ResolvedAssistantPluginOptions): AssistantController;
@@ -0,0 +1,2 @@
1
+ import type { App, Component } from "vue";
2
+ export declare function mountAssistantHost(app: App, component: Component): void;
@@ -0,0 +1,10 @@
1
+ import type { InjectionKey } from "vue";
2
+ import type { AssistantController } from "../composables/useAssistantChat";
3
+ import type { AssistantPluginOptions, ResolvedAssistantPluginOptions } from "../types/plugin";
4
+ export declare const ASSISTANT_PAGE_REFRESH_KEY: unique symbol;
5
+ export declare const assistantOptionsKey: InjectionKey<ResolvedAssistantPluginOptions>;
6
+ export declare const assistantControllerKey: InjectionKey<AssistantController>;
7
+ export declare function resolveAssistantOptions(options: AssistantPluginOptions): ResolvedAssistantPluginOptions;
8
+ export declare function buildAssistantCssVars(options: ResolvedAssistantPluginOptions): Record<string, string>;
9
+ export declare function useAssistantOptions(): ResolvedAssistantPluginOptions;
10
+ export declare function useAssistantController(): AssistantController;
@@ -0,0 +1,7 @@
1
+ import type { Plugin } from "vue";
2
+ import { type AssistantController } from "../composables/useAssistantChat";
3
+ import type { AssistantPluginOptions } from "../types/plugin";
4
+ export type AssistantPluginInstance = Plugin & {
5
+ controller: AssistantController;
6
+ };
7
+ export declare function createAssistant(options: AssistantPluginOptions): AssistantPluginInstance;
@@ -0,0 +1,9 @@
1
+ import "./style/index.css";
2
+ export { createAssistant } from "./core/plugin";
3
+ export { ASSISTANT_PAGE_REFRESH_KEY, useAssistantController, useAssistantOptions, } from "./core/context";
4
+ export { defaultTransport } from "./transport/defaultTransport";
5
+ export { default as AssistantWidget } from "./components/AssistantWidget.vue";
6
+ export type { AssistantController } from "./composables/useAssistantChat";
7
+ export type * from "./types/assistant";
8
+ export type * from "./types/plugin";
9
+ export type * from "./types/transport";
@@ -0,0 +1,2 @@
1
+ import type { AssistantTransport } from "../types/transport";
2
+ export declare const defaultTransport: AssistantTransport;
@@ -0,0 +1,2 @@
1
+ import type { StreamCallbacks } from "../types/assistant";
2
+ export declare function parseSSEStream(response: Response, callbacks: StreamCallbacks): Promise<void>;
@@ -0,0 +1,121 @@
1
+ export type AssistantId = string | number;
2
+ export interface AssistantOperator {
3
+ id: AssistantId;
4
+ name?: string;
5
+ }
6
+ export interface ApprovalAction {
7
+ taskId: number;
8
+ action: "APPROVE" | "REJECT";
9
+ approvalToken?: string;
10
+ idempotencyKey?: string;
11
+ }
12
+ export interface AssistantChatRequest {
13
+ sessionId?: string;
14
+ message?: string;
15
+ approval?: ApprovalAction;
16
+ }
17
+ export interface AssistantChatResponse {
18
+ code: number;
19
+ message: string;
20
+ data: AssistantChatData;
21
+ }
22
+ export interface AssistantChatData {
23
+ sessionId: string;
24
+ type: AssistantResponseType;
25
+ message: string;
26
+ taskId?: number;
27
+ pendingApprovals?: PendingApproval[];
28
+ steps?: AgentStep[];
29
+ usage?: UsageInfo;
30
+ }
31
+ export type AssistantResponseType = "REPLY" | "APPROVAL_REQUIRED" | "CONFIRMED" | "REJECTED" | "ERROR";
32
+ export interface PendingApproval {
33
+ toolCallId: string;
34
+ toolName: string;
35
+ toolArguments: string;
36
+ riskLevel: "READ" | "WRITE";
37
+ }
38
+ export interface AgentStep {
39
+ stepIndex: number;
40
+ toolName: string;
41
+ riskLevel: string;
42
+ executed: boolean;
43
+ resultSummary?: string;
44
+ durationMs?: number;
45
+ success?: boolean;
46
+ errorMessage?: string;
47
+ }
48
+ export interface UsageInfo {
49
+ promptTokens: number;
50
+ completionTokens: number;
51
+ totalTokens: number;
52
+ model: string;
53
+ }
54
+ export interface StepEvent {
55
+ tool: string;
56
+ status: "executing" | "completed";
57
+ success?: boolean;
58
+ }
59
+ export interface ApprovalRequiredEvent {
60
+ taskId: number;
61
+ pendingApprovals: PendingApproval[];
62
+ }
63
+ export type MessageSegment = {
64
+ type: "text";
65
+ content: string;
66
+ } | {
67
+ type: "step";
68
+ step: StepEvent;
69
+ };
70
+ export interface ChatMessage {
71
+ id: string;
72
+ role: "user" | "assistant";
73
+ content: string;
74
+ thinkingContent?: string;
75
+ streaming?: boolean;
76
+ segments?: MessageSegment[];
77
+ approval?: ApprovalRequiredEvent;
78
+ approvalHandled?: boolean;
79
+ isError?: boolean;
80
+ timestamp: number;
81
+ }
82
+ export interface SessionItem {
83
+ sessionId: string;
84
+ title: string;
85
+ status: string;
86
+ lastMessageAt: string;
87
+ createTime: string;
88
+ }
89
+ export interface SessionListResponse {
90
+ code: number;
91
+ data: SessionItem[];
92
+ }
93
+ export interface HistoryMessage {
94
+ role: "user" | "assistant";
95
+ content: string;
96
+ createTime: string;
97
+ }
98
+ export interface SessionMessagesResponse {
99
+ code: number;
100
+ data: HistoryMessage[];
101
+ }
102
+ export interface TaskStatusResponse {
103
+ code: number;
104
+ data: TaskStatus;
105
+ }
106
+ export interface TaskStatus {
107
+ taskId: number;
108
+ status: TaskStatusEnum;
109
+ errorMessage?: string;
110
+ }
111
+ export type TaskStatusEnum = "RUNNING" | "WAITING_APPROVAL" | "COMPLETED" | "CANCELLED" | "FAILED" | "MAX_STEPS_EXCEEDED";
112
+ export interface StreamCallbacks {
113
+ onMessage: (text: string) => void;
114
+ onThinking?: (text: string) => void;
115
+ onStep: (step: StepEvent) => void;
116
+ onApprovalRequired: (event: ApprovalRequiredEvent) => void;
117
+ onSessionId?: (id: string) => void;
118
+ onDone: () => void;
119
+ onError: (msg: string) => void;
120
+ }
121
+ export type PanelView = "chat" | "history";
@@ -0,0 +1,112 @@
1
+ import type { AssistantOperator } from "./assistant";
2
+ import type { AssistantTransport } from "./transport";
3
+ export type MaybePromise<T> = T | Promise<T>;
4
+ export interface AssistantLocale {
5
+ title: string;
6
+ welcomeMessage: string;
7
+ inputPlaceholder: string;
8
+ newConversationLabel: string;
9
+ historyLabel: string;
10
+ closeLabel: string;
11
+ historyTitle: string;
12
+ historyLoading: string;
13
+ historyEmpty: string;
14
+ unnamedSession: string;
15
+ currentSession: string;
16
+ deleteSessionLabel: string;
17
+ thinkingLabel: string;
18
+ thinkingExpandLabel: string;
19
+ thinkingCollapseLabel: string;
20
+ stepCompletedLabel: string;
21
+ stepFailedLabel: string;
22
+ stepExecutingLabel: string;
23
+ approvalHeader: string;
24
+ approveLabel: string;
25
+ rejectLabel: string;
26
+ approvalHandledLabel: string;
27
+ networkError: string;
28
+ approvalApprovedMessage: string;
29
+ approvalRejectedMessage: string;
30
+ pendingApprovalRecovery: string;
31
+ switchedHistorySession: string;
32
+ historyLoadFailedContinue: string;
33
+ dateLocale: string;
34
+ }
35
+ export interface AssistantTheme {
36
+ primary: string;
37
+ primarySoft: string;
38
+ primaryMuted: string;
39
+ panelBackground: string;
40
+ panelBorderColor: string;
41
+ panelShadow: string;
42
+ assistantBubbleBackground: string;
43
+ assistantBubbleTextColor: string;
44
+ userBubbleBackground: string;
45
+ userBubbleTextColor: string;
46
+ triggerBackground: string;
47
+ triggerActiveBackground: string;
48
+ triggerActiveColor: string;
49
+ }
50
+ export interface AssistantWidgetOptions {
51
+ right: string;
52
+ triggerBottom: string;
53
+ panelBottom: string;
54
+ panelWidth: string;
55
+ panelHeight: string;
56
+ panelMinHeight: string;
57
+ panelMaxHeight: string;
58
+ zIndex: number;
59
+ }
60
+ export interface AssistantSecurityOptions {
61
+ sanitizeHtml: boolean;
62
+ allowedLinkProtocols: string[];
63
+ allowedImageProtocols: string[];
64
+ maskKeys: string[];
65
+ warnOnInsecureBaseURL: boolean;
66
+ }
67
+ export interface AssistantBusinessEvent {
68
+ type: "panel-visibility-changed" | "message-sent" | "approval-submitted" | "conversation-reset" | "history-opened" | "history-closed" | "session-selected" | "session-deleted";
69
+ payload?: unknown;
70
+ }
71
+ export interface AssistantSecurityEvent {
72
+ type: "invalid-base-url" | "insecure-base-url" | "unsafe-link-removed" | "unsafe-image-removed" | "html-sanitized" | "transport-error";
73
+ detail?: unknown;
74
+ }
75
+ export interface AssistantEventHooks {
76
+ onBusinessEvent?: (event: AssistantBusinessEvent) => void;
77
+ onSecurityEvent?: (event: AssistantSecurityEvent) => void;
78
+ }
79
+ export interface AssistantPluginOptions {
80
+ mount?: "auto" | "manual";
81
+ baseURL?: string;
82
+ accessKey?: string;
83
+ requestTimeoutMs?: number;
84
+ componentName?: string;
85
+ initialVisible?: boolean;
86
+ getOperator: () => MaybePromise<AssistantOperator>;
87
+ getAuthToken?: () => MaybePromise<string | undefined | null>;
88
+ getAuthHeaders?: () => MaybePromise<Record<string, string> | undefined>;
89
+ transport?: AssistantTransport;
90
+ locale?: Partial<AssistantLocale>;
91
+ theme?: Partial<AssistantTheme>;
92
+ widget?: Partial<AssistantWidgetOptions>;
93
+ security?: Partial<AssistantSecurityOptions>;
94
+ events?: AssistantEventHooks;
95
+ }
96
+ export interface ResolvedAssistantPluginOptions {
97
+ mount: "auto" | "manual";
98
+ baseURL: string;
99
+ accessKey?: string;
100
+ requestTimeoutMs: number;
101
+ componentName: string;
102
+ initialVisible: boolean;
103
+ getOperator: () => MaybePromise<AssistantOperator>;
104
+ getAuthToken?: () => MaybePromise<string | undefined | null>;
105
+ getAuthHeaders?: () => MaybePromise<Record<string, string> | undefined>;
106
+ transport: AssistantTransport;
107
+ locale: AssistantLocale;
108
+ theme: AssistantTheme;
109
+ widget: AssistantWidgetOptions;
110
+ security: AssistantSecurityOptions;
111
+ events: AssistantEventHooks;
112
+ }
@@ -0,0 +1,21 @@
1
+ import type { AssistantChatRequest, AssistantOperator, SessionListResponse, SessionMessagesResponse, StreamCallbacks, TaskStatusResponse } from "./assistant";
2
+ import type { AssistantEventHooks, AssistantSecurityOptions } from "./plugin";
3
+ export interface AssistantRequestContext {
4
+ baseURL: string;
5
+ accessKey?: string;
6
+ requestTimeoutMs: number;
7
+ operator: AssistantOperator;
8
+ authToken?: string;
9
+ authHeaders?: Record<string, string>;
10
+ security: AssistantSecurityOptions;
11
+ events: AssistantEventHooks;
12
+ }
13
+ export interface AssistantTransport {
14
+ streamChat(request: AssistantChatRequest, callbacks: StreamCallbacks, context: AssistantRequestContext): Promise<void>;
15
+ getTaskStatus(taskId: number, context: AssistantRequestContext): Promise<TaskStatusResponse>;
16
+ getSessions(context: AssistantRequestContext): Promise<SessionListResponse>;
17
+ getSessionMessages(sessionId: string, context: AssistantRequestContext): Promise<SessionMessagesResponse>;
18
+ deleteSession(sessionId: string, context: AssistantRequestContext): Promise<{
19
+ code: number;
20
+ }>;
21
+ }
@@ -0,0 +1 @@
1
+ export declare function formatLocale(template: string, params: Record<string, string | number | undefined>): string;
@@ -0,0 +1,2 @@
1
+ import type { AssistantEventHooks, AssistantSecurityOptions } from "../types/plugin";
2
+ export declare function renderAssistantMarkdown(text: string, security: AssistantSecurityOptions, hooks: AssistantEventHooks): string;
@@ -0,0 +1,8 @@
1
+ import type { AssistantEventHooks, AssistantSecurityEvent, AssistantSecurityOptions } from "../types/plugin";
2
+ export declare function emitSecurityEvent(hooks: AssistantEventHooks, event: AssistantSecurityEvent): void;
3
+ export declare function normalizeBaseURL(baseURL: string | undefined, security: AssistantSecurityOptions, hooks: AssistantEventHooks): string;
4
+ export declare function buildAssistantUrl(baseURL: string, path: string): string;
5
+ export declare function sanitizeHeaders(headers: Record<string, string | undefined>): Record<string, string>;
6
+ export declare function isAllowedUrlProtocol(target: string, allowedProtocols: string[]): boolean;
7
+ export declare function redactSensitivePayload(value: unknown, maskKeys: string[]): unknown;
8
+ export declare function extractErrorMessage(error: unknown, fallback: string): string;
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@hotmail007/vue-admin-ai-assistant",
3
+ "version": "0.1.0-beta.1",
4
+ "description": "A secure, pluggable Vue 3 admin assistant widget with auto-mount and manual-mount integration modes.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "vue",
9
+ "vue3",
10
+ "admin",
11
+ "assistant",
12
+ "chat",
13
+ "widget"
14
+ ],
15
+ "sideEffects": [
16
+ "*.css"
17
+ ],
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "main": "./dist/index.cjs",
22
+ "module": "./dist/index.js",
23
+ "types": "./dist/types/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/types/index.d.ts",
27
+ "import": "./dist/index.js",
28
+ "require": "./dist/index.cjs"
29
+ },
30
+ "./style.css": "./dist/style.css"
31
+ },
32
+ "scripts": {
33
+ "build": "vite build && vue-tsc -p tsconfig.json",
34
+ "type-check": "vue-tsc -p tsconfig.json --noEmit",
35
+ "lint": "eslint \"src/**/*.{ts,vue}\"",
36
+ "lint:fix": "eslint \"src/**/*.{ts,vue}\" --fix",
37
+ "format": "prettier --write \"src/**/*.{ts,vue,css,md,json}\"",
38
+ "pack:dry-run": "npm pack --dry-run",
39
+ "pack:local": "npm pack",
40
+ "prepack": "pnpm run build",
41
+ "prepublishOnly": "pnpm run lint && pnpm run type-check"
42
+ },
43
+ "publishConfig": {
44
+ "registry": "https://registry.npmjs.org/",
45
+ "access": "public"
46
+ },
47
+ "engines": {
48
+ "node": ">=18.0.0"
49
+ },
50
+ "peerDependencies": {
51
+ "vue": "^3.4.0"
52
+ },
53
+ "dependencies": {
54
+ "dompurify": "^3.2.5",
55
+ "markdown-it": "^14.1.1"
56
+ },
57
+ "devDependencies": {
58
+ "@vitejs/plugin-vue": "^5.0.5",
59
+ "sass": "^1.77.6",
60
+ "typescript": "^5.4.5",
61
+ "vite": "^5.4.21",
62
+ "vue-tsc": "^2.0.21"
63
+ }
64
+ }