@pi-harness/pi-harness 0.1.10 → 0.1.12
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-D6dtMTPb.js +20 -0
- package/apps/web/dist/assets/index-De8Rm01Z.css +2 -0
- package/apps/web/dist/assets/{react-vendor-BD7-wQo9.js → react-vendor-BxoMtjVy.js} +1 -1
- package/apps/web/dist/index.html +3 -3
- package/apps/web/package.json +6 -6
- package/apps/web/src/style.css +30 -30
- 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 +8 -7
- 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/api-gateway/test/release-package.test.ts +1 -0
- 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 +199 -59
- 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 +350 -187
- package/packages/core/package.json +1 -1
- package/packages/host-webserver/package.json +1 -1
- package/apps/web/dist/assets/index-CW3u-pEm.css +0 -2
- package/apps/web/dist/assets/index-DNYYxKc7.js +0 -20
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState, type FormEvent } from "react";
|
|
2
|
+
import { createPortal } from "react-dom";
|
|
2
3
|
import {
|
|
3
4
|
createClientApi,
|
|
4
5
|
failedRefreshLabels,
|
|
@@ -645,35 +646,55 @@ function ConfirmDialog({
|
|
|
645
646
|
|
|
646
647
|
function SessionActionMenu({
|
|
647
648
|
busy,
|
|
649
|
+
position,
|
|
648
650
|
onRename,
|
|
649
651
|
onFork,
|
|
650
652
|
onArchive,
|
|
651
653
|
onDelete,
|
|
652
654
|
}: {
|
|
653
655
|
busy: boolean;
|
|
656
|
+
position: { left: number; top: number };
|
|
654
657
|
onRename: () => void;
|
|
655
658
|
onFork: () => void;
|
|
656
659
|
onArchive: () => void;
|
|
657
660
|
onDelete: () => void;
|
|
658
661
|
}) {
|
|
659
|
-
return (
|
|
660
|
-
<div className="session-row-menu-popover" onClick={(event) => event.stopPropagation()}>
|
|
661
|
-
<button disabled={busy} onClick={onRename} type="button">
|
|
662
|
+
return createPortal(
|
|
663
|
+
<div className="session-row-menu-popover" data-session-popover onClick={(event) => event.stopPropagation()} role="menu" style={position}>
|
|
664
|
+
<button autoFocus disabled={busy} onClick={onRename} role="menuitem" type="button">
|
|
662
665
|
重命名
|
|
663
666
|
</button>
|
|
664
|
-
<button disabled={busy} onClick={onFork} type="button">
|
|
667
|
+
<button disabled={busy} onClick={onFork} role="menuitem" type="button">
|
|
665
668
|
复制会话
|
|
666
669
|
</button>
|
|
667
|
-
<button disabled={busy} onClick={onArchive} type="button">
|
|
670
|
+
<button disabled={busy} onClick={onArchive} role="menuitem" type="button">
|
|
668
671
|
归档会话
|
|
669
672
|
</button>
|
|
670
|
-
<button className="danger" disabled={busy} onClick={onDelete} type="button">
|
|
673
|
+
<button className="danger" disabled={busy} onClick={onDelete} role="menuitem" type="button">
|
|
671
674
|
删除会话
|
|
672
675
|
</button>
|
|
673
|
-
</div
|
|
676
|
+
</div>,
|
|
677
|
+
document.body,
|
|
674
678
|
);
|
|
675
679
|
}
|
|
676
680
|
|
|
681
|
+
const sidebarPopoverPosition = (
|
|
682
|
+
trigger: HTMLButtonElement,
|
|
683
|
+
width: number,
|
|
684
|
+
estimatedHeight: number,
|
|
685
|
+
placement: "beside" | "below",
|
|
686
|
+
): { left: number; top: number } => {
|
|
687
|
+
const rect = trigger.getBoundingClientRect();
|
|
688
|
+
const gutter = 8;
|
|
689
|
+
const spaceOnRight = window.innerWidth - rect.right - gutter;
|
|
690
|
+
const left = spaceOnRight >= width ? rect.right + gutter : Math.max(gutter, rect.left - width - gutter);
|
|
691
|
+
const preferredTop = placement === "below" ? rect.bottom + 6 : rect.top - 4;
|
|
692
|
+
return {
|
|
693
|
+
left: Math.round(left),
|
|
694
|
+
top: Math.round(Math.min(Math.max(gutter, preferredTop), Math.max(gutter, window.innerHeight - estimatedHeight - gutter))),
|
|
695
|
+
};
|
|
696
|
+
};
|
|
697
|
+
|
|
677
698
|
function PromptError({ message }: { message: string }) {
|
|
678
699
|
const everyApiAuth = /No API key found for everyapi/i.test(message);
|
|
679
700
|
const requiresAuth = everyApiAuth || /No API key found|authentication|未配置认证/i.test(message);
|
|
@@ -5679,7 +5700,13 @@ function PromptCompletionPopover({
|
|
|
5679
5700
|
? filterCommands(commands, query).slice(0, 12)
|
|
5680
5701
|
: files.filter((file) => `${file.path} ${file.label} ${file.status}`.toLowerCase().includes(query.trim().toLowerCase())).slice(0, 12);
|
|
5681
5702
|
return (
|
|
5682
|
-
<div
|
|
5703
|
+
<div
|
|
5704
|
+
aria-label={kind === "command" ? "命令补全" : "文件补全"}
|
|
5705
|
+
className="prompt-completion"
|
|
5706
|
+
data-prompt-completion
|
|
5707
|
+
id="prompt-completion-list"
|
|
5708
|
+
role="listbox"
|
|
5709
|
+
>
|
|
5683
5710
|
<small>{kind === "command" ? "命令" : "文件"}</small>
|
|
5684
5711
|
{items.length ? (
|
|
5685
5712
|
items.slice(0, 12).map((item, index) => {
|
|
@@ -5874,9 +5901,12 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
5874
5901
|
const [commandIndex, setCommandIndex] = useState(0);
|
|
5875
5902
|
const [sessionMenuOpen, setSessionMenuOpen] = useState(false);
|
|
5876
5903
|
const [sessionMenuPath, setSessionMenuPath] = useState<string>();
|
|
5904
|
+
const [sessionMenuPosition, setSessionMenuPosition] = useState<{ left: number; top: number }>();
|
|
5877
5905
|
const [sessionToolsOpen, setSessionToolsOpen] = useState(false);
|
|
5906
|
+
const [sessionToolsPosition, setSessionToolsPosition] = useState<{ left: number; top: number }>();
|
|
5878
5907
|
const [sessionSelectionMode, setSessionSelectionMode] = useState(false);
|
|
5879
5908
|
const [sessionDialog, setSessionDialog] = useState<"rename" | "delete" | "archive" | "batch-delete">();
|
|
5909
|
+
const [sessionActionTarget, setSessionActionTarget] = useState<{ name: string; path: string }>();
|
|
5880
5910
|
const [sessionNameDraft, setSessionNameDraft] = useState("");
|
|
5881
5911
|
const [workspaceChooserOpen, setWorkspaceChooserOpen] = useState(false);
|
|
5882
5912
|
const [workspaceError, setWorkspaceError] = useState("");
|
|
@@ -5902,7 +5932,6 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
5902
5932
|
const [installedPluginMetadata, setInstalledPluginMetadata] = useState<ClientMarketplacePlugin>();
|
|
5903
5933
|
const [marketplacePage, setMarketplacePage] = useState(initialQueryState.marketplacePage);
|
|
5904
5934
|
const [permission, setPermission] = useState(true);
|
|
5905
|
-
const [contextExpanded, setContextExpanded] = useState(false);
|
|
5906
5935
|
const [promptError, setPromptError] = useState("");
|
|
5907
5936
|
const [promptBusy, setPromptBusy] = useState(false);
|
|
5908
5937
|
const [pendingPrompt, setPendingPrompt] = useState("");
|
|
@@ -5913,6 +5942,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
5913
5942
|
const [sessionHasNext, setSessionHasNext] = useState(false);
|
|
5914
5943
|
const [selectedSessionPaths, setSelectedSessionPaths] = useState<ReadonlySet<string>>(new Set());
|
|
5915
5944
|
const importInputRef = useRef<HTMLInputElement>(null);
|
|
5945
|
+
const sessionPopoverTriggerRef = useRef<HTMLButtonElement | null>(null);
|
|
5916
5946
|
const [streamingAssistant, setStreamingAssistant] = useState<{ thinking: string; text: string }>();
|
|
5917
5947
|
const promptInputRef = useRef<HTMLTextAreaElement>(null);
|
|
5918
5948
|
const chatScrollRef = useRef<HTMLDivElement>(null);
|
|
@@ -5961,6 +5991,78 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
5961
5991
|
useEffect(() => {
|
|
5962
5992
|
setPromptCompletionIndex(0);
|
|
5963
5993
|
}, [promptCompletion?.kind, promptCompletion?.query]);
|
|
5994
|
+
useEffect(() => {
|
|
5995
|
+
if (!sessionMenuOpen && !sessionToolsOpen) return;
|
|
5996
|
+
const dismissOnPointerDown = (event: PointerEvent) => {
|
|
5997
|
+
if (event.target instanceof Element && event.target.closest("[data-session-popover]")) return;
|
|
5998
|
+
setSessionMenuOpen(false);
|
|
5999
|
+
setSessionMenuPath(undefined);
|
|
6000
|
+
setSessionMenuPosition(undefined);
|
|
6001
|
+
setSessionToolsOpen(false);
|
|
6002
|
+
setSessionToolsPosition(undefined);
|
|
6003
|
+
setSessionActionTarget(undefined);
|
|
6004
|
+
};
|
|
6005
|
+
const dismissOnEscape = (event: KeyboardEvent) => {
|
|
6006
|
+
if (event.key !== "Escape") return;
|
|
6007
|
+
event.preventDefault();
|
|
6008
|
+
event.stopPropagation();
|
|
6009
|
+
setSessionMenuOpen(false);
|
|
6010
|
+
setSessionMenuPath(undefined);
|
|
6011
|
+
setSessionMenuPosition(undefined);
|
|
6012
|
+
setSessionToolsOpen(false);
|
|
6013
|
+
setSessionToolsPosition(undefined);
|
|
6014
|
+
setSessionActionTarget(undefined);
|
|
6015
|
+
sessionPopoverTriggerRef.current?.focus();
|
|
6016
|
+
};
|
|
6017
|
+
const dismissOnViewportChange = () => {
|
|
6018
|
+
setSessionMenuOpen(false);
|
|
6019
|
+
setSessionMenuPath(undefined);
|
|
6020
|
+
setSessionMenuPosition(undefined);
|
|
6021
|
+
setSessionToolsOpen(false);
|
|
6022
|
+
setSessionToolsPosition(undefined);
|
|
6023
|
+
setSessionActionTarget(undefined);
|
|
6024
|
+
};
|
|
6025
|
+
document.addEventListener("pointerdown", dismissOnPointerDown);
|
|
6026
|
+
document.addEventListener("keydown", dismissOnEscape);
|
|
6027
|
+
document.addEventListener("scroll", dismissOnViewportChange, true);
|
|
6028
|
+
window.addEventListener("resize", dismissOnViewportChange);
|
|
6029
|
+
return () => {
|
|
6030
|
+
document.removeEventListener("pointerdown", dismissOnPointerDown);
|
|
6031
|
+
document.removeEventListener("keydown", dismissOnEscape);
|
|
6032
|
+
document.removeEventListener("scroll", dismissOnViewportChange, true);
|
|
6033
|
+
window.removeEventListener("resize", dismissOnViewportChange);
|
|
6034
|
+
};
|
|
6035
|
+
}, [sessionMenuOpen, sessionToolsOpen]);
|
|
6036
|
+
useEffect(() => {
|
|
6037
|
+
if (!commandOpen && !promptCompletionOpen) return;
|
|
6038
|
+
const dismissTransientLists = (event: PointerEvent) => {
|
|
6039
|
+
const target = event.target instanceof Element ? event.target : undefined;
|
|
6040
|
+
if (commandOpen && !target?.closest("[data-command-palette]")) {
|
|
6041
|
+
setCommandOpen(false);
|
|
6042
|
+
setCommandQuery("");
|
|
6043
|
+
}
|
|
6044
|
+
if (promptCompletionOpen && !target?.closest("[data-prompt-completion]")) setPromptCompletionSuppressed(true);
|
|
6045
|
+
};
|
|
6046
|
+
document.addEventListener("pointerdown", dismissTransientLists);
|
|
6047
|
+
return () => document.removeEventListener("pointerdown", dismissTransientLists);
|
|
6048
|
+
}, [commandOpen, promptCompletionOpen]);
|
|
6049
|
+
useEffect(() => {
|
|
6050
|
+
const dismissProviderModels = (event: PointerEvent | KeyboardEvent) => {
|
|
6051
|
+
if (event instanceof KeyboardEvent && event.key !== "Escape") return;
|
|
6052
|
+
const target = event.target instanceof Element ? event.target : undefined;
|
|
6053
|
+
document.querySelectorAll<HTMLDetailsElement>("details.provider-models-details[open]").forEach((details) => {
|
|
6054
|
+
if (event instanceof PointerEvent && target && details.contains(target)) return;
|
|
6055
|
+
details.removeAttribute("open");
|
|
6056
|
+
if (event instanceof KeyboardEvent) details.querySelector<HTMLElement>("summary")?.focus();
|
|
6057
|
+
});
|
|
6058
|
+
};
|
|
6059
|
+
document.addEventListener("pointerdown", dismissProviderModels);
|
|
6060
|
+
document.addEventListener("keydown", dismissProviderModels);
|
|
6061
|
+
return () => {
|
|
6062
|
+
document.removeEventListener("pointerdown", dismissProviderModels);
|
|
6063
|
+
document.removeEventListener("keydown", dismissProviderModels);
|
|
6064
|
+
};
|
|
6065
|
+
}, []);
|
|
5964
6066
|
useEffect(() => {
|
|
5965
6067
|
if (typeof window === "undefined") return;
|
|
5966
6068
|
const params = new URLSearchParams(window.location.search);
|
|
@@ -6370,7 +6472,10 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
6370
6472
|
setSelectedSessionPaths(new Set());
|
|
6371
6473
|
setSessionMenuOpen(false);
|
|
6372
6474
|
setSessionMenuPath(undefined);
|
|
6475
|
+
setSessionMenuPosition(undefined);
|
|
6373
6476
|
setSessionToolsOpen(false);
|
|
6477
|
+
setSessionToolsPosition(undefined);
|
|
6478
|
+
setSessionActionTarget(undefined);
|
|
6374
6479
|
setSessionSelectionMode(false);
|
|
6375
6480
|
setSessionDialog(undefined);
|
|
6376
6481
|
} catch (cause: unknown) {
|
|
@@ -6388,16 +6493,25 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
6388
6493
|
return next;
|
|
6389
6494
|
});
|
|
6390
6495
|
};
|
|
6391
|
-
const openSessionMenu = (path: string, name
|
|
6496
|
+
const openSessionMenu = (path: string, name: string | undefined, trigger: HTMLButtonElement) => {
|
|
6497
|
+
if (sessionMenuOpen && sessionMenuPath === path) {
|
|
6498
|
+
closeSessionMenu();
|
|
6499
|
+
setSessionActionTarget(undefined);
|
|
6500
|
+
return;
|
|
6501
|
+
}
|
|
6392
6502
|
setSessionToolsOpen(false);
|
|
6393
|
-
|
|
6503
|
+
setSessionToolsPosition(undefined);
|
|
6504
|
+
sessionPopoverTriggerRef.current = trigger;
|
|
6394
6505
|
setSessionNameDraft(name ?? "");
|
|
6506
|
+
setSessionActionTarget({ name: name || "未命名会话", path });
|
|
6395
6507
|
setSessionMenuPath(path);
|
|
6508
|
+
setSessionMenuPosition(sidebarPopoverPosition(trigger, 142, 190, "beside"));
|
|
6396
6509
|
setSessionMenuOpen(true);
|
|
6397
6510
|
};
|
|
6398
6511
|
const closeSessionMenu = () => {
|
|
6399
6512
|
setSessionMenuOpen(false);
|
|
6400
6513
|
setSessionMenuPath(undefined);
|
|
6514
|
+
setSessionMenuPosition(undefined);
|
|
6401
6515
|
};
|
|
6402
6516
|
const pushInstalledPluginRoute = (pluginId: string | undefined) => {
|
|
6403
6517
|
const params = new URLSearchParams(window.location.search);
|
|
@@ -6638,36 +6752,22 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
6638
6752
|
)}
|
|
6639
6753
|
</div>
|
|
6640
6754
|
<div className="composer-wrap">
|
|
6641
|
-
<div className="context-
|
|
6642
|
-
<
|
|
6643
|
-
|
|
6644
|
-
<
|
|
6645
|
-
<
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
<
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
<
|
|
6652
|
-
|
|
6755
|
+
<div className="context-shell">
|
|
6756
|
+
<div className="context-line">
|
|
6757
|
+
<span className="context-label">实时上下文</span>
|
|
6758
|
+
<div className="context-metrics">
|
|
6759
|
+
<span>
|
|
6760
|
+
<b>{data.status?.messages ?? 0}</b> 条消息
|
|
6761
|
+
</span>
|
|
6762
|
+
<span>
|
|
6763
|
+
<b>{data.status?.events ?? events.length}</b> 个事件
|
|
6764
|
+
</span>
|
|
6765
|
+
<span>
|
|
6766
|
+
<b>{value(data.status?.model)}</b>
|
|
6767
|
+
</span>
|
|
6768
|
+
</div>
|
|
6653
6769
|
</div>
|
|
6654
|
-
<button aria-expanded={contextExpanded} onClick={() => setContextExpanded((current) => !current)} type="button">
|
|
6655
|
-
{contextExpanded ? "收起" : "展开"}
|
|
6656
|
-
</button>
|
|
6657
6770
|
</div>
|
|
6658
|
-
{contextExpanded && (
|
|
6659
|
-
<div className="context-breakdown" role="status">
|
|
6660
|
-
<span>
|
|
6661
|
-
消息 <b>{data.status?.messages ?? 0}</b>
|
|
6662
|
-
</span>
|
|
6663
|
-
<span>
|
|
6664
|
-
运行时事件 <b>{data.status?.events ?? events.length}</b>
|
|
6665
|
-
</span>
|
|
6666
|
-
<span>
|
|
6667
|
-
模型 <b>{value(data.status?.model)}</b>
|
|
6668
|
-
</span>
|
|
6669
|
-
</div>
|
|
6670
|
-
)}
|
|
6671
6771
|
<div className="composer-stack">
|
|
6672
6772
|
{promptError && <PromptError message={promptError} />}
|
|
6673
6773
|
{annotationSelection ? (
|
|
@@ -6783,6 +6883,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
6783
6883
|
readOnly={!workspaceReady}
|
|
6784
6884
|
ref={promptInputRef}
|
|
6785
6885
|
rows={2}
|
|
6886
|
+
data-prompt-completion
|
|
6786
6887
|
value={draft}
|
|
6787
6888
|
></textarea>
|
|
6788
6889
|
{promptCompletionOpen && promptCompletion && (
|
|
@@ -6910,7 +7011,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
6910
7011
|
<button className="new-session" onClick={beginNewSession} type="button" aria-expanded={workspaceChooserOpen}>
|
|
6911
7012
|
+ 新建会话
|
|
6912
7013
|
</button>
|
|
6913
|
-
<div className="session-search">
|
|
7014
|
+
<div className="session-search" data-command-palette>
|
|
6914
7015
|
<input
|
|
6915
7016
|
aria-controls={commandOpen ? "command-menu" : undefined}
|
|
6916
7017
|
aria-expanded={commandOpen}
|
|
@@ -6989,56 +7090,79 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
6989
7090
|
>
|
|
6990
7091
|
{sessionSelectionMode ? "完成" : "选择"}
|
|
6991
7092
|
</button>
|
|
6992
|
-
<div className="session-tools-wrap">
|
|
7093
|
+
<div className="session-tools-wrap" data-session-popover>
|
|
6993
7094
|
<button
|
|
6994
7095
|
aria-expanded={sessionToolsOpen}
|
|
7096
|
+
aria-haspopup="menu"
|
|
6995
7097
|
aria-label="会话工具"
|
|
6996
7098
|
className="session-tool-button icon"
|
|
6997
|
-
onClick={() => {
|
|
7099
|
+
onClick={(event) => {
|
|
6998
7100
|
closeSessionMenu();
|
|
6999
|
-
|
|
7101
|
+
sessionPopoverTriggerRef.current = event.currentTarget;
|
|
7102
|
+
setSessionActionTarget(undefined);
|
|
7103
|
+
if (sessionToolsOpen) {
|
|
7104
|
+
setSessionToolsOpen(false);
|
|
7105
|
+
setSessionToolsPosition(undefined);
|
|
7106
|
+
} else {
|
|
7107
|
+
setSessionToolsPosition(sidebarPopoverPosition(event.currentTarget, 150, 190, "below"));
|
|
7108
|
+
setSessionToolsOpen(true);
|
|
7109
|
+
}
|
|
7000
7110
|
}}
|
|
7001
7111
|
type="button"
|
|
7002
7112
|
>
|
|
7003
7113
|
⋯
|
|
7004
7114
|
</button>
|
|
7005
|
-
{sessionToolsOpen &&
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
}
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7115
|
+
{sessionToolsOpen &&
|
|
7116
|
+
sessionToolsPosition &&
|
|
7117
|
+
createPortal(
|
|
7118
|
+
<div className="session-tools-popover" data-session-popover role="menu" style={sessionToolsPosition}>
|
|
7119
|
+
<button autoFocus onClick={() => window.location.reload()} role="menuitem" type="button">
|
|
7120
|
+
刷新列表
|
|
7121
|
+
</button>
|
|
7122
|
+
<button
|
|
7123
|
+
onClick={() => {
|
|
7124
|
+
setSessionToolsOpen(false);
|
|
7125
|
+
setSessionToolsPosition(undefined);
|
|
7126
|
+
importInputRef.current?.click();
|
|
7127
|
+
}}
|
|
7128
|
+
role="menuitem"
|
|
7129
|
+
type="button"
|
|
7130
|
+
>
|
|
7131
|
+
导入会话
|
|
7132
|
+
</button>
|
|
7133
|
+
<button
|
|
7134
|
+
disabled={!activeSessionPath || sessionActionBusy}
|
|
7135
|
+
onClick={() => {
|
|
7136
|
+
if (!activeSessionPath) return;
|
|
7137
|
+
void sessionAction(async () => {
|
|
7138
|
+
const blob = await api.exportSession(activeSessionPath);
|
|
7139
|
+
const link = document.createElement("a");
|
|
7140
|
+
link.href = URL.createObjectURL(blob);
|
|
7141
|
+
link.download = `${data.session?.sessionId ?? "session"}.jsonl`;
|
|
7142
|
+
link.click();
|
|
7143
|
+
URL.revokeObjectURL(link.href);
|
|
7144
|
+
});
|
|
7145
|
+
}}
|
|
7146
|
+
role="menuitem"
|
|
7147
|
+
type="button"
|
|
7148
|
+
>
|
|
7149
|
+
导出当前会话
|
|
7150
|
+
</button>
|
|
7151
|
+
<button
|
|
7152
|
+
onClick={() => {
|
|
7153
|
+
setIncludeArchivedSessions((current) => !current);
|
|
7154
|
+
setSessionToolsOpen(false);
|
|
7155
|
+
setSessionToolsPosition(undefined);
|
|
7156
|
+
void refresh();
|
|
7157
|
+
}}
|
|
7158
|
+
role="menuitem"
|
|
7159
|
+
type="button"
|
|
7160
|
+
>
|
|
7161
|
+
{includeArchivedSessions ? "隐藏归档会话" : "显示归档会话"}
|
|
7162
|
+
</button>
|
|
7163
|
+
</div>,
|
|
7164
|
+
document.body,
|
|
7165
|
+
)}
|
|
7042
7166
|
</div>
|
|
7043
7167
|
</div>
|
|
7044
7168
|
</div>
|
|
@@ -7054,6 +7178,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
7054
7178
|
<button
|
|
7055
7179
|
className="danger"
|
|
7056
7180
|
onClick={() => {
|
|
7181
|
+
setSessionActionTarget(undefined);
|
|
7057
7182
|
setSessionDialog("batch-delete");
|
|
7058
7183
|
}}
|
|
7059
7184
|
type="button"
|
|
@@ -7097,17 +7222,23 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
7097
7222
|
</button>
|
|
7098
7223
|
{!sessionSelectionMode && activeSessionPath && (
|
|
7099
7224
|
<button
|
|
7225
|
+
aria-expanded={sessionMenuOpen && sessionMenuPath === activeSessionPath}
|
|
7226
|
+
aria-haspopup="menu"
|
|
7100
7227
|
aria-label="当前会话操作"
|
|
7101
7228
|
className="session-row-more"
|
|
7102
|
-
|
|
7229
|
+
data-session-popover
|
|
7230
|
+
onClick={(event) =>
|
|
7231
|
+
openSessionMenu(activeSessionPath, data.session?.messages.length ? data.session?.sessionId.slice(0, 12) : "新会话", event.currentTarget)
|
|
7232
|
+
}
|
|
7103
7233
|
type="button"
|
|
7104
7234
|
>
|
|
7105
7235
|
⋯
|
|
7106
7236
|
</button>
|
|
7107
7237
|
)}
|
|
7108
|
-
{!sessionSelectionMode && activeSessionPath && sessionMenuPath === activeSessionPath && sessionMenuOpen && (
|
|
7238
|
+
{!sessionSelectionMode && activeSessionPath && sessionMenuPath === activeSessionPath && sessionMenuOpen && sessionMenuPosition && (
|
|
7109
7239
|
<SessionActionMenu
|
|
7110
7240
|
busy={sessionActionBusy}
|
|
7241
|
+
position={sessionMenuPosition}
|
|
7111
7242
|
onArchive={() => {
|
|
7112
7243
|
closeSessionMenu();
|
|
7113
7244
|
setSessionDialog("archive");
|
|
@@ -7166,43 +7297,51 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
7166
7297
|
</button>
|
|
7167
7298
|
{!sessionSelectionMode && typeof session.path === "string" && (
|
|
7168
7299
|
<button
|
|
7300
|
+
aria-expanded={sessionMenuOpen && sessionMenuPath === session.path}
|
|
7301
|
+
aria-haspopup="menu"
|
|
7169
7302
|
aria-label={`会话操作 ${value(session.name ?? session.firstMessage, "未命名会话")}`}
|
|
7170
7303
|
className="session-row-more"
|
|
7304
|
+
data-session-popover
|
|
7171
7305
|
onClick={(event) => {
|
|
7172
7306
|
event.stopPropagation();
|
|
7173
|
-
openSessionMenu(session.path as string, value(session.name ?? session.firstMessage, ""));
|
|
7307
|
+
openSessionMenu(session.path as string, value(session.name ?? session.firstMessage, ""), event.currentTarget);
|
|
7174
7308
|
}}
|
|
7175
7309
|
type="button"
|
|
7176
7310
|
>
|
|
7177
7311
|
⋯
|
|
7178
7312
|
</button>
|
|
7179
7313
|
)}
|
|
7180
|
-
{!sessionSelectionMode &&
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7314
|
+
{!sessionSelectionMode &&
|
|
7315
|
+
typeof session.path === "string" &&
|
|
7316
|
+
sessionMenuPath === session.path &&
|
|
7317
|
+
sessionMenuOpen &&
|
|
7318
|
+
sessionMenuPosition && (
|
|
7319
|
+
<SessionActionMenu
|
|
7320
|
+
busy={sessionActionBusy}
|
|
7321
|
+
position={sessionMenuPosition}
|
|
7322
|
+
onArchive={() => {
|
|
7323
|
+
closeSessionMenu();
|
|
7324
|
+
setSessionDialog("archive");
|
|
7325
|
+
}}
|
|
7326
|
+
onDelete={() => {
|
|
7327
|
+
closeSessionMenu();
|
|
7328
|
+
setSessionDialog("delete");
|
|
7329
|
+
}}
|
|
7330
|
+
onFork={() =>
|
|
7331
|
+
void sessionAction(async () => {
|
|
7332
|
+
const result = await api.forkSession(session.path as string);
|
|
7333
|
+
if (result.sessionFile) {
|
|
7334
|
+
setSelectedSessionPath(result.sessionFile);
|
|
7335
|
+
await api.openSession(result.sessionFile);
|
|
7336
|
+
}
|
|
7337
|
+
})
|
|
7338
|
+
}
|
|
7339
|
+
onRename={() => {
|
|
7340
|
+
closeSessionMenu();
|
|
7341
|
+
setSessionDialog("rename");
|
|
7342
|
+
}}
|
|
7343
|
+
/>
|
|
7344
|
+
)}
|
|
7206
7345
|
</div>
|
|
7207
7346
|
))}
|
|
7208
7347
|
</div>
|
|
@@ -7308,7 +7447,7 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
7308
7447
|
</footer>
|
|
7309
7448
|
</aside>
|
|
7310
7449
|
<section className="main-pane">
|
|
7311
|
-
<header className=
|
|
7450
|
+
<header className={`main-header ${!settings && page === "session" ? "session-track" : ""}`}>
|
|
7312
7451
|
<div className="active-heading">
|
|
7313
7452
|
<strong>
|
|
7314
7453
|
{settings
|
|
@@ -7380,17 +7519,91 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
7380
7519
|
{!settings && page === "session" && <span aria-hidden="true" className="header-divider"></span>}
|
|
7381
7520
|
{!settings && page === "session" && (
|
|
7382
7521
|
<>
|
|
7383
|
-
<
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7522
|
+
<div className="session-menu-wrap" data-session-popover>
|
|
7523
|
+
<button
|
|
7524
|
+
aria-expanded={sessionMenuOpen && !sessionMenuPath}
|
|
7525
|
+
aria-haspopup="menu"
|
|
7526
|
+
className="session-menu"
|
|
7527
|
+
onClick={(event) => {
|
|
7528
|
+
const closeCurrentMenu = sessionMenuOpen && !sessionMenuPath;
|
|
7529
|
+
setSessionMenuPath(undefined);
|
|
7530
|
+
setSessionMenuPosition(undefined);
|
|
7531
|
+
sessionPopoverTriggerRef.current = event.currentTarget;
|
|
7532
|
+
setSessionActionTarget(
|
|
7533
|
+
!closeCurrentMenu && activeSessionPath
|
|
7534
|
+
? { name: data.session?.sessionId?.slice(0, 12) || "当前会话", path: activeSessionPath }
|
|
7535
|
+
: undefined,
|
|
7536
|
+
);
|
|
7537
|
+
setSessionMenuOpen(!closeCurrentMenu);
|
|
7538
|
+
}}
|
|
7539
|
+
type="button"
|
|
7540
|
+
aria-label="会话操作"
|
|
7541
|
+
>
|
|
7542
|
+
⋯
|
|
7543
|
+
</button>
|
|
7544
|
+
{sessionMenuOpen && !sessionMenuPath && (
|
|
7545
|
+
<div className="session-menu-popover compact-session-menu" role="menu">
|
|
7546
|
+
<button
|
|
7547
|
+
className="session-action"
|
|
7548
|
+
disabled={!activeSessionPath || sessionActionBusy}
|
|
7549
|
+
onClick={() => {
|
|
7550
|
+
setSessionNameDraft(data.session?.sessionId?.slice(0, 12) ?? "");
|
|
7551
|
+
setSessionDialog("rename");
|
|
7552
|
+
setSessionMenuOpen(false);
|
|
7553
|
+
}}
|
|
7554
|
+
role="menuitem"
|
|
7555
|
+
type="button"
|
|
7556
|
+
>
|
|
7557
|
+
<strong>重命名</strong>
|
|
7558
|
+
<small>设置一个容易识别的名称</small>
|
|
7559
|
+
</button>
|
|
7560
|
+
<button
|
|
7561
|
+
className="session-action"
|
|
7562
|
+
disabled={!activeSessionPath || sessionActionBusy}
|
|
7563
|
+
onClick={() =>
|
|
7564
|
+
void sessionAction(async () => {
|
|
7565
|
+
const result = await api.forkSession(activeSessionPath as string);
|
|
7566
|
+
if (result.sessionFile) {
|
|
7567
|
+
setSelectedSessionPath(result.sessionFile);
|
|
7568
|
+
await api.openSession(result.sessionFile);
|
|
7569
|
+
}
|
|
7570
|
+
})
|
|
7571
|
+
}
|
|
7572
|
+
role="menuitem"
|
|
7573
|
+
type="button"
|
|
7574
|
+
>
|
|
7575
|
+
<strong>复制会话</strong>
|
|
7576
|
+
<small>复制上下文并打开副本</small>
|
|
7577
|
+
</button>
|
|
7578
|
+
<button
|
|
7579
|
+
className="session-action"
|
|
7580
|
+
disabled={!activeSessionPath || sessionActionBusy}
|
|
7581
|
+
onClick={() => {
|
|
7582
|
+
setSessionMenuOpen(false);
|
|
7583
|
+
setSessionDialog("archive");
|
|
7584
|
+
}}
|
|
7585
|
+
role="menuitem"
|
|
7586
|
+
type="button"
|
|
7587
|
+
>
|
|
7588
|
+
<strong>归档会话</strong>
|
|
7589
|
+
<small>从默认列表隐藏</small>
|
|
7590
|
+
</button>
|
|
7591
|
+
<button
|
|
7592
|
+
className="session-action danger"
|
|
7593
|
+
disabled={!activeSessionPath || sessionActionBusy}
|
|
7594
|
+
onClick={() => {
|
|
7595
|
+
setSessionMenuOpen(false);
|
|
7596
|
+
setSessionDialog("delete");
|
|
7597
|
+
}}
|
|
7598
|
+
role="menuitem"
|
|
7599
|
+
type="button"
|
|
7600
|
+
>
|
|
7601
|
+
<strong>删除会话</strong>
|
|
7602
|
+
<small>永久删除本地记录</small>
|
|
7603
|
+
</button>
|
|
7604
|
+
</div>
|
|
7605
|
+
)}
|
|
7606
|
+
</div>
|
|
7394
7607
|
<button
|
|
7395
7608
|
aria-label={details !== undefined ? "关闭详情" : "打开详情"}
|
|
7396
7609
|
aria-pressed={details !== undefined}
|
|
@@ -7402,64 +7615,6 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
7402
7615
|
</button>
|
|
7403
7616
|
</>
|
|
7404
7617
|
)}
|
|
7405
|
-
{!settings && page === "session" && sessionMenuOpen && !sessionMenuPath && (
|
|
7406
|
-
<div className="session-menu-popover compact-session-menu">
|
|
7407
|
-
<button
|
|
7408
|
-
className="session-action"
|
|
7409
|
-
disabled={!activeSessionPath || sessionActionBusy}
|
|
7410
|
-
onClick={() => {
|
|
7411
|
-
setSessionNameDraft(data.session?.sessionId?.slice(0, 12) ?? "");
|
|
7412
|
-
setSessionDialog("rename");
|
|
7413
|
-
setSessionMenuOpen(false);
|
|
7414
|
-
}}
|
|
7415
|
-
type="button"
|
|
7416
|
-
>
|
|
7417
|
-
<strong>重命名</strong>
|
|
7418
|
-
<small>设置一个容易识别的名称</small>
|
|
7419
|
-
</button>
|
|
7420
|
-
<button
|
|
7421
|
-
className="session-action"
|
|
7422
|
-
disabled={!activeSessionPath || sessionActionBusy}
|
|
7423
|
-
onClick={() =>
|
|
7424
|
-
void sessionAction(async () => {
|
|
7425
|
-
const result = await api.forkSession(activeSessionPath as string);
|
|
7426
|
-
if (result.sessionFile) {
|
|
7427
|
-
setSelectedSessionPath(result.sessionFile);
|
|
7428
|
-
await api.openSession(result.sessionFile);
|
|
7429
|
-
}
|
|
7430
|
-
})
|
|
7431
|
-
}
|
|
7432
|
-
type="button"
|
|
7433
|
-
>
|
|
7434
|
-
<strong>复制会话</strong>
|
|
7435
|
-
<small>复制上下文并打开副本</small>
|
|
7436
|
-
</button>
|
|
7437
|
-
<button
|
|
7438
|
-
className="session-action"
|
|
7439
|
-
disabled={!activeSessionPath || sessionActionBusy}
|
|
7440
|
-
onClick={() => {
|
|
7441
|
-
setSessionMenuOpen(false);
|
|
7442
|
-
setSessionDialog("archive");
|
|
7443
|
-
}}
|
|
7444
|
-
type="button"
|
|
7445
|
-
>
|
|
7446
|
-
<strong>归档会话</strong>
|
|
7447
|
-
<small>从默认列表隐藏</small>
|
|
7448
|
-
</button>
|
|
7449
|
-
<button
|
|
7450
|
-
className="session-action danger"
|
|
7451
|
-
disabled={!activeSessionPath || sessionActionBusy}
|
|
7452
|
-
onClick={() => {
|
|
7453
|
-
setSessionMenuOpen(false);
|
|
7454
|
-
setSessionDialog("delete");
|
|
7455
|
-
}}
|
|
7456
|
-
type="button"
|
|
7457
|
-
>
|
|
7458
|
-
<strong>删除会话</strong>
|
|
7459
|
-
<small>永久删除本地记录</small>
|
|
7460
|
-
</button>
|
|
7461
|
-
</div>
|
|
7462
|
-
)}
|
|
7463
7618
|
</header>
|
|
7464
7619
|
{refreshIssues.length > 0 && (
|
|
7465
7620
|
<div aria-live="polite" className="refresh-warning" role="status">
|
|
@@ -7522,19 +7677,27 @@ export function ControlRoomView({ api = createClientApi(), appVersion }: { api?:
|
|
|
7522
7677
|
busy={sessionActionBusy}
|
|
7523
7678
|
count={sessionDialog === "batch-delete" ? selectedSessionPaths.size : undefined}
|
|
7524
7679
|
kind={sessionDialog}
|
|
7525
|
-
name={
|
|
7680
|
+
name={
|
|
7681
|
+
sessionDialog === "rename" || sessionDialog === "batch-delete"
|
|
7682
|
+
? undefined
|
|
7683
|
+
: (sessionActionTarget?.name ?? value(data.session?.sessionId, "当前会话"))
|
|
7684
|
+
}
|
|
7526
7685
|
onChange={setSessionNameDraft}
|
|
7527
|
-
onClose={() =>
|
|
7686
|
+
onClose={() => {
|
|
7687
|
+
setSessionDialog(undefined);
|
|
7688
|
+
setSessionActionTarget(undefined);
|
|
7689
|
+
}}
|
|
7528
7690
|
onConfirm={() => {
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7691
|
+
const targetPath = sessionActionTarget?.path ?? activeSessionPath;
|
|
7692
|
+
if (sessionDialog === "rename" && targetPath) {
|
|
7693
|
+
void sessionAction(() => api.renameSession(targetPath, sessionNameDraft.trim()).then(() => undefined));
|
|
7694
|
+
} else if (sessionDialog === "archive" && targetPath) {
|
|
7532
7695
|
void sessionAction(async () => {
|
|
7533
|
-
await api.setSessionMetadata(
|
|
7696
|
+
await api.setSessionMetadata(targetPath, { archived: true });
|
|
7534
7697
|
});
|
|
7535
|
-
} else if (sessionDialog === "delete" &&
|
|
7698
|
+
} else if (sessionDialog === "delete" && targetPath) {
|
|
7536
7699
|
void sessionAction(async () => {
|
|
7537
|
-
await api.deleteSession(
|
|
7700
|
+
await api.deleteSession(targetPath);
|
|
7538
7701
|
});
|
|
7539
7702
|
} else if (sessionDialog === "batch-delete") {
|
|
7540
7703
|
void sessionAction(() => api.batchSessions("delete", [...selectedSessionPaths]).then(() => undefined));
|