@duxi999/usdp-eacp-conversation 0.0.0-stage → 0.0.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/README.md CHANGED
@@ -1,3 +1,180 @@
1
- # Temporary Holding Version
1
+ ---
2
+ AIGC:
3
+ ContentProducer: '001191110102MAD55U9H0F10002'
4
+ ContentPropagator: '001191110102MAD55U9H0F10002'
5
+ Label: '1'
6
+ ProduceID: '5aa6a920-96ea-48c9-8bec-0c843c9f4f62'
7
+ PropagateID: '5aa6a920-96ea-48c9-8bec-0c843c9f4f62'
8
+ ReservedCode1: 'f337fd8e-d741-4f30-9c11-2234bdc62525'
9
+ ReservedCode2: 'f337fd8e-d741-4f30-9c11-2234bdc62525'
10
+ ---
2
11
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
12
+ # @duxi999/usdp-eacp-conversation
13
+
14
+ 政务信息化智能对话会话组件库。承载单个智能体会话的完整生命周期:环境启动/停止/重启/重建、iframe 加载监控、轮询与心跳保活。
15
+
16
+ ## 特性
17
+
18
+ - 基于 Vue 3 + TypeScript + Element Plus
19
+ - **组件自包含**:HTTP 请求对象(axios 封装)由宿主通过 `request` prop 注入,组件内部直接调用请求地址,不依赖任何宿主业务模块(store / api / utils)
20
+ - 状态机完备:`not_exist` / `starting` / `running` / `start_failed` / `stopped` / `stopping`
21
+ - iframe 加载监控:域名可达性探测(HEAD /test)、加载超时兜底、自动重试(最多 30 次)
22
+ - 轮询(2s × 30 次)与心跳(5 分钟)保活
23
+ - 环境数量超限弹窗(内置于 `ConversationSession`)自动拉取运行中环境并支持批量关闭后重试
24
+
25
+ ## 安装
26
+
27
+ ```bash
28
+ npm install @duxi999/usdp-eacp-conversation
29
+ ```
30
+
31
+ 需要 peer 依赖:
32
+
33
+ ```bash
34
+ npm install vue element-plus @element-plus/icons-vue
35
+ ```
36
+
37
+ ## 快速开始
38
+
39
+ `ConversationSession` 通过 `request` prop 接收一个由宿主应用提供的 HTTP 请求适配器(满足 `RequestAdapter` 接口,通常为 axios 封装)。
40
+
41
+ ### request 适配器
42
+
43
+ 宿主需提供一个满足 `RequestAdapter` 接口的对象(`get` / `post` / `put` / `delete`),约定返回**解包后的业务数据**(`Promise<T>`):
44
+
45
+ ```ts
46
+ import axios from 'axios'
47
+ import type { AxiosResponse } from 'axios'
48
+ import type { RequestAdapter } from '@duxi999/usdp-eacp-conversation'
49
+
50
+ const http = axios.create({ baseURL: '/api', timeout: 30000 })
51
+
52
+ // 响应拦截器:解包 { code, message, data } 为 data
53
+ http.interceptors.response.use(
54
+ (response: AxiosResponse<{ code: number; message: string; data: any }>) => {
55
+ const res = response.data
56
+ if (res.code === 200) return res.data
57
+ const error = new Error(res.message || '请求失败') as Error & { code: number }
58
+ error.code = res.code
59
+ return Promise.reject(error)
60
+ },
61
+ (error) => Promise.reject(error)
62
+ )
63
+
64
+ const request: RequestAdapter = {
65
+ get: (url, params) => http.get(url, { params }),
66
+ post: (url, data) => http.post(url, data),
67
+ put: (url, data) => http.put(url, data),
68
+ delete: (url, params) => http.delete(url, { params }),
69
+ }
70
+ ```
71
+
72
+ > 注意:`RequestAdapter` 的 `get` 返回 `Promise<T>`(业务数据)。若直接传入原生 axios 实例,需注意其返回类型为 `Promise<AxiosResponse<T>>`,建议在封装层解包(如上拦截器)并做类型适配。
73
+
74
+ ### 模板中使用
75
+
76
+ ```vue
77
+ <template>
78
+ <ConversationSession
79
+ :request="request"
80
+ :scene-type="'workspace'"
81
+ :scene-id="'workspace-001'"
82
+ :agent-id="123"
83
+ @state-change="onStateChange"
84
+ />
85
+ </template>
86
+
87
+ <script setup lang="ts">
88
+ import type { RequestAdapter } from '@duxi999/usdp-eacp-conversation'
89
+
90
+ const request: RequestAdapter = /* 见上文 */
91
+
92
+ function onStateChange(e) {
93
+ console.log(e.status, e.nickname, e.agentId)
94
+ }
95
+ </script>
96
+ ```
97
+
98
+ ### Props
99
+
100
+ | 名称 | 类型 | 必填 | 说明 |
101
+ | --------- | ------------------ | ---- | ------------------------------------------------- |
102
+ | request | `RequestAdapter` | 是 | 由宿主注入的 HTTP 请求适配器(axios 封装) |
103
+ | sceneType | `SceneType` | 是 | 场景类型(workspace / knowledge_base / skill / personal_assistant / bid) |
104
+ | sceneId | `string` | 是 | 场景 ID |
105
+ | agentId | `string \| number` | 否 | 指定智能体 ID(workspace/knowledge_base 生效) |
106
+
107
+ ### Events
108
+
109
+ | 事件 | 载荷 | 说明 |
110
+ | ------------ | --------------------------------- | ------------------------- |
111
+ | state-change | `{ status, nickname, agentId }` | 会话状态变更(供外层标题栏渲染) |
112
+
113
+ ### Exposed 方法(通过 ref 获取)
114
+
115
+ `start` / `stop` / `restart` / `rebuild` / `refresh` / `resolveAgentId`
116
+
117
+ ## 组件内部请求地址
118
+
119
+ 组件自包含,请求地址直接在组件内部写死调用:
120
+
121
+ | 方法 | 地址 |
122
+ | ---- | ------------------------------------------------ |
123
+ | GET | `/conversation/environment-status` |
124
+ | GET | `/conversation/session-info` |
125
+ | GET | `/conversation/my-running-environments` |
126
+ | POST | `/conversation/start-environment` |
127
+ | POST | `/conversation/stop-environment` |
128
+ | POST | `/conversation/destroy-environment` |
129
+ | POST | `/conversation/batch-stop-environments` |
130
+
131
+ ## 全局注册(可选)
132
+
133
+ 组件库默认导出 Vue 插件,支持 `app.use()` 一次注册全部组件。**注册名与包名一致(`usdp-eacp-conversation`)**,模板中即可使用 `<usdp-eacp-conversation>`:
134
+
135
+ ```ts
136
+ import UsdpEacpConversation from '@duxi999/usdp-eacp-conversation'
137
+ app.use(UsdpEacpConversation)
138
+ ```
139
+
140
+ ```vue
141
+ <template>
142
+ <usdp-eacp-conversation
143
+ :request="request"
144
+ :scene-type="'workspace'"
145
+ :scene-id="'workspace-001'"
146
+ />
147
+ </template>
148
+ ```
149
+
150
+ 全局注册同时注册了两种名字,均可使用:
151
+ - `<usdp-eacp-conversation>`(kebab-case,与包名一致)
152
+ - `<UsdpEacpConversation>`(PascalCase,Vue 推荐写法)
153
+
154
+ > 组件内部 `defineOptions({ name: 'UsdpEacpConversation' })` 也已设置组件名,DevTools 中显示为 `UsdpEacpConversation`。
155
+
156
+ ## 导出内容
157
+
158
+ - 组件:`ConversationSession`
159
+ - 类型:`RequestAdapter`、`EnvironmentStatus`、`SceneType`、`EnvironmentParams`、`EnvironmentStatusResult`、`SessionInfoResult`、`RunningEnvironmentItem`、`BatchStopResult`
160
+
161
+ ## 开发
162
+
163
+ ```bash
164
+ npm install # 安装依赖
165
+ npm run dev # 启动 demo 页(http://localhost:5174)
166
+ npm run type-check # TS 类型检查
167
+ npm run build # 构建 npm 包(产出 dist/)
168
+ ```
169
+
170
+ ## 发布
171
+
172
+ ```bash
173
+ npm login
174
+ npm run build
175
+ npm publish --access public
176
+ ```
177
+
178
+ 包名:`@duxi999/usdp-eacp-conversation`。发布前请确认包名未被占用且有权限。
179
+
180
+ > AI生成
@@ -0,0 +1,68 @@
1
+ import { EnvironmentStatus, RequestAdapter } from '../types';
2
+ interface Props {
3
+ /** 应用编码 */
4
+ appCode: string;
5
+ /** 由宿主注入的 HTTP 请求适配器(axios 封装),必传 */
6
+ request: RequestAdapter;
7
+ }
8
+ /**
9
+ * 启动环境
10
+ */
11
+ declare function handleStart(): Promise<void>;
12
+ /**
13
+ * 停止环境(确认交互由外层标题栏负责)
14
+ *
15
+ * @returns 是否停止成功
16
+ */
17
+ declare function stop(): Promise<boolean>;
18
+ /**
19
+ * 解析当前会话的智能体ID(用于更新智能体等需要 appCode 的操作)
20
+ */
21
+ declare function resolveAgentId(): Promise<string | undefined>;
22
+ /**
23
+ * 手动刷新 iframe(附加随机参数强制重新加载)
24
+ */
25
+ declare function refresh(): void;
26
+ /**
27
+ * 重启会话:停止当前环境 → 重置状态 → 重新启动
28
+ */
29
+ declare function restart(): Promise<void>;
30
+ /**
31
+ * 重建会话:销毁当前容器 → 重置状态 → 创建全新环境
32
+ */
33
+ declare function rebuild(): Promise<void>;
34
+ /**
35
+ * 向 dsh 内部(iframe 沙箱)抛出一个事件。
36
+ *
37
+ * 供外层宿主(ConversationPanel 经 dsh-bridge)把提示词注入等事件投递给 dsh。
38
+ * 消息协议与 dsh 插件保持一致:{ target: 'dsh', type, payload }。
39
+ *
40
+ * @param type - 事件类型(如 prompt:inject)。
41
+ * @param payload - 事件载荷。
42
+ */
43
+ declare function postDshEvent(type: string, payload: unknown): void;
44
+ declare const _default: import('vue').DefineComponent<Props, {
45
+ start: typeof handleStart;
46
+ stop: typeof stop;
47
+ restart: typeof restart;
48
+ rebuild: typeof rebuild;
49
+ refresh: typeof refresh;
50
+ resolveAgentId: typeof resolveAgentId;
51
+ postDshEvent: typeof postDshEvent;
52
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
53
+ "state-change": (value: {
54
+ status: EnvironmentStatus;
55
+ nickname: string;
56
+ appCode: string | null;
57
+ }) => any;
58
+ }, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
59
+ "onState-change"?: ((value: {
60
+ status: EnvironmentStatus;
61
+ nickname: string;
62
+ appCode: string | null;
63
+ }) => any) | undefined;
64
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
65
+ iframeRef: HTMLIFrameElement;
66
+ envLimitTableRef: unknown;
67
+ }, HTMLDivElement>;
68
+ export default _default;
package/dist/env.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ interface ImportMetaEnv {
4
+ /** API 请求基础路径(演示用) */
5
+ readonly VITE_API_BASE?: string
6
+ }
7
+
8
+ interface ImportMeta {
9
+ readonly env: ImportMetaEnv
10
+ }
11
+
12
+ declare module '*.vue' {
13
+ import type { DefineComponent } from 'vue'
14
+ const component: DefineComponent<{}, {}, any>
15
+ export default component
16
+ }
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),ue=require("@element-plus/icons-vue"),O=require("element-plus"),Be={class:"conversation-session"},Ae={key:0,class:"status-placeholder"},Re={key:1,class:"status-placeholder"},De={key:2,class:"status-placeholder"},Me={key:3,class:"iframe-container"},$e=["src"],qe={key:4,class:"status-placeholder"},Pe={key:5,class:"status-placeholder"},Oe={class:"env-limit-dialog"},ce=30,ze=2e3,He=45,Xe=300*1e3,je=e.defineComponent({name:"UsdpXjgzConversation",__name:"UsdpEacpConversation",props:{appCode:{},request:{}},emits:["state-change"],setup(h,{expose:z,emit:D}){const i=h,H=D,X=e.computed(()=>i.appCode!==void 0&&i.appCode!==null&&i.appCode!==""?String(i.appCode):void 0),a=e.ref("not_exist"),j=e.ref(""),l=e.ref(""),r=e.ref(""),f=e.ref(""),x=e.ref(""),p=e.ref(!1),m=e.computed(()=>a.value);e.computed(()=>r.value||"智能助手");const de=e.computed(()=>x.value||X.value||null);e.watch([m,()=>r.value,de],([t,n,o])=>{H("state-change",{status:t,nickname:n,appCode:o})},{immediate:!0});const E=e.ref(!1),ve={workspace:"工作区",knowledge_base:"知识库",agent:"智能体",skill:"技能构建",personal_assistant:"个人助手",bid:"智能投标"},W=e.ref(!1),Y=e.ref(!1),F=e.ref([]),V=e.ref([]),fe=e.ref();function pe(t){if(!t)return"-";try{return new Date(t).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"})}catch{return t}}async function me(){W.value=!0,V.value=[];try{F.value=await i.request.get("/app-conversation/my-running-environments")}catch{O.ElMessage.error("获取运行中环境列表失败"),F.value=[]}finally{W.value=!1}}e.watch(E,t=>{t&&me()});function ge(t){V.value=t}async function ye(){if(V.value.length!==0){Y.value=!0;try{const t=V.value.map(o=>({appCode:o.appCode})),n=await i.request.post("/app-conversation/batch-stop-environments",{environments:t});n.allSuccess||O.ElMessage.warning(`关闭完成:成功 ${n.successCount} 个,失败 ${n.failedCount} 个`),E.value=!1,await _e()}catch{O.ElMessage.error("关闭环境失败,请重试")}finally{Y.value=!1}}}const g=e.ref(""),te=e.ref(null),y=e.ref("");let T=0,I=null,L=null,U=null,_=null,B=!1,M=null,$=0,q=null;function P(t){if(!t)return"";try{const n=new URL(t);return n.searchParams.delete("token"),n.toString()}catch{return t}}async function G(){p.value=!0;try{const t=await i.request.post("/app-conversation/start-environment",{appCode:i.appCode});return t.status!==a.value&&(a.value=t.status),t.environmentId&&t.environmentId!==f.value&&(f.value=t.environmentId),t.proxyUrl&&t.proxyUrl!==l.value&&(l.value=t.proxyUrl),t}finally{p.value=!1}}async function N(){try{const t=await i.request.get("/app-conversation/environment-status",{appCode:i.appCode},{silent:!0});t.status!==a.value&&(a.value=t.status),t.environmentId&&t.environmentId!==f.value&&(f.value=t.environmentId),t.proxyUrl&&t.proxyUrl!==l.value&&(l.value=t.proxyUrl)}catch{}}async function ne(){p.value=!0;try{await i.request.post("/app-conversation/stop-environment",{appCode:i.appCode}),a.value="stopped"}finally{p.value=!1}}async function he(){p.value=!0;try{await i.request.post("/app-conversation/destroy-environment",{appCode:i.appCode}),a.value="not_exist",l.value="",f.value=""}finally{p.value=!1}}async function C(){try{const t=await i.request.get("/app-conversation/session-info",{appCode:i.appCode},{silent:!0});return t.sessionId!==j.value&&(j.value=t.sessionId),t.proxyUrl!==l.value&&(l.value=t.proxyUrl),t.agentNickname!==r.value&&(r.value=t.agentNickname),t.environmentId!==f.value&&(f.value=t.environmentId),t.appCode&&t.appCode!==x.value&&(x.value=t.appCode),t.environmentStatus!==a.value&&(a.value=t.environmentStatus),t}catch{return}}function A(){s(),$=0,M=setInterval(async()=>{if($++,$>He){if(await N(),a.value==="running"){s(),w(),r.value||C();return}s(),a.value="start_failed";return}await N(),a.value==="running"?(s(),w(),r.value||C()):a.value==="start_failed"&&s()},ze)}function s(){M!==null&&(clearInterval(M),M=null),$=0}function w(){b(),q=setInterval(async()=>{document.visibilityState==="visible"&&await N()},Xe)}function b(){q!==null&&(clearInterval(q),q=null)}function J(){s(),b(),a.value="not_exist",j.value="",l.value="",r.value="",f.value="",x.value="",p.value=!1}e.watch([()=>a.value,()=>l.value],([t,n],[o,c])=>{if(!n||t!=="running"){g.value="",y.value="",u(),S();return}P(n)!==P(c||"")&&ie(n,o==="starting")},{immediate:!0}),e.watch(()=>a.value,(t,n)=>{if(t==="running"&&n==="starting"){const o=l.value;if(!o)return;(!g.value||P(o)===P(g.value))&&ie(o,!0)}});async function k(){if(p.value)return;const t=a.value;if(!(t==="running"||t==="starting")){if(t==="start_failed"){await N();const n=a.value;if(n==="running"){w();return}if(n==="starting"){A();return}}try{await G(),r.value||C(),a.value==="starting"?A():a.value==="running"&&w()}catch(n){if((n==null?void 0:n.code)===23010){E.value=!0;return}}}}async function _e(){await new Promise(t=>setTimeout(t,500)),await k()}async function Ce(){a.value="stopping",s(),b(),u(),S();try{return await ne(),!0}catch{return a.value="running",!1}}async function we(){let t=x.value||X.value;return t||(await C(),t=x.value||X.value),t||void 0}function xe(){const t=g.value;if(!t)return;u(),T=0;const n=t.includes("?")?"&":"?";y.value=`${t}${n}_refresh=${Date.now()}`,Q(y.value)}function Ee(){ae()}function Te(){Z("network")}function ae(){B&&(u(),T=0)}function Ne(t){try{const n=new URL(t);return n.pathname="/test",n.search="",n.hash="",n.toString()}catch{return`${t.split("?")[0].split("#")[0].replace(/\/+$/,"")}/test`}}async function be(t){try{const n=Ne(t),o=new AbortController,c=setTimeout(()=>o.abort(),5e3),d=await fetch(n,{method:"HEAD",mode:"cors",cache:"no-cache",signal:o.signal});return clearTimeout(c),d.status===200}catch{return!1}}async function K(t,n=0){if(await be(t)){oe(t);return}n<ce?I=setTimeout(()=>{K(t,n+1)},100):oe(t)}function oe(t){g.value=t,y.value=t,Q(t)}function ie(t,n){u(),S(),T=0,n?L=setTimeout(()=>{K(t),L=null},1500):K(t)}function S(){I&&(clearTimeout(I),I=null),L&&(clearTimeout(L),L=null),_&&(clearTimeout(_),_=null)}function Q(t){if(u(),!window.PerformanceObserver){re();return}B=!0;try{U=new PerformanceObserver(n=>{for(const o of n.getEntries()){const c=o;if(o.name!==t&&o.name!==y.value)continue;const d=c.responseStatus;if(d===502){Z("502");return}d>=200&&d<400&&ae()}}),U.observe({type:"resource",buffered:!0})}catch{}re()}function u(){U&&(U.disconnect(),U=null),_&&(clearTimeout(_),_=null),B=!1}function re(t){_=setTimeout(()=>{B&&Z("timeout")},15e3)}function Z(t){if(!B)return;if(u(),T++,T>ce){O.ElMessage.error("应用加载失败,请刷新页面重试");return}console.warn(`[ConversationSession] 加载失败: ${t==="network"?"网络错误":t==="timeout"?"加载超时":"应用暂不可用"}, 第 ${T} 次重试`),I=setTimeout(()=>{if(!g.value)return;const o=g.value.includes("?")?"&":"?";y.value=`${g.value}${o}_retry=${Date.now()}`,Q(y.value)},1e3)}function le(){document.visibilityState==="visible"&&m.value==="running"&&N()}e.onMounted(async()=>{document.addEventListener("visibilitychange",le),await N();const t=a.value;t==="not_exist"||t==="stopped"?k():(await C(),t==="starting"?A():t==="running"&&w())});async function ke(){const t=a.value;if(a.value="stopping",s(),b(),u(),S(),t==="running"||t==="starting")try{await ne()}catch{}J(),a.value="starting";try{await G(),C(),a.value==="starting"?A():a.value==="running"&&w()}catch{}}async function Se(){a.value="stopping",s(),b(),u(),S();try{await he()}catch{}J(),a.value="starting";try{await G(),C(),a.value==="starting"?A():a.value==="running"&&w()}catch{}}function Ve(t,n){var c;const o=(c=te.value)==null?void 0:c.contentWindow;o&&o.postMessage({target:"dsh",type:t,payload:n},"*")}return z({start:k,stop:Ce,restart:ke,rebuild:Se,refresh:xe,resolveAgentId:we,postDshEvent:Ve}),e.onUnmounted(()=>{s(),b(),document.removeEventListener("visibilitychange",le),u(),S(),J()}),(t,n)=>{const o=e.resolveComponent("el-button"),c=e.resolveComponent("el-empty"),d=e.resolveComponent("el-icon"),se=e.resolveComponent("el-result"),R=e.resolveComponent("el-table-column"),Ie=e.resolveComponent("el-table"),Le=e.resolveComponent("el-dialog"),Ue=e.resolveDirective("loading");return e.openBlock(),e.createElementBlock("div",Be,[m.value==="not_exist"?(e.openBlock(),e.createElementBlock("div",Ae,[e.createVNode(c,{description:`${r.value} 环境未启动`},{default:e.withCtx(()=>[e.createVNode(o,{type:"primary",onClick:k},{default:e.withCtx(()=>[...n[2]||(n[2]=[e.createTextVNode("启动环境",-1)])]),_:1})]),_:1},8,["description"])])):m.value==="starting"?(e.openBlock(),e.createElementBlock("div",Re,[e.createVNode(d,{class:"is-loading",size:48},{default:e.withCtx(()=>[e.createVNode(e.unref(ue.Loading))]),_:1}),e.createElementVNode("p",null,e.toDisplayString(r.value)+" 环境启动中...",1)])):m.value==="stopping"?(e.openBlock(),e.createElementBlock("div",De,[e.createVNode(d,{class:"is-loading",size:48},{default:e.withCtx(()=>[e.createVNode(e.unref(ue.Loading))]),_:1}),e.createElementVNode("p",null,"正在停止 "+e.toDisplayString(r.value)+"...",1)])):m.value==="running"?(e.openBlock(),e.createElementBlock("div",Me,[e.createElementVNode("iframe",{ref_key:"iframeRef",ref:te,src:y.value,class:"conversation-iframe",onLoad:Ee,onError:Te},null,40,$e)])):m.value==="start_failed"?(e.openBlock(),e.createElementBlock("div",qe,[e.createVNode(se,{icon:"error",title:"环境启动失败"},{extra:e.withCtx(()=>[e.createVNode(o,{type:"primary",onClick:k},{default:e.withCtx(()=>[...n[3]||(n[3]=[e.createTextVNode("重新启动",-1)])]),_:1})]),_:1})])):m.value==="stopped"?(e.openBlock(),e.createElementBlock("div",Pe,[e.createVNode(se,{icon:"info",title:"环境已停止"},{extra:e.withCtx(()=>[e.createVNode(o,{type:"primary",onClick:k},{default:e.withCtx(()=>[...n[4]||(n[4]=[e.createTextVNode("重新启动",-1)])]),_:1})]),_:1})])):e.createCommentVNode("",!0),e.createVNode(Le,{"model-value":E.value,title:"运行中环境数量已达上限",width:"720px","close-on-click-modal":!1,"onUpdate:modelValue":n[1]||(n[1]=v=>E.value=v)},{footer:e.withCtx(()=>[e.createVNode(o,{onClick:n[0]||(n[0]=v=>E.value=!1)},{default:e.withCtx(()=>[...n[6]||(n[6]=[e.createTextVNode("暂不关闭",-1)])]),_:1}),e.createVNode(o,{type:"primary",loading:Y.value,disabled:V.value.length===0,onClick:ye},{default:e.withCtx(()=>[...n[7]||(n[7]=[e.createTextVNode(" 关闭已选环境 ",-1)])]),_:1},8,["loading","disabled"])]),default:e.withCtx(()=>[e.createElementVNode("div",Oe,[n[5]||(n[5]=e.createElementVNode("p",{class:"env-limit-dialog__tip"}," 您的运行中智能会话数量已达上限,请选择需要关闭的会话后重试。 ",-1)),e.withDirectives((e.openBlock(),e.createBlock(Ie,{ref_key:"envLimitTableRef",ref:fe,data:F.value,"max-height":"520","header-cell-style":{textAlign:"center"},onSelectionChange:ge},{default:e.withCtx(()=>[e.createVNode(R,{type:"selection",width:"42"}),e.createVNode(R,{label:"场景类型","min-width":"100"},{default:e.withCtx(({row:v})=>[e.createTextVNode(e.toDisplayString(ve[v.sceneType]||v.sceneType),1)]),_:1}),e.createVNode(R,{prop:"sceneName",label:"场景名称","min-width":"150","show-overflow-tooltip":""}),e.createVNode(R,{label:"智能体","min-width":"130","show-overflow-tooltip":""},{default:e.withCtx(({row:v})=>[e.createTextVNode(e.toDisplayString(v.agentNickname||"-"),1)]),_:1}),e.createVNode(R,{label:"创建时间","min-width":"170"},{default:e.withCtx(({row:v})=>[e.createTextVNode(e.toDisplayString(pe(v.createdAt)),1)]),_:1})]),_:1},8,["data"])),[[Ue,W.value]])])]),_:1},8,["model-value"])])}}}),We=(h,z)=>{const D=h.__vccOpts||h;for(const[i,H]of z)D[i]=H;return D},ee=We(je,[["__scopeId","data-v-e1586830"]]),Ye="usdp-eacp-conversation",Fe={install(h){h.component(Ye,ee),h.component("UsdpEacpConversation",ee)}};exports.ConversationSession=ee;exports.default=Fe;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/components/UsdpEacpConversation.vue","../src/index.ts"],"sourcesContent":["<template>\r\n <div class=\"conversation-session\">\r\n <!-- not_exist 状态:启动提示 -->\r\n <div v-if=\"status === 'not_exist'\" class=\"status-placeholder\">\r\n <el-empty :description=\"`${agentNickname} 环境未启动`\">\r\n <el-button type=\"primary\" @click=\"handleStart\">启动环境</el-button>\r\n </el-empty>\r\n </div>\r\n\r\n <!-- starting 状态:加载动画 -->\r\n <div v-else-if=\"status === 'starting'\" class=\"status-placeholder\">\r\n <el-icon class=\"is-loading\" :size=\"48\"><Loading /></el-icon>\r\n <p>{{ agentNickname }} 环境启动中...</p>\r\n </div>\r\n\r\n <!-- stopping 状态:停止中动画 -->\r\n <div v-else-if=\"status === 'stopping'\" class=\"status-placeholder\">\r\n <el-icon class=\"is-loading\" :size=\"48\"><Loading /></el-icon>\r\n <p>正在停止 {{ agentNickname }}...</p>\r\n </div>\r\n\r\n <!-- running 状态:iframe -->\r\n <div v-else-if=\"status === 'running'\" class=\"iframe-container\">\r\n <iframe\r\n ref=\"iframeRef\"\r\n :src=\"displayedIframeSrc\"\r\n class=\"conversation-iframe\"\r\n @load=\"onIframeLoad\"\r\n @error=\"onIframeError\"\r\n />\r\n </div>\r\n\r\n <!-- start_failed 状态:错误提示 -->\r\n <div v-else-if=\"status === 'start_failed'\" class=\"status-placeholder\">\r\n <el-result icon=\"error\" title=\"环境启动失败\">\r\n <template #extra>\r\n <el-button type=\"primary\" @click=\"handleStart\">重新启动</el-button>\r\n </template>\r\n </el-result>\r\n </div>\r\n\r\n <!-- stopped 状态:已停止 -->\r\n <div v-else-if=\"status === 'stopped'\" class=\"status-placeholder\">\r\n <el-result icon=\"info\" title=\"环境已停止\">\r\n <template #extra>\r\n <el-button type=\"primary\" @click=\"handleStart\">重新启动</el-button>\r\n </template>\r\n </el-result>\r\n </div>\r\n\r\n <!-- 环境数量超限弹窗 -->\r\n <el-dialog\r\n :model-value=\"envLimitDialogVisible\"\r\n title=\"运行中环境数量已达上限\"\r\n width=\"720px\"\r\n :close-on-click-modal=\"false\"\r\n @update:model-value=\"envLimitDialogVisible = $event\"\r\n >\r\n <div class=\"env-limit-dialog\">\r\n <p class=\"env-limit-dialog__tip\">\r\n 您的运行中智能会话数量已达上限,请选择需要关闭的会话后重试。\r\n </p>\r\n\r\n <el-table\r\n ref=\"envLimitTableRef\"\r\n :data=\"runningEnvironments\"\r\n v-loading=\"envLimitLoading\"\r\n max-height=\"520\"\r\n :header-cell-style=\"{ textAlign: 'center' }\"\r\n @selection-change=\"handleEnvSelectionChange\"\r\n >\r\n <el-table-column type=\"selection\" width=\"42\" />\r\n <el-table-column label=\"场景类型\" min-width=\"100\">\r\n <template #default=\"{ row }\">\r\n {{ SCENE_TYPE_LABELS[row.sceneType] || row.sceneType }}\r\n </template>\r\n </el-table-column>\r\n <el-table-column prop=\"sceneName\" label=\"场景名称\" min-width=\"150\" show-overflow-tooltip />\r\n <el-table-column label=\"智能体\" min-width=\"130\" show-overflow-tooltip>\r\n <template #default=\"{ row }\">\r\n {{ row.agentNickname || '-' }}\r\n </template>\r\n </el-table-column>\r\n <el-table-column label=\"创建时间\" min-width=\"170\">\r\n <template #default=\"{ row }\">\r\n {{ formatTime(row.createdAt) }}\r\n </template>\r\n </el-table-column>\r\n </el-table>\r\n </div>\r\n\r\n <template #footer>\r\n <el-button @click=\"envLimitDialogVisible = false\">暂不关闭</el-button>\r\n <el-button\r\n type=\"primary\"\r\n :loading=\"envLimitClosing\"\r\n :disabled=\"selectedEnvItems.length === 0\"\r\n @click=\"handleCloseEnvironments\"\r\n >\r\n 关闭已选环境\r\n </el-button>\r\n </template>\r\n </el-dialog>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n/**\r\n * 单个智能对话会话组件\r\n *\r\n * 承载一个智能体会话的完整生命周期(环境查询/启动/停止/重启/重建、iframe 加载监控、\r\n * 轮询与心跳保活)。组件完全自包含:\r\n *\r\n * 组件名与包名一致(usdp-xjgz-conversation),模板中可使用:\r\n * - <usdp-xjgz-conversation>\r\n * - <UsdpXjgzConversation>\r\n */\r\n\r\ndefineOptions({ name: 'UsdpXjgzConversation' })\r\n\r\n/**\r\n * 由宿主注入 RequestAdapter(axios 封装),通过 props 传入;\r\n * 组件内部直接调用具体请求地址,不依赖任何外部 store / api / utils 模块;\r\n * 每个组件实例拥有独立的状态和定时器,避免多会话状态覆盖。\r\n */\r\n\r\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue'\r\nimport { Loading } from '@element-plus/icons-vue'\r\nimport { ElMessage } from 'element-plus'\r\nimport type {\r\n BatchStopResult,\r\n EnvironmentStatus,\r\n EnvironmentStatusResult,\r\n RequestAdapter,\r\n RunningEnvironmentItem,\r\n SessionInfoResult,\r\n} from '../types'\r\n\r\n// ==================== Props ====================\r\n\r\ninterface Props {\r\n /** 应用编码 */\r\n appCode: string\r\n /** 由宿主注入的 HTTP 请求适配器(axios 封装),必传 */\r\n request: RequestAdapter\r\n}\r\n\r\nconst props = defineProps<Props>()\r\n\r\n/** 会话状态变更事件(供外层堆叠面板渲染标题栏) */\r\nconst emit = defineEmits<{\r\n (e: 'state-change', value: { status: EnvironmentStatus; nickname: string; appCode: string | null }): void\r\n}>()\r\n\r\n/** 转换为字符串的智能体ID(用于接口调用) */\r\nconst effectiveAgentId = computed<string | undefined>(() =>\r\n props.appCode !== undefined && props.appCode !== null && props.appCode !== ''\r\n ? String(props.appCode)\r\n : undefined\r\n)\r\n\r\n// ==================== 状态(每组件实例独立) ====================\r\n\r\nconst environmentStatus = ref<EnvironmentStatus>('not_exist')\r\nconst sessionId = ref<string>('')\r\nconst proxyUrl = ref<string>('')\r\nconst agentNickname = ref<string>('')\r\nconst environmentId = ref<string>('')\r\nconst appCode = ref<string>('')\r\nconst loading = ref<boolean>(false)\r\n\r\n// ==================== 计算属性 ====================\r\n\r\n/** 当前环境状态 */\r\nconst status = computed(() => environmentStatus.value)\r\n\r\n/** 智能体昵称(用于状态提示文案) */\r\nconst displayNickname = computed(() => agentNickname.value || '智能助手')\r\n\r\n/** 当前智能体 ID(用于详情弹窗与更新智能体) */\r\nconst currentAgentId = computed<string | null>(() => {\r\n const resolved: string | undefined = appCode.value || effectiveAgentId.value\r\n return resolved || null\r\n})\r\n\r\n/** 同步会话状态到外层堆叠面板 */\r\nwatch(\r\n [status, () => agentNickname.value, currentAgentId],\r\n ([st, nickname, agentIdVal]) => {\r\n emit('state-change', {\r\n status: st,\r\n nickname: nickname,\r\n appCode: agentIdVal,\r\n })\r\n },\r\n { immediate: true }\r\n)\r\n\r\n/** 环境数量超限弹窗可见状态 */\r\nconst envLimitDialogVisible = ref(false)\r\n\r\n// ==================== 环境数量超限弹窗(合并自 EnvironmentLimitDialog) ====================\r\n\r\n/** 场景类型中文标签映射(保留 agent 标签以兼容历史运行中环境展示) */\r\nconst SCENE_TYPE_LABELS: Record<string, string> = {\r\n workspace: '工作区',\r\n knowledge_base: '知识库',\r\n agent: '智能体',\r\n skill: '技能构建',\r\n personal_assistant: '个人助手',\r\n bid: '智能投标',\r\n}\r\n\r\n/** 运行中环境列表加载状态 */\r\nconst envLimitLoading = ref(false)\r\n\r\n/** 批量关闭进行中状态 */\r\nconst envLimitClosing = ref(false)\r\n\r\n/** 运行中环境列表 */\r\nconst runningEnvironments = ref<RunningEnvironmentItem[]>([])\r\n\r\n/** 多选选中的环境 */\r\nconst selectedEnvItems = ref<RunningEnvironmentItem[]>([])\r\n\r\n/** 环境表格 ref */\r\nconst envLimitTableRef = ref()\r\n\r\n/** 格式化时间 */\r\nfunction formatTime(time: string): string {\r\n if (!time) return '-'\r\n try {\r\n const d = new Date(time)\r\n return d.toLocaleString('zh-CN', {\r\n year: 'numeric',\r\n month: '2-digit',\r\n day: '2-digit',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n })\r\n } catch {\r\n return time\r\n }\r\n}\r\n\r\n/** 加载运行中环境列表 */\r\nasync function loadRunningEnvironments() {\r\n envLimitLoading.value = true\r\n selectedEnvItems.value = []\r\n try {\r\n runningEnvironments.value = await props.request.get<RunningEnvironmentItem[]>('/app-conversation/my-running-environments')\r\n } catch {\r\n ElMessage.error('获取运行中环境列表失败')\r\n runningEnvironments.value = []\r\n } finally {\r\n envLimitLoading.value = false\r\n }\r\n}\r\n\r\n/** 弹窗打开时加载数据 */\r\nwatch(envLimitDialogVisible, (val) => {\r\n if (val) {\r\n loadRunningEnvironments()\r\n }\r\n})\r\n\r\n/** 多选变化 */\r\nfunction handleEnvSelectionChange(rows: RunningEnvironmentItem[]) {\r\n selectedEnvItems.value = rows\r\n}\r\n\r\n/** 关闭已选环境:批量并行停止后触发重试 */\r\nasync function handleCloseEnvironments() {\r\n if (selectedEnvItems.value.length === 0) return\r\n envLimitClosing.value = true\r\n try {\r\n const environments = selectedEnvItems.value.map((item) => ({\r\n appCode: item.appCode\r\n }))\r\n const result = await props.request.post<BatchStopResult>('/app-conversation/batch-stop-environments', { environments })\r\n if (!result.allSuccess) {\r\n ElMessage.warning(`关闭完成:成功 ${result.successCount} 个,失败 ${result.failedCount} 个`)\r\n }\r\n envLimitDialogVisible.value = false\r\n await handleEnvClosedAndRetry()\r\n } catch {\r\n ElMessage.error('关闭环境失败,请重试')\r\n } finally {\r\n envLimitClosing.value = false\r\n }\r\n}\r\n\r\n/** iframe 地址缓存(避免无差异的 proxyUrl 更新导致 iframe 重新加载) */\r\nconst iframeSrc = ref('')\r\n\r\n/** iframe 元素引用(用于向 dsh 内部 postMessage 抛事件) */\r\nconst iframeRef = ref<HTMLIFrameElement | null>(null)\r\n\r\n/** 实际展示在 iframe 上的地址(支持刷新时附加随机参数) */\r\nconst displayedIframeSrc = ref('')\r\n\r\n/** 自动重试次数 */\r\nlet retryCount = 0\r\nconst MAX_RETRY_COUNT = 30\r\n\r\n/** 重试定时器 */\r\nlet retryTimer: ReturnType<typeof setTimeout> | null = null\r\n\r\n/** 启动后延迟加载定时器 */\r\nlet delayTimer: ReturnType<typeof setTimeout> | null = null\r\n\r\n/** PerformanceObserver 实例 */\r\nlet perfObserver: PerformanceObserver | null = null\r\n\r\n/** 加载超时定时器 */\r\nlet loadTimeout: ReturnType<typeof setTimeout> | null = null\r\n\r\n/** 当前是否处于等待 iframe 加载成功状态 */\r\nlet isWaitingLoadSuccess = false\r\n\r\n/** 轮询定时器 */\r\nlet pollTimer: ReturnType<typeof setInterval> | null = null\r\n\r\n/** 轮询计数器 */\r\nlet pollCount = 0\r\n\r\n/** 心跳定时器 */\r\nlet heartbeatTimer: ReturnType<typeof setInterval> | null = null\r\n\r\n/** 轮询间隔(毫秒) */\r\nconst POLL_INTERVAL = 2000\r\n\r\n/** 轮询最大次数(2秒 × 45次 = 90秒超时;覆盖容器创建+引擎就绪的完整启动窗口) */\r\nconst POLL_MAX_COUNT = 45\r\n\r\n/** 心跳间隔(毫秒,5分钟) */\r\nconst HEARTBEAT_INTERVAL = 5 * 60 * 1000\r\n\r\n/** 提取不含 token 的基础 URL,用于比对是否只有 token 刷新 */\r\nfunction getBaseUrl(url: string): string {\r\n if (!url) return ''\r\n try {\r\n const u = new URL(url)\r\n u.searchParams.delete('token')\r\n return u.toString()\r\n } catch {\r\n return url\r\n }\r\n}\r\n\r\n// ==================== Actions(直接调用请求地址) ====================\r\n\r\n/**\r\n * 启动执行环境\r\n */\r\nasync function startEnv(): Promise<EnvironmentStatusResult> {\r\n loading.value = true\r\n try {\r\n const res = await props.request.post<EnvironmentStatusResult>('/app-conversation/start-environment', {\r\n appCode: props.appCode\r\n })\r\n if (res.status !== environmentStatus.value) {\r\n environmentStatus.value = res.status\r\n }\r\n if (res.environmentId && res.environmentId !== environmentId.value) {\r\n environmentId.value = res.environmentId\r\n }\r\n if (res.proxyUrl && res.proxyUrl !== proxyUrl.value) {\r\n proxyUrl.value = res.proxyUrl\r\n }\r\n return res\r\n } finally {\r\n loading.value = false\r\n }\r\n}\r\n\r\n/**\r\n * 查询环境状态(兼心跳保活)\r\n */\r\nasync function queryStatus(): Promise<void> {\r\n try {\r\n // silent: 状态轮询为后台尽力而为查询。环境启动窗口期后端可能返回瞬时的\r\n // 系统内部错误(如 10001),属预期暂态:宿主请求层应对其静默(不弹全局提示),\r\n // 本组件捕获后保持当前状态继续轮询,直至环境就绪。\r\n const res = await props.request.get<EnvironmentStatusResult>('/app-conversation/environment-status', {\r\n appCode: props.appCode\r\n }, { silent: true })\r\n if (res.status !== environmentStatus.value) {\r\n environmentStatus.value = res.status\r\n }\r\n if (res.environmentId && res.environmentId !== environmentId.value) {\r\n environmentId.value = res.environmentId\r\n }\r\n if (res.proxyUrl && res.proxyUrl !== proxyUrl.value) {\r\n proxyUrl.value = res.proxyUrl\r\n }\r\n } catch {\r\n // 查询失败静默处理,保持当前状态\r\n }\r\n}\r\n\r\n/**\r\n * 停止执行环境\r\n */\r\nasync function stopEnv(): Promise<void> {\r\n loading.value = true\r\n try {\r\n await props.request.post<null>('/app-conversation/stop-environment', {\r\n appCode: props.appCode\r\n })\r\n environmentStatus.value = 'stopped'\r\n } finally {\r\n loading.value = false\r\n }\r\n}\r\n\r\n/**\r\n * 销毁执行环境(销毁容器并重置 session,下次启动将创建全新容器)\r\n */\r\nasync function destroyEnv(): Promise<void> {\r\n loading.value = true\r\n try {\r\n await props.request.post<null>('/app-conversation/destroy-environment', {\r\n appCode: props.appCode\r\n })\r\n environmentStatus.value = 'not_exist'\r\n proxyUrl.value = ''\r\n environmentId.value = ''\r\n } finally {\r\n loading.value = false\r\n }\r\n}\r\n\r\n/**\r\n * 获取会话信息\r\n *\r\n * @returns 会话信息,失败时返回 undefined\r\n */\r\nasync function fetchSessionInfo(): Promise<SessionInfoResult | undefined> {\r\n try {\r\n // silent: 会话信息为补偿性查询(昵称/会话ID回填),启动窗口期可能瞬时失败,\r\n // 由宿主请求层静默处理,组件捕获后返回 undefined,待环境就绪后再补拉。\r\n const res = await props.request.get<SessionInfoResult>('/app-conversation/session-info', {\r\n appCode: props.appCode\r\n }, { silent: true })\r\n if (res.sessionId !== sessionId.value) {\r\n sessionId.value = res.sessionId\r\n }\r\n if (res.proxyUrl !== proxyUrl.value) {\r\n proxyUrl.value = res.proxyUrl\r\n }\r\n if (res.agentNickname !== agentNickname.value) {\r\n agentNickname.value = res.agentNickname\r\n }\r\n if (res.environmentId !== environmentId.value) {\r\n environmentId.value = res.environmentId\r\n }\r\n if (res.appCode && res.appCode !== appCode.value) {\r\n appCode.value = res.appCode\r\n }\r\n if (res.environmentStatus !== environmentStatus.value) {\r\n environmentStatus.value = res.environmentStatus\r\n }\r\n return res\r\n } catch {\r\n // 获取会话信息失败静默处理\r\n return undefined\r\n }\r\n}\r\n\r\n/**\r\n * 启动轮询(2秒间隔,60秒超时)\r\n */\r\nfunction startPolling(): void {\r\n stopPolling()\r\n pollCount = 0\r\n pollTimer = setInterval(async () => {\r\n pollCount++\r\n if (pollCount > POLL_MAX_COUNT) {\r\n // 到达轮询预算:先做最后一次状态确认再判定,避免环境刚就绪(启动窗口\r\n // 末尾查询仍在瞬时失败)时被误判为 start_failed\r\n await queryStatus()\r\n if (environmentStatus.value === 'running') {\r\n stopPolling()\r\n startHeartbeat()\r\n if (!agentNickname.value) {\r\n // 启动窗口期补拉会话信息失败的兜底:环境就绪后回填昵称/会话ID\r\n fetchSessionInfo()\r\n }\r\n return\r\n }\r\n // 超时:停止轮询,标记启动失败(可由用户手动重新启动)\r\n stopPolling()\r\n environmentStatus.value = 'start_failed'\r\n return\r\n }\r\n await queryStatus()\r\n if (environmentStatus.value === 'running') {\r\n // 环境就绪:停止轮询,启动心跳\r\n stopPolling()\r\n startHeartbeat()\r\n if (!agentNickname.value) {\r\n // 启动窗口期 fetchSessionInfo 可能因瞬时错误被跳过,就绪后补拉一次\r\n fetchSessionInfo()\r\n }\r\n } else if (environmentStatus.value === 'start_failed') {\r\n // 启动失败:停止轮询\r\n stopPolling()\r\n }\r\n }, POLL_INTERVAL)\r\n}\r\n\r\n/**\r\n * 停止轮询\r\n */\r\nfunction stopPolling(): void {\r\n if (pollTimer !== null) {\r\n clearInterval(pollTimer)\r\n pollTimer = null\r\n }\r\n pollCount = 0\r\n}\r\n\r\n/**\r\n * 启动心跳(5分钟间隔)\r\n */\r\nfunction startHeartbeat(): void {\r\n stopHeartbeat()\r\n heartbeatTimer = setInterval(async () => {\r\n // 仅在页面可见时发送心跳\r\n if (document.visibilityState === 'visible') {\r\n await queryStatus()\r\n }\r\n }, HEARTBEAT_INTERVAL)\r\n}\r\n\r\n/**\r\n * 停止心跳\r\n */\r\nfunction stopHeartbeat(): void {\r\n if (heartbeatTimer !== null) {\r\n clearInterval(heartbeatTimer)\r\n heartbeatTimer = null\r\n }\r\n}\r\n\r\n/**\r\n * 重置所有状态并清理定时器\r\n */\r\nfunction resetState(): void {\r\n stopPolling()\r\n stopHeartbeat()\r\n environmentStatus.value = 'not_exist'\r\n sessionId.value = ''\r\n proxyUrl.value = ''\r\n agentNickname.value = ''\r\n environmentId.value = ''\r\n appCode.value = ''\r\n loading.value = false\r\n}\r\n\r\n// ==================== iframe 监控逻辑(保持原样) ====================\r\n\r\nwatch(\r\n [() => environmentStatus.value, () => proxyUrl.value],\r\n ([newStatus, newUrl], [oldStatus, oldUrl]) => {\r\n if (!newUrl || newStatus !== 'running') {\r\n iframeSrc.value = ''\r\n displayedIframeSrc.value = ''\r\n stopLoadMonitoring()\r\n clearTimers()\r\n return\r\n }\r\n // 仅在运行状态且基础 URL 变化(非 token 刷新)时才更新 iframe\r\n if (getBaseUrl(newUrl) !== getBaseUrl(oldUrl || '')) {\r\n const freshStart = oldStatus === 'starting'\r\n updateIframeSrc(newUrl, freshStart)\r\n }\r\n },\r\n { immediate: true }\r\n)\r\n\r\nwatch(\r\n () => environmentStatus.value,\r\n (newStatus, oldStatus) => {\r\n // 重启等场景下 proxyUrl 基础地址可能未变,需要单独监听 running 强制刷新\r\n if (newStatus === 'running' && oldStatus === 'starting') {\r\n const url = proxyUrl.value\r\n if (!url) return\r\n // iframeSrc 为空(重启后 reset 清空)或基础地址相同时,均需强制加载\r\n if (!iframeSrc.value || getBaseUrl(url) === getBaseUrl(iframeSrc.value)) {\r\n updateIframeSrc(url, true)\r\n }\r\n }\r\n }\r\n)\r\n\r\n/**\r\n * 启动环境\r\n */\r\nasync function handleStart() {\r\n // 防止重复调用:loading 中或已在 running/starting 状态时直接忽略\r\n if (loading.value) return\r\n const currentStatus = environmentStatus.value\r\n if (currentStatus === 'running' || currentStatus === 'starting') return\r\n\r\n // start_failed 状态时,先查一次真实状态:\r\n // 容器可能已成功启动但前端因接口超时等原因误显了 start_failed\r\n if (currentStatus === 'start_failed') {\r\n await queryStatus()\r\n const refreshedStatus = environmentStatus.value\r\n if (refreshedStatus === 'running') {\r\n // 容器已在运行,启动心跳即可\r\n startHeartbeat()\r\n return\r\n }\r\n if (refreshedStatus === 'starting') {\r\n // 已在启动中,开始轮询即可\r\n startPolling()\r\n return\r\n }\r\n }\r\n\r\n try {\r\n await startEnv()\r\n // 启动成功后补查会话信息(首次启动时 fetchSessionInfo 因会话不存在被跳过,此处补偿)\r\n if (!agentNickname.value) {\r\n fetchSessionInfo()\r\n }\r\n // 启动成功后如果状态为 starting,开启轮询\r\n if (environmentStatus.value === 'starting') {\r\n startPolling()\r\n } else if (environmentStatus.value === 'running') {\r\n // 直接变为 running,启动心跳\r\n startHeartbeat()\r\n }\r\n } catch (err: any) {\r\n // 环境数量超限:弹出运行中环境列表,用户关闭后可自动重试\r\n if (err?.code === 23010) {\r\n envLimitDialogVisible.value = true\r\n return\r\n }\r\n // 其他接口错误已由宿主 request 统一处理\r\n }\r\n}\r\n\r\n/**\r\n * 环境数量超限弹窗关闭环境后重试启动\r\n */\r\nasync function handleEnvClosedAndRetry() {\r\n // 等待一小段时间让后端状态同步完成\r\n await new Promise((resolve) => setTimeout(resolve, 500))\r\n await handleStart()\r\n}\r\n\r\n/**\r\n * 停止环境(确认交互由外层标题栏负责)\r\n *\r\n * @returns 是否停止成功\r\n */\r\nasync function stop(): Promise<boolean> {\r\n // 立即切换到停止中状态,让 UI 即时响应\r\n environmentStatus.value = 'stopping'\r\n // 清理轮询、心跳、加载监控与定时器\r\n stopPolling()\r\n stopHeartbeat()\r\n stopLoadMonitoring()\r\n clearTimers()\r\n try {\r\n await stopEnv()\r\n return true\r\n } catch {\r\n // 接口错误已由宿主请求统一处理,回退状态为 running\r\n environmentStatus.value = 'running'\r\n return false\r\n }\r\n}\r\n\r\n/**\r\n * 解析当前会话的智能体ID(用于更新智能体等需要 appCode 的操作)\r\n */\r\nasync function resolveAgentId(): Promise<string | undefined> {\r\n // 尝试获取 appCode:优先使用已缓存的,否则重新查询会话信息\r\n let resolved = appCode.value || effectiveAgentId.value\r\n if (!resolved) {\r\n // 会话信息可能因初始化时序未成功获取,此处补查一次\r\n await fetchSessionInfo()\r\n resolved = appCode.value || effectiveAgentId.value\r\n }\r\n return resolved || undefined\r\n}\r\n\r\n/**\r\n * 手动刷新 iframe(附加随机参数强制重新加载)\r\n */\r\nfunction refresh() {\r\n const url = iframeSrc.value\r\n if (!url) return\r\n stopLoadMonitoring()\r\n retryCount = 0\r\n const separator = url.includes('?') ? '&' : '?'\r\n displayedIframeSrc.value = `${url}${separator}_refresh=${Date.now()}`\r\n startLoadMonitoring(displayedIframeSrc.value)\r\n}\r\n\r\n/**\r\n * iframe 加载完成\r\n */\r\nfunction onIframeLoad() {\r\n handleLoadSuccess()\r\n}\r\n\r\n/**\r\n * iframe 加载失败\r\n */\r\nfunction onIframeError() {\r\n handleLoadFailure('network')\r\n}\r\n\r\n/**\r\n * 标记加载成功:停止监控、取消超时、重置重试计数\r\n */\r\nfunction handleLoadSuccess() {\r\n if (!isWaitingLoadSuccess) return\r\n stopLoadMonitoring()\r\n retryCount = 0\r\n}\r\n\r\n// ==================== 域名探测与加载监控机制(保持原样) ====================\r\n\r\nfunction buildTestUrl(url: string): string {\r\n try {\r\n const u = new URL(url)\r\n u.pathname = '/test'\r\n u.search = ''\r\n u.hash = ''\r\n return u.toString()\r\n } catch {\r\n const base = url.split('?')[0].split('#')[0]\r\n return `${base.replace(/\\/+$/, '')}/test`\r\n }\r\n}\r\n\r\nasync function probeTargetUrl(url: string): Promise<boolean> {\r\n try {\r\n const testUrl = buildTestUrl(url)\r\n const controller = new AbortController()\r\n const timeoutId = setTimeout(() => controller.abort(), 5000)\r\n const res = await fetch(testUrl, {\r\n method: 'HEAD',\r\n mode: 'cors',\r\n cache: 'no-cache',\r\n signal: controller.signal,\r\n })\r\n clearTimeout(timeoutId)\r\n return res.status === 200\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nasync function ensureTargetReachableThenLoad(url: string, attempt = 0) {\r\n if (await probeTargetUrl(url)) {\r\n setIframeSrcAndMonitor(url)\r\n return\r\n }\r\n\r\n if (attempt < MAX_RETRY_COUNT) {\r\n retryTimer = setTimeout(() => {\r\n ensureTargetReachableThenLoad(url, attempt + 1)\r\n }, 100)\r\n } else {\r\n setIframeSrcAndMonitor(url)\r\n }\r\n}\r\n\r\nfunction setIframeSrcAndMonitor(url: string) {\r\n iframeSrc.value = url\r\n displayedIframeSrc.value = url\r\n startLoadMonitoring(url)\r\n}\r\n\r\nfunction updateIframeSrc(url: string, delay: boolean) {\r\n stopLoadMonitoring()\r\n clearTimers()\r\n retryCount = 0\r\n\r\n if (delay) {\r\n delayTimer = setTimeout(() => {\r\n ensureTargetReachableThenLoad(url)\r\n delayTimer = null\r\n }, 1500)\r\n } else {\r\n ensureTargetReachableThenLoad(url)\r\n }\r\n}\r\n\r\nfunction clearTimers() {\r\n if (retryTimer) {\r\n clearTimeout(retryTimer)\r\n retryTimer = null\r\n }\r\n if (delayTimer) {\r\n clearTimeout(delayTimer)\r\n delayTimer = null\r\n }\r\n if (loadTimeout) {\r\n clearTimeout(loadTimeout)\r\n loadTimeout = null\r\n }\r\n}\r\n\r\nfunction startLoadMonitoring(url: string) {\r\n stopLoadMonitoring()\r\n if (!window.PerformanceObserver) {\r\n startLoadTimeout(url)\r\n return\r\n }\r\n\r\n isWaitingLoadSuccess = true\r\n\r\n try {\r\n perfObserver = new PerformanceObserver((list) => {\r\n for (const entry of list.getEntries()) {\r\n const resEntry = entry as PerformanceResourceTiming\r\n if (entry.name !== url && entry.name !== displayedIframeSrc.value) continue\r\n\r\n const status = resEntry.responseStatus\r\n\r\n // 仅处理明确的 502 错误(跨域时 status 始终为 0,不可作为失败判据)\r\n if (status === 502) {\r\n handleLoadFailure('502')\r\n return\r\n }\r\n\r\n // 加载成功(仅同域或设置了 Timing-Allow-Origin 时有效)\r\n if (status >= 200 && status < 400) {\r\n handleLoadSuccess()\r\n }\r\n }\r\n })\r\n perfObserver.observe({ type: 'resource', buffered: true })\r\n } catch {\r\n // 浏览器不支持 PerformanceObserver 时静默忽略\r\n }\r\n\r\n startLoadTimeout(url)\r\n}\r\n\r\nfunction stopLoadMonitoring() {\r\n if (perfObserver) {\r\n perfObserver.disconnect()\r\n perfObserver = null\r\n }\r\n if (loadTimeout) {\r\n clearTimeout(loadTimeout)\r\n loadTimeout = null\r\n }\r\n isWaitingLoadSuccess = false\r\n}\r\n\r\nfunction startLoadTimeout(_url: string) {\r\n loadTimeout = setTimeout(() => {\r\n if (isWaitingLoadSuccess) {\r\n handleLoadFailure('timeout')\r\n }\r\n }, 15000)\r\n}\r\n\r\nfunction handleLoadFailure(reason: '502' | 'network' | 'timeout') {\r\n if (!isWaitingLoadSuccess) return\r\n stopLoadMonitoring()\r\n\r\n retryCount++\r\n if (retryCount > MAX_RETRY_COUNT) {\r\n ElMessage.error('应用加载失败,请刷新页面重试')\r\n return\r\n }\r\n\r\n const reasonText = reason === 'network'\r\n ? '网络错误'\r\n : reason === 'timeout'\r\n ? '加载超时'\r\n : '应用暂不可用'\r\n console.warn(`[ConversationSession] 加载失败: ${reasonText}, 第 ${retryCount} 次重试`)\r\n\r\n retryTimer = setTimeout(() => {\r\n if (!iframeSrc.value) return\r\n const separator = iframeSrc.value.includes('?') ? '&' : '?'\r\n displayedIframeSrc.value = `${iframeSrc.value}${separator}_retry=${Date.now()}`\r\n startLoadMonitoring(displayedIframeSrc.value)\r\n }, 1000)\r\n}\r\n\r\n// ==================== 页面可见性监听 ====================\r\n\r\nfunction handleVisibilityChange() {\r\n if (document.visibilityState === 'visible' && status.value === 'running') {\r\n // 页面恢复可见时,立即查询一次状态保活\r\n queryStatus()\r\n }\r\n}\r\n\r\n// ==================== 生命周期 ====================\r\n\r\nonMounted(async () => {\r\n // 监听页面可见性变化\r\n document.addEventListener('visibilitychange', handleVisibilityChange)\r\n\r\n // 查询当前环境状态\r\n await queryStatus()\r\n\r\n const st = environmentStatus.value\r\n if (st === 'not_exist' || st === 'stopped') {\r\n // 会话尚未创建,先启动环境,fetchSessionInfo 由 handleStart 成功后补调\r\n handleStart()\r\n } else {\r\n // 环境已存在,安全获取昵称\r\n await fetchSessionInfo()\r\n if (st === 'starting') {\r\n // 正在启动,开始轮询\r\n startPolling()\r\n } else if (st === 'running') {\r\n // 已在运行,启动心跳\r\n startHeartbeat()\r\n }\r\n }\r\n})\r\n\r\n/**\r\n * 重启会话:停止当前环境 → 重置状态 → 重新启动\r\n */\r\nasync function restart() {\r\n // 立即切换到停止中,让 UI 及时响应\r\n const originalStatus = environmentStatus.value\r\n environmentStatus.value = 'stopping'\r\n\r\n // 清理旧环境的轮询、心跳、加载监控与定时器\r\n stopPolling()\r\n stopHeartbeat()\r\n stopLoadMonitoring()\r\n clearTimers()\r\n\r\n // 如果当前环境正在运行或已启动,先停止\r\n if (originalStatus === 'running' || originalStatus === 'starting') {\r\n try {\r\n await stopEnv()\r\n } catch {\r\n // 停止失败不阻塞重启流程\r\n }\r\n }\r\n\r\n // 重置状态\r\n resetState()\r\n // 立即切换到启动中,避免内容区闪现\"环境未启动\"\r\n environmentStatus.value = 'starting'\r\n\r\n // 直接调用启动,绕过 handleStart 的状态守卫(因为已手动设置 starting)\r\n try {\r\n await startEnv()\r\n // 重新启动后重新获取昵称(reset 已清空)\r\n fetchSessionInfo()\r\n if (environmentStatus.value === 'starting') {\r\n startPolling()\r\n } else if (environmentStatus.value === 'running') {\r\n startHeartbeat()\r\n }\r\n } catch {\r\n // 接口错误已由宿主请求统一处理\r\n }\r\n}\r\n\r\n/**\r\n * 重建会话:销毁当前容器 → 重置状态 → 创建全新环境\r\n */\r\nasync function rebuild() {\r\n // 立即切换到停止中,让 UI 及时响应\r\n environmentStatus.value = 'stopping'\r\n\r\n // 清理旧环境的轮询、心跳、加载监控与定时器\r\n stopPolling()\r\n stopHeartbeat()\r\n stopLoadMonitoring()\r\n clearTimers()\r\n\r\n // 销毁当前环境(容器销毁 + session 重置为 not_exist)\r\n try {\r\n await destroyEnv()\r\n } catch {\r\n // 销毁失败不阻塞后续启动流程\r\n }\r\n\r\n // 重置全部状态\r\n resetState()\r\n // 立即切换到启动中,避免内容区闪现\"环境未启动\"\r\n environmentStatus.value = 'starting'\r\n\r\n // 创建全新环境\r\n try {\r\n await startEnv()\r\n fetchSessionInfo()\r\n if (environmentStatus.value === 'starting') {\r\n startPolling()\r\n } else if (environmentStatus.value === 'running') {\r\n startHeartbeat()\r\n }\r\n } catch {\r\n // 接口错误已由宿主请求统一处理\r\n }\r\n}\r\n\r\n/**\r\n * 向 dsh 内部(iframe 沙箱)抛出一个事件。\r\n *\r\n * 供外层宿主(ConversationPanel 经 dsh-bridge)把提示词注入等事件投递给 dsh。\r\n * 消息协议与 dsh 插件保持一致:{ target: 'dsh', type, payload }。\r\n *\r\n * @param type - 事件类型(如 prompt:inject)。\r\n * @param payload - 事件载荷。\r\n */\r\nfunction postDshEvent(type: string, payload: unknown) {\r\n const win = iframeRef.value?.contentWindow\r\n if (win) {\r\n win.postMessage({ target: 'dsh', type, payload }, '*')\r\n }\r\n}\r\n\r\n// ==================== 对外暴露 ====================\r\n\r\ndefineExpose({ start: handleStart, stop, restart, rebuild, refresh, resolveAgentId, postDshEvent })\r\n\r\nonUnmounted(() => {\r\n // 清理轮询和心跳定时器\r\n stopPolling()\r\n stopHeartbeat()\r\n // 移除页面可见性监听\r\n document.removeEventListener('visibilitychange', handleVisibilityChange)\r\n // 停止加载监控与定时器\r\n stopLoadMonitoring()\r\n clearTimers()\r\n // 重置状态\r\n resetState()\r\n})\r\n</script>\r\n\r\n<style scoped>\r\n.conversation-session {\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n margin: 8px 8px 8px 0;\r\n border-radius: 4px;\r\n background: #F8FBFC;\r\n}\r\n\r\n/* 占位状态 */\r\n.status-placeholder {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100%;\r\n color: var(--el-text-color-secondary);\r\n font-size: var(--text-meta);\r\n}\r\n\r\n.status-placeholder p {\r\n margin-top: var(--space-4);\r\n color: var(--el-text-color-secondary);\r\n}\r\n\r\n/* iframe 容器 */\r\n.iframe-container {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.conversation-iframe {\r\n width: 100%;\r\n height: 100%;\r\n border: none;\r\n}\r\n\r\n/* 环境数量超限弹窗(合并自 EnvironmentLimitDialog) */\r\n.env-limit-dialog__tip {\r\n margin-bottom: var(--space-4);\r\n color: var(--el-text-color-regular);\r\n font-size: var(--el-font-size-base);\r\n}\r\n\r\n.env-limit-dialog :deep(.el-table__body-wrapper) {\r\n overflow-x: hidden;\r\n}\r\n</style>","/**\n * @duxi999/usdp-eacp-conversation 组件库入口\n *\n * 导出对话会话组件(已合并环境超限弹窗)以及共享类型。\n * request 对象由宿主应用通过 props 注入,组件内部直接调用请求地址。\n */\n\nimport type { App } from 'vue'\nimport ConversationSession from './components/UsdpEacpConversation.vue'\n\n// ==================== 组件 ====================\n\nexport { ConversationSession }\n\n// ==================== 共享类型 ====================\n\nexport type {\n EnvironmentStatus,\n SceneType,\n EnvironmentParams,\n EnvironmentStatusResult,\n SessionInfoResult,\n RunningEnvironmentItem,\n BatchStopResult,\n RequestAdapter,\n RequestOptions,\n} from './types'\n\n// ==================== 组件库插件(可选,支持 app.use 全局注册) ====================\n\n/** 全局注册使用的组件名(与包名 usdp-eacp-conversation 一致,模板中可写 <usdp-eacp-conversation>) */\nconst REGISTERED_NAME = 'usdp-eacp-conversation'\n\nexport default {\n install(app: App) {\n // 以包名注册,便于模板中使用 <usdp-eacp-conversation>\n app.component(REGISTERED_NAME, ConversationSession)\n // 同时注册 PascalCase 与 camelCase 变体,兼容不同书写习惯\n app.component('UsdpEacpConversation', ConversationSession)\n },\n}\n\nexport type ConversationSessionInstance = InstanceType<typeof ConversationSession>"],"names":["MAX_RETRY_COUNT","POLL_INTERVAL","POLL_MAX_COUNT","HEARTBEAT_INTERVAL","props","__props","emit","__emit","effectiveAgentId","computed","environmentStatus","ref","sessionId","proxyUrl","agentNickname","environmentId","appCode","loading","status","currentAgentId","watch","st","nickname","agentIdVal","envLimitDialogVisible","SCENE_TYPE_LABELS","envLimitLoading","envLimitClosing","runningEnvironments","selectedEnvItems","envLimitTableRef","formatTime","time","loadRunningEnvironments","ElMessage","val","handleEnvSelectionChange","rows","handleCloseEnvironments","environments","item","result","handleEnvClosedAndRetry","iframeSrc","iframeRef","displayedIframeSrc","retryCount","retryTimer","delayTimer","perfObserver","loadTimeout","isWaitingLoadSuccess","pollTimer","pollCount","heartbeatTimer","getBaseUrl","url","u","startEnv","res","queryStatus","stopEnv","destroyEnv","fetchSessionInfo","startPolling","stopPolling","startHeartbeat","stopHeartbeat","resetState","newStatus","newUrl","oldStatus","oldUrl","stopLoadMonitoring","clearTimers","updateIframeSrc","handleStart","currentStatus","refreshedStatus","err","resolve","stop","resolveAgentId","resolved","refresh","separator","startLoadMonitoring","onIframeLoad","handleLoadSuccess","onIframeError","handleLoadFailure","buildTestUrl","probeTargetUrl","testUrl","controller","timeoutId","ensureTargetReachableThenLoad","attempt","setIframeSrcAndMonitor","delay","startLoadTimeout","list","entry","resEntry","_url","reason","handleVisibilityChange","onMounted","restart","originalStatus","rebuild","postDshEvent","type","payload","win","_a","__expose","onUnmounted","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_createVNode","_component_el_empty","_component_el_button","_cache","_hoisted_3","_component_el_icon","_unref","Loading","_createElementVNode","_toDisplayString","_hoisted_4","_hoisted_5","_hoisted_7","_component_el_result","_hoisted_8","_component_el_dialog","$event","_hoisted_9","_createBlock","_component_el_table","_component_el_table_column","_withCtx","row","_createTextVNode","REGISTERED_NAME","index","app","ConversationSession"],"mappings":"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"}
package/dist/index.css ADDED
@@ -0,0 +1 @@
1
+ .conversation-session[data-v-e1586830]{flex:1;min-width:0;overflow:hidden;margin:8px 8px 8px 0;border-radius:4px;background:#f8fbfc}.status-placeholder[data-v-e1586830]{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--el-text-color-secondary);font-size:var(--text-meta)}.status-placeholder p[data-v-e1586830]{margin-top:var(--space-4);color:var(--el-text-color-secondary)}.iframe-container[data-v-e1586830]{width:100%;height:100%}.conversation-iframe[data-v-e1586830]{width:100%;height:100%;border:none}.env-limit-dialog__tip[data-v-e1586830]{margin-bottom:var(--space-4);color:var(--el-text-color-regular);font-size:var(--el-font-size-base)}.env-limit-dialog[data-v-e1586830] .el-table__body-wrapper{overflow-x:hidden}
@@ -0,0 +1,9 @@
1
+ import { App } from 'vue';
2
+ import { default as ConversationSession } from './components/UsdpEacpConversation.vue';
3
+ export { ConversationSession };
4
+ export type { EnvironmentStatus, SceneType, EnvironmentParams, EnvironmentStatusResult, SessionInfoResult, RunningEnvironmentItem, BatchStopResult, RequestAdapter, RequestOptions, } from './types';
5
+ declare const _default: {
6
+ install(app: App): void;
7
+ };
8
+ export default _default;
9
+ export type ConversationSessionInstance = InstanceType<typeof ConversationSession>;