@appthen/vibe-workspace 0.1.7 → 0.1.8
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/PLUGIN_DEV.md +30 -0
- package/dist/{DocxPreview-GruinkmZ.js → DocxPreview-CAmipQT3.js} +5 -5
- package/dist/{DocxPreview-GruinkmZ.js.map → DocxPreview-CAmipQT3.js.map} +1 -1
- package/dist/{DotBadge-Dm0es7Ho.js → DotBadge-CeeLzNu3.js} +3 -3
- package/dist/{DotBadge-Dm0es7Ho.js.map → DotBadge-CeeLzNu3.js.map} +1 -1
- package/dist/{ExtensionManifestSchema-BIuNTfeS.js → ExtensionManifestSchema-INV7dTEG.js} +3 -3
- package/dist/{ExtensionManifestSchema-BIuNTfeS.js.map → ExtensionManifestSchema-INV7dTEG.js.map} +1 -1
- package/dist/{FreeCanvas-BC24RbJp.js → FreeCanvas-DritKIPq.js} +2 -2
- package/dist/{FreeCanvas-BC24RbJp.js.map → FreeCanvas-DritKIPq.js.map} +1 -1
- package/dist/{ImagePreview-BUZPZ76T.js → ImagePreview-ByIQrPzb.js} +4 -4
- package/dist/{ImagePreview-BUZPZ76T.js.map → ImagePreview-ByIQrPzb.js.map} +1 -1
- package/dist/{PdfPreview-C431TVJo.js → PdfPreview-0vwF3tLn.js} +4 -4
- package/dist/{PdfPreview-C431TVJo.js.map → PdfPreview-0vwF3tLn.js.map} +1 -1
- package/dist/{PluginContext-J-PUm9Dt.js → PluginContext-uAiGNF8S.js} +2 -20
- package/dist/PluginContext-uAiGNF8S.js.map +1 -0
- package/dist/{Workbench-C3Gi8mtZ.js → Workbench-8uTfTtsq.js} +4267 -2776
- package/dist/{Workbench-C3Gi8mtZ.js.map → Workbench-8uTfTtsq.js.map} +1 -1
- package/dist/{activate-Cn14NQGw.js → activate-DVnxnmfA.js} +84 -80
- package/dist/{activate-Cn14NQGw.js.map → activate-DVnxnmfA.js.map} +1 -1
- package/dist/canvas-core/index.js +1 -1
- package/dist/coding-kit/index.js +1 -1
- package/dist/components/index.js +4 -4
- package/dist/{devWorkbench-Ifd_a8Pb.js → devWorkbench-DZ1mFC3i.js} +2 -2
- package/dist/{devWorkbench-Ifd_a8Pb.js.map → devWorkbench-DZ1mFC3i.js.map} +1 -1
- package/dist/{dialog-DK8v51ew.js → dialog-ssICQNSV.js} +2 -2
- package/dist/{dialog-DK8v51ew.js.map → dialog-ssICQNSV.js.map} +1 -1
- package/dist/{docx-preview-BdpXCqA9.js → docx-preview-lJ7EdPsl.js} +2 -2
- package/dist/{docx-preview-BdpXCqA9.js.map → docx-preview-lJ7EdPsl.js.map} +1 -1
- package/dist/extension-cli/index.js +1 -1
- package/dist/extension-dev/index.js +1 -1
- package/dist/extension-dev-workbench/index.js +4 -4
- package/dist/extension-schema/index.js +3 -3
- package/dist/{extensionRegistry-C_OUg-8s.js → extensionRegistry-D35Ld-Wa.js} +10 -7
- package/dist/{extensionRegistry-C_OUg-8s.js.map → extensionRegistry-D35Ld-Wa.js.map} +1 -1
- package/dist/index.js +17 -17
- package/dist/index.js.map +1 -1
- package/dist/{list-detail-workspace-template-BVyGyLpE.js → list-detail-workspace-template-BTrgMGPx.js} +2 -2
- package/dist/{list-detail-workspace-template-BVyGyLpE.js.map → list-detail-workspace-template-BTrgMGPx.js.map} +1 -1
- package/dist/overlay/index.js +2 -2
- package/dist/{pluginCapabilities-9gzDTIuB.js → pluginCapabilities-BkCT7QDO.js} +197 -20
- package/dist/pluginCapabilities-BkCT7QDO.js.map +1 -0
- package/dist/plugins/agent/PluginModule.js +2 -2
- package/dist/plugins/base/index.js +1 -1
- package/dist/{sheet-CdvS0URe.js → sheet-Bsq3CLW4.js} +6 -6
- package/dist/{sheet-CdvS0URe.js.map → sheet-Bsq3CLW4.js.map} +1 -1
- package/dist/{skeleton-99iI2m9p.js → skeleton-BSqTbX9l.js} +4 -4
- package/dist/{skeleton-99iI2m9p.js.map → skeleton-BSqTbX9l.js.map} +1 -1
- package/dist/types-BL0aIpQ1.js.map +1 -1
- package/dist/ui/index.js +3 -3
- package/dist/{useBinaryFileUrl-CcgcbIxT.js → useBinaryFileUrl-D11yvGuG.js} +3 -3
- package/dist/{useBinaryFileUrl-CcgcbIxT.js.map → useBinaryFileUrl-D11yvGuG.js.map} +1 -1
- package/dist/vibe-workspace/src/components/ExtensionBadgeMark.d.ts +10 -0
- package/dist/vibe-workspace/src/components/LayoutSystem.d.ts +4 -0
- package/dist/vibe-workspace/src/components/MonacoWrapper.d.ts +5 -1
- package/dist/vibe-workspace/src/components/TopBar.d.ts +2 -0
- package/dist/vibe-workspace/src/core/extensionBadges.d.ts +47 -0
- package/dist/vibe-workspace/src/core/extensionBadges.test.d.ts +1 -0
- package/dist/vibe-workspace/src/core/extensionViews.d.ts +6 -0
- package/dist/vibe-workspace/src/core/pluginCapabilities.d.ts +15 -0
- package/dist/vibe-workspace/src/hooks/useThemeLayout.d.ts +3 -0
- package/dist/vibe-workspace/src/index.d.ts +1 -0
- package/dist/vibe-workspace/src/plugins/base/types.d.ts +1 -0
- package/dist/vibe-workspace/src/plugins/conversation-network/components/right-panel/ComponentDockBar.d.ts +6 -0
- package/dist/vibe-workspace/src/plugins/conversation-network/components/right-panel/DynamicComponentZone.d.ts +5 -3
- package/dist/vibe-workspace/src/plugins/conversation-network/components/right-panel/PanelSlotCard.d.ts +6 -1
- package/dist/vibe-workspace/src/plugins/conversation-network/components/right-panel/ParticipantBar.d.ts +1 -2
- package/dist/vibe-workspace/src/plugins/conversation-network/components/right-panel/ParticipantBarItem.d.ts +18 -15
- package/dist/vibe-workspace/src/plugins/conversation-network/conversationHubShell.d.ts +14 -1
- package/dist/vibe-workspace/src/plugins/conversation-network/services/conversationHubShellResolver.d.ts +3 -1
- package/dist/vibe-workspace/src/services/authRedirect.d.ts +1 -0
- package/dist/vibe-workspace/src/services/themeService.d.ts +81 -7
- package/dist/vibe-workspace/src/workbench/WorkbenchAccountMenu.d.ts +5 -0
- package/dist/vibe-workspace.css +36 -43
- package/dist/workbench/index.js +2 -2
- package/package.json +1 -1
- package/postcss.config.js +1 -2
- package/tailwind.config.js +10 -3
- package/dist/PluginContext-J-PUm9Dt.js.map +0 -1
- package/dist/pluginCapabilities-9gzDTIuB.js.map +0 -1
- package/dist/vibe-workspace/src/AgentEmbedPage.d.ts +0 -1
- package/dist/vibe-workspace/src/plugins/work-weixin/WorkWeixinPlugin.d.ts +0 -5
- package/dist/vibe-workspace/src/plugins/work-weixin/apiService.d.ts +0 -8
- package/dist/vibe-workspace/src/plugins/work-weixin/configService.d.ts +0 -46
- package/dist/vibe-workspace/src/plugins/work-weixin/index.d.ts +0 -2
- package/dist/vibe-workspace/src/plugins/workbench-admin/WorkbenchAdminSidebar.d.ts +0 -7
- package/dist/vibe-workspace/src/plugins/workbench-admin/activate.d.ts +0 -2
- package/dist/vibe-workspace/src/plugins/workbench-admin/index.d.ts +0 -2
|
@@ -4,7 +4,7 @@ import { createServer } from "node:http";
|
|
|
4
4
|
import { existsSync, statSync, readFileSync, watch } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { c as createExtensionWorkspace, b as buildExtension, p as packExtension, e as validateExtensionWorkspace, E as EXTENSION_PACKAGE_EXTENSION, w as writeExtensionDevWorkbenchFiles, d as discoverExtensionWorkspace, f as findExtensionWorkspaceRoot } from "../devWorkbench-
|
|
7
|
+
import { c as createExtensionWorkspace, b as buildExtension, p as packExtension, e as validateExtensionWorkspace, E as EXTENSION_PACKAGE_EXTENSION, w as writeExtensionDevWorkbenchFiles, d as discoverExtensionWorkspace, f as findExtensionWorkspaceRoot } from "../devWorkbench-DZ1mFC3i.js";
|
|
8
8
|
function printUsage() {
|
|
9
9
|
console.log(`appthen-extension
|
|
10
10
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo } from "react";
|
|
3
3
|
import { BrowserRouter, useLocation, useNavigate } from "react-router-dom";
|
|
4
|
-
import { W as Workbench } from "../Workbench-
|
|
5
|
-
import { p as parseWorkbenchRoute, a as buildWorkbenchPath } from "../PluginContext-
|
|
6
|
-
import { s as setRuntimeActor } from "../pluginCapabilities-
|
|
7
|
-
import { B as Blocks } from "../activate-
|
|
4
|
+
import { W as Workbench } from "../Workbench-8uTfTtsq.js";
|
|
5
|
+
import { p as parseWorkbenchRoute, a as buildWorkbenchPath } from "../PluginContext-uAiGNF8S.js";
|
|
6
|
+
import { s as setRuntimeActor } from "../pluginCapabilities-BkCT7QDO.js";
|
|
7
|
+
import { B as Blocks } from "../activate-DVnxnmfA.js";
|
|
8
8
|
function getExtensionId(manifest) {
|
|
9
9
|
return manifest.appId || manifest.id;
|
|
10
10
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C, a,
|
|
1
|
+
import { C, a, b, e, h, u, v } from "../ExtensionManifestSchema-INV7dTEG.js";
|
|
2
2
|
const normalizeList = (items) => (items || []).map((item) => String(item).trim()).filter(Boolean);
|
|
3
3
|
const hasIntersection = (left, right) => {
|
|
4
4
|
const leftList = normalizeList(left);
|
|
@@ -71,8 +71,8 @@ export {
|
|
|
71
71
|
C as CURRENT_EXTENSION_API_VERSION,
|
|
72
72
|
a as CURRENT_EXTENSION_MANIFEST_VERSION,
|
|
73
73
|
canAccessExtensionCapability,
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
b as extractFrontendToolsFromManifest,
|
|
75
|
+
e as extractUIResourcesFromManifest,
|
|
76
76
|
h as hasMCPConfig,
|
|
77
77
|
mergeExtensionAccessPolicy,
|
|
78
78
|
u as upgradeManifest,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { c as createLucideIcon } from "./x-DGVakEST.js";
|
|
2
|
-
import {
|
|
3
|
-
import { r as registerFrontendToolDeclaration,
|
|
2
|
+
import { e as extractUIResourcesFromManifest, b as extractFrontendToolsFromManifest } from "./ExtensionManifestSchema-INV7dTEG.js";
|
|
3
|
+
import { r as registerFrontendToolDeclaration, e as getUIResourceRegistry } from "./pluginCapabilities-BkCT7QDO.js";
|
|
4
4
|
/**
|
|
5
5
|
* @license lucide-react v0.561.0 - ISC
|
|
6
6
|
*
|
|
@@ -53,6 +53,7 @@ let nanoid = (size = 21) => {
|
|
|
53
53
|
};
|
|
54
54
|
const API_BASE_URL = "http://127.0.0.1:1626";
|
|
55
55
|
const CDN_ROOT = "https://cdn.appthen.com";
|
|
56
|
+
const DEFAULT_POST_LOGIN_PATH = "/";
|
|
56
57
|
const AUTH_STORAGE_KEYS = ["access_token", "app-user-role", "user_profile"];
|
|
57
58
|
function clearAuthStorage() {
|
|
58
59
|
AUTH_STORAGE_KEYS.forEach((key) => window.localStorage.removeItem(key));
|
|
@@ -61,8 +62,8 @@ function getCurrentRedirectPath() {
|
|
|
61
62
|
return `${window.location.pathname}${window.location.search}${window.location.hash}`;
|
|
62
63
|
}
|
|
63
64
|
function normalizePostLoginRedirect(redirect) {
|
|
64
|
-
const fallback =
|
|
65
|
-
if (!redirect || redirect === "/login") return fallback;
|
|
65
|
+
const fallback = DEFAULT_POST_LOGIN_PATH;
|
|
66
|
+
if (!redirect || redirect === "/login" || redirect === "/teams") return fallback;
|
|
66
67
|
if (!redirect.startsWith("/") || redirect.startsWith("//")) return fallback;
|
|
67
68
|
try {
|
|
68
69
|
const parsed = new URL(redirect, window.location.origin);
|
|
@@ -184,7 +185,7 @@ async function request(endpoint, options = {}) {
|
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
187
|
const authService = {
|
|
187
|
-
getCasdoorLoginUrl: (redirect =
|
|
188
|
+
getCasdoorLoginUrl: (redirect = DEFAULT_POST_LOGIN_PATH) => {
|
|
188
189
|
const params = new URLSearchParams({
|
|
189
190
|
redirect,
|
|
190
191
|
frontend: window.location.origin
|
|
@@ -681,9 +682,11 @@ export {
|
|
|
681
682
|
commonjsGlobal as c,
|
|
682
683
|
getCurrentUser as d,
|
|
683
684
|
extensionRegistry as e,
|
|
684
|
-
|
|
685
|
+
clearAuthStorage as f,
|
|
685
686
|
getDefaultExportFromCjs as g,
|
|
687
|
+
redirectToLogin as h,
|
|
688
|
+
ApiRequestError as i,
|
|
686
689
|
nanoid as n,
|
|
687
690
|
request as r
|
|
688
691
|
};
|
|
689
|
-
//# sourceMappingURL=extensionRegistry-
|
|
692
|
+
//# sourceMappingURL=extensionRegistry-D35Ld-Wa.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensionRegistry-C_OUg-8s.js","sources":["../../node_modules/.pnpm/lucide-react@0.561.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/layout-grid.js","../../node_modules/.pnpm/lucide-react@0.561.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/plus.js","../../node_modules/.pnpm/lucide-react@0.561.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/refresh-cw.js","../../node_modules/.pnpm/nanoid@5.1.16/node_modules/nanoid/url-alphabet/index.js","../../node_modules/.pnpm/nanoid@5.1.16/node_modules/nanoid/index.browser.js","../src/config.ts","../src/services/authRedirect.ts","../src/services/authService.ts","../src/core/extensionRegistry.ts"],"sourcesContent":["/**\n * @license lucide-react v0.561.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"7\", height: \"7\", x: \"3\", y: \"3\", rx: \"1\", key: \"1g98yp\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"3\", rx: \"1\", key: \"6d4xhi\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"14\", rx: \"1\", key: \"nxv5o0\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"3\", y: \"14\", rx: \"1\", key: \"1bb6yr\" }]\n];\nconst LayoutGrid = createLucideIcon(\"layout-grid\", __iconNode);\n\nexport { __iconNode, LayoutGrid as default };\n//# sourceMappingURL=layout-grid.js.map\n","/**\n * @license lucide-react v0.561.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }]\n];\nconst Plus = createLucideIcon(\"plus\", __iconNode);\n\nexport { __iconNode, Plus as default };\n//# sourceMappingURL=plus.js.map\n","/**\n * @license lucide-react v0.561.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\", key: \"v9h5vc\" }],\n [\"path\", { d: \"M21 3v5h-5\", key: \"1q7to0\" }],\n [\"path\", { d: \"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\", key: \"3uifl3\" }],\n [\"path\", { d: \"M8 16H3v5\", key: \"1cv678\" }]\n];\nconst RefreshCw = createLucideIcon(\"refresh-cw\", __iconNode);\n\nexport { __iconNode, RefreshCw as default };\n//# sourceMappingURL=refresh-cw.js.map\n","export let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\n","\n\nimport { urlAlphabet as scopedUrlAlphabet } from './url-alphabet/index.js'\n\nexport { urlAlphabet } from './url-alphabet/index.js'\n\nexport let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))\n\nexport let customRandom = (alphabet, defaultSize, getRandom) => {\n let safeByteCutoff = 256 - (256 % alphabet.length)\n\n if (safeByteCutoff === 256) {\n let mask = alphabet.length - 1\n\n return (size = defaultSize) => {\n if (!size) return ''\n let id = ''\n while (true) {\n let bytes = getRandom(size)\n let j = size\n while (j--) {\n id += alphabet[bytes[j] & mask]\n if (id.length >= size) return id\n }\n }\n }\n }\n\n let step = Math.ceil((1.6 * 256 * defaultSize) / safeByteCutoff)\n\n return (size = defaultSize) => {\n if (!size) return ''\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let j = step\n while (j--) {\n if (bytes[j] < safeByteCutoff) {\n id += alphabet[bytes[j] % alphabet.length]\n if (id.length >= size) return id\n }\n }\n }\n }\n}\n\nexport let customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size | 0, random)\n\nexport let nanoid = (size = 21) => {\n let id = ''\n let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)))\n while (size--) {\n id += scopedUrlAlphabet[bytes[size] & 63]\n }\n return id\n}\n","\n// Application Configuration\n\n// API Base URL: Can be overridden by VITE_API_BASE_URL environment variable.\n// `nest-public` builds use an empty string so mobile devices call the same host\n// that serves the static Workbench bundle.\nexport const API_BASE_URL =\n import.meta.env.VITE_API_BASE_URL ??\n (import.meta.env.MODE === 'nest-public' || import.meta.env.MODE === 'desktop'\n ? ''\n : 'http://127.0.0.1:1626');\n\nexport const CDN_ROOT = 'https://cdn.appthen.com';\nexport const QN_IMG_EXEC = '?imageView2/0/w/1000';\n","const AUTH_STORAGE_KEYS = ['access_token', 'app-user-role', 'user_profile'];\n\nexport function clearAuthStorage() {\n AUTH_STORAGE_KEYS.forEach((key) => window.localStorage.removeItem(key));\n}\n\nexport function hasAccessToken() {\n return Boolean(window.localStorage.getItem('access_token'));\n}\n\nexport function getCurrentRedirectPath() {\n return `${window.location.pathname}${window.location.search}${window.location.hash}`;\n}\n\nexport function normalizePostLoginRedirect(redirect?: string | null) {\n const fallback = '/teams';\n if (!redirect || redirect === '/login') return fallback;\n if (!redirect.startsWith('/') || redirect.startsWith('//')) return fallback;\n\n try {\n const parsed = new URL(redirect, window.location.origin);\n const path = parsed.pathname;\n const tenantRouteMatch = path.match(/^\\/t\\/([^/]+)\\/w\\//);\n const tenantId = parsed.searchParams.get('tenantId') ||\n (tenantRouteMatch?.[1] ? decodeURIComponent(tenantRouteMatch[1]) : undefined);\n const open = parsed.searchParams.get('open');\n\n if (path.startsWith('/team/') && path.includes('/admin')) {\n const routeTenantId = path.split('/')[2];\n return routeTenantId ? `/team/${encodeURIComponent(routeTenantId)}` : fallback;\n }\n\n if (\n path === '/workbench-runtime/appthen-team-admin' ||\n path.includes('/w/team-manage') ||\n open === 'workbench-admin'\n ) {\n return tenantId ? `/team/${encodeURIComponent(tenantId)}` : fallback;\n }\n\n return `${parsed.pathname}${parsed.search}${parsed.hash}`;\n } catch {\n return fallback;\n }\n}\n\nexport function buildLoginPath(redirect = getCurrentRedirectPath()) {\n const target = normalizePostLoginRedirect(redirect);\n return `/login?redirect=${encodeURIComponent(target)}`;\n}\n\nexport function redirectToLogin(redirect = getCurrentRedirectPath(), replace = true) {\n const loginPath = buildLoginPath(redirect);\n const currentPath = getCurrentRedirectPath();\n\n if (currentPath === loginPath || window.location.pathname === '/login') {\n return;\n }\n\n if (replace) {\n window.location.replace(loginPath);\n return;\n }\n\n window.location.assign(loginPath);\n}\n","import { API_BASE_URL } from '@/config';\nimport { clearAuthStorage, redirectToLogin } from './authRedirect';\n\n// Basic API Configuration\n\nconst CLIENT_BASE = 'worktop';\n\nexport interface UserRole {\n id: string;\n tenant_id?: string;\n team_id: string;\n type: string;\n}\n\nexport const getCurrentUser = () => {\n try {\n const profileStr = localStorage.getItem('user_profile');\n const roleStr = localStorage.getItem('app-user-role');\n \n let profile: UserProfile | null = null;\n let role: UserRole | null = null;\n\n if (profileStr) {\n profile = JSON.parse(profileStr) as UserProfile;\n }\n if (roleStr) {\n role = JSON.parse(roleStr) as UserRole;\n }\n\n if (profile || role) {\n return {\n // Use profile.id as the primary user ID as requested. \n // Fallback to role.id only if profile is missing (though user noted role.id is likely different).\n id: profile?.id ? String(profile.id) : role?.id,\n tenantId: role?.tenant_id || role?.team_id,\n teamId: role?.team_id,\n type: role?.type,\n name: profile?.name,\n avatar: profile?.avatar\n };\n }\n } catch (e) {\n console.error('Failed to parse user info', e);\n }\n return null;\n};\n\nexport const getAuthHeaders = () => {\n const token = localStorage.getItem('access_token');\n const authHeader = token ? `Bearer ${token}` : '';\n \n // Construct Client header\n let clientHeader = CLIENT_BASE;\n try {\n const roleStr = localStorage.getItem('app-user-role');\n if (roleStr) {\n const role = JSON.parse(roleStr) as UserRole;\n if (role && role.type && role.id && role.team_id) {\n clientHeader = `${CLIENT_BASE}-${role.type}-${role.id}-${role.team_id}`;\n }\n }\n } catch (e) {\n console.error('Failed to parse user role from storage', e);\n }\n \n return {\n 'Accept': 'application/json, text/plain, */*',\n 'Authorization': authHeader,\n 'Client': clientHeader,\n 'Content-Type': 'application/json'\n };\n};\n\nexport interface ApiResponse<T = any> {\n code: number;\n data: T;\n message?: string;\n success?: boolean;\n}\n\nexport class ApiRequestError extends Error {\n status: number;\n\n constructor(status: number, message?: string) {\n super(message || `HTTP error! status: ${status}`);\n this.name = 'ApiRequestError';\n this.status = status;\n }\n}\n\nexport async function request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const url = `${API_BASE_URL}${endpoint}`;\n const authHeaders = getAuthHeaders();\n\n const config = {\n ...options,\n headers: {\n ...authHeaders,\n ...options.headers,\n },\n };\n\n try {\n const response = await fetch(url, config);\n \n if (!response.ok) {\n if (response.status === 401) {\n clearAuthStorage();\n redirectToLogin();\n }\n throw new ApiRequestError(response.status);\n }\n \n const result = await response.json();\n \n // Assuming standard response structure. Adjust if backend differs.\n // The user doc didn't specify the wrapper structure (e.g. { code: 200, data: ... }), \n // but it's common. I'll assume the documented response is the direct body or inside 'data'.\n // For now, let's return the result directly or handle a 'data' field if present.\n // If the backend returns the fields directly at the root, we return result.\n return result; \n } catch (error) {\n console.error('API Request Failed:', error);\n throw error;\n }\n}\n\n// --- Types ---\n\nexport interface LoginParams {\n phone: string;\n password?: string;\n sms_code?: string;\n}\n\nexport interface LoginResponse {\n access_token: string;\n default_role_id: string;\n default_team_id: string;\n tenantId?: string;\n subjectId?: string;\n role?: string;\n [key: string]: any;\n}\n\nexport interface VerifyCodeParams {\n phone: string;\n}\n\nexport interface QRCodeResponse {\n qrcode: string;\n ticket: string;\n}\n\nexport interface LoginStatusParams {\n sessionId: string;\n}\n\nexport interface LoginStatusResponse {\n callbackAt?: string;\n [key: string]: any;\n}\n\nexport interface UserProfile {\n id: number;\n name: string;\n avatar: string;\n create_time: string;\n last_login_time: string;\n create_ip: string;\n last_login_ip: string;\n create_where_from: string | null;\n status: string;\n uid: number;\n wxapp_openid: string | null;\n weixin_openid: string | null;\n weixin_unionid: string | null;\n app_push_id: string;\n app_os: number;\n app_version: number;\n desc: string;\n gender: number;\n country: string | null;\n province: string | null;\n city: string | null;\n distanct: string | null;\n}\n\n// --- Auth Service ---\n\nexport const authService = {\n getCasdoorLoginUrl: (redirect = '/teams'): string => {\n const params = new URLSearchParams({\n redirect,\n frontend: window.location.origin,\n });\n return `${API_BASE_URL}/identity/casdoor/login?${params.toString()}`;\n },\n\n /**\n * Login by Auth String\n * @param authString - \"token##clientTicket\"\n */\n loginByAuth: async (authString): Promise<void> => {\n try {\n // \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6MTAwMDAxLCJzdWIiOjEwMDAwMSwiaWF0IjoxNzY3MzM3MjExLCJleHAiOjE3Njk5MjkyMTF9.KhtJhON4drnfxtiLrwZcv3kPEj7ucaeGpfEhc76yqek##worktop-user-61-118159\"\n const [token, clientTicket] = authString.split('__');\n const [type = 'user', id = '0', team_id = '0'] = (clientTicket || '').split('-');\n localStorage.setItem('access_token', token);\n await authService.getUserProfile();\n localStorage.setItem('app-user-role', JSON.stringify({\n type,\n id,\n team_id,\n }));\n } catch (error) {\n console.error('Failed to login by auth:', error);\n throw error;\n }\n },\n\n /**\n * Get User Profile & Check Token Validity\n */\n getUserProfile: async (): Promise<UserProfile> => {\n try {\n const userInfo = await request<UserProfile>('/user/profile', {\n method: 'GET',\n });\n \n // Save user profile to local storage\n localStorage.setItem('user_profile', JSON.stringify(userInfo));\n return userInfo;\n } catch (error) {\n // If error occurs (e.g. 401), consider token expired\n console.error('Failed to get user profile / Token expired:', error);\n throw error;\n }\n },\n\n /**\n * User Login (Password or SMS Code)\n */\n login: async (params: LoginParams): Promise<LoginResponse> => {\n // Mapping params to backend expected fields if necessary\n // Doc says: phone -> username/mobile, sms_code -> captcha\n // But also lists request params as phone, password, sms_code.\n // I will send as is, but if backend needs specific keys, I'll map them.\n // Based on doc: \n // 账号登录: { phone: username, password }\n // 验证码登录: { phone: mobile, sms_code: captcha }\n \n // Let's assume the backend accepts the keys as documented in the table first: phone, password, sms_code\n return request<LoginResponse>('/user/login', {\n method: 'POST',\n body: JSON.stringify(params),\n });\n },\n\n /**\n * Casdoor 密码登录(ROPC):自建登录页提交账号/密码,由后端代理到 Casdoor 验证,\n * 成功后返回 AppThen authString(token__user-roleId-teamId),交给 loginByAuth 落地。\n */\n casdoorPasswordLogin: async (\n username: string,\n password: string,\n ): Promise<{ authString: string; tenantId?: string; subjectId?: string }> => {\n return request('/identity/casdoor/password-login', {\n method: 'POST',\n body: JSON.stringify({ username, password }),\n });\n },\n\n /**\n * 手机号 + 验证码登录:验证码由平台短信服务发送/校验,账户落地到 subject 体系并签发自有 JWT。\n */\n phoneLogin: async (\n phone: string,\n code: string,\n ): Promise<{ authString: string; tenantId?: string; subjectId?: string }> => {\n return request('/identity/casdoor/phone-login', {\n method: 'POST',\n body: JSON.stringify({ phone, code }),\n });\n },\n\n /**\n * 发送手机验证码(身份体系发码入口,不再直调旧 /sms/getVerifyCode)\n */\n getVerifyCode: async (phone: string): Promise<void> => {\n return request<void>('/identity/verification-code', {\n method: 'POST',\n body: JSON.stringify({ phone }),\n });\n },\n\n /**\n * Get Login QR Code\n */\n getLoginQRCode: async (): Promise<QRCodeResponse> => {\n return request<QRCodeResponse>('/user/get-login-qrcode', {\n method: 'POST',\n body: JSON.stringify({}),\n });\n },\n\n /**\n * Check Login Status (Polling)\n */\n getLoginStatus: async (ticket: string): Promise<LoginStatusResponse> => {\n return request<LoginStatusResponse>('/user/get-login-status', {\n method: 'POST',\n body: JSON.stringify({ sessionId: ticket }),\n });\n },\n};\n","\nimport React from 'react';\nimport {\n ICustomEditorProps,\n IExtensionContribution,\n IMutationProvider,\n MenuItem,\n} from '../types';\nimport type { CollaborationAdapter } from './realtime/types';\nimport { getUIResourceRegistry } from './ui-resource';\nimport type { UIResourceRegistration } from './ui-resource';\nimport type { IEnhancedExtensionManifest, FrontendMCPTool } from './ExtensionManifestSchema';\nimport { extractUIResourcesFromManifest, extractFrontendToolsFromManifest } from './ExtensionManifestSchema';\nimport { registerFrontendToolDeclaration } from './pluginCapabilities';\nimport { request } from '@/services/authService';\n\ntype EditorComponent = React.FC<ICustomEditorProps>;\ntype SidebarComponent = React.FC<any>;\ntype MainViewComponent = React.FC<{ onClose?: () => void; [key: string]: any }>;\ntype EditorViewComponent = React.ComponentType<any>; // For custom editor views (like ChangesPage)\n\nexport interface ViewRegistrationMetadata {\n extensionId?: string;\n routeKey?: string;\n}\n\n/**\n * 编辑器提供者选择器(对标 VS Code custom editor selector)。\n * 旧字符串签名(单个后缀)保留:等价于 { fileExtension }。\n */\nexport interface EditorProviderSelector {\n /** 单个文件后缀(含点,如 '.md')。与 fileExtensions 二选一 */\n fileExtension?: string;\n /** 多个文件后缀(含点) */\n fileExtensions?: string[];\n /** 文件名 glob 模式(如 ['README*', '*.config.json']),* 通配单段 */\n filenamePatterns?: string[];\n /** MIME 类型精确匹配(如 ['text/markdown', 'text/x-markdown']) */\n mimeTypes?: string[];\n /** 优先级,默认 0,同规则命中时大者胜 */\n priority?: number;\n}\n\n/**\n * MainView 定义 - 不需要关联文件的主视图\n */\nexport interface MainViewDefinition {\n id: string;\n title: string;\n component: MainViewComponent;\n icon?: React.ReactNode;\n extensionId?: string;\n routeKey?: string;\n /** 是否在标签栏显示 */\n showInTabs?: boolean;\n /** 是否可以被用户关闭 */\n closable?: boolean;\n}\n\nexport class ExtensionRegistry {\n /** 编辑器提供者注册项(数组保注册序,匹配规则见 getEditorProvider) */\n private editorProviderEntries: Array<{\n selector: Required<Pick<EditorProviderSelector, 'fileExtensions' | 'filenamePatterns' | 'mimeTypes' | 'priority'>>;\n component: EditorComponent;\n }> = [];\n private sidebarProviders = new Map<string, SidebarComponent>();\n private mainViews = new Map<string, MainViewDefinition>();\n private editorViews = new Map<string, EditorViewComponent>(); // Custom editor views\n private editorViewMetadata = new Map<string, ViewRegistrationMetadata>();\n private sidebarViewMetadata = new Map<string, ViewRegistrationMetadata>();\n private mutationProviders: IMutationProvider[] = [];\n private contributions = new Map<string, IExtensionContribution[]>();\n private saveHandlers: Array<(fileId: string, content: string) => Promise<void>> = [];\n\n // === Main View (不需要文件的主视图) ===\n\n /**\n * 注册主视图(如市场、设置等不需要关联文件的视图)\n */\n registerMainView(definition: MainViewDefinition) {\n this.mainViews.set(definition.id, definition);\n console.log(`[ExtensionRegistry] Registered main view: ${definition.id}`);\n }\n\n /**\n * 获取主视图\n */\n getMainView(id: string): MainViewDefinition | undefined {\n return this.mainViews.get(id);\n }\n\n /**\n * 获取所有主视图\n */\n getAllMainViews(): MainViewDefinition[] {\n return Array.from(this.mainViews.values());\n }\n\n /**\n * 注销主视图\n */\n unregisterMainView(id: string): boolean {\n const result = this.mainViews.delete(id);\n if (result) {\n console.log(`[ExtensionRegistry] Unregistered main view: ${id}`);\n }\n return result;\n }\n\n registerSaveHandler(handler: (fileId: string, content: string) => Promise<void>) {\n this.saveHandlers.push(handler);\n }\n\n /**\n * 注销保存处理器\n *\n * @param handler - 要注销的处理器函数\n * @returns 是否成功注销\n */\n unregisterSaveHandler(handler: (fileId: string, content: string) => Promise<void>): boolean {\n const index = this.saveHandlers.indexOf(handler);\n if (index !== -1) {\n this.saveHandlers.splice(index, 1);\n return true;\n }\n return false;\n }\n\n /**\n * 清空所有保存处理器\n */\n clearSaveHandlers(): void {\n this.saveHandlers = [];\n }\n\n async notifySave(fileId: string, content: string) {\n await Promise.all(this.saveHandlers.map(h => h(fileId, content).catch(console.error)));\n }\n\n /**\n * 注册编辑器提供者。\n * 兼容旧签名 registerEditorProvider('.md', component);\n * 新签名支持对象选择器(后缀数组 / 文件名模式 / MIME / 优先级)。\n */\n registerEditorProvider(\n fileExtensionOrSelector: string | EditorProviderSelector,\n component: EditorComponent,\n ) {\n const selector: EditorProviderSelector =\n typeof fileExtensionOrSelector === 'string'\n ? { fileExtension: fileExtensionOrSelector }\n : fileExtensionOrSelector;\n\n const extensions = selector.fileExtensions?.slice() ?? (\n selector.fileExtension ? [selector.fileExtension] : []\n );\n const patterns = selector.filenamePatterns?.slice() ?? [];\n const mimes = selector.mimeTypes?.slice() ?? [];\n if (extensions.length === 0 && patterns.length === 0 && mimes.length === 0) {\n console.warn('[ExtensionRegistry] registerEditorProvider ignored: empty selector');\n return;\n }\n\n this.editorProviderEntries.push({\n selector: {\n fileExtensions: extensions,\n filenamePatterns: patterns,\n mimeTypes: mimes,\n priority: selector.priority ?? 0,\n },\n component,\n });\n }\n\n /**\n * 解析编辑器提供者。匹配优先级:\n * filenamePattern > mimeType 精确 > mimeType 通配(type/*)> 最长后缀 > priority > 注册序。\n * mimeType 缺省时跳过 mime 规则(不视为命中)。\n */\n getEditorProvider(filename: string, mimeType?: string): EditorComponent | undefined {\n const lowerName = filename.toLowerCase();\n let best: { component: EditorComponent; score: number } | null = null;\n\n for (let i = 0; i < this.editorProviderEntries.length; i += 1) {\n const { selector, component } = this.editorProviderEntries[i];\n let score: number | null = null;\n\n const pattern = selector.filenamePatterns.find((p) =>\n matchFilenamePattern(lowerName, p.toLowerCase()),\n );\n if (pattern) {\n score = 3_000_000 + selector.priority * 1000 - i;\n } else if (mimeType && selector.mimeTypes.includes(mimeType)) {\n score = 2_000_000 + selector.priority * 1000 - i;\n } else if (\n mimeType &&\n selector.mimeTypes.some(\n (m) => m.endsWith('/*') && mimeType.startsWith(m.slice(0, -1)),\n )\n ) {\n // 通配 mime(如 image/*):低于精确 mime(2M 档),高于后缀(1M 档)\n score = 1_900_000 + selector.priority * 1000 - i;\n } else {\n const ext = selector.fileExtensions\n .filter((e) => lowerName.endsWith(e.toLowerCase()))\n .sort((a, b) => b.length - a.length)[0];\n if (ext) {\n score = 1_000_000 + ext.length * 1000 + selector.priority * 100 - i;\n }\n }\n\n if (score !== null && (!best || score > best.score)) {\n best = { component, score };\n }\n }\n return best?.component;\n }\n\n /**\n * 注销编辑器提供者。字符串 = 精确删除该后缀的所有注册;\n * 对象 = 删除首个同时命中其后缀/mime/pattern 集合的注册项。\n */\n unregisterEditorProvider(\n fileExtensionOrSelector: string | EditorProviderSelector,\n ): boolean {\n if (typeof fileExtensionOrSelector === 'string') {\n const ext = fileExtensionOrSelector;\n const before = this.editorProviderEntries.length;\n this.editorProviderEntries = this.editorProviderEntries.filter(\n (entry) => !(entry.selector.fileExtensions.length === 1 && entry.selector.fileExtensions[0] === ext),\n );\n return this.editorProviderEntries.length < before;\n }\n\n const { fileExtension, fileExtensions, filenamePatterns, mimeTypes, priority } = fileExtensionOrSelector;\n const wantExts = new Set((fileExtensions ?? (fileExtension ? [fileExtension] : [])).map((e) => e.toLowerCase()));\n const index = this.editorProviderEntries.findIndex((entry) => {\n const s = entry.selector;\n if (wantExts.size > 0 && (!s.fileExtensions.length || !s.fileExtensions.every((e) => wantExts.has(e.toLowerCase())))) return false;\n if (filenamePatterns && filenamePatterns.join('\\n') !== s.filenamePatterns.join('\\n')) return false;\n if (mimeTypes && mimeTypes.join('\\n') !== s.mimeTypes.join('\\n')) return false;\n if (priority !== undefined && priority !== s.priority) return false;\n return true;\n });\n if (index < 0) return false;\n this.editorProviderEntries.splice(index, 1);\n return true;\n }\n\n registerSidebarView(\n id: string,\n component: SidebarComponent,\n metadata: ViewRegistrationMetadata = {},\n ) {\n this.sidebarProviders.set(id, component);\n this.sidebarViewMetadata.set(id, metadata);\n }\n\n getSidebarView(id: string): SidebarComponent | undefined {\n return this.sidebarProviders.get(id);\n }\n\n /**\n * 注销侧边栏视图\n */\n unregisterSidebarView(id: string): boolean {\n this.sidebarViewMetadata.delete(id);\n return this.sidebarProviders.delete(id);\n }\n\n // === Editor Views (自定义编辑器视图) ===\n\n /**\n * 注册编辑器视图 (如 ChangesPage 等)\n */\n registerEditorView(\n viewId: string,\n component: EditorViewComponent,\n metadata: ViewRegistrationMetadata = {},\n ) {\n this.editorViews.set(viewId, component);\n this.editorViewMetadata.set(viewId, metadata);\n console.log(`[ExtensionRegistry] Registered editor view: ${viewId}`);\n }\n\n /**\n * 获取编辑器视图组件\n */\n getEditorView(viewId: string): EditorViewComponent | undefined {\n return this.editorViews.get(viewId);\n }\n\n /**\n * 注销编辑器视图\n */\n unregisterEditorView(viewId: string): boolean {\n this.editorViewMetadata.delete(viewId);\n const result = this.editorViews.delete(viewId);\n if (result) {\n console.log(`[ExtensionRegistry] Unregistered editor view: ${viewId}`);\n }\n return result;\n }\n\n getEditorViewMetadata(viewId: string): ViewRegistrationMetadata | undefined {\n return this.editorViewMetadata.get(viewId);\n }\n\n getSidebarViewMetadata(viewId: string): ViewRegistrationMetadata | undefined {\n return this.sidebarViewMetadata.get(viewId);\n }\n\n getEditorViewIdByRouteKey(extensionId: string, routeKey: string): string | undefined {\n return Array.from(this.editorViewMetadata.entries()).find(([, metadata]) =>\n metadata.extensionId === extensionId && metadata.routeKey === routeKey,\n )?.[0];\n }\n\n getMainViewIdByRouteKey(extensionId: string, routeKey: string): string | undefined {\n return Array.from(this.mainViews.values()).find((view) =>\n view.extensionId === extensionId && view.routeKey === routeKey,\n )?.id;\n }\n\n // --- NEW: Granular Mutation Support ---\n\n registerMutationProvider(provider: IMutationProvider) {\n this.mutationProviders.push(provider);\n console.log(`[ExtensionRegistry] Registered Mutation Provider: ${provider.id}`);\n }\n\n getMutationProvider(filename: string): IMutationProvider | undefined {\n return this.mutationProviders.find(p => p.fileMatch(filename));\n }\n\n getAllMutationProviders(): IMutationProvider[] {\n return this.mutationProviders;\n }\n\n /**\n * 注销变更提供者\n */\n unregisterMutationProvider(providerId: string): boolean {\n const index = this.mutationProviders.findIndex(p => p.id === providerId);\n if (index !== -1) {\n this.mutationProviders.splice(index, 1);\n console.log(`[ExtensionRegistry] Unregistered Mutation Provider: ${providerId}`);\n return true;\n }\n return false;\n }\n\n /**\n * 注册扩展贡献点\n *\n * @example\n * // Flow 节点贡献\n * extensionRegistry.registerContribution('flow.node', 'my.node', {\n * type: 'custom',\n * label: 'My Node',\n * icon: <Icon />,\n * component: MyComponent,\n * category: 'custom'\n * });\n *\n * @param point - 贡献点标识符 (如 'flow.node', 'topbar.item', 'explorer.context')\n * @param id - 贡献唯一标识符\n * @param data - 贡献数据,根据 point 的不同而不同\n */\n // Type-safe overloads for common contribution points\n registerContribution(point: 'explorer.context', id: string, data: (context: any) => MenuItem[]): void;\n registerContribution(point: 'topbar.item' | 'topbar.menu', id: string, data: { id?: string; component: React.ComponentType<any> }): void;\n registerContribution(point: 'collaboration.adapter', id: string, data: CollaborationAdapter): void;\n // Fallback for unknown contribution points\n registerContribution(point: string, id: string, data: unknown): void;\n\n registerContribution(point: string, id: string, data: unknown) {\n if (!this.contributions.has(point)) {\n this.contributions.set(point, []);\n }\n const list = this.contributions.get(point)!;\n const existingIndex = list.findIndex(c => c.id === id);\n\n if (existingIndex !== -1) {\n // Update existing contribution\n list[existingIndex] = { id, point, data };\n } else {\n // Add new contribution\n list.push({ id, point, data });\n }\n }\n\n /**\n * 获取指定贡献点的所有贡献数据\n *\n * @template T - 期望的贡献数据类型\n * @param point - 贡献点标识符\n * @returns 贡献数据数组\n */\n getContributions<T = unknown>(point: string): T[] {\n return this.contributions.get(point)?.map(c => c.data as T) || [];\n }\n\n getCollaborationAdapters(): CollaborationAdapter[] {\n return this.getContributions<CollaborationAdapter>('collaboration.adapter')\n .sort((a, b) => (b.priority || 0) - (a.priority || 0));\n }\n\n /**\n * 注销贡献点\n *\n * @param point - 贡献点标识符 (如 'flow.node', 'topbar.item', 'explorer.context')\n * @param id - 贡献唯一标识符\n * @returns 是否成功注销\n */\n unregisterContribution(point: string, id: string): boolean {\n if (!this.contributions.has(point)) {\n return false;\n }\n const list = this.contributions.get(point)!;\n const index = list.findIndex(c => c.id === id);\n\n if (index !== -1) {\n list.splice(index, 1);\n // 如果该贡献点下没有贡献了,删除整个 key\n if (list.length === 0) {\n this.contributions.delete(point);\n }\n return true;\n }\n return false;\n }\n\n /**\n * 注销某个贡献点下的所有贡献\n *\n * @param point - 贡献点标识符\n * @returns 注销的贡献数量\n */\n unregisterAllContributions(point: string): number {\n if (!this.contributions.has(point)) {\n return 0;\n }\n const count = this.contributions.get(point)!.length;\n this.contributions.delete(point);\n return count;\n }\n\n // === MCP Apps 集成 ===\n\n /**\n * 注册 UI 资源 (来自插件的 MCP Apps 配置)\n */\n registerUIResourceFromManifest(manifest: IEnhancedExtensionManifest) {\n if (!manifest.mcp?.enabled && manifest.mcp?.enabled !== undefined) {\n return;\n }\n\n const uiRegistry = getUIResourceRegistry();\n const resources = extractUIResourcesFromManifest(manifest);\n\n for (const resourceRef of resources) {\n if ('content' in resourceRef) {\n // 完整的 UIResourceRegistration\n const registration = resourceRef as UIResourceRegistration;\n uiRegistry.register(registration);\n console.log(`[ExtensionRegistry] Registered UI resource: ${resourceRef.uri}`);\n \n // 同步到后端\n this.syncUIResourceToBackend(registration, manifest.id);\n } else {\n // UIResourceReference - 需要从其他地方加载完整资源\n // 这里可以触发资源加载或通知需要加载\n console.log(`[ExtensionRegistry] UI resource reference found: ${resourceRef.uri}`);\n }\n }\n }\n\n /**\n * 将 UI 资源同步到后端\n */\n private async syncUIResourceToBackend(resource: UIResourceRegistration, sourceId?: string) {\n try {\n const payload = {\n ...resource,\n source: sourceId ? `extension:${sourceId}` : 'unknown'\n };\n\n await request('/ui-resources/register', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n\n console.log(`[ExtensionRegistry] Successfully synced UI resource ${resource.uri} to backend`);\n } catch (error) {\n console.error(`[ExtensionRegistry] Error syncing UI resource ${resource.uri}:`, error);\n }\n }\n\n /**\n * 注册前端 MCP 工具 (来自插件的 MCP Apps 配置)\n */\n registerFrontendToolsFromManifest(manifest: IEnhancedExtensionManifest) {\n if (!manifest.mcp?.enabled && manifest.mcp?.enabled !== undefined) {\n return;\n }\n\n const tools = extractFrontendToolsFromManifest(manifest);\n tools.forEach(tool => {\n registerFrontendToolDeclaration({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n appOnly: tool.appOnly,\n source: `manifest:${manifest.id}`,\n handlerRef: tool.handler,\n });\n });\n console.log(`[ExtensionRegistry] Registered ${tools.length} frontend tool declarations from manifest: ${manifest.id}`);\n }\n\n /**\n * 从插件 Manifest 注册所有 MCP 相关配置\n */\n registerMCPFromManifest(manifest: IEnhancedExtensionManifest) {\n this.registerUIResourceFromManifest(manifest);\n this.registerFrontendToolsFromManifest(manifest);\n }\n}\n\n/**\n * 简单文件名 glob 匹配(仅 * 通配,不支持递归 **)。\n * 'readme*' / '*.config.json' / 'dockerfile' 等常见模式。\n */\nfunction matchFilenamePattern(lowerFilename: string, pattern: string): boolean {\n const parts = pattern.split('*');\n let cursor = 0;\n for (let i = 0; i < parts.length; i += 1) {\n const part = parts[i];\n if (part === '') continue;\n if (i === 0) {\n // 首段必须前缀命中\n if (!lowerFilename.startsWith(part)) return false;\n cursor = part.length;\n } else if (i === parts.length - 1) {\n // 末段必须后缀命中且不重叠前文\n if (!lowerFilename.endsWith(part) || cursor > lowerFilename.length - part.length) return false;\n cursor = lowerFilename.length;\n } else {\n const found = lowerFilename.indexOf(part, cursor);\n if (found < 0) return false;\n cursor = found + part.length;\n }\n }\n return true;\n}\n\nexport const extensionRegistry = new ExtensionRegistry();\n"],"names":["__iconNode","scopedUrlAlphabet"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4]}
|
|
1
|
+
{"version":3,"file":"extensionRegistry-D35Ld-Wa.js","sources":["../../node_modules/.pnpm/lucide-react@0.561.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/layout-grid.js","../../node_modules/.pnpm/lucide-react@0.561.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/plus.js","../../node_modules/.pnpm/lucide-react@0.561.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/refresh-cw.js","../../node_modules/.pnpm/nanoid@5.1.16/node_modules/nanoid/url-alphabet/index.js","../../node_modules/.pnpm/nanoid@5.1.16/node_modules/nanoid/index.browser.js","../src/config.ts","../src/services/authRedirect.ts","../src/services/authService.ts","../src/core/extensionRegistry.ts"],"sourcesContent":["/**\n * @license lucide-react v0.561.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"7\", height: \"7\", x: \"3\", y: \"3\", rx: \"1\", key: \"1g98yp\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"3\", rx: \"1\", key: \"6d4xhi\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"14\", y: \"14\", rx: \"1\", key: \"nxv5o0\" }],\n [\"rect\", { width: \"7\", height: \"7\", x: \"3\", y: \"14\", rx: \"1\", key: \"1bb6yr\" }]\n];\nconst LayoutGrid = createLucideIcon(\"layout-grid\", __iconNode);\n\nexport { __iconNode, LayoutGrid as default };\n//# sourceMappingURL=layout-grid.js.map\n","/**\n * @license lucide-react v0.561.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }]\n];\nconst Plus = createLucideIcon(\"plus\", __iconNode);\n\nexport { __iconNode, Plus as default };\n//# sourceMappingURL=plus.js.map\n","/**\n * @license lucide-react v0.561.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\", key: \"v9h5vc\" }],\n [\"path\", { d: \"M21 3v5h-5\", key: \"1q7to0\" }],\n [\"path\", { d: \"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\", key: \"3uifl3\" }],\n [\"path\", { d: \"M8 16H3v5\", key: \"1cv678\" }]\n];\nconst RefreshCw = createLucideIcon(\"refresh-cw\", __iconNode);\n\nexport { __iconNode, RefreshCw as default };\n//# sourceMappingURL=refresh-cw.js.map\n","export let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\n","\n\nimport { urlAlphabet as scopedUrlAlphabet } from './url-alphabet/index.js'\n\nexport { urlAlphabet } from './url-alphabet/index.js'\n\nexport let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))\n\nexport let customRandom = (alphabet, defaultSize, getRandom) => {\n let safeByteCutoff = 256 - (256 % alphabet.length)\n\n if (safeByteCutoff === 256) {\n let mask = alphabet.length - 1\n\n return (size = defaultSize) => {\n if (!size) return ''\n let id = ''\n while (true) {\n let bytes = getRandom(size)\n let j = size\n while (j--) {\n id += alphabet[bytes[j] & mask]\n if (id.length >= size) return id\n }\n }\n }\n }\n\n let step = Math.ceil((1.6 * 256 * defaultSize) / safeByteCutoff)\n\n return (size = defaultSize) => {\n if (!size) return ''\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let j = step\n while (j--) {\n if (bytes[j] < safeByteCutoff) {\n id += alphabet[bytes[j] % alphabet.length]\n if (id.length >= size) return id\n }\n }\n }\n }\n}\n\nexport let customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size | 0, random)\n\nexport let nanoid = (size = 21) => {\n let id = ''\n let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)))\n while (size--) {\n id += scopedUrlAlphabet[bytes[size] & 63]\n }\n return id\n}\n","\n// Application Configuration\n\n// API Base URL: Can be overridden by VITE_API_BASE_URL environment variable.\n// `nest-public` builds use an empty string so mobile devices call the same host\n// that serves the static Workbench bundle.\nexport const API_BASE_URL =\n import.meta.env.VITE_API_BASE_URL ??\n (import.meta.env.MODE === 'nest-public' || import.meta.env.MODE === 'desktop'\n ? ''\n : 'http://127.0.0.1:1626');\n\nexport const CDN_ROOT = 'https://cdn.appthen.com';\nexport const QN_IMG_EXEC = '?imageView2/0/w/1000';\n","// 登录后的默认落点:直接进入内置工作台首页;无团队用户会由 Workbench 兜底到 /teams 创建团队\nexport const DEFAULT_POST_LOGIN_PATH = '/';\n\nconst AUTH_STORAGE_KEYS = ['access_token', 'app-user-role', 'user_profile'];\n\nexport function clearAuthStorage() {\n AUTH_STORAGE_KEYS.forEach((key) => window.localStorage.removeItem(key));\n}\n\nexport function hasAccessToken() {\n return Boolean(window.localStorage.getItem('access_token'));\n}\n\nexport function getCurrentRedirectPath() {\n return `${window.location.pathname}${window.location.search}${window.location.hash}`;\n}\n\nexport function normalizePostLoginRedirect(redirect?: string | null) {\n const fallback = DEFAULT_POST_LOGIN_PATH;\n if (!redirect || redirect === '/login' || redirect === '/teams') return fallback;\n if (!redirect.startsWith('/') || redirect.startsWith('//')) return fallback;\n\n try {\n const parsed = new URL(redirect, window.location.origin);\n const path = parsed.pathname;\n const tenantRouteMatch = path.match(/^\\/t\\/([^/]+)\\/w\\//);\n const tenantId = parsed.searchParams.get('tenantId') ||\n (tenantRouteMatch?.[1] ? decodeURIComponent(tenantRouteMatch[1]) : undefined);\n const open = parsed.searchParams.get('open');\n\n if (path.startsWith('/team/') && path.includes('/admin')) {\n const routeTenantId = path.split('/')[2];\n return routeTenantId ? `/team/${encodeURIComponent(routeTenantId)}` : fallback;\n }\n\n if (\n path === '/workbench-runtime/appthen-team-admin' ||\n path.includes('/w/team-manage') ||\n open === 'workbench-admin'\n ) {\n return tenantId ? `/team/${encodeURIComponent(tenantId)}` : fallback;\n }\n\n return `${parsed.pathname}${parsed.search}${parsed.hash}`;\n } catch {\n return fallback;\n }\n}\n\nexport function buildLoginPath(redirect = getCurrentRedirectPath()) {\n const target = normalizePostLoginRedirect(redirect);\n return `/login?redirect=${encodeURIComponent(target)}`;\n}\n\nexport function redirectToLogin(redirect = getCurrentRedirectPath(), replace = true) {\n const loginPath = buildLoginPath(redirect);\n const currentPath = getCurrentRedirectPath();\n\n if (currentPath === loginPath || window.location.pathname === '/login') {\n return;\n }\n\n if (replace) {\n window.location.replace(loginPath);\n return;\n }\n\n window.location.assign(loginPath);\n}\n","import { API_BASE_URL } from '@/config';\nimport { clearAuthStorage, redirectToLogin, DEFAULT_POST_LOGIN_PATH } from './authRedirect';\n\n// Basic API Configuration\n\nconst CLIENT_BASE = 'worktop';\n\nexport interface UserRole {\n id: string;\n tenant_id?: string;\n team_id: string;\n type: string;\n}\n\nexport const getCurrentUser = () => {\n try {\n const profileStr = localStorage.getItem('user_profile');\n const roleStr = localStorage.getItem('app-user-role');\n \n let profile: UserProfile | null = null;\n let role: UserRole | null = null;\n\n if (profileStr) {\n profile = JSON.parse(profileStr) as UserProfile;\n }\n if (roleStr) {\n role = JSON.parse(roleStr) as UserRole;\n }\n\n if (profile || role) {\n return {\n // Use profile.id as the primary user ID as requested. \n // Fallback to role.id only if profile is missing (though user noted role.id is likely different).\n id: profile?.id ? String(profile.id) : role?.id,\n tenantId: role?.tenant_id || role?.team_id,\n teamId: role?.team_id,\n type: role?.type,\n name: profile?.name,\n avatar: profile?.avatar\n };\n }\n } catch (e) {\n console.error('Failed to parse user info', e);\n }\n return null;\n};\n\nexport const getAuthHeaders = () => {\n const token = localStorage.getItem('access_token');\n const authHeader = token ? `Bearer ${token}` : '';\n \n // Construct Client header\n let clientHeader = CLIENT_BASE;\n try {\n const roleStr = localStorage.getItem('app-user-role');\n if (roleStr) {\n const role = JSON.parse(roleStr) as UserRole;\n if (role && role.type && role.id && role.team_id) {\n clientHeader = `${CLIENT_BASE}-${role.type}-${role.id}-${role.team_id}`;\n }\n }\n } catch (e) {\n console.error('Failed to parse user role from storage', e);\n }\n \n return {\n 'Accept': 'application/json, text/plain, */*',\n 'Authorization': authHeader,\n 'Client': clientHeader,\n 'Content-Type': 'application/json'\n };\n};\n\nexport interface ApiResponse<T = any> {\n code: number;\n data: T;\n message?: string;\n success?: boolean;\n}\n\nexport class ApiRequestError extends Error {\n status: number;\n\n constructor(status: number, message?: string) {\n super(message || `HTTP error! status: ${status}`);\n this.name = 'ApiRequestError';\n this.status = status;\n }\n}\n\nexport async function request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const url = `${API_BASE_URL}${endpoint}`;\n const authHeaders = getAuthHeaders();\n\n const config = {\n ...options,\n headers: {\n ...authHeaders,\n ...options.headers,\n },\n };\n\n try {\n const response = await fetch(url, config);\n \n if (!response.ok) {\n if (response.status === 401) {\n clearAuthStorage();\n redirectToLogin();\n }\n throw new ApiRequestError(response.status);\n }\n \n const result = await response.json();\n \n // Assuming standard response structure. Adjust if backend differs.\n // The user doc didn't specify the wrapper structure (e.g. { code: 200, data: ... }), \n // but it's common. I'll assume the documented response is the direct body or inside 'data'.\n // For now, let's return the result directly or handle a 'data' field if present.\n // If the backend returns the fields directly at the root, we return result.\n return result; \n } catch (error) {\n console.error('API Request Failed:', error);\n throw error;\n }\n}\n\n// --- Types ---\n\nexport interface LoginParams {\n phone: string;\n password?: string;\n sms_code?: string;\n}\n\nexport interface LoginResponse {\n access_token: string;\n default_role_id: string;\n default_team_id: string;\n tenantId?: string;\n subjectId?: string;\n role?: string;\n [key: string]: any;\n}\n\nexport interface VerifyCodeParams {\n phone: string;\n}\n\nexport interface QRCodeResponse {\n qrcode: string;\n ticket: string;\n}\n\nexport interface LoginStatusParams {\n sessionId: string;\n}\n\nexport interface LoginStatusResponse {\n callbackAt?: string;\n [key: string]: any;\n}\n\nexport interface UserProfile {\n id: number;\n name: string;\n avatar: string;\n create_time: string;\n last_login_time: string;\n create_ip: string;\n last_login_ip: string;\n create_where_from: string | null;\n status: string;\n uid: number;\n wxapp_openid: string | null;\n weixin_openid: string | null;\n weixin_unionid: string | null;\n app_push_id: string;\n app_os: number;\n app_version: number;\n desc: string;\n gender: number;\n country: string | null;\n province: string | null;\n city: string | null;\n distanct: string | null;\n}\n\n// --- Auth Service ---\n\nexport const authService = {\n getCasdoorLoginUrl: (redirect = DEFAULT_POST_LOGIN_PATH): string => {\n const params = new URLSearchParams({\n redirect,\n frontend: window.location.origin,\n });\n return `${API_BASE_URL}/identity/casdoor/login?${params.toString()}`;\n },\n\n /**\n * Login by Auth String\n * @param authString - \"token##clientTicket\"\n */\n loginByAuth: async (authString): Promise<void> => {\n try {\n // \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6MTAwMDAxLCJzdWIiOjEwMDAwMSwiaWF0IjoxNzY3MzM3MjExLCJleHAiOjE3Njk5MjkyMTF9.KhtJhON4drnfxtiLrwZcv3kPEj7ucaeGpfEhc76yqek##worktop-user-61-118159\"\n const [token, clientTicket] = authString.split('__');\n const [type = 'user', id = '0', team_id = '0'] = (clientTicket || '').split('-');\n localStorage.setItem('access_token', token);\n await authService.getUserProfile();\n localStorage.setItem('app-user-role', JSON.stringify({\n type,\n id,\n team_id,\n }));\n } catch (error) {\n console.error('Failed to login by auth:', error);\n throw error;\n }\n },\n\n /**\n * Get User Profile & Check Token Validity\n */\n getUserProfile: async (): Promise<UserProfile> => {\n try {\n const userInfo = await request<UserProfile>('/user/profile', {\n method: 'GET',\n });\n \n // Save user profile to local storage\n localStorage.setItem('user_profile', JSON.stringify(userInfo));\n return userInfo;\n } catch (error) {\n // If error occurs (e.g. 401), consider token expired\n console.error('Failed to get user profile / Token expired:', error);\n throw error;\n }\n },\n\n /**\n * User Login (Password or SMS Code)\n */\n login: async (params: LoginParams): Promise<LoginResponse> => {\n // Mapping params to backend expected fields if necessary\n // Doc says: phone -> username/mobile, sms_code -> captcha\n // But also lists request params as phone, password, sms_code.\n // I will send as is, but if backend needs specific keys, I'll map them.\n // Based on doc: \n // 账号登录: { phone: username, password }\n // 验证码登录: { phone: mobile, sms_code: captcha }\n \n // Let's assume the backend accepts the keys as documented in the table first: phone, password, sms_code\n return request<LoginResponse>('/user/login', {\n method: 'POST',\n body: JSON.stringify(params),\n });\n },\n\n /**\n * Casdoor 密码登录(ROPC):自建登录页提交账号/密码,由后端代理到 Casdoor 验证,\n * 成功后返回 AppThen authString(token__user-roleId-teamId),交给 loginByAuth 落地。\n */\n casdoorPasswordLogin: async (\n username: string,\n password: string,\n ): Promise<{ authString: string; tenantId?: string; subjectId?: string }> => {\n return request('/identity/casdoor/password-login', {\n method: 'POST',\n body: JSON.stringify({ username, password }),\n });\n },\n\n /**\n * 手机号 + 验证码登录:验证码由平台短信服务发送/校验,账户落地到 subject 体系并签发自有 JWT。\n */\n phoneLogin: async (\n phone: string,\n code: string,\n ): Promise<{ authString: string; tenantId?: string; subjectId?: string }> => {\n return request('/identity/casdoor/phone-login', {\n method: 'POST',\n body: JSON.stringify({ phone, code }),\n });\n },\n\n /**\n * 发送手机验证码(身份体系发码入口,不再直调旧 /sms/getVerifyCode)\n */\n getVerifyCode: async (phone: string): Promise<void> => {\n return request<void>('/identity/verification-code', {\n method: 'POST',\n body: JSON.stringify({ phone }),\n });\n },\n\n /**\n * Get Login QR Code\n */\n getLoginQRCode: async (): Promise<QRCodeResponse> => {\n return request<QRCodeResponse>('/user/get-login-qrcode', {\n method: 'POST',\n body: JSON.stringify({}),\n });\n },\n\n /**\n * Check Login Status (Polling)\n */\n getLoginStatus: async (ticket: string): Promise<LoginStatusResponse> => {\n return request<LoginStatusResponse>('/user/get-login-status', {\n method: 'POST',\n body: JSON.stringify({ sessionId: ticket }),\n });\n },\n};\n","\nimport React from 'react';\nimport {\n ICustomEditorProps,\n IExtensionContribution,\n IMutationProvider,\n MenuItem,\n} from '../types';\nimport type { CollaborationAdapter } from './realtime/types';\nimport { getUIResourceRegistry } from './ui-resource';\nimport type { UIResourceRegistration } from './ui-resource';\nimport type { IEnhancedExtensionManifest, FrontendMCPTool } from './ExtensionManifestSchema';\nimport { extractUIResourcesFromManifest, extractFrontendToolsFromManifest } from './ExtensionManifestSchema';\nimport { registerFrontendToolDeclaration } from './pluginCapabilities';\nimport { request } from '@/services/authService';\n\ntype EditorComponent = React.FC<ICustomEditorProps>;\ntype SidebarComponent = React.FC<any>;\ntype MainViewComponent = React.FC<{ onClose?: () => void; [key: string]: any }>;\ntype EditorViewComponent = React.ComponentType<any>; // For custom editor views (like ChangesPage)\n\nexport interface ViewRegistrationMetadata {\n extensionId?: string;\n routeKey?: string;\n}\n\n/**\n * 编辑器提供者选择器(对标 VS Code custom editor selector)。\n * 旧字符串签名(单个后缀)保留:等价于 { fileExtension }。\n */\nexport interface EditorProviderSelector {\n /** 单个文件后缀(含点,如 '.md')。与 fileExtensions 二选一 */\n fileExtension?: string;\n /** 多个文件后缀(含点) */\n fileExtensions?: string[];\n /** 文件名 glob 模式(如 ['README*', '*.config.json']),* 通配单段 */\n filenamePatterns?: string[];\n /** MIME 类型精确匹配(如 ['text/markdown', 'text/x-markdown']) */\n mimeTypes?: string[];\n /** 优先级,默认 0,同规则命中时大者胜 */\n priority?: number;\n}\n\n/**\n * MainView 定义 - 不需要关联文件的主视图\n */\nexport interface MainViewDefinition {\n id: string;\n title: string;\n component: MainViewComponent;\n icon?: React.ReactNode;\n extensionId?: string;\n routeKey?: string;\n /** 是否在标签栏显示 */\n showInTabs?: boolean;\n /** 是否可以被用户关闭 */\n closable?: boolean;\n}\n\nexport class ExtensionRegistry {\n /** 编辑器提供者注册项(数组保注册序,匹配规则见 getEditorProvider) */\n private editorProviderEntries: Array<{\n selector: Required<Pick<EditorProviderSelector, 'fileExtensions' | 'filenamePatterns' | 'mimeTypes' | 'priority'>>;\n component: EditorComponent;\n }> = [];\n private sidebarProviders = new Map<string, SidebarComponent>();\n private mainViews = new Map<string, MainViewDefinition>();\n private editorViews = new Map<string, EditorViewComponent>(); // Custom editor views\n private editorViewMetadata = new Map<string, ViewRegistrationMetadata>();\n private sidebarViewMetadata = new Map<string, ViewRegistrationMetadata>();\n private mutationProviders: IMutationProvider[] = [];\n private contributions = new Map<string, IExtensionContribution[]>();\n private saveHandlers: Array<(fileId: string, content: string) => Promise<void>> = [];\n\n // === Main View (不需要文件的主视图) ===\n\n /**\n * 注册主视图(如市场、设置等不需要关联文件的视图)\n */\n registerMainView(definition: MainViewDefinition) {\n this.mainViews.set(definition.id, definition);\n console.log(`[ExtensionRegistry] Registered main view: ${definition.id}`);\n }\n\n /**\n * 获取主视图\n */\n getMainView(id: string): MainViewDefinition | undefined {\n return this.mainViews.get(id);\n }\n\n /**\n * 获取所有主视图\n */\n getAllMainViews(): MainViewDefinition[] {\n return Array.from(this.mainViews.values());\n }\n\n /**\n * 注销主视图\n */\n unregisterMainView(id: string): boolean {\n const result = this.mainViews.delete(id);\n if (result) {\n console.log(`[ExtensionRegistry] Unregistered main view: ${id}`);\n }\n return result;\n }\n\n registerSaveHandler(handler: (fileId: string, content: string) => Promise<void>) {\n this.saveHandlers.push(handler);\n }\n\n /**\n * 注销保存处理器\n *\n * @param handler - 要注销的处理器函数\n * @returns 是否成功注销\n */\n unregisterSaveHandler(handler: (fileId: string, content: string) => Promise<void>): boolean {\n const index = this.saveHandlers.indexOf(handler);\n if (index !== -1) {\n this.saveHandlers.splice(index, 1);\n return true;\n }\n return false;\n }\n\n /**\n * 清空所有保存处理器\n */\n clearSaveHandlers(): void {\n this.saveHandlers = [];\n }\n\n async notifySave(fileId: string, content: string) {\n await Promise.all(this.saveHandlers.map(h => h(fileId, content).catch(console.error)));\n }\n\n /**\n * 注册编辑器提供者。\n * 兼容旧签名 registerEditorProvider('.md', component);\n * 新签名支持对象选择器(后缀数组 / 文件名模式 / MIME / 优先级)。\n */\n registerEditorProvider(\n fileExtensionOrSelector: string | EditorProviderSelector,\n component: EditorComponent,\n ) {\n const selector: EditorProviderSelector =\n typeof fileExtensionOrSelector === 'string'\n ? { fileExtension: fileExtensionOrSelector }\n : fileExtensionOrSelector;\n\n const extensions = selector.fileExtensions?.slice() ?? (\n selector.fileExtension ? [selector.fileExtension] : []\n );\n const patterns = selector.filenamePatterns?.slice() ?? [];\n const mimes = selector.mimeTypes?.slice() ?? [];\n if (extensions.length === 0 && patterns.length === 0 && mimes.length === 0) {\n console.warn('[ExtensionRegistry] registerEditorProvider ignored: empty selector');\n return;\n }\n\n this.editorProviderEntries.push({\n selector: {\n fileExtensions: extensions,\n filenamePatterns: patterns,\n mimeTypes: mimes,\n priority: selector.priority ?? 0,\n },\n component,\n });\n }\n\n /**\n * 解析编辑器提供者。匹配优先级:\n * filenamePattern > mimeType 精确 > mimeType 通配(type/*)> 最长后缀 > priority > 注册序。\n * mimeType 缺省时跳过 mime 规则(不视为命中)。\n */\n getEditorProvider(filename: string, mimeType?: string): EditorComponent | undefined {\n const lowerName = filename.toLowerCase();\n let best: { component: EditorComponent; score: number } | null = null;\n\n for (let i = 0; i < this.editorProviderEntries.length; i += 1) {\n const { selector, component } = this.editorProviderEntries[i];\n let score: number | null = null;\n\n const pattern = selector.filenamePatterns.find((p) =>\n matchFilenamePattern(lowerName, p.toLowerCase()),\n );\n if (pattern) {\n score = 3_000_000 + selector.priority * 1000 - i;\n } else if (mimeType && selector.mimeTypes.includes(mimeType)) {\n score = 2_000_000 + selector.priority * 1000 - i;\n } else if (\n mimeType &&\n selector.mimeTypes.some(\n (m) => m.endsWith('/*') && mimeType.startsWith(m.slice(0, -1)),\n )\n ) {\n // 通配 mime(如 image/*):低于精确 mime(2M 档),高于后缀(1M 档)\n score = 1_900_000 + selector.priority * 1000 - i;\n } else {\n const ext = selector.fileExtensions\n .filter((e) => lowerName.endsWith(e.toLowerCase()))\n .sort((a, b) => b.length - a.length)[0];\n if (ext) {\n score = 1_000_000 + ext.length * 1000 + selector.priority * 100 - i;\n }\n }\n\n if (score !== null && (!best || score > best.score)) {\n best = { component, score };\n }\n }\n return best?.component;\n }\n\n /**\n * 注销编辑器提供者。字符串 = 精确删除该后缀的所有注册;\n * 对象 = 删除首个同时命中其后缀/mime/pattern 集合的注册项。\n */\n unregisterEditorProvider(\n fileExtensionOrSelector: string | EditorProviderSelector,\n ): boolean {\n if (typeof fileExtensionOrSelector === 'string') {\n const ext = fileExtensionOrSelector;\n const before = this.editorProviderEntries.length;\n this.editorProviderEntries = this.editorProviderEntries.filter(\n (entry) => !(entry.selector.fileExtensions.length === 1 && entry.selector.fileExtensions[0] === ext),\n );\n return this.editorProviderEntries.length < before;\n }\n\n const { fileExtension, fileExtensions, filenamePatterns, mimeTypes, priority } = fileExtensionOrSelector;\n const wantExts = new Set((fileExtensions ?? (fileExtension ? [fileExtension] : [])).map((e) => e.toLowerCase()));\n const index = this.editorProviderEntries.findIndex((entry) => {\n const s = entry.selector;\n if (wantExts.size > 0 && (!s.fileExtensions.length || !s.fileExtensions.every((e) => wantExts.has(e.toLowerCase())))) return false;\n if (filenamePatterns && filenamePatterns.join('\\n') !== s.filenamePatterns.join('\\n')) return false;\n if (mimeTypes && mimeTypes.join('\\n') !== s.mimeTypes.join('\\n')) return false;\n if (priority !== undefined && priority !== s.priority) return false;\n return true;\n });\n if (index < 0) return false;\n this.editorProviderEntries.splice(index, 1);\n return true;\n }\n\n registerSidebarView(\n id: string,\n component: SidebarComponent,\n metadata: ViewRegistrationMetadata = {},\n ) {\n this.sidebarProviders.set(id, component);\n this.sidebarViewMetadata.set(id, metadata);\n }\n\n getSidebarView(id: string): SidebarComponent | undefined {\n return this.sidebarProviders.get(id);\n }\n\n /**\n * 注销侧边栏视图\n */\n unregisterSidebarView(id: string): boolean {\n this.sidebarViewMetadata.delete(id);\n return this.sidebarProviders.delete(id);\n }\n\n // === Editor Views (自定义编辑器视图) ===\n\n /**\n * 注册编辑器视图 (如 ChangesPage 等)\n */\n registerEditorView(\n viewId: string,\n component: EditorViewComponent,\n metadata: ViewRegistrationMetadata = {},\n ) {\n this.editorViews.set(viewId, component);\n this.editorViewMetadata.set(viewId, metadata);\n console.log(`[ExtensionRegistry] Registered editor view: ${viewId}`);\n }\n\n /**\n * 获取编辑器视图组件\n */\n getEditorView(viewId: string): EditorViewComponent | undefined {\n return this.editorViews.get(viewId);\n }\n\n /**\n * 注销编辑器视图\n */\n unregisterEditorView(viewId: string): boolean {\n this.editorViewMetadata.delete(viewId);\n const result = this.editorViews.delete(viewId);\n if (result) {\n console.log(`[ExtensionRegistry] Unregistered editor view: ${viewId}`);\n }\n return result;\n }\n\n getEditorViewMetadata(viewId: string): ViewRegistrationMetadata | undefined {\n return this.editorViewMetadata.get(viewId);\n }\n\n getSidebarViewMetadata(viewId: string): ViewRegistrationMetadata | undefined {\n return this.sidebarViewMetadata.get(viewId);\n }\n\n getEditorViewIdByRouteKey(extensionId: string, routeKey: string): string | undefined {\n return Array.from(this.editorViewMetadata.entries()).find(([, metadata]) =>\n metadata.extensionId === extensionId && metadata.routeKey === routeKey,\n )?.[0];\n }\n\n getMainViewIdByRouteKey(extensionId: string, routeKey: string): string | undefined {\n return Array.from(this.mainViews.values()).find((view) =>\n view.extensionId === extensionId && view.routeKey === routeKey,\n )?.id;\n }\n\n // --- NEW: Granular Mutation Support ---\n\n registerMutationProvider(provider: IMutationProvider) {\n this.mutationProviders.push(provider);\n console.log(`[ExtensionRegistry] Registered Mutation Provider: ${provider.id}`);\n }\n\n getMutationProvider(filename: string): IMutationProvider | undefined {\n return this.mutationProviders.find(p => p.fileMatch(filename));\n }\n\n getAllMutationProviders(): IMutationProvider[] {\n return this.mutationProviders;\n }\n\n /**\n * 注销变更提供者\n */\n unregisterMutationProvider(providerId: string): boolean {\n const index = this.mutationProviders.findIndex(p => p.id === providerId);\n if (index !== -1) {\n this.mutationProviders.splice(index, 1);\n console.log(`[ExtensionRegistry] Unregistered Mutation Provider: ${providerId}`);\n return true;\n }\n return false;\n }\n\n /**\n * 注册扩展贡献点\n *\n * @example\n * // Flow 节点贡献\n * extensionRegistry.registerContribution('flow.node', 'my.node', {\n * type: 'custom',\n * label: 'My Node',\n * icon: <Icon />,\n * component: MyComponent,\n * category: 'custom'\n * });\n *\n * @param point - 贡献点标识符 (如 'flow.node', 'topbar.item', 'explorer.context')\n * @param id - 贡献唯一标识符\n * @param data - 贡献数据,根据 point 的不同而不同\n */\n // Type-safe overloads for common contribution points\n registerContribution(point: 'explorer.context', id: string, data: (context: any) => MenuItem[]): void;\n registerContribution(point: 'topbar.item' | 'topbar.menu', id: string, data: { id?: string; component: React.ComponentType<any> }): void;\n registerContribution(point: 'collaboration.adapter', id: string, data: CollaborationAdapter): void;\n // Fallback for unknown contribution points\n registerContribution(point: string, id: string, data: unknown): void;\n\n registerContribution(point: string, id: string, data: unknown) {\n if (!this.contributions.has(point)) {\n this.contributions.set(point, []);\n }\n const list = this.contributions.get(point)!;\n const existingIndex = list.findIndex(c => c.id === id);\n\n if (existingIndex !== -1) {\n // Update existing contribution\n list[existingIndex] = { id, point, data };\n } else {\n // Add new contribution\n list.push({ id, point, data });\n }\n }\n\n /**\n * 获取指定贡献点的所有贡献数据\n *\n * @template T - 期望的贡献数据类型\n * @param point - 贡献点标识符\n * @returns 贡献数据数组\n */\n getContributions<T = unknown>(point: string): T[] {\n return this.contributions.get(point)?.map(c => c.data as T) || [];\n }\n\n getCollaborationAdapters(): CollaborationAdapter[] {\n return this.getContributions<CollaborationAdapter>('collaboration.adapter')\n .sort((a, b) => (b.priority || 0) - (a.priority || 0));\n }\n\n /**\n * 注销贡献点\n *\n * @param point - 贡献点标识符 (如 'flow.node', 'topbar.item', 'explorer.context')\n * @param id - 贡献唯一标识符\n * @returns 是否成功注销\n */\n unregisterContribution(point: string, id: string): boolean {\n if (!this.contributions.has(point)) {\n return false;\n }\n const list = this.contributions.get(point)!;\n const index = list.findIndex(c => c.id === id);\n\n if (index !== -1) {\n list.splice(index, 1);\n // 如果该贡献点下没有贡献了,删除整个 key\n if (list.length === 0) {\n this.contributions.delete(point);\n }\n return true;\n }\n return false;\n }\n\n /**\n * 注销某个贡献点下的所有贡献\n *\n * @param point - 贡献点标识符\n * @returns 注销的贡献数量\n */\n unregisterAllContributions(point: string): number {\n if (!this.contributions.has(point)) {\n return 0;\n }\n const count = this.contributions.get(point)!.length;\n this.contributions.delete(point);\n return count;\n }\n\n // === MCP Apps 集成 ===\n\n /**\n * 注册 UI 资源 (来自插件的 MCP Apps 配置)\n */\n registerUIResourceFromManifest(manifest: IEnhancedExtensionManifest) {\n if (!manifest.mcp?.enabled && manifest.mcp?.enabled !== undefined) {\n return;\n }\n\n const uiRegistry = getUIResourceRegistry();\n const resources = extractUIResourcesFromManifest(manifest);\n\n for (const resourceRef of resources) {\n if ('content' in resourceRef) {\n // 完整的 UIResourceRegistration\n const registration = resourceRef as UIResourceRegistration;\n uiRegistry.register(registration);\n console.log(`[ExtensionRegistry] Registered UI resource: ${resourceRef.uri}`);\n \n // 同步到后端\n this.syncUIResourceToBackend(registration, manifest.id);\n } else {\n // UIResourceReference - 需要从其他地方加载完整资源\n // 这里可以触发资源加载或通知需要加载\n console.log(`[ExtensionRegistry] UI resource reference found: ${resourceRef.uri}`);\n }\n }\n }\n\n /**\n * 将 UI 资源同步到后端\n */\n private async syncUIResourceToBackend(resource: UIResourceRegistration, sourceId?: string) {\n try {\n const payload = {\n ...resource,\n source: sourceId ? `extension:${sourceId}` : 'unknown'\n };\n\n await request('/ui-resources/register', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n\n console.log(`[ExtensionRegistry] Successfully synced UI resource ${resource.uri} to backend`);\n } catch (error) {\n console.error(`[ExtensionRegistry] Error syncing UI resource ${resource.uri}:`, error);\n }\n }\n\n /**\n * 注册前端 MCP 工具 (来自插件的 MCP Apps 配置)\n */\n registerFrontendToolsFromManifest(manifest: IEnhancedExtensionManifest) {\n if (!manifest.mcp?.enabled && manifest.mcp?.enabled !== undefined) {\n return;\n }\n\n const tools = extractFrontendToolsFromManifest(manifest);\n tools.forEach(tool => {\n registerFrontendToolDeclaration({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n appOnly: tool.appOnly,\n source: `manifest:${manifest.id}`,\n handlerRef: tool.handler,\n });\n });\n console.log(`[ExtensionRegistry] Registered ${tools.length} frontend tool declarations from manifest: ${manifest.id}`);\n }\n\n /**\n * 从插件 Manifest 注册所有 MCP 相关配置\n */\n registerMCPFromManifest(manifest: IEnhancedExtensionManifest) {\n this.registerUIResourceFromManifest(manifest);\n this.registerFrontendToolsFromManifest(manifest);\n }\n}\n\n/**\n * 简单文件名 glob 匹配(仅 * 通配,不支持递归 **)。\n * 'readme*' / '*.config.json' / 'dockerfile' 等常见模式。\n */\nfunction matchFilenamePattern(lowerFilename: string, pattern: string): boolean {\n const parts = pattern.split('*');\n let cursor = 0;\n for (let i = 0; i < parts.length; i += 1) {\n const part = parts[i];\n if (part === '') continue;\n if (i === 0) {\n // 首段必须前缀命中\n if (!lowerFilename.startsWith(part)) return false;\n cursor = part.length;\n } else if (i === parts.length - 1) {\n // 末段必须后缀命中且不重叠前文\n if (!lowerFilename.endsWith(part) || cursor > lowerFilename.length - part.length) return false;\n cursor = lowerFilename.length;\n } else {\n const found = lowerFilename.indexOf(part, cursor);\n if (found < 0) return false;\n cursor = found + part.length;\n }\n }\n return true;\n}\n\nexport const extensionRegistry = new ExtensionRegistry();\n"],"names":["__iconNode","scopedUrlAlphabet"],"mappings":";;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,eAAa;AAAA,EACjB,CAAC,QAAQ,EAAE,OAAO,KAAK,QAAQ,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,KAAK,SAAQ,CAAE;AAAA,EAC5E,CAAC,QAAQ,EAAE,OAAO,KAAK,QAAQ,KAAK,GAAG,MAAM,GAAG,KAAK,IAAI,KAAK,KAAK,SAAQ,CAAE;AAAA,EAC7E,CAAC,QAAQ,EAAE,OAAO,KAAK,QAAQ,KAAK,GAAG,MAAM,GAAG,MAAM,IAAI,KAAK,KAAK,SAAQ,CAAE;AAAA,EAC9E,CAAC,QAAQ,EAAE,OAAO,KAAK,QAAQ,KAAK,GAAG,KAAK,GAAG,MAAM,IAAI,KAAK,KAAK,SAAQ,CAAE;AAC/E;AACK,MAAC,aAAa,iBAAiB,eAAeA,YAAU;ACf7D;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,eAAa;AAAA,EACjB,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAAA,EACzC,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAC3C;AACK,MAAC,OAAO,iBAAiB,QAAQA,YAAU;ACbhD;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAM,aAAa;AAAA,EACjB,CAAC,QAAQ,EAAE,GAAG,sDAAsD,KAAK,SAAQ,CAAE;AAAA,EACnF,CAAC,QAAQ,EAAE,GAAG,cAAc,KAAK,SAAQ,CAAE;AAAA,EAC3C,CAAC,QAAQ,EAAE,GAAG,uDAAuD,KAAK,SAAQ,CAAE;AAAA,EACpF,CAAC,QAAQ,EAAE,GAAG,aAAa,KAAK,SAAQ,CAAE;AAC5C;AACK,MAAC,YAAY,iBAAiB,cAAc,UAAU;;;;;ACfpD,IAAI,cACT;ACgDQ,IAAC,SAAS,CAAC,OAAO,OAAO;AACjC,MAAI,KAAK;AACT,MAAI,QAAQ,OAAO,gBAAgB,IAAI,WAAY,QAAQ,CAAC,CAAE;AAC9D,SAAO,QAAQ;AACb,UAAMC,YAAkB,MAAM,IAAI,IAAI,EAAE;AAAA,EAC1C;AACA,SAAO;AACT;AClDO,MAAM,eAIP;AAEC,MAAM,WAAW;ACXjB,MAAM,0BAA0B;AAEvC,MAAM,oBAAoB,CAAC,gBAAgB,iBAAiB,cAAc;AAEnE,SAAS,mBAAmB;AACjC,oBAAkB,QAAQ,CAAC,QAAQ,OAAO,aAAa,WAAW,GAAG,CAAC;AACxE;AAMO,SAAS,yBAAyB;AACvC,SAAO,GAAG,OAAO,SAAS,QAAQ,GAAG,OAAO,SAAS,MAAM,GAAG,OAAO,SAAS,IAAI;AACpF;AAEO,SAAS,2BAA2B,UAA0B;AACnE,QAAM,WAAW;AACjB,MAAI,CAAC,YAAY,aAAa,YAAY,aAAa,SAAU,QAAO;AACxE,MAAI,CAAC,SAAS,WAAW,GAAG,KAAK,SAAS,WAAW,IAAI,EAAG,QAAO;AAEnE,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,UAAU,OAAO,SAAS,MAAM;AACvD,UAAM,OAAO,OAAO;AACpB,UAAM,mBAAmB,KAAK,MAAM,oBAAoB;AACxD,UAAM,WAAW,OAAO,aAAa,IAAI,UAAU,OAChD,qDAAmB,MAAK,mBAAmB,iBAAiB,CAAC,CAAC,IAAI;AACrE,UAAM,OAAO,OAAO,aAAa,IAAI,MAAM;AAE3C,QAAI,KAAK,WAAW,QAAQ,KAAK,KAAK,SAAS,QAAQ,GAAG;AACxD,YAAM,gBAAgB,KAAK,MAAM,GAAG,EAAE,CAAC;AACvC,aAAO,gBAAgB,SAAS,mBAAmB,aAAa,CAAC,KAAK;AAAA,IACxE;AAEA,QACE,SAAS,2CACT,KAAK,SAAS,gBAAgB,KAC9B,SAAS,mBACT;AACA,aAAO,WAAW,SAAS,mBAAmB,QAAQ,CAAC,KAAK;AAAA,IAC9D;AAEA,WAAO,GAAG,OAAO,QAAQ,GAAG,OAAO,MAAM,GAAG,OAAO,IAAI;AAAA,EACzD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAe,WAAW,0BAA0B;AAClE,QAAM,SAAS,2BAA2B,QAAQ;AAClD,SAAO,mBAAmB,mBAAmB,MAAM,CAAC;AACtD;AAEO,SAAS,gBAAgB,WAAW,0BAA0B,UAAU,MAAM;AACnF,QAAM,YAAY,eAAe,QAAQ;AACzC,QAAM,cAAc,uBAAA;AAEpB,MAAI,gBAAgB,aAAa,OAAO,SAAS,aAAa,UAAU;AACtE;AAAA,EACF;AAEA,MAAI,SAAS;AACX,WAAO,SAAS,QAAQ,SAAS;AACjC;AAAA,EACF;AAEA,SAAO,SAAS,OAAO,SAAS;AAClC;AC/DA,MAAM,cAAc;AASb,MAAM,iBAAiB,MAAM;AAClC,MAAI;AACF,UAAM,aAAa,aAAa,QAAQ,cAAc;AACtD,UAAM,UAAU,aAAa,QAAQ,eAAe;AAEpD,QAAI,UAA8B;AAClC,QAAI,OAAwB;AAE5B,QAAI,YAAY;AACd,gBAAU,KAAK,MAAM,UAAU;AAAA,IACjC;AACA,QAAI,SAAS;AACX,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B;AAEA,QAAI,WAAW,MAAM;AACnB,aAAO;AAAA;AAAA;AAAA,QAGL,KAAI,mCAAS,MAAK,OAAO,QAAQ,EAAE,IAAI,6BAAM;AAAA,QAC7C,WAAU,6BAAM,eAAa,6BAAM;AAAA,QACnC,QAAQ,6BAAM;AAAA,QACd,MAAM,6BAAM;AAAA,QACZ,MAAM,mCAAS;AAAA,QACf,QAAQ,mCAAS;AAAA,MAAA;AAAA,IAErB;AAAA,EACF,SAAS,GAAG;AACV,YAAQ,MAAM,6BAA6B,CAAC;AAAA,EAC9C;AACA,SAAO;AACT;AAEO,MAAM,iBAAiB,MAAM;AAClC,QAAM,QAAQ,aAAa,QAAQ,cAAc;AACjD,QAAM,aAAa,QAAQ,UAAU,KAAK,KAAK;AAG/C,MAAI,eAAe;AACnB,MAAI;AACF,UAAM,UAAU,aAAa,QAAQ,eAAe;AACpD,QAAI,SAAS;AACX,YAAM,OAAO,KAAK,MAAM,OAAO;AAC/B,UAAI,QAAQ,KAAK,QAAQ,KAAK,MAAM,KAAK,SAAS;AAChD,uBAAe,GAAG,WAAW,IAAI,KAAK,IAAI,IAAI,KAAK,EAAE,IAAI,KAAK,OAAO;AAAA,MACvE;AAAA,IACF;AAAA,EACF,SAAS,GAAG;AACV,YAAQ,MAAM,0CAA0C,CAAC;AAAA,EAC3D;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,UAAU;AAAA,IACV,gBAAgB;AAAA,EAAA;AAEpB;AASO,MAAM,wBAAwB,MAAM;AAAA,EAGzC,YAAY,QAAgB,SAAkB;AAC5C,UAAM,WAAW,uBAAuB,MAAM,EAAE;AAChD,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AACF;AAEA,eAAsB,QAAW,UAAkB,UAAuB,IAAgB;AACxF,QAAM,MAAM,GAAG,YAAY,GAAG,QAAQ;AACtC,QAAM,cAAc,eAAA;AAEpB,QAAM,SAAS;AAAA,IACb,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAG;AAAA,MACH,GAAG,QAAQ;AAAA,IAAA;AAAA,EACb;AAGF,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,KAAK,MAAM;AAExC,QAAI,CAAC,SAAS,IAAI;AACd,UAAI,SAAS,WAAW,KAAK;AAC3B,yBAAA;AACA,wBAAA;AAAA,MACF;AACA,YAAM,IAAI,gBAAgB,SAAS,MAAM;AAAA,IAC7C;AAEA,UAAM,SAAS,MAAM,SAAS,KAAA;AAO9B,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,uBAAuB,KAAK;AAC1C,UAAM;AAAA,EACR;AACF;AAiEO,MAAM,cAAc;AAAA,EACzB,oBAAoB,CAAC,WAAW,4BAAoC;AAClE,UAAM,SAAS,IAAI,gBAAgB;AAAA,MACjC;AAAA,MACA,UAAU,OAAO,SAAS;AAAA,IAAA,CAC3B;AACD,WAAO,GAAG,YAAY,2BAA2B,OAAO,UAAU;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,OAAO,eAA8B;AAChD,QAAI;AAEF,YAAM,CAAC,OAAO,YAAY,IAAI,WAAW,MAAM,IAAI;AACnD,YAAM,CAAC,OAAO,QAAQ,KAAK,KAAK,UAAU,GAAG,KAAK,gBAAgB,IAAI,MAAM,GAAG;AAC/E,mBAAa,QAAQ,gBAAgB,KAAK;AAC1C,YAAM,YAAY,eAAA;AAClB,mBAAa,QAAQ,iBAAiB,KAAK,UAAU;AAAA,QACnD;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD,CAAC;AAAA,IACJ,SAAS,OAAO;AACd,cAAQ,MAAM,4BAA4B,KAAK;AAC/C,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,YAAkC;AAChD,QAAI;AACF,YAAM,WAAW,MAAM,QAAqB,iBAAiB;AAAA,QAC3D,QAAQ;AAAA,MAAA,CACT;AAGD,mBAAa,QAAQ,gBAAgB,KAAK,UAAU,QAAQ,CAAC;AAC7D,aAAO;AAAA,IACT,SAAS,OAAO;AAEd,cAAQ,MAAM,+CAA+C,KAAK;AAClE,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,OAAO,WAAgD;AAU5D,WAAO,QAAuB,eAAe;AAAA,MAC3C,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,MAAM;AAAA,IAAA,CAC5B;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB,OACpB,UACA,aAC2E;AAC3E,WAAO,QAAQ,oCAAoC;AAAA,MACjD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,UAAU,UAAU;AAAA,IAAA,CAC5C;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,OACV,OACA,SAC2E;AAC3E,WAAO,QAAQ,iCAAiC;AAAA,MAC9C,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,OAAO,MAAM;AAAA,IAAA,CACrC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,OAAO,UAAiC;AACrD,WAAO,QAAc,+BAA+B;AAAA,MAClD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,OAAO;AAAA,IAAA,CAC/B;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,YAAqC;AACnD,WAAO,QAAwB,0BAA0B;AAAA,MACvD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,CAAA,CAAE;AAAA,IAAA,CACxB;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,OAAO,WAAiD;AACtE,WAAO,QAA6B,0BAA0B;AAAA,MAC5D,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,WAAW,QAAQ;AAAA,IAAA,CAC3C;AAAA,EACH;AACF;AChQO,MAAM,kBAAkB;AAAA,EAAxB,cAAA;AAEH,SAAQ,wBAGH,CAAA;AACL,SAAQ,uCAAuB,IAAA;AAC/B,SAAQ,gCAAgB,IAAA;AACxB,SAAQ,kCAAkB,IAAA;AAC1B,SAAQ,yCAAyB,IAAA;AACjC,SAAQ,0CAA0B,IAAA;AAClC,SAAQ,oBAAyC,CAAA;AACjD,SAAQ,oCAAoB,IAAA;AAC5B,SAAQ,eAA0E,CAAA;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnF,iBAAiB,YAAgC;AAC7C,SAAK,UAAU,IAAI,WAAW,IAAI,UAAU;AAC5C,YAAQ,IAAI,6CAA6C,WAAW,EAAE,EAAE;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,IAA4C;AACpD,WAAO,KAAK,UAAU,IAAI,EAAE;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAwC;AACpC,WAAO,MAAM,KAAK,KAAK,UAAU,QAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,IAAqB;AACpC,UAAM,SAAS,KAAK,UAAU,OAAO,EAAE;AACvC,QAAI,QAAQ;AACR,cAAQ,IAAI,+CAA+C,EAAE,EAAE;AAAA,IACnE;AACA,WAAO;AAAA,EACX;AAAA,EAEA,oBAAoB,SAA6D;AAC7E,SAAK,aAAa,KAAK,OAAO;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,sBAAsB,SAAsE;AACxF,UAAM,QAAQ,KAAK,aAAa,QAAQ,OAAO;AAC/C,QAAI,UAAU,IAAI;AACd,WAAK,aAAa,OAAO,OAAO,CAAC;AACjC,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA,EAKA,oBAA0B;AACtB,SAAK,eAAe,CAAA;AAAA,EACxB;AAAA,EAEA,MAAM,WAAW,QAAgB,SAAiB;AAC9C,UAAM,QAAQ,IAAI,KAAK,aAAa,IAAI,CAAA,MAAK,EAAE,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,uBACI,yBACA,WACF;;AACE,UAAM,WACF,OAAO,4BAA4B,WAC7B,EAAE,eAAe,4BACjB;AAEV,UAAM,eAAa,cAAS,mBAAT,mBAAyB,aACxC,SAAS,gBAAgB,CAAC,SAAS,aAAa,IAAI,CAAA;AAExD,UAAM,aAAW,cAAS,qBAAT,mBAA2B,YAAW,CAAA;AACvD,UAAM,UAAQ,cAAS,cAAT,mBAAoB,YAAW,CAAA;AAC7C,QAAI,WAAW,WAAW,KAAK,SAAS,WAAW,KAAK,MAAM,WAAW,GAAG;AACxE,cAAQ,KAAK,oEAAoE;AACjF;AAAA,IACJ;AAEA,SAAK,sBAAsB,KAAK;AAAA,MAC5B,UAAU;AAAA,QACN,gBAAgB;AAAA,QAChB,kBAAkB;AAAA,QAClB,WAAW;AAAA,QACX,UAAU,SAAS,YAAY;AAAA,MAAA;AAAA,MAEnC;AAAA,IAAA,CACH;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kBAAkB,UAAkB,UAAgD;AAChF,UAAM,YAAY,SAAS,YAAA;AAC3B,QAAI,OAA6D;AAEjE,aAAS,IAAI,GAAG,IAAI,KAAK,sBAAsB,QAAQ,KAAK,GAAG;AAC3D,YAAM,EAAE,UAAU,UAAA,IAAc,KAAK,sBAAsB,CAAC;AAC5D,UAAI,QAAuB;AAE3B,YAAM,UAAU,SAAS,iBAAiB;AAAA,QAAK,CAAC,MAC5C,qBAAqB,WAAW,EAAE,aAAa;AAAA,MAAA;AAEnD,UAAI,SAAS;AACT,gBAAQ,MAAY,SAAS,WAAW,MAAO;AAAA,MACnD,WAAW,YAAY,SAAS,UAAU,SAAS,QAAQ,GAAG;AAC1D,gBAAQ,MAAY,SAAS,WAAW,MAAO;AAAA,MACnD,WACI,YACA,SAAS,UAAU;AAAA,QACf,CAAC,MAAM,EAAE,SAAS,IAAI,KAAK,SAAS,WAAW,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,MAAA,GAEnE;AAEE,gBAAQ,OAAY,SAAS,WAAW,MAAO;AAAA,MACnD,OAAO;AACH,cAAM,MAAM,SAAS,eAChB,OAAO,CAAC,MAAM,UAAU,SAAS,EAAE,YAAA,CAAa,CAAC,EACjD,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AAC1C,YAAI,KAAK;AACL,kBAAQ,MAAY,IAAI,SAAS,MAAO,SAAS,WAAW,MAAM;AAAA,QACtE;AAAA,MACJ;AAEA,UAAI,UAAU,SAAS,CAAC,QAAQ,QAAQ,KAAK,QAAQ;AACjD,eAAO,EAAE,WAAW,MAAA;AAAA,MACxB;AAAA,IACJ;AACA,WAAO,6BAAM;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBACI,yBACO;AACP,QAAI,OAAO,4BAA4B,UAAU;AAC7C,YAAM,MAAM;AACZ,YAAM,SAAS,KAAK,sBAAsB;AAC1C,WAAK,wBAAwB,KAAK,sBAAsB;AAAA,QACpD,CAAC,UAAU,EAAE,MAAM,SAAS,eAAe,WAAW,KAAK,MAAM,SAAS,eAAe,CAAC,MAAM;AAAA,MAAA;AAEpG,aAAO,KAAK,sBAAsB,SAAS;AAAA,IAC/C;AAEA,UAAM,EAAE,eAAe,gBAAgB,kBAAkB,WAAW,aAAa;AACjF,UAAM,WAAW,IAAI,KAAK,mBAAmB,gBAAgB,CAAC,aAAa,IAAI,CAAA,IAAK,IAAI,CAAC,MAAM,EAAE,YAAA,CAAa,CAAC;AAC/G,UAAM,QAAQ,KAAK,sBAAsB,UAAU,CAAC,UAAU;AAC1D,YAAM,IAAI,MAAM;AAChB,UAAI,SAAS,OAAO,MAAM,CAAC,EAAE,eAAe,UAAU,CAAC,EAAE,eAAe,MAAM,CAAC,MAAM,SAAS,IAAI,EAAE,aAAa,CAAC,GAAI,QAAO;AAC7H,UAAI,oBAAoB,iBAAiB,KAAK,IAAI,MAAM,EAAE,iBAAiB,KAAK,IAAI,EAAG,QAAO;AAC9F,UAAI,aAAa,UAAU,KAAK,IAAI,MAAM,EAAE,UAAU,KAAK,IAAI,EAAG,QAAO;AACzE,UAAI,aAAa,UAAa,aAAa,EAAE,SAAU,QAAO;AAC9D,aAAO;AAAA,IACX,CAAC;AACD,QAAI,QAAQ,EAAG,QAAO;AACtB,SAAK,sBAAsB,OAAO,OAAO,CAAC;AAC1C,WAAO;AAAA,EACX;AAAA,EAEA,oBACI,IACA,WACA,WAAqC,CAAA,GACvC;AACE,SAAK,iBAAiB,IAAI,IAAI,SAAS;AACvC,SAAK,oBAAoB,IAAI,IAAI,QAAQ;AAAA,EAC7C;AAAA,EAEA,eAAe,IAA0C;AACrD,WAAO,KAAK,iBAAiB,IAAI,EAAE;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,sBAAsB,IAAqB;AACvC,SAAK,oBAAoB,OAAO,EAAE;AAClC,WAAO,KAAK,iBAAiB,OAAO,EAAE;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBACI,QACA,WACA,WAAqC,CAAA,GACvC;AACE,SAAK,YAAY,IAAI,QAAQ,SAAS;AACtC,SAAK,mBAAmB,IAAI,QAAQ,QAAQ;AAC5C,YAAQ,IAAI,+CAA+C,MAAM,EAAE;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,QAAiD;AAC3D,WAAO,KAAK,YAAY,IAAI,MAAM;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAqB,QAAyB;AAC1C,SAAK,mBAAmB,OAAO,MAAM;AACrC,UAAM,SAAS,KAAK,YAAY,OAAO,MAAM;AAC7C,QAAI,QAAQ;AACR,cAAQ,IAAI,iDAAiD,MAAM,EAAE;AAAA,IACzE;AACA,WAAO;AAAA,EACX;AAAA,EAEA,sBAAsB,QAAsD;AACxE,WAAO,KAAK,mBAAmB,IAAI,MAAM;AAAA,EAC7C;AAAA,EAEA,uBAAuB,QAAsD;AACzE,WAAO,KAAK,oBAAoB,IAAI,MAAM;AAAA,EAC9C;AAAA,EAEA,0BAA0B,aAAqB,UAAsC;;AACjF,YAAO,WAAM,KAAK,KAAK,mBAAmB,QAAA,CAAS,EAAE;AAAA,MAAK,CAAC,CAAA,EAAG,QAAQ,MAClE,SAAS,gBAAgB,eAAe,SAAS,aAAa;AAAA,IAAA,MAD3D,mBAEH;AAAA,EACR;AAAA,EAEA,wBAAwB,aAAqB,UAAsC;;AAC/E,YAAO,WAAM,KAAK,KAAK,UAAU,OAAA,CAAQ,EAAE;AAAA,MAAK,CAAC,SAC7C,KAAK,gBAAgB,eAAe,KAAK,aAAa;AAAA,IAAA,MADnD,mBAEJ;AAAA,EACP;AAAA;AAAA,EAIA,yBAAyB,UAA6B;AAClD,SAAK,kBAAkB,KAAK,QAAQ;AACpC,YAAQ,IAAI,qDAAqD,SAAS,EAAE,EAAE;AAAA,EAClF;AAAA,EAEA,oBAAoB,UAAiD;AACjE,WAAO,KAAK,kBAAkB,KAAK,OAAK,EAAE,UAAU,QAAQ,CAAC;AAAA,EACjE;AAAA,EAEA,0BAA+C;AAC3C,WAAO,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,2BAA2B,YAA6B;AACpD,UAAM,QAAQ,KAAK,kBAAkB,UAAU,CAAA,MAAK,EAAE,OAAO,UAAU;AACvE,QAAI,UAAU,IAAI;AACd,WAAK,kBAAkB,OAAO,OAAO,CAAC;AACtC,cAAQ,IAAI,uDAAuD,UAAU,EAAE;AAC/E,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACX;AAAA,EA0BA,qBAAqB,OAAe,IAAY,MAAe;AAC3D,QAAI,CAAC,KAAK,cAAc,IAAI,KAAK,GAAG;AAChC,WAAK,cAAc,IAAI,OAAO,CAAA,CAAE;AAAA,IACpC;AACA,UAAM,OAAO,KAAK,cAAc,IAAI,KAAK;AACzC,UAAM,gBAAgB,KAAK,UAAU,CAAA,MAAK,EAAE,OAAO,EAAE;AAErD,QAAI,kBAAkB,IAAI;AAEtB,WAAK,aAAa,IAAI,EAAE,IAAI,OAAO,KAAA;AAAA,IACvC,OAAO;AAEH,WAAK,KAAK,EAAE,IAAI,OAAO,MAAM;AAAA,IACjC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,iBAA8B,OAAoB;;AAC9C,aAAO,UAAK,cAAc,IAAI,KAAK,MAA5B,mBAA+B,IAAI,CAAA,MAAK,EAAE,UAAc,CAAA;AAAA,EACnE;AAAA,EAEA,2BAAmD;AAC/C,WAAO,KAAK,iBAAuC,uBAAuB,EACrE,KAAK,CAAC,GAAG,OAAO,EAAE,YAAY,MAAM,EAAE,YAAY,EAAE;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,uBAAuB,OAAe,IAAqB;AACvD,QAAI,CAAC,KAAK,cAAc,IAAI,KAAK,GAAG;AAChC,aAAO;AAAA,IACX;AACA,UAAM,OAAO,KAAK,cAAc,IAAI,KAAK;AACzC,UAAM,QAAQ,KAAK,UAAU,CAAA,MAAK,EAAE,OAAO,EAAE;AAE7C,QAAI,UAAU,IAAI;AACd,WAAK,OAAO,OAAO,CAAC;AAEpB,UAAI,KAAK,WAAW,GAAG;AACnB,aAAK,cAAc,OAAO,KAAK;AAAA,MACnC;AACA,aAAO;AAAA,IACX;AACA,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,2BAA2B,OAAuB;AAC9C,QAAI,CAAC,KAAK,cAAc,IAAI,KAAK,GAAG;AAChC,aAAO;AAAA,IACX;AACA,UAAM,QAAQ,KAAK,cAAc,IAAI,KAAK,EAAG;AAC7C,SAAK,cAAc,OAAO,KAAK;AAC/B,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,+BAA+B,UAAsC;;AACjE,QAAI,GAAC,cAAS,QAAT,mBAAc,cAAW,cAAS,QAAT,mBAAc,aAAY,QAAW;AAC/D;AAAA,IACJ;AAEA,UAAM,aAAa,sBAAA;AACnB,UAAM,YAAY,+BAA+B,QAAQ;AAEzD,eAAW,eAAe,WAAW;AACjC,UAAI,aAAa,aAAa;AAE1B,cAAM,eAAe;AACrB,mBAAW,SAAS,YAAY;AAChC,gBAAQ,IAAI,+CAA+C,YAAY,GAAG,EAAE;AAG5E,aAAK,wBAAwB,cAAc,SAAS,EAAE;AAAA,MAC1D,OAAO;AAGH,gBAAQ,IAAI,oDAAoD,YAAY,GAAG,EAAE;AAAA,MACrF;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,wBAAwB,UAAkC,UAAmB;AACvF,QAAI;AACA,YAAM,UAAU;AAAA,QACZ,GAAG;AAAA,QACH,QAAQ,WAAW,aAAa,QAAQ,KAAK;AAAA,MAAA;AAGjD,YAAM,QAAQ,0BAA0B;AAAA,QACpC,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,OAAO;AAAA,MAAA,CAC/B;AAED,cAAQ,IAAI,uDAAuD,SAAS,GAAG,aAAa;AAAA,IAChG,SAAS,OAAO;AACZ,cAAQ,MAAM,iDAAiD,SAAS,GAAG,KAAK,KAAK;AAAA,IACzF;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKA,kCAAkC,UAAsC;;AACpE,QAAI,GAAC,cAAS,QAAT,mBAAc,cAAW,cAAS,QAAT,mBAAc,aAAY,QAAW;AAC/D;AAAA,IACJ;AAEA,UAAM,QAAQ,iCAAiC,QAAQ;AACvD,UAAM,QAAQ,CAAA,SAAQ;AAClB,sCAAgC;AAAA,QAC5B,MAAM,KAAK;AAAA,QACX,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,QAClB,SAAS,KAAK;AAAA,QACd,QAAQ,YAAY,SAAS,EAAE;AAAA,QAC/B,YAAY,KAAK;AAAA,MAAA,CACpB;AAAA,IACL,CAAC;AACD,YAAQ,IAAI,kCAAkC,MAAM,MAAM,8CAA8C,SAAS,EAAE,EAAE;AAAA,EACzH;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwB,UAAsC;AAC1D,SAAK,+BAA+B,QAAQ;AAC5C,SAAK,kCAAkC,QAAQ;AAAA,EACnD;AACJ;AAMA,SAAS,qBAAqB,eAAuB,SAA0B;AAC3E,QAAM,QAAQ,QAAQ,MAAM,GAAG;AAC/B,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACtC,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,SAAS,GAAI;AACjB,QAAI,MAAM,GAAG;AAET,UAAI,CAAC,cAAc,WAAW,IAAI,EAAG,QAAO;AAC5C,eAAS,KAAK;AAAA,IAClB,WAAW,MAAM,MAAM,SAAS,GAAG;AAE/B,UAAI,CAAC,cAAc,SAAS,IAAI,KAAK,SAAS,cAAc,SAAS,KAAK,OAAQ,QAAO;AACzF,eAAS,cAAc;AAAA,IAC3B,OAAO;AACH,YAAM,QAAQ,cAAc,QAAQ,MAAM,MAAM;AAChD,UAAI,QAAQ,EAAG,QAAO;AACtB,eAAS,QAAQ,KAAK;AAAA,IAC1B;AAAA,EACJ;AACA,SAAO;AACX;AAEO,MAAM,oBAAoB,IAAI,kBAAA;","x_google_ignoreList":[0,1,2,3,4]}
|
package/dist/index.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { G as GoalManagementWorkspace, D as DetailMetaGrid, d as DetailSection, e as DetailListSection, f as DetailFilterTabs, h as DetailTimeline, i as DetailCommentComposer, j as DetailFieldPanel } from "./Workbench-
|
|
2
|
-
import { A, E, F, k, l, I, W, b, m, n, o, p, q, t, s, u } from "./Workbench-
|
|
3
|
-
import { b as b2, a, c, d, g, e, f, p as p2 } from "./PluginContext-
|
|
4
|
-
import { D, D as D2, a as a2, b as b3, c as c2, d as d2, e as e2, f as f2, g as g2, h, i } from "./dialog-
|
|
5
|
-
import { S, S as S2, a as a3, b as b4, c as c3, d as d3, e as e3, f as f3, g as g3, h as h2, i as i2 } from "./sheet-
|
|
6
|
-
import { A as A2, a as a4, b as b5, c as c4, d as d4, e as e4, B, f as f4, C, D as D3, g as g4, h as h3, i as i3, j, k as k2, l as l2, m as m2, n as n2, o as o2, p as p3, q as q2, r, s as s2, t as t2, E as E2, I as I2, R, u as u2, S as S3, v, w, x, y, z, F as F2, G, H, J, T, K, L, M, N, O, P, Q, U, A as A3, a as a5, b as b6, c as c5, d as d5, e as e5, B as B2, f as f5, C as C2, D as D4, g as g5, h as h4, i as i4, j as j2, k as k3, l as l3, m as m3, n as n3, o as o3, p as p4, q as q3, r as r2, s as s3, t as t3, E as E3, I as I3, R as R2, u as u3, S as S4, v as v2, w as w2, x as x2, y as y2, W as W2, X, z as z2, F as F3, G as G2, H as H2, J as J2, T as T2, K as K2, L as L2, M as M2, N as N2, O as O2, P as P2, Q as Q2, U as U2, V, V as V2, Y } from "./skeleton-
|
|
1
|
+
import { G as GoalManagementWorkspace, D as DetailMetaGrid, d as DetailSection, e as DetailListSection, f as DetailFilterTabs, h as DetailTimeline, i as DetailCommentComposer, j as DetailFieldPanel } from "./Workbench-8uTfTtsq.js";
|
|
2
|
+
import { A, E, F, k, l, I, W, b, m, n, o, p, q, t, s, u } from "./Workbench-8uTfTtsq.js";
|
|
3
|
+
import { b as b2, a, c, d, g, e, f, p as p2 } from "./PluginContext-uAiGNF8S.js";
|
|
4
|
+
import { D, D as D2, a as a2, b as b3, c as c2, d as d2, e as e2, f as f2, g as g2, h, i } from "./dialog-ssICQNSV.js";
|
|
5
|
+
import { S, S as S2, a as a3, b as b4, c as c3, d as d3, e as e3, f as f3, g as g3, h as h2, i as i2 } from "./sheet-Bsq3CLW4.js";
|
|
6
|
+
import { A as A2, a as a4, b as b5, c as c4, d as d4, e as e4, B, f as f4, C, D as D3, g as g4, h as h3, i as i3, j, k as k2, l as l2, m as m2, n as n2, o as o2, p as p3, q as q2, r, s as s2, t as t2, E as E2, I as I2, R, u as u2, S as S3, v, w, x, y, z, F as F2, G, H, J, T, K, L, M, N, O, P, Q, U, A as A3, a as a5, b as b6, c as c5, d as d5, e as e5, B as B2, f as f5, C as C2, D as D4, g as g5, h as h4, i as i4, j as j2, k as k3, l as l3, m as m3, n as n3, o as o3, p as p4, q as q3, r as r2, s as s3, t as t3, E as E3, I as I3, R as R2, u as u3, S as S4, v as v2, w as w2, x as x2, y as y2, W as W2, X, z as z2, F as F3, G as G2, H as H2, J as J2, T as T2, K as K2, L as L2, M as M2, N as N2, O as O2, P as P2, Q as Q2, U as U2, V, V as V2, Y } from "./skeleton-BSqTbX9l.js";
|
|
7
7
|
import { P as P3, T as T3, a as a6, b as b7, c as c6, d as d6, e as e6, f as f6, g as g6, h as h5, i as i5, j as j3, P as P4, T as T4, a as a7, b as b8, c as c7, d as d7, e as e7, f as f7, g as g7, h as h6, i as i6, j as j4 } from "./toast-C4mLAjyT.js";
|
|
8
|
-
import { D as D5, S as S5 } from "./DotBadge-
|
|
8
|
+
import { D as D5, S as S5 } from "./DotBadge-CeeLzNu3.js";
|
|
9
9
|
import { c as c8 } from "./types-BL0aIpQ1.js";
|
|
10
10
|
import { AgentPluginFactory, AgentPluginModule, DEFAULT_AGENT_CONFIG } from "./plugins/agent/PluginModule.js";
|
|
11
11
|
import { D as DaemonBackedAgentChannelService, W as WorkspaceAgentChannelClient } from "./index-C_Ynfr_s.js";
|
|
12
12
|
import { A as A4, H as H3, a as a8, R as R3, c as c9, b as b9, i as i7, n as n4, p as p5, d as d8, r as r3, e as e8, f as f8, g as g8, h as h7, s as s4, t as t4 } from "./index-C_Ynfr_s.js";
|
|
13
|
-
import { L as LayoutGrid, P as Plus } from "./extensionRegistry-
|
|
14
|
-
import { E as E4, a as a9, e as e9 } from "./extensionRegistry-
|
|
15
|
-
import { d as Bot, S as Sparkles, C as Cable, e as CircleQuestionMark, E as ExternalLink, W as Wrench, f as ListFilter, T as ToggleLeft, g as Star, h as SlidersHorizontal, i as Activity, j as Rocket, k as ChartLine, G as GitCommitHorizontal, l as ListTodo, m as ArrowUp, n as ArrowDown, o as CalendarRange, p as FolderKanban, q as GripHorizontal, U as Upload, r as FolderOpen, F as FileText, s as Clock3, t as Users, u as Menu, v as Funnel, w as Ellipsis, x as ChevronLeft, y as ScrollText, z as Megaphone, H as HardDrive, D as ShieldCheck, J as UserCog, K as CalendarClock, N as Building2, O as ChevronsUpDown, P as ArrowRight, Q as Settings, V as Shield, X as Workflow, Y as CirclePlus, _ as CodeXml, $ as ShieldAlert, a0 as CheckCheck, a1 as TriangleAlert, a2 as MessageSquarePlus, a3 as Bug, a4 as CircleCheck } from "./activate-
|
|
16
|
-
import { b as b10, a5 as a52 } from "./activate-
|
|
17
|
-
import { C as ConsoleButton, d as ProjectWorkspaceShell, c as CodingProductRail, b as CodingListDetailWorkspace } from "./list-detail-workspace-template-
|
|
18
|
-
import { A as A5, a as a10, D as D6, M as M3, P as P5 } from "./list-detail-workspace-template-
|
|
13
|
+
import { L as LayoutGrid, P as Plus } from "./extensionRegistry-D35Ld-Wa.js";
|
|
14
|
+
import { E as E4, a as a9, e as e9 } from "./extensionRegistry-D35Ld-Wa.js";
|
|
15
|
+
import { d as Bot, S as Sparkles, C as Cable, e as CircleQuestionMark, E as ExternalLink, W as Wrench, f as ListFilter, T as ToggleLeft, g as Star, h as SlidersHorizontal, i as Activity, j as Rocket, k as ChartLine, G as GitCommitHorizontal, l as ListTodo, m as ArrowUp, n as ArrowDown, o as CalendarRange, p as FolderKanban, q as GripHorizontal, U as Upload, r as FolderOpen, F as FileText, s as Clock3, t as Users, u as Menu, v as Funnel, w as Ellipsis, x as ChevronLeft, y as ScrollText, z as Megaphone, H as HardDrive, D as ShieldCheck, J as UserCog, K as CalendarClock, N as Building2, O as ChevronsUpDown, P as ArrowRight, Q as Settings, V as Shield, X as Workflow, Y as CirclePlus, _ as CodeXml, $ as ShieldAlert, a0 as CheckCheck, a1 as TriangleAlert, a2 as MessageSquarePlus, a3 as Bug, a4 as CircleCheck } from "./activate-DVnxnmfA.js";
|
|
16
|
+
import { b as b10, a5 as a52 } from "./activate-DVnxnmfA.js";
|
|
17
|
+
import { C as ConsoleButton, d as ProjectWorkspaceShell, c as CodingProductRail, b as CodingListDetailWorkspace } from "./list-detail-workspace-template-BTrgMGPx.js";
|
|
18
|
+
import { A as A5, a as a10, D as D6, M as M3, P as P5 } from "./list-detail-workspace-template-BTrgMGPx.js";
|
|
19
19
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
20
20
|
import { S as SurfacePanel, a as ConsoleSelectTrigger, C as ConsoleInput } from "./panel-Brh_nRmF.js";
|
|
21
21
|
import * as React from "react";
|
|
@@ -4142,7 +4142,7 @@ const APPROVAL_ROWS = [
|
|
|
4142
4142
|
})
|
|
4143
4143
|
];
|
|
4144
4144
|
function TypeBadge({ value }) {
|
|
4145
|
-
const tone = value === "需求" ? "bg-[#
|
|
4145
|
+
const tone = value === "需求" ? "bg-[#edf0fe] text-[#3e5bec]" : value === "缺陷" || value.includes("缺陷") ? "bg-[#fff1ef] text-[#c5342f]" : value === "审批单" ? "bg-[#f3f1ff] text-[#7057ff]" : "bg-[#edf8f1] text-[#18794e]";
|
|
4146
4146
|
return /* @__PURE__ */ jsx("span", { className: `rounded-[3px] px-1.5 py-[2px] text-[11px] font-medium ${tone}`, children: value });
|
|
4147
4147
|
}
|
|
4148
4148
|
function PriorityPill({ value }) {
|
|
@@ -4150,7 +4150,7 @@ function PriorityPill({ value }) {
|
|
|
4150
4150
|
return /* @__PURE__ */ jsx("span", { className: `rounded-full px-2 py-[3px] text-[11px] font-medium ${tone}`, children: value });
|
|
4151
4151
|
}
|
|
4152
4152
|
function StatusPill({ value }) {
|
|
4153
|
-
const tone = value.includes("进行") || value.includes("修复") || value.includes("审批中") ? "bg-[#
|
|
4153
|
+
const tone = value.includes("进行") || value.includes("修复") || value.includes("审批中") ? "bg-[#edf0fe] text-[#3e5bec]" : value.includes("待") || value === "未开始" ? "bg-[#f6f8fb] text-[var(--ck-text-secondary)]" : value.includes("已") ? "bg-[#edf8f1] text-[#18794e]" : "bg-[#f6f8fb] text-[var(--ck-text-secondary)]";
|
|
4154
4154
|
return /* @__PURE__ */ jsx("span", { className: `rounded-full px-2 py-[3px] text-[11px] font-medium ${tone}`, children: value });
|
|
4155
4155
|
}
|
|
4156
4156
|
function MemberPill({ value }) {
|
|
@@ -4165,7 +4165,7 @@ function TitleCell({ row }) {
|
|
|
4165
4165
|
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
4166
4166
|
/* @__PURE__ */ jsx(TypeBadge, { value: row.ticketType }),
|
|
4167
4167
|
/* @__PURE__ */ jsx("span", { className: "truncate text-[13px] font-medium text-[var(--ck-text-primary)]", children: row.title }),
|
|
4168
|
-
updatedToday ? /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-[#
|
|
4168
|
+
updatedToday ? /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-[#edf0fe] px-2 py-[2px] text-[10px] font-medium text-[#3e5bec]", children: "刚更新" }) : null
|
|
4169
4169
|
] }),
|
|
4170
4170
|
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-3 text-[11px] text-[var(--ck-text-muted)]", children: [
|
|
4171
4171
|
/* @__PURE__ */ jsx("span", { children: row.project }),
|
|
@@ -4200,7 +4200,7 @@ function buildRow(row) {
|
|
|
4200
4200
|
/* @__PURE__ */ jsx(
|
|
4201
4201
|
"span",
|
|
4202
4202
|
{
|
|
4203
|
-
className: updatedToday ? "inline-flex h-6 items-center rounded-full bg-[#
|
|
4203
|
+
className: updatedToday ? "inline-flex h-6 items-center rounded-full bg-[#edf0fe] px-2 font-medium text-[var(--ck-brand-primary)]" : void 0,
|
|
4204
4204
|
children: row.updatedAt
|
|
4205
4205
|
}
|
|
4206
4206
|
)
|