dsh-xrxs-lingting 0.4.0-dev.48 → 0.4.0-dev.50
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 +3 -1
- package/package.json +1 -1
- package/plugin-dist/client.js +78 -11
- package/plugin-dist/index.js +2 -2
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ LINGTING_XIN_PROBE=1 nohup "/path/to/DSH Desktop Dev.app/Contents/MacOS/DSH Desk
|
|
|
98
98
|
|
|
99
99
|
## 客户端兼容性验证
|
|
100
100
|
|
|
101
|
-
`0.4.0-dev.48` 起不再要求宿主提供旧版补丁的 `layout.business
|
|
101
|
+
`0.4.0-dev.48` 起不再要求宿主提供旧版补丁的 `layout.business`。`0.4.0-dev.50` 起,标准薪灵客户端通过渲染器公开的 `[data-slot="conversation"]` 标记,将原有灵听页面挂载到主内容区:保留侧栏,暂时隐藏而不卸载聊天,返回时恢复原聊天和草稿。弹窗、列表、实时转写仍复用原组件;转写面板继续使用 `shell.overlay`。提供业务页扩展的旧宿主仍沿用原入口。
|
|
102
102
|
|
|
103
103
|
发布前除单元测试外,应在构建后对目标薪灵源码运行客户端产物冒烟,验证真实布局对象、公开插槽、页面打开及返回聊天:
|
|
104
104
|
|
|
@@ -108,3 +108,5 @@ npm run smoke:client -- /path/to/cinlyn-desktop
|
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
该检查不代替安装后对授权、录音、转写和回放的人工验证。
|
|
111
|
+
|
|
112
|
+
布局回归验证:`node scripts/smoke-layout-browser.mjs <playwright/index.mjs 路径>`,使用 Chrome 无头浏览器运行真实插件产物,验证页面边界、弹窗居中、转写面板层级、窗口缩放与卸载后聊天恢复。使用合成录音状态,不访问业务数据、不采集声音。
|
package/package.json
CHANGED
package/plugin-dist/client.js
CHANGED
|
@@ -30,7 +30,7 @@ module.exports = __toCommonJS(client_exports);
|
|
|
30
30
|
var define_import_meta_env_default = { VITE_XIN_PACKAGED: "1" };
|
|
31
31
|
|
|
32
32
|
// src/plugin/client.tsx
|
|
33
|
-
var
|
|
33
|
+
var import_react23 = require("react");
|
|
34
34
|
|
|
35
35
|
// node_modules/lucide-react/dist/esm/createLucideIcon.js
|
|
36
36
|
var import_react2 = require("react");
|
|
@@ -4449,24 +4449,39 @@ function isState(value) {
|
|
|
4449
4449
|
const state = value;
|
|
4450
4450
|
return typeof state?.reason === "string" && typeof state.businessReady === "boolean";
|
|
4451
4451
|
}
|
|
4452
|
+
function unavailableHostState() {
|
|
4453
|
+
return {
|
|
4454
|
+
protocol: 1,
|
|
4455
|
+
providerAvailable: false,
|
|
4456
|
+
configured: false,
|
|
4457
|
+
authorized: false,
|
|
4458
|
+
businessReady: false,
|
|
4459
|
+
reason: "state-unavailable",
|
|
4460
|
+
context: null,
|
|
4461
|
+
capabilities: { atomicSnapshot: false, recoverSession: false, versioned: false }
|
|
4462
|
+
};
|
|
4463
|
+
}
|
|
4452
4464
|
async function fetchXinHostState(fetchImpl = (input, init) => fetch(input, init)) {
|
|
4453
4465
|
let response;
|
|
4454
4466
|
try {
|
|
4455
4467
|
response = await fetchImpl(XIN_STATE_ENDPOINT, { headers: { accept: "application/json" } });
|
|
4456
4468
|
} catch {
|
|
4457
|
-
return
|
|
4469
|
+
return unavailableHostState();
|
|
4458
4470
|
}
|
|
4459
|
-
if (
|
|
4471
|
+
if (response.status === 404) return null;
|
|
4472
|
+
if (!response.ok) return unavailableHostState();
|
|
4460
4473
|
try {
|
|
4461
4474
|
const payload = await response.json();
|
|
4462
|
-
return isState(payload) ? payload :
|
|
4475
|
+
return isState(payload) ? payload : unavailableHostState();
|
|
4463
4476
|
} catch {
|
|
4464
|
-
return
|
|
4477
|
+
return unavailableHostState();
|
|
4465
4478
|
}
|
|
4466
4479
|
}
|
|
4467
4480
|
function explainXinState(state) {
|
|
4468
4481
|
if (!state || state.businessReady) return "";
|
|
4469
4482
|
switch (state.reason) {
|
|
4483
|
+
case "state-unavailable":
|
|
4484
|
+
return "\u65E0\u6CD5\u8BFB\u53D6\u85AA\u4EBA\u85AA\u4E8B\u6388\u6743\u72B6\u6001\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\uFF1B\u82E5\u6301\u7EED\u5931\u8D25\uFF0C\u8BF7\u91CD\u542F\u5BA2\u6237\u7AEF\u3002";
|
|
4470
4485
|
case "provider-missing":
|
|
4471
4486
|
return "\u672A\u5B89\u88C5\u300C\u85AA\u4EBA\u85AA\u4E8B\u6388\u6743\u300D\u63D2\u4EF6\uFF1A\u8BF7\u5728\u540C\u4E00 profile \u4E2D\u5B89\u88C5\u540E\u91CD\u542F DSH\u3002";
|
|
4472
4487
|
case "provider-unconfigured":
|
|
@@ -5404,11 +5419,63 @@ function createBusinessNavigation() {
|
|
|
5404
5419
|
};
|
|
5405
5420
|
}
|
|
5406
5421
|
|
|
5422
|
+
// src/plugin/business-surface.tsx
|
|
5423
|
+
var import_react22 = require("react");
|
|
5424
|
+
var import_react_dom = require("react-dom");
|
|
5425
|
+
function mountBusinessSurface(doc) {
|
|
5426
|
+
const conversation = doc.querySelector('[data-slot="conversation"]');
|
|
5427
|
+
const center = conversation?.parentElement;
|
|
5428
|
+
if (!conversation || !center) return null;
|
|
5429
|
+
const target = doc.createElement("section");
|
|
5430
|
+
target.className = "lt-business-surface";
|
|
5431
|
+
target.setAttribute("aria-label", "\u7075\u542C");
|
|
5432
|
+
const display = conversation.style.getPropertyValue("display");
|
|
5433
|
+
const displayPriority = conversation.style.getPropertyPriority("display");
|
|
5434
|
+
const position = center.style.getPropertyValue("position");
|
|
5435
|
+
const positionPriority = center.style.getPropertyPriority("position");
|
|
5436
|
+
const inert = conversation.inert;
|
|
5437
|
+
conversation.style.setProperty("display", "none", "important");
|
|
5438
|
+
conversation.inert = true;
|
|
5439
|
+
center.style.setProperty("position", "relative");
|
|
5440
|
+
center.appendChild(target);
|
|
5441
|
+
let disposed = false;
|
|
5442
|
+
return { target, dispose() {
|
|
5443
|
+
if (disposed) return;
|
|
5444
|
+
disposed = true;
|
|
5445
|
+
target.remove();
|
|
5446
|
+
if (display) conversation.style.setProperty("display", display, displayPriority);
|
|
5447
|
+
else conversation.style.removeProperty("display");
|
|
5448
|
+
conversation.inert = inert;
|
|
5449
|
+
if (position) center.style.setProperty("position", position, positionPriority);
|
|
5450
|
+
else center.style.removeProperty("position");
|
|
5451
|
+
} };
|
|
5452
|
+
}
|
|
5453
|
+
function BusinessSurface({ children }) {
|
|
5454
|
+
const [target, setTarget] = (0, import_react22.useState)(null);
|
|
5455
|
+
(0, import_react22.useLayoutEffect)(() => {
|
|
5456
|
+
let mounted = null;
|
|
5457
|
+
const attach = () => {
|
|
5458
|
+
if (mounted?.target.isConnected) return;
|
|
5459
|
+
mounted?.dispose();
|
|
5460
|
+
mounted = mountBusinessSurface(document);
|
|
5461
|
+
setTarget(mounted?.target ?? null);
|
|
5462
|
+
};
|
|
5463
|
+
attach();
|
|
5464
|
+
const observer = new MutationObserver(attach);
|
|
5465
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
5466
|
+
return () => {
|
|
5467
|
+
observer.disconnect();
|
|
5468
|
+
mounted?.dispose();
|
|
5469
|
+
};
|
|
5470
|
+
}, []);
|
|
5471
|
+
return target ? (0, import_react_dom.createPortal)(children, target) : null;
|
|
5472
|
+
}
|
|
5473
|
+
|
|
5407
5474
|
// src/plugin/embedded.css
|
|
5408
5475
|
var tag3 = document.createElement("style");
|
|
5409
5476
|
tag3.dataset.plugin = "dsh-xrxs-lingting";
|
|
5410
5477
|
tag3.dataset.pluginCss = "dsh-xrxs-lingting/embedded.css";
|
|
5411
|
-
tag3.textContent = ".lingting-root { color-scheme: light; }\n/* Host \u9002\u914D\u5C42\u72B6\u6001\u63D0\u793A\uFF08\u6388\u6743/\u8EAB\u4EFD/\u76EE\u7684\u5730\u672A\u5C31\u7EEA\uFF09\uFF1A\u56FA\u5B9A\u9876\u90E8\uFF0C\u53EF\u5173\u95ED\uFF0C\u4E0D\u53C2\u4E0E\u9875\u9762\u5E03\u5C40 */\n.lt-host-notice { position: fixed; top: 12px; left: 50%; transform: translateX(-50%); z-index: 60; display: flex; align-items: center; gap: 12px; max-width: min(680px, calc(100vw - 32px)); padding: 10px 14px; border: 1px solid #e7e0fa; border-radius: 10px; background: #fff; box-shadow: 0 6px 24px rgb(40 28 74 / 16%); color: #605972; font-size: 13px; line-height: 1.5; }\n.lt-host-notice-text { flex: 1; }\n.lt-host-notice-close { flex-shrink: 0; border: 0; background: transparent; color: inherit; font-size: 16px; line-height: 1; padding: 2px 4px; border-radius: 6px; cursor: pointer; }\n.lt-host-notice-close:hover { background: #6650d814; }\n.lt-host-notice-close:focus-visible { outline: 2px solid #6650d8; outline-offset: 2px; }\n/* \u5D4C\u5165\u6A21\u5F0F\u4E0B\u6839\u5143\u7D20\u5373 .app\uFF08lingting-root app \u540C\u5143\u7D20\uFF09\uFF0C\u89C4\u5219\u9700\u7528\u7EC4\u5408\u9009\u62E9\u5668\uFF1B\u4FDD\u7559\u540E\u4EE3\u5F62\u5F0F\u517C\u5BB9\u53CC\u5C42\u5305\u88F9\u7ED3\u6784 */\n.lingting-root[data-embedded] { height: 100%; min-height: 0; container-type: inline-size; }\n.lingting-root[data-embedded].app, .lingting-root[data-embedded] .app { height: 100%; min-height: 0; display: flex; flex-direction: column; overflow: hidden; position: relative; padding-bottom: 0; }\n.lingting-root[data-embedded].app .app-header, .lingting-root[data-embedded] .app-header { height: 66px; flex-shrink: 0; }\n.lingting-root[data-embedded].app .header-inner, .lingting-root[data-embedded] .header-inner { padding: 0 28px; max-width: none; }\n.lingting-root[data-embedded].app .brand-caption, .lingting-root[data-embedded] .brand-caption { display: none; }\n.lingting-root[data-embedded].app .main-content, .lingting-root[data-embedded] .main-content { width: 100%; max-width: none; min-height: 0; flex: 1; overflow: auto; padding: 30px 28px 0; scrollbar-width: thin; }\n\n.lingting-root[data-embedded].app .toast, .lingting-root[data-embedded] .toast { position: absolute; top: 77px; }\n.lingting-root[data-global-status] { flex-shrink: 0; border-top: 1px solid #e7e0fa; background: white; padding: 0 24px; }\n.lingting-root[data-global-status] .recording-controls.compact { min-height: 76px; padding: 12px 0; }\n.lingting-root[data-global-status] .error-notice { margin: 8px 0 0; }\n.lingting-sidebar-entry { display: flex; align-items: center; gap: 10px; border: 0; background: transparent; color: var(--dsw-alias-text-primary, #605972); padding: 10px 12px; width: 100%; border-radius: 9px; cursor: pointer; font: inherit; font-size: 14px; }\n.lingting-sidebar-entry:hover, .lingting-sidebar-entry[data-active] { background: #6650d814; color: #6650d8; }\n.lingting-sidebar-entry:focus-visible { outline: 2px solid #6650d8; outline-offset: 2px; }\n@container (max-width: 900px) {\n .lingting-root[data-embedded] .overview-note { display: none; }\n .lingting-root[data-embedded] .overview { grid-template-columns: 1fr 1fr; }\n .lingting-root[data-embedded] .list-heading { flex-wrap: wrap; }\n .lingting-root[data-embedded] .source-label { display: none; }\n}\n\n/*
|
|
5478
|
+
tag3.textContent = ".lingting-root { color-scheme: light; }\n/* Host \u9002\u914D\u5C42\u72B6\u6001\u63D0\u793A\uFF08\u6388\u6743/\u8EAB\u4EFD/\u76EE\u7684\u5730\u672A\u5C31\u7EEA\uFF09\uFF1A\u56FA\u5B9A\u9876\u90E8\uFF0C\u53EF\u5173\u95ED\uFF0C\u4E0D\u53C2\u4E0E\u9875\u9762\u5E03\u5C40 */\n.lt-host-notice { position: fixed; top: 12px; left: 50%; transform: translateX(-50%); z-index: 60; display: flex; align-items: center; gap: 12px; max-width: min(680px, calc(100vw - 32px)); padding: 10px 14px; border: 1px solid #e7e0fa; border-radius: 10px; background: #fff; box-shadow: 0 6px 24px rgb(40 28 74 / 16%); color: #605972; font-size: 13px; line-height: 1.5; }\n.lt-host-notice-text { flex: 1; }\n.lt-host-notice-close { flex-shrink: 0; border: 0; background: transparent; color: inherit; font-size: 16px; line-height: 1; padding: 2px 4px; border-radius: 6px; cursor: pointer; }\n.lt-host-notice-close:hover { background: #6650d814; }\n.lt-host-notice-close:focus-visible { outline: 2px solid #6650d8; outline-offset: 2px; }\n/* \u5D4C\u5165\u6A21\u5F0F\u4E0B\u6839\u5143\u7D20\u5373 .app\uFF08lingting-root app \u540C\u5143\u7D20\uFF09\uFF0C\u89C4\u5219\u9700\u7528\u7EC4\u5408\u9009\u62E9\u5668\uFF1B\u4FDD\u7559\u540E\u4EE3\u5F62\u5F0F\u517C\u5BB9\u53CC\u5C42\u5305\u88F9\u7ED3\u6784 */\n.lingting-root[data-embedded] { height: 100%; min-height: 0; container-type: inline-size; }\n.lingting-root[data-embedded].app, .lingting-root[data-embedded] .app { height: 100%; min-height: 0; display: flex; flex-direction: column; overflow: hidden; position: relative; padding-bottom: 0; }\n.lingting-root[data-embedded].app .app-header, .lingting-root[data-embedded] .app-header { height: 66px; flex-shrink: 0; }\n.lingting-root[data-embedded].app .header-inner, .lingting-root[data-embedded] .header-inner { padding: 0 28px; max-width: none; }\n.lingting-root[data-embedded].app .brand-caption, .lingting-root[data-embedded] .brand-caption { display: none; }\n.lingting-root[data-embedded].app .main-content, .lingting-root[data-embedded] .main-content { width: 100%; max-width: none; min-height: 0; flex: 1; overflow: auto; padding: 30px 28px 0; scrollbar-width: thin; }\n\n.lingting-root[data-embedded].app .toast, .lingting-root[data-embedded] .toast { position: absolute; top: 77px; }\n.lingting-root[data-global-status] { flex-shrink: 0; border-top: 1px solid #e7e0fa; background: white; padding: 0 24px; }\n.lingting-root[data-global-status] .recording-controls.compact { min-height: 76px; padding: 12px 0; }\n.lingting-root[data-global-status] .error-notice { margin: 8px 0 0; }\n.lingting-sidebar-entry { display: flex; align-items: center; gap: 10px; border: 0; background: transparent; color: var(--dsw-alias-text-primary, #605972); padding: 10px 12px; width: 100%; border-radius: 9px; cursor: pointer; font: inherit; font-size: 14px; }\n.lingting-sidebar-entry:hover, .lingting-sidebar-entry[data-active] { background: #6650d814; color: #6650d8; }\n.lingting-sidebar-entry:focus-visible { outline: 2px solid #6650d8; outline-offset: 2px; }\n@container (max-width: 900px) {\n .lingting-root[data-embedded] .overview-note { display: none; }\n .lingting-root[data-embedded] .overview { grid-template-columns: 1fr 1fr; }\n .lingting-root[data-embedded] .list-heading { flex-wrap: wrap; }\n .lingting-root[data-embedded] .source-label { display: none; }\n}\n\n/* Use the real center column, preserving the host sidebar and conversation state. */\n.lt-business-surface { position: absolute; inset: 0; z-index: 1; min-width: 0; overflow: hidden; background: #f8f9fc; pointer-events: auto; -webkit-app-region: no-drag; }\n/* Host reset styles must not remove the native dialog's centered placement. */\n.lingting-root .modal { margin: auto; background: #fff; }\n";
|
|
5412
5479
|
document.querySelectorAll("style[data-plugin-css=" + JSON.stringify("dsh-xrxs-lingting/embedded.css") + "]").forEach((old) => old.remove());
|
|
5413
5480
|
document.head.appendChild(tag3);
|
|
5414
5481
|
|
|
@@ -5416,7 +5483,7 @@ document.head.appendChild(tag3);
|
|
|
5416
5483
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
5417
5484
|
var ID = "dsh-xrxs-lingting";
|
|
5418
5485
|
var inject = ["slots", "layout"];
|
|
5419
|
-
var PanelBoundary = class extends
|
|
5486
|
+
var PanelBoundary = class extends import_react23.Component {
|
|
5420
5487
|
state = { failed: false };
|
|
5421
5488
|
static getDerivedStateFromError() {
|
|
5422
5489
|
return { failed: true };
|
|
@@ -5457,8 +5524,8 @@ async function apply(ctx) {
|
|
|
5457
5524
|
}));
|
|
5458
5525
|
const unregisterPage = business.register(ID);
|
|
5459
5526
|
function Entry({ wide }) {
|
|
5460
|
-
const panel = (0,
|
|
5461
|
-
const layout = (0,
|
|
5527
|
+
const panel = (0, import_react23.useSyncExternalStore)(controller.subscribe, controller.getSnapshot);
|
|
5528
|
+
const layout = (0, import_react23.useSyncExternalStore)(business.subscribe, business.getSnapshot);
|
|
5462
5529
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("button", { type: "button", className: "lingting-sidebar-entry", "data-active": layout.activeId === ID || panel.open || void 0, title: "\u7075\u542C", "aria-label": "\u7075\u542C", onClick: () => business.open(ID), children: [
|
|
5463
5530
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Headphones, { size: 19 }),
|
|
5464
5531
|
wide && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "\u7075\u542C" })
|
|
@@ -5468,9 +5535,9 @@ async function apply(ctx) {
|
|
|
5468
5535
|
return activeId === ID ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PanelBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LingtingApp, { service, navigation, visible: true, embedded: true, hostState, onBackToHost: () => business.close(), onOpenLive: () => controller.open(), onOpenRecord: (id) => controller.openRecord(id) }) }) : null;
|
|
5469
5536
|
}
|
|
5470
5537
|
function Overlay() {
|
|
5471
|
-
const page = (0,
|
|
5538
|
+
const page = (0, import_react23.useSyncExternalStore)(business.subscribe, business.getSnapshot, business.getSnapshot);
|
|
5472
5539
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
5473
|
-
!hostBusiness && page.activeId === ID && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
5540
|
+
!hostBusiness && page.activeId === ID && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(BusinessSurface, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Page, { activeId: page.activeId }) }),
|
|
5474
5541
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PanelBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(XinHostNotice, { store: hostState }) }),
|
|
5475
5542
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PanelBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LingtingSidebar, { service, controller, onOpenPage: () => business.open(ID) }) }),
|
|
5476
5543
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PanelBoundary, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MeetingPrompt, { service }) })
|
package/plugin-dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var PRESENCE_STATES = /* @__PURE__ */ new Set(["idle", "starting", "recording",
|
|
|
65
65
|
function registerMeetingRoutes(connection, runtime) {
|
|
66
66
|
const disposers = [];
|
|
67
67
|
const register = (path, methods, fetch2) => {
|
|
68
|
-
disposers.push(connection.fetch.register({ path, methods, fetch: fetch2 }));
|
|
68
|
+
disposers.push(connection.fetch.register({ path, methods, requestBody: "buffered", fetch: fetch2 }));
|
|
69
69
|
};
|
|
70
70
|
register("/api/lingting/meeting.state", ["GET"], () => json(runtime.view()));
|
|
71
71
|
register("/api/lingting/runtime.state", ["GET"], () => {
|
|
@@ -2840,7 +2840,7 @@ function registerXinRoutes(deps) {
|
|
|
2840
2840
|
let counter = 0;
|
|
2841
2841
|
const requestId = () => `xz-${Date.now().toString(36)}-${(counter += 1).toString(36)}`;
|
|
2842
2842
|
const register = (path, methods, fetch2) => {
|
|
2843
|
-
disposers.push(deps.connection.fetch.register({ path, methods, fetch: fetch2 }));
|
|
2843
|
+
disposers.push(deps.connection.fetch.register({ path, methods, requestBody: "buffered", fetch: fetch2 }));
|
|
2844
2844
|
};
|
|
2845
2845
|
register("/api/lingting/xin.state", ["GET"], async () => {
|
|
2846
2846
|
const state = await deps.context.state();
|