@pi-harness/pi-harness 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/apps/web/dist/assets/index-CCZGqUaU.css +2 -0
- package/apps/web/dist/assets/index-DZjjpslQ.js +20 -0
- package/apps/web/dist/index.html +2 -2
- package/apps/web/package.json +6 -6
- package/apps/web/src/style.css +148 -41
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/at-file.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/canvas-draw.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/dependency-checker.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/history-compressor.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/hol-guard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/image-compressor.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-client.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/openpets.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-guard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reverse-skill.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-guard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/test-harness.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-search.json +1 -1
- package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -1
- package/node_modules/@pi-harness/api-gateway/package.json +1 -1
- package/node_modules/@pi-harness/cli/package.json +1 -1
- package/node_modules/@pi-harness/core/package.json +1 -1
- package/node_modules/@pi-harness/host-webserver/package.json +1 -1
- package/node_modules/@pi-harness/web-app/package.json +1 -1
- package/package.json +6 -6
- package/packages/api-gateway/dist/marketplace-entries/official/agent-teams.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/annotation.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/at-file.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/browser-fetch.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/browser-session.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/canvas-draw.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/cleaner.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/cli-notifier.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/code2skill.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/context-doctor.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/context.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/cost-meter.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/dependency-checker.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/fail-logger.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/genui.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/graph-memory.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/history-compressor.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/hol-guard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/i18n-pair.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/image-compressor.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mcp-client.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/modlens.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/openpets.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-dev.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/plugin-stars.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/prompt-guard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/readme-gen.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/recall-unread.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/reverse-skill.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-bridge.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-insights.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/skill-guard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/sql-lens.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/test-harness.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/token-guard.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/turn-rewind.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/workspace-search.json +1 -1
- package/packages/api-gateway/dist/marketplace-entries/official/yaml-validator.json +1 -1
- package/packages/api-gateway/package.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/agent-teams.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/anchored-standard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/annotation.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/archify.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/at-file.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/auto-mode.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/better-sidebar.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/browser-fetch.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/browser-session.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/canvas-draw.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/change-verifier.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/cleaner.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/cli-notifier.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/code2skill.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/colleague-skill.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/context-doctor.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/context.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/cost-meter.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/dependency-checker.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/docker-sandbox.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/fail-logger.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/genui.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/git-time-capsule.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/graph-memory.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/history-compressor.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/hol-guard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/i18n-pair.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/image-compressor.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/llm-verifier.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mcp-client.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mcp-panel.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/memory.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mirage-bridge.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/mock-server.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/modlens.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/module-search.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/obsidian-sync.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/openpets.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plan-execute.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-check.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-dev.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-finder.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-radar.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/plugin-stars.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/prompt-guard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/prompt-library.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/readme-gen.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/recall-unread.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/reverse-skill.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/reviewer-bot.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/runtime-doctor.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/secure-audit.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-bookmarks.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-bridge.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-export.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-insights.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/session-search.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/skill-catalog.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/skill-guard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/sql-lens.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/synapse.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/tab-manager.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/taskboard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/telemetry-blocker.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/test-harness.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/theme-studio.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/token-guard.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/turn-rewind.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/undo-savepoint.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/vision-toolkit.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/web-research.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/workspace-navigator.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/workspace-search.json +1 -1
- package/packages/api-gateway/src/marketplace-entries/official/yaml-validator.json +1 -1
- package/packages/bundle-web-app/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/client-web/dist/react-room.d.ts.map +1 -1
- package/packages/client-web/dist/react-room.js +128 -38
- package/packages/client-web/dist/react-room.js.map +1 -1
- package/packages/client-web/package.json +1 -1
- package/packages/client-web/src/react-room.tsx +220 -73
- package/packages/core/package.json +1 -1
- package/packages/host-webserver/package.json +1 -1
- package/apps/web/dist/assets/index-CkGv0zrr.css +0 -2
- package/apps/web/dist/assets/index-pMtwuwHh.js +0 -20
|
@@ -11,7 +11,7 @@ import { loadMarketplaceCatalog } from "./marketplace-catalog.js";
|
|
|
11
11
|
import { pluginStarsRows } from "./plugin-stars-view.js";
|
|
12
12
|
import { browserSessionTabs } from "./browser-session-view.js";
|
|
13
13
|
import { matchesPluginQuery } from "./plugin-search.js";
|
|
14
|
-
import {
|
|
14
|
+
import { readInstalledPluginDetailId } from "./plugin-navigation.js";
|
|
15
15
|
import { installedPluginCardContent } from "./plugin-card.js";
|
|
16
16
|
const value = (input, fallback = "—") => {
|
|
17
17
|
if (input === undefined || input === null || input === "")
|
|
@@ -388,7 +388,7 @@ function Details({ event, onClose, onCopy }) {
|
|
|
388
388
|
["耗时", value(event.duration ?? event.dur)],
|
|
389
389
|
["时间", value(event.timestamp ?? event.ts ?? event.time)],
|
|
390
390
|
];
|
|
391
|
-
return (_jsxs("aside", { className: "details-panel", children: [_jsxs("header", { children: [_jsx("strong", { children: eventLabel(event) }), _jsx("button", { "aria-label": "
|
|
391
|
+
return (_jsxs("aside", { className: "details-panel", children: [_jsxs("header", { children: [_jsx("strong", { children: eventLabel(event) }), _jsx("button", { "aria-label": fileDetail ? "关闭文件差异" : "关闭事件详情", onClick: onClose, type: "button", children: "\u00D7" })] }), _jsxs("div", { className: "details-body", children: [_jsx("div", { className: `detail-stats ${fileDetail ? "is-file" : ""}`, children: stats.map(([key, item]) => (_jsxs("div", { children: [_jsx("small", { children: key }), _jsx("b", { children: item })] }, key))) }), output !== undefined && (_jsxs("div", { className: "detail-section", children: [_jsx("small", { children: "\u8F93\u51FA" }), _jsx("pre", { className: "tool-output", children: typeof output === "string" ? output : JSON.stringify(output, null, 2) })] })), _jsxs("div", { className: "detail-section", children: [_jsx("small", { children: fileDetail ? "数据来源" : "经过的插件" }), _jsx("div", { className: "detail-plugin", children: fileDetail ? "Git workspace · /api/files" : "Runtime loader · event" })] }), _jsxs("div", { className: "detail-actions", children: [_jsx("button", { onClick: onCopy, type: "button", children: "\u590D\u5236 JSON" }), _jsx("button", { disabled: true, title: "\u5F53\u524D API \u672A\u63D0\u4F9B\u91CD\u653E\u63A5\u53E3", type: "button", children: "\u91CD\u653E" })] }), _jsxs("details", { className: "raw-json", children: [_jsx("summary", { children: "\u539F\u59CB JSON" }), _jsx("pre", { className: "raw-json-body", children: JSON.stringify(event, null, 2) })] })] })] }));
|
|
392
392
|
}
|
|
393
393
|
function Trajectory({ events, onSelect }) {
|
|
394
394
|
const [filter, setFilter] = useState("all");
|
|
@@ -403,11 +403,12 @@ function Trajectory({ events, onSelect }) {
|
|
|
403
403
|
const visible = events.filter((event) => filter === "all" || value(event.type, "event") === filter);
|
|
404
404
|
return (_jsxs("section", { className: "view-panel trajectory-view", children: [_jsxs("div", { className: "trajectory-summary", children: [_jsx("span", { children: "\u6309\u8F6E\u6B21" }), _jsxs("b", { children: [events.length, " \u4E2A\u4E8B\u4EF6"] }), _jsx("div", { className: "timeline", children: events.length ? (events.map((event, index) => (_jsx("span", { className: "timeline-turn", children: _jsx("i", { className: "timeline-strip", title: eventLabel(event) }) }, index)))) : (_jsx("span", { className: "timeline-empty", children: "\u7B49\u5F85\u771F\u5B9E\u4E8B\u4EF6\u2026" })) })] }), _jsxs("div", { className: "source-filters", children: [_jsxs("button", { className: `filter ${filter === "all" ? "active" : ""}`, onClick: () => setFilter("all"), type: "button", children: ["\u5168\u90E8 ", events.length] }), [...counts].map(([type, count]) => (_jsxs("button", { className: `filter ${filter === type ? "active" : ""}`, onClick: () => setFilter(type), type: "button", children: [type, " ", count] }, type)))] }), _jsxs("div", { className: "event-table", children: [_jsxs("div", { className: "event-head", children: [_jsx("span", { children: "\u65F6\u95F4" }), _jsx("span", { children: "\u6765\u6E90" }), _jsx("span", { children: "\u4E8B\u4EF6" }), _jsx("span", { children: "\u4EA7\u751F\u8005" }), _jsx("span", { children: "\u8017\u65F6" })] }), visible.map((event, index) => (_jsxs("button", { className: "event-row", onClick: () => onSelect(event), type: "button", children: [_jsx("span", { children: value(event.timestamp ?? event.ts ?? event.time) }), _jsxs("span", { children: [_jsx("i", { className: "event-dot" }), value(event.type, "event")] }), _jsx("strong", { children: eventLabel(event) }), _jsx("span", { children: value(event.by ?? event.source) }), _jsx("span", { children: value(event.duration ?? event.dur) })] }, index))), !visible.length && _jsx("div", { className: "empty-state", children: "\u6682\u65E0\u8F68\u8FF9\u4E8B\u4EF6\u3002" })] })] }));
|
|
405
405
|
}
|
|
406
|
-
function Files({ files, api, onDiff, onRefresh }) {
|
|
406
|
+
function Files({ files, api, onDiff, onRefresh, }) {
|
|
407
407
|
const additions = files.filter((file) => file.status.includes("A") || file.status === "??").length;
|
|
408
408
|
const deletions = files.filter((file) => file.status.includes("D")).length;
|
|
409
409
|
const [message, setMessage] = useState("");
|
|
410
410
|
const [busy, setBusy] = useState(false);
|
|
411
|
+
const [diffPending, setDiffPending] = useState();
|
|
411
412
|
const [error, setError] = useState("");
|
|
412
413
|
const [revertConfirmOpen, setRevertConfirmOpen] = useState(false);
|
|
413
414
|
const commit = () => {
|
|
@@ -437,7 +438,16 @@ function Files({ files, api, onDiff, onRefresh }) {
|
|
|
437
438
|
.catch((cause) => setError(cause instanceof Error ? cause.message : String(cause)))
|
|
438
439
|
.finally(() => setBusy(false));
|
|
439
440
|
};
|
|
440
|
-
|
|
441
|
+
const openDiff = (path) => {
|
|
442
|
+
if (busy || diffPending)
|
|
443
|
+
return;
|
|
444
|
+
setDiffPending(path);
|
|
445
|
+
setError("");
|
|
446
|
+
void onDiff(path)
|
|
447
|
+
.catch((cause) => setError(cause instanceof Error ? cause.message : String(cause)))
|
|
448
|
+
.finally(() => setDiffPending(undefined));
|
|
449
|
+
};
|
|
450
|
+
return (_jsxs("section", { className: "view-panel files-view", children: [_jsxs("div", { className: "files-content", children: [_jsxs("div", { className: "files-title", children: [_jsx("strong", { children: "\u672C\u6B21\u4F1A\u8BDD\u6539\u52A8" }), _jsx("span", { children: "\u7531 /api/files \u63D0\u4F9B" })] }), _jsx("div", { className: "file-summary", children: `${files.length} 个文件 · ${additions} 个新增 · ${deletions} 个删除` }), _jsx("div", { className: "file-list", children: files.length ? (files.map((file) => (_jsxs("div", { className: "file-row", children: [_jsx("b", { className: `file-kind ${file.label === "untracked" ? "new" : ""}`, children: file.label }), _jsx("code", { children: file.path }), _jsx("span", { className: file.status.includes("D") ? "del" : "add", children: file.status }), _jsx("button", { "aria-label": `${diffPending === file.path ? "正在读取" : "查看"}${file.path}的差异`, className: "diff-button", disabled: busy || diffPending !== undefined, onClick: () => openDiff(file.path), type: "button", children: diffPending === file.path ? "读取中…" : "查看差异" })] }, file.path)))) : (_jsx("div", { className: "empty-state", children: "\u5DE5\u4F5C\u533A\u6CA1\u6709\u672A\u63D0\u4EA4\u6539\u52A8\u3002" })) }), files.length > 0 && (_jsxs("div", { className: "file-actions", children: [_jsx("input", { "aria-label": "\u63D0\u4EA4\u8BF4\u660E", onChange: (event) => setMessage(event.target.value), placeholder: "\u63D0\u4EA4\u8BF4\u660E", value: message }), _jsx("button", { className: "primary", disabled: busy || !message.trim(), onClick: commit, type: "button", children: busy ? "处理中…" : "提交这些改动" }), _jsx("button", { disabled: busy, onClick: () => setRevertConfirmOpen(true), type: "button", children: "\u5168\u90E8\u64A4\u9500" })] })), error && _jsx("p", { className: "files-error", children: error })] }), revertConfirmOpen && (_jsx(ConfirmDialog, { busy: busy, confirmLabel: "\u786E\u8BA4\u64A4\u9500", description: "\u8FD9\u4F1A\u4E22\u5F03\u5F53\u524D\u5DE5\u4F5C\u533A\u7684\u5168\u90E8\u672A\u63D0\u4EA4\u6539\u52A8\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u6062\u590D\u3002", onClose: () => setRevertConfirmOpen(false), onConfirm: revert, target: `${files.length} 个文件`, title: "\u64A4\u9500\u5168\u90E8\u6539\u52A8" }))] }));
|
|
441
451
|
}
|
|
442
452
|
function pluginPanelValue(input) {
|
|
443
453
|
if (typeof input === "string")
|
|
@@ -1034,6 +1044,42 @@ function PluginUninstallDialog({ pluginName, busy, error, onCancel, onConfirm, }
|
|
|
1034
1044
|
onCancel();
|
|
1035
1045
|
}, children: _jsxs("div", { "aria-label": "\u786E\u8BA4\u5378\u8F7D\u63D2\u4EF6", "aria-modal": "true", className: "plugin-confirm-dialog", onClick: (event) => event.stopPropagation(), ref: dialogRef, role: "dialog", tabIndex: -1, children: [_jsx("header", { children: _jsxs("div", { children: [_jsx("strong", { children: "\u5378\u8F7D\u63D2\u4EF6\uFF1F" }), _jsx("small", { children: "\u5C06\u4ECE\u8FD0\u884C\u914D\u7F6E\u4E2D\u79FB\u9664\uFF0C\u4E4B\u540E\u53EF\u4EE5\u4ECE\u63D2\u4EF6\u5E02\u573A\u91CD\u65B0\u5B89\u88C5\u3002" })] }) }), _jsx("code", { children: pluginName }), error && (_jsx("p", { className: "plugin-confirm-error", role: "alert", children: error })), _jsxs("footer", { children: [_jsx("button", { "data-dialog-initial-focus": true, disabled: busy, onClick: onCancel, type: "button", children: "\u53D6\u6D88" }), _jsx("button", { className: "danger", disabled: busy, onClick: onConfirm, type: "button", children: busy ? "卸载中…" : "确认卸载" })] })] }) }));
|
|
1036
1046
|
}
|
|
1047
|
+
function PluginCategoryNav({ label, categories, activeCategory, onChange, }) {
|
|
1048
|
+
const navRef = useRef(null);
|
|
1049
|
+
const [canScrollLeft, setCanScrollLeft] = useState(false);
|
|
1050
|
+
const [canScrollRight, setCanScrollRight] = useState(false);
|
|
1051
|
+
const updateScrollState = useCallback(() => {
|
|
1052
|
+
const nav = navRef.current;
|
|
1053
|
+
if (!nav)
|
|
1054
|
+
return;
|
|
1055
|
+
const maximum = Math.max(0, nav.scrollWidth - nav.clientWidth);
|
|
1056
|
+
setCanScrollLeft(nav.scrollLeft > 1);
|
|
1057
|
+
setCanScrollRight(nav.scrollLeft < maximum - 1);
|
|
1058
|
+
}, []);
|
|
1059
|
+
useEffect(() => {
|
|
1060
|
+
const nav = navRef.current;
|
|
1061
|
+
if (!nav)
|
|
1062
|
+
return;
|
|
1063
|
+
updateScrollState();
|
|
1064
|
+
const observer = typeof ResizeObserver === "undefined" ? undefined : new ResizeObserver(updateScrollState);
|
|
1065
|
+
observer?.observe(nav);
|
|
1066
|
+
window.addEventListener("resize", updateScrollState);
|
|
1067
|
+
return () => {
|
|
1068
|
+
observer?.disconnect();
|
|
1069
|
+
window.removeEventListener("resize", updateScrollState);
|
|
1070
|
+
};
|
|
1071
|
+
}, [categories, updateScrollState]);
|
|
1072
|
+
const scroll = (direction) => {
|
|
1073
|
+
const nav = navRef.current;
|
|
1074
|
+
if (!nav)
|
|
1075
|
+
return;
|
|
1076
|
+
nav.scrollBy({ behavior: "smooth", left: direction * Math.max(180, nav.clientWidth * 0.72) });
|
|
1077
|
+
};
|
|
1078
|
+
return (_jsxs("div", { className: `marketplace-categories-shell ${canScrollLeft ? "can-scroll-left" : ""} ${canScrollRight ? "can-scroll-right" : ""}`, children: [canScrollLeft && (_jsx("button", { "aria-label": "\u5411\u5DE6\u67E5\u770B\u66F4\u591A\u5206\u7C7B", className: "marketplace-category-scroll previous", onClick: () => scroll(-1), type: "button", children: "\u2039" })), _jsx("nav", { "aria-label": label, className: "marketplace-categories", onScroll: updateScrollState, ref: navRef, children: categories.map((category) => {
|
|
1079
|
+
const active = activeCategory === category.id;
|
|
1080
|
+
return (_jsxs("button", { "aria-pressed": active, className: `marketplace-category ${active ? "active" : ""}`, onClick: () => onChange(category.id), type: "button", children: [_jsx("span", { children: category.label }), _jsx("span", { className: active ? "font-mono text-[10px] text-[#3565c5]" : "font-mono text-[10px] text-[#687381]", children: category.count })] }, category.id || "all"));
|
|
1081
|
+
}) }), canScrollRight && (_jsx("button", { "aria-label": "\u5411\u53F3\u67E5\u770B\u66F4\u591A\u5206\u7C7B", className: "marketplace-category-scroll next", onClick: () => scroll(1), type: "button", children: "\u203A" }))] }));
|
|
1082
|
+
}
|
|
1037
1083
|
function Plugins({ plugins, panels, catalog, onMarketplace, onOpenDetail, onToml, onToggle, onUninstall, }) {
|
|
1038
1084
|
const catalogByPackage = useMemo(() => new Map(catalog.map((plugin) => [plugin.packageName, plugin])), [catalog]);
|
|
1039
1085
|
const panelPluginIds = useMemo(() => new Set(panels.map((panel) => panel.pluginId)), [panels]);
|
|
@@ -1096,10 +1142,7 @@ function Plugins({ plugins, panels, catalog, onMarketplace, onOpenDetail, onToml
|
|
|
1096
1142
|
return (_jsx("section", { className: "view-panel plugins-view", children: _jsxs("div", { className: "plugins-page", children: [_jsxs("div", { className: "subnav", children: [_jsxs("div", { "aria-label": "\u63D2\u4EF6\u76EE\u5F55", className: "segmented", children: [_jsx("button", { "aria-pressed": "true", className: "active", type: "button", children: "\u5DF2\u5B89\u88C5" }), _jsx("button", { "aria-pressed": "false", onClick: onMarketplace, type: "button", children: "\u63D2\u4EF6\u5E02\u573A" })] }), _jsx("span", { children: "\u5DF2\u5B89\u88C5\u63D2\u4EF6" }), _jsx("a", { href: "#", onClick: (event) => {
|
|
1097
1143
|
event.preventDefault();
|
|
1098
1144
|
onToml();
|
|
1099
|
-
}, children: "\u67E5\u770B\u8FD0\u884C\u914D\u7F6E" })] }), _jsxs("div", { className: "plugins-toolbar", children: [_jsx("input", { "aria-label": "\u641C\u7D22\u5DF2\u5B89\u88C5\u63D2\u4EF6", onChange: (event) => setQuery(event.target.value), placeholder: "\u641C\u7D22\u540D\u79F0\u3001\u5305\u540D\u6216\u80FD\u529B\u2026", type: "search", value: query }), _jsxs("span", { "aria-live": "polite", children: [query.trim() || categoryFilter ? `${visiblePlugins.length} / ${installedPlugins.length}` : `${installedPlugins.length}`, " \u4E2A\u63D2\u4EF6"] })] }), _jsx(
|
|
1100
|
-
const active = categoryFilter === category.id;
|
|
1101
|
-
return (_jsxs("button", { "aria-pressed": active, className: `marketplace-category ${active ? "active" : ""}`, onClick: () => setCategoryFilter(category.id), type: "button", children: [_jsx("span", { children: category.label }), _jsx("span", { className: active ? "font-mono text-[10px] text-[#3565c5]" : "font-mono text-[10px] text-[#687381]", children: category.count })] }, category.id || "all"));
|
|
1102
|
-
}) }), _jsxs("div", { className: "plugins-scroll", ref: scrollRef, children: [_jsxs("div", { className: "plugins-list", children: [visiblePlugins.map((plugin) => {
|
|
1145
|
+
}, children: "\u67E5\u770B\u8FD0\u884C\u914D\u7F6E" })] }), _jsxs("div", { className: "plugins-toolbar", children: [_jsx("input", { "aria-label": "\u641C\u7D22\u5DF2\u5B89\u88C5\u63D2\u4EF6", onChange: (event) => setQuery(event.target.value), placeholder: "\u641C\u7D22\u540D\u79F0\u3001\u5305\u540D\u6216\u80FD\u529B\u2026", type: "search", value: query }), _jsxs("span", { "aria-live": "polite", children: [query.trim() || categoryFilter ? `${visiblePlugins.length} / ${installedPlugins.length}` : `${installedPlugins.length}`, " \u4E2A\u63D2\u4EF6"] })] }), _jsx(PluginCategoryNav, { activeCategory: categoryFilter, categories: installedCategories, label: "\u5DF2\u5B89\u88C5\u63D2\u4EF6\u5206\u7C7B", onChange: setCategoryFilter }), _jsxs("div", { className: "plugins-scroll", ref: scrollRef, children: [_jsxs("div", { className: "plugins-list", children: [visiblePlugins.map((plugin) => {
|
|
1103
1146
|
const metadata = catalogByPackage.get(plugin.name);
|
|
1104
1147
|
const categoryLabel = metadata?.category.label ?? plugin.category?.label;
|
|
1105
1148
|
const capabilityLabel = capability(plugin.name);
|
|
@@ -1108,10 +1151,7 @@ function Plugins({ plugins, panels, catalog, onMarketplace, onOpenDetail, onToml
|
|
|
1108
1151
|
return (_jsxs("article", { className: "catalog-card plugin-card", children: [_jsxs("div", { className: "plugin-card-head", children: [_jsx("span", { className: "plugin-icon", children: "\u25C8" }), _jsx("div", { className: "plugin-copy", children: _jsxs("div", { className: "plugin-heading", children: [_jsxs("div", { className: "plugin-title", children: [_jsx("strong", { children: pluginTitle }), _jsx("span", { className: `plugin-state ${plugin.enabled ? "active" : ""}`, children: plugin.enabled ? "运行中" : "已停用" }), categoryLabel && _jsx("span", { className: "capability", children: categoryLabel }), categoryLabel !== capabilityLabel && _jsx("span", { className: "capability", children: capabilityLabel })] }), _jsx("div", { className: "plugin-actions", children: plugin.removable ? (_jsxs(_Fragment, { children: [_jsx("button", { "aria-label": `${plugin.enabled ? "停用" : "启用"} ${pluginTitle}`, "aria-pressed": plugin.enabled, className: "plugin-switch-button", disabled: busyPlugin !== undefined, onClick: () => void runPluginAction(plugin, (item) => onToggle(item)), type: "button", children: _jsx("span", { "aria-hidden": "true", className: `switch ${plugin.enabled ? "on" : ""}`, children: _jsx("i", {}) }) }), _jsx("button", { className: "plugin-uninstall", disabled: busyPlugin !== undefined, onClick: () => {
|
|
1109
1152
|
setPluginError("");
|
|
1110
1153
|
setPendingUninstall(plugin);
|
|
1111
|
-
}, type: "button", children: "\u5378\u8F7D" })] })) : (_jsx("span", { className: `switch ${plugin.enabled ? "on" : ""}`, children: _jsx("i", {}) })) })] }) })] }), _jsxs("div", { className: "plugin-card-body", children: [_jsx("code", { className: "plugin-package", children: cardContent.packageLabel }), _jsx("p", { className: "plugin-description", children: cardContent.description }), _jsx("div", { className: "hook-list", children: cardContent.tags.map((tag, index) => (_jsx("span", { children: tag }, `${tag}-${index}`))) })] }), _jsxs("footer", { className: "plugin-card-footer", children: [_jsx("
|
|
1112
|
-
event.preventDefault();
|
|
1113
|
-
onOpenDetail(plugin);
|
|
1114
|
-
}, children: "\u67E5\u770B\u8BE6\u60C5 \u2192" }), panelPluginIds.has(plugin.name) ? _jsx("span", { children: "\u5B9E\u65F6\u9762\u677F" }) : null] })] }, plugin.id));
|
|
1154
|
+
}, type: "button", children: "\u5378\u8F7D" })] })) : (_jsx("span", { className: `switch ${plugin.enabled ? "on" : ""}`, children: _jsx("i", {}) })) })] }) })] }), _jsxs("div", { className: "plugin-card-body", children: [_jsx("code", { className: "plugin-package", children: cardContent.packageLabel }), _jsx("p", { className: "plugin-description", children: cardContent.description }), _jsx("div", { className: "hook-list", children: cardContent.tags.map((tag, index) => (_jsx("span", { children: tag }, `${tag}-${index}`))) })] }), _jsxs("footer", { className: "plugin-card-footer", children: [_jsx("button", { "aria-label": `查看 ${pluginTitle} 详情`, className: "plugin-detail-link", onClick: () => onOpenDetail(plugin), type: "button", children: "\u67E5\u770B\u8BE6\u60C5 \u2192" }), panelPluginIds.has(plugin.name) ? _jsx("span", { children: "\u5B9E\u65F6\u9762\u677F" }) : null] })] }, plugin.id));
|
|
1115
1155
|
}), !installedPlugins.length ? (_jsx("div", { className: "empty-state", children: "\u8FD8\u6CA1\u6709\u5B89\u88C5\u53EF\u7BA1\u7406\u7684\u63D2\u4EF6\u3002\u53BB\u63D2\u4EF6\u5E02\u573A\u5B89\u88C5\u4E00\u4E2A\u5427\u3002" })) : !visiblePlugins.length ? (_jsx("div", { className: "empty-state", children: "\u6CA1\u6709\u5339\u914D\u5F53\u524D\u641C\u7D22\u4E0E\u5206\u7C7B\u6761\u4EF6\u7684\u5DF2\u5B89\u88C5\u63D2\u4EF6\u3002" })) : null] }), pluginError && _jsx("p", { className: "plugin-action-error", children: pluginError }), panels.length > installedPlugins.length && (_jsxs("section", { className: "mt-4 border-t border-[#e3e7ee] pt-4", children: [_jsxs("div", { className: "mb-3 flex items-baseline justify-between gap-3", children: [_jsxs("div", { children: [_jsx("strong", { className: "text-[13px] font-semibold text-[#20252b]", children: "\u5176\u4ED6\u63D2\u4EF6\u9762\u677F" }), _jsx("p", { className: "mt-1 text-[12px] text-[#687381]", children: "\u7531\u5DF2\u542F\u7528\u63D2\u4EF6\u63D0\u4F9B\u7684\u5B9E\u65F6\u72B6\u6001\u3002" })] }), _jsx("span", { className: "font-mono text-[10px] uppercase tracking-[0.08em] text-[#687381]", children: "LIVE" })] }), _jsx("div", { className: "grid gap-3 xl:grid-cols-2", children: panels
|
|
1116
1156
|
.filter((panel) => !installedPlugins.some((plugin) => plugin.name === panel.pluginId))
|
|
1117
1157
|
.map((panel) => (_jsx(PluginPanelCard, { panel: panel }, panel.id))) })] }))] }), pendingUninstall && (_jsx(PluginUninstallDialog, { busy: busyPlugin !== undefined, error: pluginError, onCancel: () => setPendingUninstall(undefined), onConfirm: () => void runPluginAction(pendingUninstall, onUninstall).then((completed) => {
|
|
@@ -1154,7 +1194,7 @@ function Marketplace({ plugins, capabilities, categories, total, page, hasNext,
|
|
|
1154
1194
|
const [installing, setInstalling] = useState();
|
|
1155
1195
|
const [installError, setInstallError] = useState("");
|
|
1156
1196
|
const [installNotice, setInstallNotice] = useState("");
|
|
1157
|
-
const categoryTabs = marketplaceCategoryTabs(categories);
|
|
1197
|
+
const categoryTabs = useMemo(() => marketplaceCategoryTabs(categories), [categories]);
|
|
1158
1198
|
const install = async (plugin) => {
|
|
1159
1199
|
setInstallError("");
|
|
1160
1200
|
setInstallNotice("");
|
|
@@ -1174,14 +1214,11 @@ function Marketplace({ plugins, capabilities, categories, total, page, hasNext,
|
|
|
1174
1214
|
return (_jsx("section", { className: "marketplace-page flex min-w-0 flex-1 flex-col", children: _jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [_jsxs("div", { className: "subnav", children: [_jsxs("div", { "aria-label": "\u63D2\u4EF6\u76EE\u5F55", className: "segmented", children: [_jsx("button", { "aria-pressed": "false", onClick: onBack, type: "button", children: "\u5DF2\u5B89\u88C5" }), _jsx("button", { "aria-pressed": "true", className: "active", type: "button", children: "\u63D2\u4EF6\u5E02\u573A" })] }), _jsx("span", { children: "\u5DF2\u5BA1\u6838\u63D2\u4EF6\u76EE\u5F55" }), _jsx("a", { href: "#", onClick: (event) => {
|
|
1175
1215
|
event.preventDefault();
|
|
1176
1216
|
onToml();
|
|
1177
|
-
}, children: "\u67E5\u770B\u8FD0\u884C\u914D\u7F6E" })] }), _jsxs("div", { className: "marketplace-toolbar", children: [_jsx("input", { className: "marketplace-search", "aria-label": "\u641C\u7D22\u63D2\u4EF6", onChange: (event) => onQueryChange(event.target.value), placeholder: "\u641C\u7D22\u540D\u79F0\u3001\u5305\u540D\u3001\u80FD\u529B\u2026", value: query }), _jsxs("select", { className: "marketplace-filter", "aria-label": "\u6309\u80FD\u529B\u7B5B\u9009", onChange: (event) => onCapabilityChange(event.target.value), value: capabilityFilter, children: [_jsx("option", { value: "", children: "\u5168\u90E8\u80FD\u529B" }), capabilities.map((item) => (_jsx("option", { value: item, children: item }, item)))] }), _jsxs("span", { className: "marketplace-count", children: [total, " \u4E2A\u5DF2\u5BA1\u6838\u6761\u76EE \u00B7 \u63A8\u8350\u6392\u5E8F"] })] }), _jsx(
|
|
1178
|
-
const active = categoryFilter === category.id;
|
|
1179
|
-
return (_jsxs("button", { "aria-pressed": active, className: `marketplace-category ${active ? "active" : ""}`, onClick: () => onCategoryChange(category.id), type: "button", children: [_jsx("span", { children: category.label }), _jsx("span", { className: active ? "font-mono text-[10px] text-[#3565c5]" : "font-mono text-[10px] text-[#687381]", children: category.count })] }, category.id || "all"));
|
|
1180
|
-
}) }), _jsxs("div", { className: "marketplace-scroll", children: [_jsxs("div", { className: "marketplace-grid", children: [plugins.map((plugin) => (_jsxs("article", { className: "catalog-card marketplace-card", children: [_jsxs("header", { className: "marketplace-card-head", children: [_jsx("div", { className: "marketplace-card-mark", children: "\u25C8" }), _jsx("div", { className: "min-w-0 flex-1", children: _jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx("strong", { className: "marketplace-title", children: plugin.name }), _jsx("span", { className: plugin.status === "verified"
|
|
1217
|
+
}, children: "\u67E5\u770B\u8FD0\u884C\u914D\u7F6E" })] }), _jsxs("div", { className: "marketplace-toolbar", children: [_jsx("input", { className: "marketplace-search", "aria-label": "\u641C\u7D22\u63D2\u4EF6", onChange: (event) => onQueryChange(event.target.value), placeholder: "\u641C\u7D22\u540D\u79F0\u3001\u5305\u540D\u3001\u80FD\u529B\u2026", value: query }), _jsxs("select", { className: "marketplace-filter", "aria-label": "\u6309\u80FD\u529B\u7B5B\u9009", onChange: (event) => onCapabilityChange(event.target.value), value: capabilityFilter, children: [_jsx("option", { value: "", children: "\u5168\u90E8\u80FD\u529B" }), capabilities.map((item) => (_jsx("option", { value: item, children: item }, item)))] }), _jsxs("span", { className: "marketplace-count", children: [total, " \u4E2A\u5DF2\u5BA1\u6838\u6761\u76EE \u00B7 \u63A8\u8350\u6392\u5E8F"] })] }), _jsx(PluginCategoryNav, { activeCategory: categoryFilter, categories: categoryTabs, label: "\u63D2\u4EF6\u5206\u7C7B", onChange: onCategoryChange }), _jsxs("div", { className: "marketplace-scroll", children: [_jsxs("div", { className: "marketplace-grid", children: [plugins.map((plugin) => (_jsxs("article", { className: "catalog-card marketplace-card", children: [_jsxs("header", { className: "marketplace-card-head", children: [_jsx("div", { className: "marketplace-card-mark", children: "\u25C8" }), _jsx("div", { className: "min-w-0 flex-1", children: _jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx("strong", { className: "marketplace-title", children: plugin.name }), _jsx("span", { className: plugin.status === "verified"
|
|
1181
1218
|
? "rounded bg-[#e6faed] px-1.5 py-px font-mono text-[10px] text-[#14733f]"
|
|
1182
1219
|
: "rounded bg-[#fff5e7] px-1.5 py-px font-mono text-[10px] text-[#9a6700]", children: plugin.status === "verified" ? "已验证" : "实验性" }), _jsx("span", { className: plugin.source === "official"
|
|
1183
1220
|
? "rounded bg-[#e4edfd] px-1.5 py-px font-mono text-[10px] text-[#3565c5]"
|
|
1184
|
-
: "rounded bg-[#fef5e7] px-1.5 py-px font-mono text-[10px] text-[#9a6700]", children: plugin.source === "official" ? "官方" : "社区" }), _jsx("span", { className: "rounded bg-[#f2edff] px-1.5 py-px text-[10px] text-[#6d4bc3]", children: plugin.category.label })] }) })] }), _jsxs("div", { className: "marketplace-card-body", children: [_jsxs("code", { className: "marketplace-package", children: [displayPluginName(plugin.packageName), " \u00B7 v", plugin.version] }), _jsx("p", { className: "marketplace-description", children: plugin.description }), _jsxs("div", { className: "marketplace-tags", children: [plugin.capabilities.map((item) => (_jsx("span", { className: "rounded bg-[#f1f4f9] px-1.5 py-px font-mono text-[10px] text-[#61666b]", children: item }, item))), plugin.hooks.map((item) => (_jsxs("span", { className: "rounded bg-[#f1f4f9] px-1.5 py-px font-mono text-[10px] text-[#61666b]", children: ["hook:", item] }, `hook:${item}`)))] }), plugin.statistics && (_jsx("div", { className: "mt-3 grid grid-cols-3 divide-x divide-[#e3e7ee] rounded-md border border-[#e3e7ee] bg-[#f8f9fb]", children: marketplaceStatisticItems(plugin.statistics).map((item) => (_jsxs("span", { className: "min-w-0 px-2 py-1.5", title: `${item.label} ${item.value}`, children: [_jsx("small", { className: "block truncate text-[9px] text-[#687381]", children: item.label }), _jsx("strong", { className: "mt-0.5 block truncate font-mono text-[10px] font-medium text-[#3b424b]", children: item.value })] }, item.label))) }))] }), _jsxs("footer", { className: "marketplace-card-footer", children: [_jsxs("span", { children: [plugin.author, " \u00B7 ", plugin.license] }), _jsx("a", { href: marketplaceDetailPath(plugin.id), onClick: (event) => {
|
|
1221
|
+
: "rounded bg-[#fef5e7] px-1.5 py-px font-mono text-[10px] text-[#9a6700]", children: plugin.source === "official" ? "官方" : "社区" }), _jsx("span", { className: "rounded bg-[#f2edff] px-1.5 py-px text-[10px] text-[#6d4bc3]", children: plugin.category.label })] }) })] }), _jsxs("div", { className: "marketplace-card-body", children: [_jsxs("code", { className: "marketplace-package", children: [displayPluginName(plugin.packageName), " \u00B7 v", plugin.version] }), _jsx("p", { className: "marketplace-description", children: plugin.description }), _jsxs("div", { className: "marketplace-tags", children: [plugin.capabilities.map((item) => (_jsx("span", { className: "rounded bg-[#f1f4f9] px-1.5 py-px font-mono text-[10px] text-[#61666b]", children: item }, item))), plugin.hooks.map((item) => (_jsxs("span", { className: "rounded bg-[#f1f4f9] px-1.5 py-px font-mono text-[10px] text-[#61666b]", children: ["hook:", item] }, `hook:${item}`)))] }), plugin.statistics && (_jsx("div", { className: "marketplace-statistics mt-3 grid grid-cols-3 divide-x divide-[#e3e7ee] rounded-md border border-[#e3e7ee] bg-[#f8f9fb]", children: marketplaceStatisticItems(plugin.statistics).map((item) => (_jsxs("span", { className: "min-w-0 px-2 py-1.5", title: `${item.label} ${item.value}`, children: [_jsx("small", { className: "block truncate text-[9px] text-[#687381]", children: item.label }), _jsx("strong", { className: "mt-0.5 block truncate font-mono text-[10px] font-medium text-[#3b424b]", children: item.value })] }, item.label))) }))] }), _jsxs("footer", { className: "marketplace-card-footer", children: [_jsxs("span", { children: [plugin.author, " \u00B7 ", plugin.license] }), _jsx("a", { href: marketplaceDetailPath(plugin.id), onClick: (event) => {
|
|
1185
1222
|
event.preventDefault();
|
|
1186
1223
|
onOpenDetail(plugin);
|
|
1187
1224
|
}, children: "\u67E5\u770B\u8BE6\u60C5 \u2192" }), _jsx("a", { href: plugin.repository, target: "_blank", rel: "noreferrer", children: "\u67E5\u770B\u6E90\u7801 \u2197" }), _jsx("button", { disabled: installedPackages.has(plugin.packageName) || installing !== undefined, onClick: () => void install(plugin), type: "button", children: installedPackages.has(plugin.packageName) ? "已安装" : installing === plugin.id ? "安装中…" : "安装" })] })] }, plugin.id))), !plugins.length && _jsx("div", { className: "empty-state", children: "\u6CA1\u6709\u5339\u914D\u7684\u63D2\u4EF6\u3002" })] }), installNotice && _jsx("p", { className: "mt-2 text-[11px] text-[#3565c5]", children: installNotice }), installError && _jsxs("p", { className: "mt-2 text-[11px] text-[#b42318]", children: ["\u5B89\u88C5\u5931\u8D25\uFF1A", installError] }), _jsxs("div", { className: "marketplace-pagination", children: [_jsx("button", { className: "marketplace-pagination-button", disabled: page === 0, onClick: () => onPageChange(page - 1), type: "button", children: "\u4E0A\u4E00\u9875" }), _jsxs("span", { children: ["\u7B2C ", page + 1, " \u9875"] }), _jsx("button", { className: "marketplace-pagination-button", disabled: !hasNext, onClick: () => onPageChange(page + 1), type: "button", children: "\u4E0B\u4E00\u9875" })] }), _jsxs("div", { className: "marketplace-contribute mt-3 flex items-center gap-2.5 rounded-[10px] border border-dashed border-[#b8ccf5] bg-[#f8f9ff] p-2.5 text-[11.5px] text-[#687381]", children: [_jsx("strong", { className: "text-[12px] text-[#0f1115]", children: "\u4F60\u6709\u4E00\u4E2A Pi Harness \u63D2\u4EF6\uFF1F" }), _jsx("span", { children: "\u5728 entries \u76EE\u5F55\u65B0\u589E\u4E00\u4E2A\u5143\u6570\u636E\u6587\u4EF6\uFF0C\u9644\u6D4B\u8BD5\u548C README \u540E\u63D0\u4EA4 PR\uFF1B\u5BA1\u6838\u901A\u8FC7\u540E\u4F1A\u51FA\u73B0\u5728\u8FD9\u91CC\u3002" }), _jsx("a", { className: "ml-auto flex-none text-[#3565c5]", href: "https://github.com/pi-harness/pi-harness/blob/main/docs/plugin-marketplace.md", target: "_blank", rel: "noreferrer", children: "\u67E5\u770B\u8D21\u732E\u89C4\u8303 \u2197" })] })] })] }) }));
|
|
@@ -1349,10 +1386,10 @@ function PromptCompletionPopover({ kind, commands, files, query, activeIndex, on
|
|
|
1349
1386
|
const items = kind === "command"
|
|
1350
1387
|
? filterCommands(commands, query).slice(0, 12)
|
|
1351
1388
|
: files.filter((file) => `${file.path} ${file.label} ${file.status}`.toLowerCase().includes(query.trim().toLowerCase())).slice(0, 12);
|
|
1352
|
-
return (_jsxs("div", { "aria-label": kind === "command" ? "命令补全" : "文件补全", className: "prompt-completion", role: "listbox", children: [_jsx("small", { children: kind === "command" ? "命令" : "文件" }), items.length ? (items.slice(0, 12).map((item, index) => {
|
|
1389
|
+
return (_jsxs("div", { "aria-label": kind === "command" ? "命令补全" : "文件补全", className: "prompt-completion", id: "prompt-completion-list", role: "listbox", children: [_jsx("small", { children: kind === "command" ? "命令" : "文件" }), items.length ? (items.slice(0, 12).map((item, index) => {
|
|
1353
1390
|
const label = kind === "command" ? `/${item.invocationName}` : `@${item.path}`;
|
|
1354
1391
|
const detail = kind === "command" ? (item.description ?? item.source ?? "由当前运行时注册") : item.status;
|
|
1355
|
-
return (_jsxs("button", { "aria-selected": index === activeIndex, onClick: () => onUse(label), onMouseEnter: () => onActiveIndexChange(index), role: "option", type: "button", children: [_jsx("strong", { children: label }), _jsx("span", { children: detail })] }, `${kind}:${label}`));
|
|
1392
|
+
return (_jsxs("button", { "aria-selected": index === activeIndex, id: `prompt-completion-option-${index}`, onClick: () => onUse(label), onMouseEnter: () => onActiveIndexChange(index), role: "option", type: "button", children: [_jsx("strong", { children: label }), _jsx("span", { children: detail })] }, `${kind}:${label}`));
|
|
1356
1393
|
})) : (_jsx("span", { className: "prompt-completion-empty", children: "\u6CA1\u6709\u5339\u914D\u9879" }))] }));
|
|
1357
1394
|
}
|
|
1358
1395
|
function GlobalSearch({ commands, sessions, files, onClose, onUse, onOpenSession, onOpenFile, }) {
|
|
@@ -1370,6 +1407,8 @@ function GlobalSearch({ commands, sessions, files, onClose, onUse, onOpenSession
|
|
|
1370
1407
|
.map((session) => ({ kind: "session", session })),
|
|
1371
1408
|
...files.filter((file) => matches(`${file.path} ${file.label} ${file.status}`)).map((file) => ({ kind: "file", file })),
|
|
1372
1409
|
];
|
|
1410
|
+
const selectedIndex = items.length ? Math.min(activeIndex, items.length - 1) : -1;
|
|
1411
|
+
const activeItemId = selectedIndex >= 0 ? `global-search-option-${selectedIndex}` : undefined;
|
|
1373
1412
|
useEffect(() => setActiveIndex(0), [query]);
|
|
1374
1413
|
const execute = (item) => {
|
|
1375
1414
|
if (!item)
|
|
@@ -1385,7 +1424,7 @@ function GlobalSearch({ commands, sessions, files, onClose, onUse, onOpenSession
|
|
|
1385
1424
|
return (_jsx("div", { className: "global-search", onClick: (event) => {
|
|
1386
1425
|
if (event.target === event.currentTarget)
|
|
1387
1426
|
onClose();
|
|
1388
|
-
}, children: _jsxs("div", { "aria-label": "\u5168\u5C40\u641C\u7D22", "aria-modal": "true", className: "global-search-dialog", ref: dialogRef, role: "dialog", tabIndex: -1, children: [_jsxs("div", { className: "global-search-heading", children: [_jsx("strong", { children: "\u5168\u5C40\u641C\u7D22" }), _jsx("small", { children: "\u547D\u4EE4 \u00B7 \u4F1A\u8BDD \u00B7 \u6587\u4EF6" })] }), _jsx("input", { "aria-label": "\u5168\u5C40\u641C\u7D22", "data-dialog-initial-focus": true, onChange: (event) => setQuery(event.target.value), onKeyDown: (event) => {
|
|
1427
|
+
}, children: _jsxs("div", { "aria-label": "\u5168\u5C40\u641C\u7D22", "aria-modal": "true", className: "global-search-dialog", ref: dialogRef, role: "dialog", tabIndex: -1, children: [_jsxs("div", { className: "global-search-heading", children: [_jsx("strong", { children: "\u5168\u5C40\u641C\u7D22" }), _jsx("small", { children: "\u547D\u4EE4 \u00B7 \u4F1A\u8BDD \u00B7 \u6587\u4EF6" }), _jsx("button", { "aria-label": "\u5173\u95ED\u5168\u5C40\u641C\u7D22", onClick: onClose, type: "button", children: "\u00D7" })] }), _jsx("input", { "aria-activedescendant": activeItemId, "aria-autocomplete": "list", "aria-controls": "global-search-results", "aria-expanded": "true", "aria-label": "\u5168\u5C40\u641C\u7D22", "data-dialog-initial-focus": true, onChange: (event) => setQuery(event.target.value), onKeyDown: (event) => {
|
|
1389
1428
|
if (event.key === "Escape") {
|
|
1390
1429
|
event.preventDefault();
|
|
1391
1430
|
onClose();
|
|
@@ -1400,14 +1439,14 @@ function GlobalSearch({ commands, sessions, files, onClose, onUse, onOpenSession
|
|
|
1400
1439
|
}
|
|
1401
1440
|
else if (event.key === "Enter") {
|
|
1402
1441
|
event.preventDefault();
|
|
1403
|
-
execute(items[
|
|
1442
|
+
execute(items[selectedIndex]);
|
|
1404
1443
|
}
|
|
1405
|
-
}, placeholder: "\u641C\u7D22\u547D\u4EE4\u3001\u4F1A\u8BDD\u6216\u6587\u4EF6", value: query }), _jsx("div", { className: "global-search-results", role: "listbox", children: items.length ? (["command", "session", "file"].map((kind) => {
|
|
1444
|
+
}, placeholder: "\u641C\u7D22\u547D\u4EE4\u3001\u4F1A\u8BDD\u6216\u6587\u4EF6", role: "combobox", value: query }), _jsx("div", { className: "global-search-results", id: "global-search-results", role: "listbox", children: items.length ? (["command", "session", "file"].map((kind) => {
|
|
1406
1445
|
const group = items.filter((item) => item.kind === kind);
|
|
1407
1446
|
if (!group.length)
|
|
1408
1447
|
return null;
|
|
1409
1448
|
const label = kind === "command" ? "命令" : kind === "session" ? "会话" : "文件";
|
|
1410
|
-
return (_jsxs("section", { className: "global-search-group", children: [_jsx("small", { children: label }), group.map((item) => {
|
|
1449
|
+
return (_jsxs("section", { "aria-label": label, className: "global-search-group", role: "group", children: [_jsx("small", { "aria-hidden": "true", children: label }), group.map((item) => {
|
|
1411
1450
|
const index = items.indexOf(item);
|
|
1412
1451
|
const title = item.kind === "command"
|
|
1413
1452
|
? `/${item.command.invocationName}`
|
|
@@ -1419,7 +1458,7 @@ function GlobalSearch({ commands, sessions, files, onClose, onUse, onOpenSession
|
|
|
1419
1458
|
: item.kind === "session"
|
|
1420
1459
|
? `${value(item.session.messageCount, "0")} 条消息`
|
|
1421
1460
|
: `${item.file.path} · ${item.file.status}`;
|
|
1422
|
-
return (_jsxs("button", { "aria-selected": index ===
|
|
1461
|
+
return (_jsxs("button", { "aria-selected": index === selectedIndex, id: `global-search-option-${index}`, onClick: () => execute(item), onMouseEnter: () => setActiveIndex(index), role: "option", type: "button", children: [_jsx("strong", { children: title }), _jsx("span", { children: detail })] }, `${item.kind}:${title}:${index}`));
|
|
1423
1462
|
})] }, kind));
|
|
1424
1463
|
})) : (_jsx("div", { className: "empty-state", children: "\u6CA1\u6709\u5339\u914D\u7684\u547D\u4EE4\u3001\u4F1A\u8BDD\u6216\u6587\u4EF6\u3002" })) })] }) }));
|
|
1425
1464
|
}
|
|
@@ -1531,6 +1570,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
1531
1570
|
.slice(0, 12);
|
|
1532
1571
|
}, [data.commands, data.files, promptCompletion]);
|
|
1533
1572
|
const promptCompletionOpen = Boolean(promptCompletion && !promptCompletionSuppressed && promptCompletionItems.length);
|
|
1573
|
+
const promptCompletionActiveIndex = Math.min(promptCompletionIndex, Math.max(promptCompletionItems.length - 1, 0));
|
|
1534
1574
|
const installedPackages = useMemo(() => new Set(data.plugins.filter((plugin) => plugin.removable).map((plugin) => plugin.name)), [data.plugins]);
|
|
1535
1575
|
const workspaceReady = !workspaceChooserOpen && Boolean(selectedWorkspacePath || data.status?.cwd || data.workspaces.find((workspace) => workspace.current)?.path || data.session);
|
|
1536
1576
|
const installedPluginCount = useMemo(() => {
|
|
@@ -1937,6 +1977,26 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
1937
1977
|
setAnnotationSelection("");
|
|
1938
1978
|
setAnnotationNote("");
|
|
1939
1979
|
};
|
|
1980
|
+
const openCommandCompletion = () => {
|
|
1981
|
+
const input = promptInputRef.current;
|
|
1982
|
+
const caret = input?.selectionStart ?? draft.length;
|
|
1983
|
+
const existing = getPromptCompletion(draft, caret);
|
|
1984
|
+
let nextCaret = caret;
|
|
1985
|
+
if (existing?.kind !== "command") {
|
|
1986
|
+
const separator = caret > 0 && !/\s/.test(draft[caret - 1] ?? "") ? " " : "";
|
|
1987
|
+
const insertion = `${separator}/`;
|
|
1988
|
+
const nextDraft = `${draft.slice(0, caret)}${insertion}${draft.slice(caret)}`;
|
|
1989
|
+
nextCaret = caret + insertion.length;
|
|
1990
|
+
setDraft(nextDraft);
|
|
1991
|
+
}
|
|
1992
|
+
setPromptCaret(nextCaret);
|
|
1993
|
+
setPromptCompletionSuppressed(false);
|
|
1994
|
+
setPromptCompletionIndex(0);
|
|
1995
|
+
window.requestAnimationFrame(() => {
|
|
1996
|
+
input?.focus();
|
|
1997
|
+
input?.setSelectionRange(nextCaret, nextCaret);
|
|
1998
|
+
});
|
|
1999
|
+
};
|
|
1940
2000
|
const openSession = (session) => {
|
|
1941
2001
|
const path = typeof session.path === "string" ? session.path : "";
|
|
1942
2002
|
if (!path)
|
|
@@ -1987,6 +2047,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
1987
2047
|
});
|
|
1988
2048
|
};
|
|
1989
2049
|
const openSessionMenu = (path, name) => {
|
|
2050
|
+
setSessionToolsOpen(false);
|
|
1990
2051
|
setSelectedSessionPath(path);
|
|
1991
2052
|
setSessionNameDraft(name ?? "");
|
|
1992
2053
|
setSessionMenuPath(path);
|
|
@@ -2095,7 +2156,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
2095
2156
|
})) : (_jsx(Workspace, { status: data.status, workspaces: data.workspaces, onCreate: (workspace) => void createNewSession(workspace), onStarter: setDraft, onToml: () => {
|
|
2096
2157
|
setDetails(undefined);
|
|
2097
2158
|
setSettings("toml");
|
|
2098
|
-
} })), streamingAssistant && data.status?.status === "running" && (_jsxs("article", { className: "turn text streaming-turn", "aria-live": "polite", children: [streamingAssistant.thinking && (_jsxs("details", { className: "reasoning message-reasoning", children: [_jsx("summary", { className: "reasoning-head", children: "\u601D\u8003\u4E2D\u2026" }), _jsx("div", { className: "reasoning-body", children: _jsx(MarkdownMessage, { text: streamingAssistant.thinking }) })] })), !streamingAssistant.thinking && !streamingAssistant.text && _jsx("div", { className: "streaming-placeholder", children: "\u6B63\u5728\u751F\u6210\u2026" }), streamingAssistant.text && _jsx(MarkdownMessage, { onMouseUp: captureAnnotationSelection, text: streamingAssistant.text })] })), pendingPrompt && !data.session?.messages.some((message) => message.role === "user" && messageText(message) === pendingPrompt) && (_jsx("article", { className: "turn user pending-turn", children: _jsx(UserMessageBubble, { text: pendingPrompt }) }))] }), _jsxs("div", { className: "composer-wrap", children: [_jsxs("div", { className: "context-line", children: [_jsx("span", { className: "context-label", children: "\u5B9E\u65F6\u4E0A\u4E0B\u6587" }), _jsxs("div", { className: "context-metrics", children: [_jsxs("span", { children: [_jsx("b", { children: data.status?.messages ?? 0 }), " \u6761\u6D88\u606F"] }), _jsxs("span", { children: [_jsx("b", { children: data.status?.events ?? events.length }), " \u4E2A\u4E8B\u4EF6"] }), _jsx("span", { children: _jsx("b", { children: value(data.status?.model) }) })] }), _jsx("button", { "aria-expanded": contextExpanded, onClick: () => setContextExpanded((current) => !current), type: "button", children: contextExpanded ? "收起" : "展开" })] }), contextExpanded && (_jsxs("div", { className: "context-breakdown", role: "status", children: [_jsxs("span", { children: ["\u6D88\u606F ", _jsx("b", { children: data.status?.messages ?? 0 })] }), _jsxs("span", { children: ["\u8FD0\u884C\u65F6\u4E8B\u4EF6 ", _jsx("b", { children: data.status?.events ?? events.length })] }), _jsxs("span", { children: ["\u6A21\u578B ", _jsx("b", { children: value(data.status?.model) })] })] })), _jsxs("div", { className: "composer-stack", children: [promptError && _jsx(PromptError, { message: promptError }), annotationSelection ? (_jsxs("div", { "aria-label": "\u6DFB\u52A0\u6279\u6CE8", className: "rounded-lg border border-[#cdddf8] bg-[#f6f8ff] px-3 py-2", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 shrink-0 rounded bg-[#dce9ff] px-1.5 py-0.5 text-[10px] text-[#315fb8]", children: "\u9009\u4E2D\u7247\u6BB5" }), _jsx("p", { className: "max-h-16 flex-1 overflow-auto whitespace-pre-wrap text-[11px] text-[#30343b]", children: annotationSelection }), _jsx("button", { "aria-label": "\u53D6\u6D88\u6279\u6CE8", className: "text-[12px] text-[#687381]", onClick: () => setAnnotationSelection(""), type: "button", children: "\u00D7" })] }), _jsxs("div", { className: "mt-2 flex items-center gap-2", children: [_jsx("input", { "aria-label": "\u6279\u6CE8\u5907\u6CE8", className: "min-w-0 flex-1 rounded-md border border-[#dce5f5] bg-white px-2 py-1.5 text-[11px] outline-none", onChange: (event) => setAnnotationNote(event.target.value), placeholder: "\u5907\u6CE8\uFF08\u53EF\u9009\uFF09", value: annotationNote }), _jsx("button", { className: "rounded-md bg-[#3565c5] px-3 py-1.5 text-[11px] font-medium text-white", onClick: addAnnotation, type: "button", children: "\u52A0\u5165\u6279\u6CE8" })] })] })) : null, annotations.length > 0 ? (_jsxs("div", { className: "flex items-center gap-2 overflow-x-auto text-[10px]", children: [_jsxs("span", { className: "shrink-0 rounded-md bg-[#edf3fe] px-2 py-1 font-medium text-[#315fb8]", children: ["\u6279\u6CE8 \u00D7", annotations.length] }), annotations.map((annotation) => (_jsxs("button", { className: "max-w-48 shrink-0 truncate rounded-md border border-[#dce5f5] bg-white px-2 py-1 text-left text-[#65707b]", onClick: () => setAnnotations((current) => current.filter((item) => item.id !== annotation.id)), title: "\u70B9\u51FB\u79FB\u9664\u6279\u6CE8", type: "button", children: ["#", annotation.id, " ", annotation.quote] }, annotation.id))), _jsx("button", { className: "shrink-0 text-[#687381]", onClick: () => setAnnotations([]), type: "button", children: "\u6E05\u7A7A" })] })) : null, _jsxs("form", { className: "composer", onSubmit: submit, children: [_jsx("textarea", { "aria-label": "Prompt", onChange: (event) => {
|
|
2159
|
+
} })), streamingAssistant && data.status?.status === "running" && (_jsxs("article", { className: "turn text streaming-turn", "aria-live": "polite", children: [streamingAssistant.thinking && (_jsxs("details", { className: "reasoning message-reasoning", children: [_jsx("summary", { className: "reasoning-head", children: "\u601D\u8003\u4E2D\u2026" }), _jsx("div", { className: "reasoning-body", children: _jsx(MarkdownMessage, { text: streamingAssistant.thinking }) })] })), !streamingAssistant.thinking && !streamingAssistant.text && _jsx("div", { className: "streaming-placeholder", children: "\u6B63\u5728\u751F\u6210\u2026" }), streamingAssistant.text && _jsx(MarkdownMessage, { onMouseUp: captureAnnotationSelection, text: streamingAssistant.text })] })), pendingPrompt && !data.session?.messages.some((message) => message.role === "user" && messageText(message) === pendingPrompt) && (_jsx("article", { className: "turn user pending-turn", children: _jsx(UserMessageBubble, { text: pendingPrompt }) }))] }), _jsxs("div", { className: "composer-wrap", children: [_jsxs("div", { className: "context-line", children: [_jsx("span", { className: "context-label", children: "\u5B9E\u65F6\u4E0A\u4E0B\u6587" }), _jsxs("div", { className: "context-metrics", children: [_jsxs("span", { children: [_jsx("b", { children: data.status?.messages ?? 0 }), " \u6761\u6D88\u606F"] }), _jsxs("span", { children: [_jsx("b", { children: data.status?.events ?? events.length }), " \u4E2A\u4E8B\u4EF6"] }), _jsx("span", { children: _jsx("b", { children: value(data.status?.model) }) })] }), _jsx("button", { "aria-expanded": contextExpanded, onClick: () => setContextExpanded((current) => !current), type: "button", children: contextExpanded ? "收起" : "展开" })] }), contextExpanded && (_jsxs("div", { className: "context-breakdown", role: "status", children: [_jsxs("span", { children: ["\u6D88\u606F ", _jsx("b", { children: data.status?.messages ?? 0 })] }), _jsxs("span", { children: ["\u8FD0\u884C\u65F6\u4E8B\u4EF6 ", _jsx("b", { children: data.status?.events ?? events.length })] }), _jsxs("span", { children: ["\u6A21\u578B ", _jsx("b", { children: value(data.status?.model) })] })] })), _jsxs("div", { className: "composer-stack", children: [promptError && _jsx(PromptError, { message: promptError }), annotationSelection ? (_jsxs("div", { "aria-label": "\u6DFB\u52A0\u6279\u6CE8", className: "rounded-lg border border-[#cdddf8] bg-[#f6f8ff] px-3 py-2", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 shrink-0 rounded bg-[#dce9ff] px-1.5 py-0.5 text-[10px] text-[#315fb8]", children: "\u9009\u4E2D\u7247\u6BB5" }), _jsx("p", { className: "max-h-16 flex-1 overflow-auto whitespace-pre-wrap text-[11px] text-[#30343b]", children: annotationSelection }), _jsx("button", { "aria-label": "\u53D6\u6D88\u6279\u6CE8", className: "text-[12px] text-[#687381]", onClick: () => setAnnotationSelection(""), type: "button", children: "\u00D7" })] }), _jsxs("div", { className: "mt-2 flex items-center gap-2", children: [_jsx("input", { "aria-label": "\u6279\u6CE8\u5907\u6CE8", className: "min-w-0 flex-1 rounded-md border border-[#dce5f5] bg-white px-2 py-1.5 text-[11px] outline-none", onChange: (event) => setAnnotationNote(event.target.value), placeholder: "\u5907\u6CE8\uFF08\u53EF\u9009\uFF09", value: annotationNote }), _jsx("button", { className: "rounded-md bg-[#3565c5] px-3 py-1.5 text-[11px] font-medium text-white", onClick: addAnnotation, type: "button", children: "\u52A0\u5165\u6279\u6CE8" })] })] })) : null, annotations.length > 0 ? (_jsxs("div", { className: "flex items-center gap-2 overflow-x-auto text-[10px]", children: [_jsxs("span", { className: "shrink-0 rounded-md bg-[#edf3fe] px-2 py-1 font-medium text-[#315fb8]", children: ["\u6279\u6CE8 \u00D7", annotations.length] }), annotations.map((annotation) => (_jsxs("button", { className: "max-w-48 shrink-0 truncate rounded-md border border-[#dce5f5] bg-white px-2 py-1 text-left text-[#65707b]", onClick: () => setAnnotations((current) => current.filter((item) => item.id !== annotation.id)), title: "\u70B9\u51FB\u79FB\u9664\u6279\u6CE8", type: "button", children: ["#", annotation.id, " ", annotation.quote] }, annotation.id))), _jsx("button", { className: "shrink-0 text-[#687381]", onClick: () => setAnnotations([]), type: "button", children: "\u6E05\u7A7A" })] })) : null, _jsxs("form", { className: "composer", onSubmit: submit, children: [_jsx("textarea", { "aria-activedescendant": promptCompletionOpen ? `prompt-completion-option-${promptCompletionActiveIndex}` : undefined, "aria-autocomplete": "list", "aria-controls": promptCompletionOpen ? "prompt-completion-list" : undefined, "aria-expanded": promptCompletionOpen, "aria-haspopup": "listbox", "aria-label": "Prompt", onChange: (event) => {
|
|
2099
2160
|
setDraft(event.target.value);
|
|
2100
2161
|
setPromptCaret(event.currentTarget.selectionStart ?? event.target.value.length);
|
|
2101
2162
|
setPromptCompletionSuppressed(false);
|
|
@@ -2119,7 +2180,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
2119
2180
|
}
|
|
2120
2181
|
if (popupOpen && (event.key === "Enter" || event.key === "Tab")) {
|
|
2121
2182
|
event.preventDefault();
|
|
2122
|
-
const item = items[promptCompletionIndex];
|
|
2183
|
+
const item = items[Math.min(promptCompletionIndex, items.length - 1)];
|
|
2123
2184
|
if (item && completion) {
|
|
2124
2185
|
const value = completion.kind === "command" ? `/${item.invocationName}` : `@${item.path}`;
|
|
2125
2186
|
const replacement = replacePromptCompletion(event.currentTarget.value, completion, `${value} `);
|
|
@@ -2151,7 +2212,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
2151
2212
|
event.currentTarget.blur();
|
|
2152
2213
|
setWorkspaceChooserOpen(true);
|
|
2153
2214
|
}
|
|
2154
|
-
}, placeholder: workspaceReady ? "描述要做的改动,⌘↵ 发送;@ 引用文件,/ 调用命令" : "先选择工作区,再描述要做的改动", readOnly: !workspaceReady, ref: promptInputRef, rows: 2, value: draft }), promptCompletionOpen && promptCompletion && (_jsx(PromptCompletionPopover, { activeIndex:
|
|
2215
|
+
}, placeholder: workspaceReady ? "描述要做的改动,⌘↵ 发送;@ 引用文件,/ 调用命令" : "先选择工作区,再描述要做的改动", readOnly: !workspaceReady, ref: promptInputRef, rows: 2, value: draft }), promptCompletionOpen && promptCompletion && (_jsx(PromptCompletionPopover, { activeIndex: promptCompletionActiveIndex, commands: data.commands, files: data.files, kind: promptCompletion.kind, onActiveIndexChange: setPromptCompletionIndex, onUse: (value) => {
|
|
2155
2216
|
const replacement = replacePromptCompletion(draft, promptCompletion, `${value} `);
|
|
2156
2217
|
setDraft(replacement.text);
|
|
2157
2218
|
setPromptCaret(replacement.caret);
|
|
@@ -2162,10 +2223,23 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
2162
2223
|
input?.setSelectionRange(replacement.caret, replacement.caret);
|
|
2163
2224
|
});
|
|
2164
2225
|
}, query: promptCompletion.query })), _jsxs("div", { className: "composer-tools", children: [_jsx("select", { "aria-label": "\u6A21\u578B", disabled: !data.models.length || promptBusy, value: data.status?.model ?? "", onChange: (event) => {
|
|
2165
|
-
const [provider,
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2226
|
+
const [provider, ...modelParts] = event.target.value.split("/");
|
|
2227
|
+
const model = modelParts.join("/");
|
|
2228
|
+
if (!provider || !model)
|
|
2229
|
+
return;
|
|
2230
|
+
setPromptError("");
|
|
2231
|
+
void api
|
|
2232
|
+
.selectModel(provider, model)
|
|
2233
|
+
.then(refresh)
|
|
2234
|
+
.catch((cause) => setPromptError(cause instanceof Error ? cause.message : String(cause)));
|
|
2235
|
+
}, children: data.models.length ? (data.models.map((model) => (_jsx("option", { value: `${model.provider}/${model.id}`, children: model.name === model.id ? `${model.provider}/${model.id}` : `${model.name} (${model.provider})` }, `${model.provider}/${model.id}`)))) : (_jsx("option", { value: "", children: "\u6682\u65E0\u53EF\u7528\u6A21\u578B" })) }), _jsxs("button", { className: "tool-chip", onClick: () => setPermission((current) => !current), type: "button", children: ["\u25CF ", permission ? "改动前询问" : "自动允许"] }), _jsx("button", { className: "tool-chip", onClick: openCommandCompletion, type: "button", children: "\uFF0F \u547D\u4EE4" }), _jsx("span", { className: "composer-hint", children: "\u2318\u21B5 \u53D1\u9001 \u00B7 \u2318K \u547D\u4EE4 \u00B7 \u2303C \u4E2D\u65AD" }), _jsx("button", { "aria-label": promptBusy ? "发送中" : "发送消息", className: "send-button", disabled: promptBusy || !draft.trim(), title: promptBusy ? "正在发送" : "发送消息(⌘↵)", type: "submit", children: promptBusy ? "…" : "↑" })] })] })] })] })] })) : view === "trajectory" ? (_jsx(Trajectory, { events: displayEvents, onSelect: setDetails })) : (_jsx(Files, { api: api, files: data.files, onDiff: async (file) => {
|
|
2236
|
+
const diff = await api.getFileDiff(file);
|
|
2237
|
+
setDetails({
|
|
2238
|
+
type: "file_diff",
|
|
2239
|
+
path: diff.path,
|
|
2240
|
+
output: diff.diff || "没有可显示的差异(工作区可能已更新)。",
|
|
2241
|
+
});
|
|
2242
|
+
}, onRefresh: () => void refresh() }));
|
|
2169
2243
|
const groups = sessionGroups(filteredSessions);
|
|
2170
2244
|
const showCurrentSession = Boolean(data.session && !search && !filteredSessions.some((session) => session.sessionId === data.session?.sessionId));
|
|
2171
2245
|
const visibleCommands = filterCommands(data.commands, commandQuery);
|
|
@@ -2226,9 +2300,14 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
2226
2300
|
setSelectedSessionPath(imported.sessionFile);
|
|
2227
2301
|
});
|
|
2228
2302
|
}, ref: importInputRef, type: "file" })] }), _jsxs("div", { className: "session-list-toolbar", children: [_jsxs("div", { className: "session-list-title", children: [_jsx("strong", { children: "\u4F1A\u8BDD" }), _jsx("span", { children: sessionTotal || data.sessions.length })] }), _jsxs("div", { className: "session-list-tools", children: [_jsx("button", { "aria-pressed": sessionSelectionMode, className: `session-tool-button ${sessionSelectionMode ? "active" : ""}`, onClick: () => {
|
|
2229
|
-
setSessionSelectionMode(
|
|
2303
|
+
setSessionSelectionMode(!sessionSelectionMode);
|
|
2230
2304
|
setSelectedSessionPaths(new Set());
|
|
2231
|
-
|
|
2305
|
+
setSessionToolsOpen(false);
|
|
2306
|
+
closeSessionMenu();
|
|
2307
|
+
}, type: "button", children: sessionSelectionMode ? "完成" : "选择" }), _jsxs("div", { className: "session-tools-wrap", children: [_jsx("button", { "aria-expanded": sessionToolsOpen, "aria-label": "\u4F1A\u8BDD\u5DE5\u5177", className: "session-tool-button icon", onClick: () => {
|
|
2308
|
+
closeSessionMenu();
|
|
2309
|
+
setSessionToolsOpen((current) => !current);
|
|
2310
|
+
}, type: "button", children: "\u22EF" }), sessionToolsOpen && (_jsxs("div", { className: "session-tools-popover", children: [_jsx("button", { onClick: () => window.location.reload(), type: "button", children: "\u5237\u65B0\u5217\u8868" }), _jsx("button", { onClick: () => importInputRef.current?.click(), type: "button", children: "\u5BFC\u5165\u4F1A\u8BDD" }), _jsx("button", { disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
|
|
2232
2311
|
if (!activeSessionPath)
|
|
2233
2312
|
return;
|
|
2234
2313
|
void sessionAction(async () => {
|
|
@@ -2293,7 +2372,12 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
2293
2372
|
} }))] }, index)))] }, label)))) : !showCurrentSession ? (_jsx("div", { className: "empty-state", children: "\u6682\u65E0\u5DF2\u4FDD\u5B58\u4F1A\u8BDD" })) : null, sessionTotal > 30 && (_jsxs("div", { className: "session-pagination", children: [_jsx("button", { disabled: sessionPage === 0, onClick: () => setSessionPage((page) => Math.max(0, page - 1)), type: "button", children: "\u4E0A\u4E00\u9875" }), _jsxs("span", { children: [sessionPage + 1, " / ", Math.max(1, Math.ceil(sessionTotal / 30))] }), _jsx("button", { disabled: !sessionHasNext, onClick: () => setSessionPage((page) => page + 1), type: "button", children: "\u4E0B\u4E00\u9875" })] })), betterSidebarData && (_jsxs("section", { "aria-label": "\u5DE5\u4F5C\u533A\u6982\u89C8", className: "mx-3 mt-3 rounded-lg border border-[#dce5f5] bg-[#f6f8ff] px-3 py-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("strong", { className: "text-[11px] font-semibold text-[#253044]", children: "\u5DE5\u4F5C\u533A\u6982\u89C8" }), _jsx("span", { className: `rounded px-1.5 py-0.5 font-mono text-[9px] ${betterSidebarData.clean === true ? "bg-[#eaf8f0] text-[#14733f]" : "bg-[#fff0f0] text-[#b42318]"}`, children: betterSidebarData.clean === true ? "clean" : `${value(betterSidebarData.changedCount ?? 0)} 变更` })] }), _jsx("code", { className: "mt-2 block truncate text-[10px] text-[#315fb8]", children: value(betterSidebarData.cwd ?? "当前工作区") }), _jsx("p", { className: "mt-1 truncate font-mono text-[10px] text-[#65707b]", children: value(betterSidebarData.branch ?? "非 Git 工作区") }), Array.isArray(betterSidebarData.changedFiles) && betterSidebarData.changedFiles.length > 0 ? (_jsx("div", { className: "mt-2 grid gap-1 border-t border-[#dce5f5] pt-2", children: betterSidebarData.changedFiles.slice(0, 3).map((item, index) => {
|
|
2294
2373
|
const file = item !== null && typeof item === "object" ? item : {};
|
|
2295
2374
|
return (_jsxs("code", { className: "truncate text-[9px] text-[#65707b]", children: [value(file.status ?? "??"), " ", value(file.path ?? "未命名")] }, `${value(file.path ?? "file")}-${index}`));
|
|
2296
|
-
}) })) : null] }))] }), _jsxs("footer", { className: "sidebar-footer", children: [_jsxs("div", { className: "runtime-cells", children: [_jsxs("span", { children: ["model ", _jsx("b", { children: value(data.status?.model) })] }), _jsxs("span", { children: ["msgs ", _jsx("b", { children: data.status?.messages ?? 0 })] }), _jsxs("span", { children: ["status ", _jsx("b", { children: value(data.status?.status, "connecting") })] })] }), _jsx("button", { "aria-label": "\
|
|
2375
|
+
}) })) : null] }))] }), _jsxs("footer", { className: "sidebar-footer", children: [_jsxs("div", { className: "runtime-cells", children: [_jsxs("span", { children: ["model ", _jsx("b", { children: value(data.status?.model) })] }), _jsxs("span", { children: ["msgs ", _jsx("b", { children: data.status?.messages ?? 0 })] }), _jsxs("span", { children: ["status ", _jsx("b", { children: value(data.status?.status, "connecting") })] })] }), _jsx("button", { "aria-label": "\u641C\u7D22\u4F1A\u8BDD\u3001\u6587\u4EF6\u548C\u547D\u4EE4", className: "sidebar-link compact-session-search", onClick: () => {
|
|
2376
|
+
setCommandOpen(false);
|
|
2377
|
+
setSessionToolsOpen(false);
|
|
2378
|
+
closeSessionMenu();
|
|
2379
|
+
setGlobalSearchOpen(true);
|
|
2380
|
+
}, title: "\u641C\u7D22\u4F1A\u8BDD\u3001\u6587\u4EF6\u548C\u547D\u4EE4", type: "button", children: "\u2315" }), _jsx("button", { "aria-label": "\u65B0\u5EFA\u4F1A\u8BDD", className: "sidebar-link compact-new-session", onClick: beginNewSession, title: "\u65B0\u5EFA\u4F1A\u8BDD", type: "button", children: "\uFF0B" }), _jsxs("button", { "aria-label": `插件,已安装 ${installedPluginCount} 个`, className: `sidebar-link ${page === "plugins" || page === "marketplace" ? "active" : ""}`, onClick: () => pushInstalledPluginRoute(undefined), title: `插件 · ${installedPluginCount} 个`, type: "button", children: ["\u25C8 ", _jsx("span", { children: "\u63D2\u4EF6" }), _jsx("b", { children: installedPluginCount })] }), _jsxs("button", { "aria-label": "\u8BBE\u7F6E", className: `sidebar-link ${settings ? "active" : ""}`, onClick: () => {
|
|
2297
2381
|
setCommandOpen(false);
|
|
2298
2382
|
setGlobalSearchOpen(false);
|
|
2299
2383
|
setSessionMenuOpen(false);
|
|
@@ -2322,13 +2406,19 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
2322
2406
|
? marketplacePluginId
|
|
2323
2407
|
? (marketplaceDetail?.name ?? marketplacePluginId)
|
|
2324
2408
|
: "官方与社区 · 已审核目录"
|
|
2325
|
-
: sessionSource(data.status, data.session) })] }), _jsx("div", { className: "header-spacer" }), data.status?.status === "running" && (_jsxs("div", { className: "run-indicator running", children: [_jsx("span", { className: "run-dot" }), _jsx("span", { children: "\u8FD0\u884C\u4E2D \u00B7 Pi agent" }), _jsx("button", { className: "stop-button", onClick: () =>
|
|
2409
|
+
: sessionSource(data.status, data.session) })] }), _jsx("div", { className: "header-spacer" }), data.status?.status === "running" && (_jsxs("div", { className: "run-indicator running", children: [_jsx("span", { className: "run-dot" }), _jsx("span", { children: "\u8FD0\u884C\u4E2D \u00B7 Pi agent" }), _jsx("button", { className: "stop-button", onClick: () => {
|
|
2410
|
+
setPromptError("");
|
|
2411
|
+
void api
|
|
2412
|
+
.abort()
|
|
2413
|
+
.then(refresh)
|
|
2414
|
+
.catch((cause) => setPromptError(cause instanceof Error ? cause.message : String(cause)));
|
|
2415
|
+
}, type: "button", children: "\u505C\u6B62" })] })), !settings && page === "session" && (_jsx("div", { "aria-label": "\u4F1A\u8BDD\u89C6\u56FE", className: "view-tabs", children: ["chat", "trajectory", "files"].map((item) => (_jsx("button", { "aria-pressed": view === item, className: `view-tab ${view === item ? "active" : ""}`, onClick: () => {
|
|
2326
2416
|
setView(item);
|
|
2327
2417
|
setDetails(undefined);
|
|
2328
2418
|
}, type: "button", children: item === "chat" ? "对话" : item === "trajectory" ? "轨迹" : "产出" }, item))) })), !settings && page === "session" && _jsx("span", { "aria-hidden": "true", className: "header-divider" }), !settings && page === "session" && (_jsxs(_Fragment, { children: [_jsx("button", { className: "session-menu", onClick: () => {
|
|
2329
2419
|
setSessionMenuPath(undefined);
|
|
2330
2420
|
setSessionMenuOpen((current) => !current);
|
|
2331
|
-
}, type: "button", "aria-label": "\u4F1A\u8BDD\u64CD\u4F5C", children: "\u22EF" }),
|
|
2421
|
+
}, type: "button", "aria-label": "\u4F1A\u8BDD\u64CD\u4F5C", children: "\u22EF" }), _jsxs("button", { "aria-label": details !== undefined ? "关闭详情" : "打开详情", "aria-pressed": details !== undefined, className: "details-toggle", onClick: () => setDetails(details ? undefined : {}), type: "button", children: [_jsx("span", { "aria-hidden": "true", children: "\u25E8" }), " ", _jsx("span", { className: "details-toggle-label", children: "\u8BE6\u60C5" })] })] })), !settings && page === "session" && sessionMenuOpen && !sessionMenuPath && (_jsxs("div", { className: "session-menu-popover compact-session-menu", children: [_jsxs("button", { className: "session-action", disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
|
|
2332
2422
|
setSessionNameDraft(data.session?.sessionId?.slice(0, 12) ?? "");
|
|
2333
2423
|
setSessionDialog("rename");
|
|
2334
2424
|
setSessionMenuOpen(false);
|
|
@@ -2344,7 +2434,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }) {
|
|
|
2344
2434
|
}, type: "button", children: [_jsx("strong", { children: "\u5F52\u6863\u4F1A\u8BDD" }), _jsx("small", { children: "\u4ECE\u9ED8\u8BA4\u5217\u8868\u9690\u85CF" })] }), _jsxs("button", { className: "session-action danger", disabled: !activeSessionPath || sessionActionBusy, onClick: () => {
|
|
2345
2435
|
setSessionMenuOpen(false);
|
|
2346
2436
|
setSessionDialog("delete");
|
|
2347
|
-
}, type: "button", children: [_jsx("strong", { children: "\u5220\u9664\u4F1A\u8BDD" }), _jsx("small", { children: "\u6C38\u4E45\u5220\u9664\u672C\u5730\u8BB0\u5F55" })] })] }))] }), refreshIssues.length > 0 && (_jsxs("div", { "aria-live": "polite", className: "refresh-warning", role: "status", children: [_jsxs("span", { children: [_jsx("strong", { children: "\u90E8\u5206\u6570\u636E\u5237\u65B0\u5931\u8D25" }), refreshIssues.join("、"), "\u53EF\u80FD\u4E3A\u7A7A\u6216\u663E\u793A\u4E0A\u6B21\u7ED3\u679C\u3002"] }), _jsx("button", { onClick: () => void refresh(), type: "button", children: "\u91CD\u8BD5" })] })), _jsx("div", { className: "view-host", children: initialRefreshPending ? (_jsxs("div", { "aria-live": "polite", className: "initial-loading", role: "status", children: [_jsx("span", { "aria-hidden": "true" }), "\u6B63\u5728\u8FDE\u63A5 Pi runtime\u2026"] })) : (content) })] }), !settings && page === "session" && details !== undefined && (_jsx(Details, { event: Object.keys(details).length ? details : undefined, onClose: () => setDetails(undefined), onCopy: () => void navigator.clipboard?.writeText(JSON.stringify(details, null, 2)) })), globalSearchOpen && (_jsx(GlobalSearch, { commands: data.commands, files: data.files, onClose: () => setGlobalSearchOpen(false), onOpenFile: (file) => {
|
|
2437
|
+
}, type: "button", children: [_jsx("strong", { children: "\u5220\u9664\u4F1A\u8BDD" }), _jsx("small", { children: "\u6C38\u4E45\u5220\u9664\u672C\u5730\u8BB0\u5F55" })] })] }))] }), refreshIssues.length > 0 && (_jsxs("div", { "aria-live": "polite", className: "refresh-warning", role: "status", children: [_jsxs("span", { children: [_jsx("strong", { children: "\u90E8\u5206\u6570\u636E\u5237\u65B0\u5931\u8D25" }), refreshIssues.join("、"), "\u53EF\u80FD\u4E3A\u7A7A\u6216\u663E\u793A\u4E0A\u6B21\u7ED3\u679C\u3002"] }), _jsx("button", { onClick: () => void refresh(), type: "button", children: "\u91CD\u8BD5" })] })), _jsx("div", { className: "view-host", children: initialRefreshPending ? (_jsxs("div", { "aria-live": "polite", className: "initial-loading", role: "status", children: [_jsx("span", { "aria-hidden": "true" }), "\u6B63\u5728\u8FDE\u63A5 Pi runtime\u2026"] })) : (content) })] }), !settings && page === "session" && details !== undefined && (_jsxs(_Fragment, { children: [_jsx("button", { "aria-label": "\u5173\u95ED\u8BE6\u60C5", className: "details-backdrop", onClick: () => setDetails(undefined), type: "button" }), _jsx(Details, { event: Object.keys(details).length ? details : undefined, onClose: () => setDetails(undefined), onCopy: () => void navigator.clipboard?.writeText(JSON.stringify(details, null, 2)) })] })), globalSearchOpen && (_jsx(GlobalSearch, { commands: data.commands, files: data.files, onClose: () => setGlobalSearchOpen(false), onOpenFile: (file) => {
|
|
2348
2438
|
setPage("session");
|
|
2349
2439
|
setView("files");
|
|
2350
2440
|
setDetails({ type: "file", path: file.path, status: file.status });
|