@rightkit/agent-ui-settings 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +44 -2
  5. package/dist/appName.d.ts +1 -0
  6. package/dist/appName.js +1 -0
  7. package/dist/components/PluginContributionHost.d.ts +17 -0
  8. package/dist/components/PluginContributionHost.js +23 -0
  9. package/dist/components/ReadinessCard.d.ts +4 -0
  10. package/dist/components/ReadinessCard.js +19 -0
  11. package/dist/components/remote/RemoteDevicesPanel.d.ts +7 -0
  12. package/dist/components/remote/RemoteDevicesPanel.js +153 -0
  13. package/dist/components/remote/RemoteHostsPanel.d.ts +8 -0
  14. package/dist/components/remote/RemoteHostsPanel.js +139 -0
  15. package/dist/components/settings/analytics/AnalyticsConsentCard.d.ts +14 -0
  16. package/dist/components/settings/analytics/AnalyticsConsentCard.js +22 -0
  17. package/dist/components/settings/cliUpdate/CliUpdatePanel.d.ts +9 -0
  18. package/dist/components/settings/cliUpdate/CliUpdatePanel.js +18 -0
  19. package/dist/components/settings/helpers.d.ts +7 -0
  20. package/dist/components/settings/helpers.js +40 -0
  21. package/dist/components/settings/keyboard/KeyboardShortcutsSettings.d.ts +12 -0
  22. package/dist/components/settings/keyboard/KeyboardShortcutsSettings.js +75 -0
  23. package/dist/components/settings/keyboard/ShortcutRecordingDialog.d.ts +27 -0
  24. package/dist/components/settings/keyboard/ShortcutRecordingDialog.js +154 -0
  25. package/dist/components/settings/marketplace/McpDiscoverPanel.d.ts +34 -0
  26. package/dist/components/settings/marketplace/McpDiscoverPanel.js +66 -0
  27. package/dist/components/settings/marketplace/SkillMarketplace.d.ts +22 -0
  28. package/dist/components/settings/marketplace/SkillMarketplace.js +51 -0
  29. package/dist/components/settings/tabs/ApiKeyAccounts.d.ts +9 -0
  30. package/dist/components/settings/tabs/ApiKeyAccounts.js +67 -0
  31. package/dist/components/settings/tabs/AppearanceTab.d.ts +1 -0
  32. package/dist/components/settings/tabs/AppearanceTab.js +31 -0
  33. package/dist/components/settings/tabs/AppleSyncPanel.d.ts +14 -0
  34. package/dist/components/settings/tabs/AppleSyncPanel.js +65 -0
  35. package/dist/components/settings/tabs/ChildProviderPolicy.d.ts +9 -0
  36. package/dist/components/settings/tabs/ChildProviderPolicy.js +84 -0
  37. package/dist/components/settings/tabs/ConductorsTab.d.ts +6 -0
  38. package/dist/components/settings/tabs/ConductorsTab.js +135 -0
  39. package/dist/components/settings/tabs/DiagnosticsTab.d.ts +13 -0
  40. package/dist/components/settings/tabs/DiagnosticsTab.js +39 -0
  41. package/dist/components/settings/tabs/ExecutionBackendsTab.d.ts +29 -0
  42. package/dist/components/settings/tabs/ExecutionBackendsTab.js +13 -0
  43. package/dist/components/settings/tabs/LicenseTab.d.ts +20 -0
  44. package/dist/components/settings/tabs/LicenseTab.js +66 -0
  45. package/dist/components/settings/tabs/LinkComputerPanel.d.ts +6 -0
  46. package/dist/components/settings/tabs/LinkComputerPanel.js +39 -0
  47. package/dist/components/settings/tabs/LspTab.d.ts +11 -0
  48. package/dist/components/settings/tabs/LspTab.js +34 -0
  49. package/dist/components/settings/tabs/MemoryTab.d.ts +7 -0
  50. package/dist/components/settings/tabs/MemoryTab.js +68 -0
  51. package/dist/components/settings/tabs/ProvidersTab.d.ts +10 -0
  52. package/dist/components/settings/tabs/ProvidersTab.js +214 -0
  53. package/dist/components/settings/tabs/RepairTab.d.ts +6 -0
  54. package/dist/components/settings/tabs/RepairTab.js +44 -0
  55. package/dist/components/settings/tabs/RootModelPicker.d.ts +10 -0
  56. package/dist/components/settings/tabs/RootModelPicker.js +42 -0
  57. package/dist/components/settings/tabs/RuntimeMiddlewareTab.d.ts +8 -0
  58. package/dist/components/settings/tabs/RuntimeMiddlewareTab.js +12 -0
  59. package/dist/components/settings/tabs/WorkspaceTab.d.ts +6 -0
  60. package/dist/components/settings/tabs/WorkspaceTab.js +9 -0
  61. package/dist/components/settings/tabs/execution/CoreSandboxTierPanel.d.ts +9 -0
  62. package/dist/components/settings/tabs/execution/CoreSandboxTierPanel.js +43 -0
  63. package/dist/components/settings/tabs/execution/ExecutionBackendCard.d.ts +20 -0
  64. package/dist/components/settings/tabs/execution/ExecutionBackendCard.js +48 -0
  65. package/dist/components/settings/tabs/execution/ExecutionBackendLimitsForm.d.ts +10 -0
  66. package/dist/components/settings/tabs/execution/ExecutionBackendLimitsForm.js +62 -0
  67. package/dist/components/settings/tabs/execution/ExecutionBackendList.d.ts +19 -0
  68. package/dist/components/settings/tabs/execution/ExecutionBackendList.js +8 -0
  69. package/dist/components/settings/tabs/execution/ExecutionNetworkProfilesPanel.d.ts +16 -0
  70. package/dist/components/settings/tabs/execution/ExecutionNetworkProfilesPanel.js +53 -0
  71. package/dist/components/settings/tabs/execution/RemoteStatusCard.d.ts +2 -0
  72. package/dist/components/settings/tabs/execution/RemoteStatusCard.js +5 -0
  73. package/dist/components/settings/tabs/execution/TextSettingInput.d.ts +15 -0
  74. package/dist/components/settings/tabs/execution/TextSettingInput.js +10 -0
  75. package/dist/components/settings/tabs/execution/types.d.ts +27 -0
  76. package/dist/components/settings/tabs/execution/types.js +1 -0
  77. package/dist/components/settings/tabs/models/ModelEmptyStates.d.ts +12 -0
  78. package/dist/components/settings/tabs/models/ModelEmptyStates.js +63 -0
  79. package/dist/components/settings/tabs/permissions/PersistentPermissionRuleList.d.ts +7 -0
  80. package/dist/components/settings/tabs/permissions/PersistentPermissionRuleList.js +15 -0
  81. package/dist/components/settings/tabs/plugins/InstalledPluginsList.d.ts +6 -0
  82. package/dist/components/settings/tabs/plugins/InstalledPluginsList.js +38 -0
  83. package/dist/components/settings/tabs/remote/RemoteChannelsPanel.d.ts +4 -0
  84. package/dist/components/settings/tabs/remote/RemoteChannelsPanel.js +14 -0
  85. package/dist/components/settings/tabs/remote/RemoteStatusCard.d.ts +8 -0
  86. package/dist/components/settings/tabs/remote/RemoteStatusCard.js +6 -0
  87. package/dist/components/settings/tabs/remote/TelegramStatusPanel.d.ts +6 -0
  88. package/dist/components/settings/tabs/remote/TelegramStatusPanel.js +41 -0
  89. package/dist/components/settings/tabs/shared.d.ts +18 -0
  90. package/dist/components/settings/tabs/shared.js +36 -0
  91. package/dist/components/settings/tabs/skills/SkillShared.d.ts +20 -0
  92. package/dist/components/settings/tabs/skills/SkillShared.js +28 -0
  93. package/dist/components/settings/tabs/skills/SkillTrainingRunList.d.ts +6 -0
  94. package/dist/components/settings/tabs/skills/SkillTrainingRunList.js +11 -0
  95. package/dist/components/settings/tools/ManagedToolHealthPanel.d.ts +16 -0
  96. package/dist/components/settings/tools/ManagedToolHealthPanel.js +24 -0
  97. package/dist/env.d.ts +59 -0
  98. package/dist/index.d.ts +31 -0
  99. package/dist/index.js +33 -0
  100. package/package.json +165 -3
@@ -0,0 +1,135 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+ import { discoverDriver, getDriverStatus, interruptDriver, issueDriverLease, resumeDriver, startDriver, stopDriver, } from "@rightkit/agent-ui-core/lib/daemon";
4
+ import { CodeBlock } from "@rightkit/doc-render";
5
+ import { hostAppName } from "../../../appName.js";
6
+ const DRIVER_LABELS = {
7
+ codex: "Codex",
8
+ claude: "Claude",
9
+ };
10
+ const REPAIR_COMMANDS = {
11
+ codex: "codex login",
12
+ claude: "claude login",
13
+ };
14
+ const EXTERNAL_DRIVER_KINDS = ["codex", "claude"];
15
+ export default function ConductorsTab({ config, selectedSession }) {
16
+ return (_jsxs("section", { className: "flex max-w-[720px] flex-col gap-4 p-6", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "text-[16px] font-bold text-text", children: "Conductors" }), _jsxs("p", { className: "text-[12px] text-text-3", children: [hostAppName(), " launches your own installed Codex or Claude Code CLI (for example", " ", _jsx("code", { children: "codex app-server --stdio --strict-config" }), "), gives it exactly one MCP server \u2014", hostAppName(), "'s session-scoped capability gateway \u2014 and disables its native mutation routes, so every shell command and file write it makes is governed. Same login, same subscription."] })] }), EXTERNAL_DRIVER_KINDS.map((kind) => (_jsx(ConductorCard, { kind: kind, config: config }, kind))), _jsx(SessionDriverControls, { config: config, session: selectedSession })] }));
17
+ }
18
+ function ConductorCard({ kind, config, }) {
19
+ const [discovery, setDiscovery] = useState(null);
20
+ const [error, setError] = useState(null);
21
+ const [pending, setPending] = useState(false);
22
+ const refresh = useCallback(async () => {
23
+ if (!config)
24
+ return;
25
+ setPending(true);
26
+ setError(null);
27
+ try {
28
+ const next = await discoverDriver(config, kind);
29
+ setDiscovery(next);
30
+ }
31
+ catch (cause) {
32
+ setError(cause instanceof Error ? cause.message : `${DRIVER_LABELS[kind]} discovery failed`);
33
+ }
34
+ finally {
35
+ setPending(false);
36
+ }
37
+ }, [config, kind]);
38
+ useEffect(() => {
39
+ void refresh();
40
+ }, [refresh]);
41
+ const diagnostic = error ?? discovery?.diagnostic ?? null;
42
+ const tools = discovery?.capabilities.tools ?? [];
43
+ return (_jsxs("section", { className: "grid gap-3 rounded-lg border border-line bg-panel p-4", "aria-label": `${DRIVER_LABELS[kind]} conductor`, children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("h4", { className: "text-[13px] font-semibold text-text", children: DRIVER_LABELS[kind] }), _jsx("button", { type: "button", className: "cr-control-pill px-3 py-1 text-[12px]", disabled: pending || !config, onClick: () => void refresh(), children: pending ? "Checking…" : "Refresh" })] }), _jsxs("dl", { className: "grid grid-cols-2 gap-x-4 gap-y-1 text-[12px]", children: [_jsx("dt", { className: "text-text-3", children: "Installed" }), _jsx("dd", { children: discovery ? (discovery.installed ? "Yes" : "No") : "Checking…" }), _jsx("dt", { className: "text-text-3", children: "Authenticated" }), _jsx("dd", { children: discovery ? (discovery.authRequired ? "Needs login" : "Yes") : "Checking…" }), _jsx("dt", { className: "text-text-3", children: "Binary version" }), _jsx("dd", { children: discovery?.version.binaryVersion ?? "—" }), _jsx("dt", { className: "text-text-3", children: "Protocol version" }), _jsx("dd", { children: discovery?.version.protocolVersion ?? "—" }), _jsx("dt", { className: "text-text-3", children: "Governed tools" }), _jsx("dd", { className: "truncate", children: tools.length > 0 ? `${tools.length} (${tools.map((tool) => tool.id).join(", ")})` : "—" })] }), diagnostic ? (_jsxs("div", { className: "grid gap-2", children: [_jsx("p", { className: "rounded border border-red-500/30 bg-red-500/10 p-2 text-[12px] text-red-300", children: diagnostic }), _jsx(CodeBlock, { code: REPAIR_COMMANDS[kind], language: "shell" })] })) : null] }));
44
+ }
45
+ function SessionDriverControls({ config, session, }) {
46
+ const kind = session?.driverKind;
47
+ const externalKind = kind === "codex" || kind === "claude" ? kind : null;
48
+ const [discovery, setDiscovery] = useState(null);
49
+ const [status, setStatus] = useState(null);
50
+ const [pending, setPending] = useState(null);
51
+ const [error, setError] = useState(null);
52
+ const leaseRef = useRef(null);
53
+ const refresh = useCallback(async () => {
54
+ if (!config || !session || !externalKind)
55
+ return;
56
+ setError(null);
57
+ try {
58
+ const [nextDiscovery, nextStatus] = await Promise.all([
59
+ discoverDriver(config, externalKind),
60
+ getDriverStatus(config, session.id),
61
+ ]);
62
+ setDiscovery(nextDiscovery);
63
+ setStatus(nextStatus);
64
+ }
65
+ catch (cause) {
66
+ setError(cause instanceof Error ? cause.message : "Driver status could not be loaded");
67
+ }
68
+ }, [config, externalKind, session]);
69
+ useEffect(() => {
70
+ leaseRef.current = null;
71
+ setDiscovery(null);
72
+ setStatus(null);
73
+ void refresh();
74
+ }, [refresh]);
75
+ if (!externalKind) {
76
+ return (_jsxs("section", { className: "grid gap-2 rounded-lg border border-line bg-panel p-4", children: [_jsx("h4", { className: "text-[13px] font-semibold text-text", children: "Active session" }), _jsx("p", { className: "text-[12px] text-text-3", children: "Select a session that runs on Codex or Claude to start, resume, interrupt, or stop its driver here." })] }));
77
+ }
78
+ const driverKind = externalKind;
79
+ const binding = status?.drivers.find((item) => item.driverKind === externalKind) ?? null;
80
+ const diagnostic = error ?? binding?.diagnostic ?? discovery?.diagnostic ?? null;
81
+ const repairCommand = REPAIR_COMMANDS[externalKind];
82
+ async function withAction(name, action) {
83
+ setPending(name);
84
+ setError(null);
85
+ try {
86
+ await action();
87
+ await refresh();
88
+ }
89
+ catch (cause) {
90
+ setError(cause instanceof Error ? cause.message : `Driver ${name} failed`);
91
+ }
92
+ finally {
93
+ setPending(null);
94
+ }
95
+ }
96
+ async function leaseFor(bindingForLease) {
97
+ if (!config || !session || !discovery?.version.binaryVersion || !discovery.version.schemaHash) {
98
+ throw new Error("Driver discovery must report version and schema before it can start");
99
+ }
100
+ const lease = await issueDriverLease(config, session.id, {
101
+ driverKind,
102
+ binaryVersion: bindingForLease?.version.binaryVersion ?? discovery.version.binaryVersion,
103
+ schemaHash: bindingForLease?.version.schemaHash ?? discovery.version.schemaHash,
104
+ });
105
+ leaseRef.current = lease;
106
+ return lease;
107
+ }
108
+ return (_jsxs("section", { className: "grid gap-3 rounded-lg border border-line bg-panel p-4", "aria-label": "Driver session", children: [_jsxs("div", { children: [_jsxs("h4", { className: "text-[13px] font-semibold text-text", children: [DRIVER_LABELS[externalKind], " driver \u2014 ", session?.title ?? session?.id] }), _jsx("p", { className: "text-[12px] text-text-3", children: "Session-scoped gateway only; native vendor effects remain disabled." })] }), _jsxs("dl", { className: "grid grid-cols-2 gap-x-4 gap-y-1 text-[12px]", children: [_jsx("dt", { className: "text-text-3", children: "Lifecycle" }), _jsx("dd", { children: binding?.lifecycle ?? "not started" }), _jsx("dt", { className: "text-text-3", children: "Gateway" }), _jsx("dd", { children: binding?.gatewayState.state ?? "not started" }), _jsx("dt", { className: "text-text-3", children: "Vendor session id" }), _jsx("dd", { className: "truncate", children: binding?.vendorSessionId ?? "—" }), _jsx("dt", { className: "text-text-3", children: "Generation" }), _jsx("dd", { children: binding?.processGeneration ?? "—" })] }), diagnostic ? (_jsxs("div", { className: "grid gap-2", children: [_jsx("p", { className: "rounded border border-red-500/30 bg-red-500/10 p-2 text-[12px] text-red-300", children: diagnostic }), _jsx(CodeBlock, { code: repairCommand, language: "shell" })] })) : null, _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx("button", { type: "button", className: "cr-control-pill px-3 py-1 text-[12px]", disabled: pending !== null, onClick: () => void withAction("refresh", refresh), children: pending === "refresh" ? "Refreshing…" : "Refresh binary & auth" }), _jsx("button", { type: "button", className: "cr-control-pill px-3 py-1 text-[12px]", disabled: pending !== null || !discovery?.installed || discovery.authRequired, onClick: () => void withAction("start", async () => {
109
+ if (!config || !session)
110
+ return;
111
+ const lease = await leaseFor();
112
+ await startDriver(config, session.id, lease.capabilityToken, lease.bindingId, discovery?.version.executable);
113
+ }), children: pending === "start" ? "Starting…" : "Start" }), _jsx("button", { type: "button", className: "cr-control-pill px-3 py-1 text-[12px]", disabled: pending !== null || !binding?.vendorSessionId || !leaseRef.current, onClick: () => void withAction("resume", async () => {
114
+ if (!config || !session || !binding?.vendorSessionId)
115
+ return;
116
+ const lease = leaseRef.current ?? (await leaseFor(binding));
117
+ await resumeDriver(config, session.id, lease.capabilityToken, binding.bindingId, binding.vendorSessionId);
118
+ }), children: "Resume" }), _jsx("button", { type: "button", className: "cr-control-pill px-3 py-1 text-[12px]", disabled: pending !== null ||
119
+ !binding?.vendorSessionId ||
120
+ !binding.vendorTurnId ||
121
+ !leaseRef.current, onClick: () => void withAction("interrupt", async () => {
122
+ if (!config ||
123
+ !session ||
124
+ !binding?.vendorSessionId ||
125
+ !binding.vendorTurnId ||
126
+ !leaseRef.current)
127
+ return;
128
+ await interruptDriver(config, session.id, leaseRef.current.capabilityToken, binding.bindingId, binding.vendorSessionId, binding.vendorTurnId);
129
+ }), children: "Interrupt" }), _jsx("button", { type: "button", className: "cr-control-pill px-3 py-1 text-[12px]", disabled: pending !== null || !binding || !leaseRef.current, onClick: () => void withAction("stop", async () => {
130
+ if (!config || !session || !binding || !leaseRef.current)
131
+ return;
132
+ await stopDriver(config, session.id, leaseRef.current.capabilityToken, binding.bindingId);
133
+ leaseRef.current = null;
134
+ }), children: "Stop" })] })] }));
135
+ }
@@ -0,0 +1,13 @@
1
+ import type { DaemonConfig, DiagnosticsReport, InstructionStatus, SupportBundle } from "@rightkit/agent-ui-core/lib/types";
2
+ export default function DiagnosticsTab({ config, report, supportBundle, supportBundlePending, instructionStatus, loading, error, onRefresh, onCreateBundle, onDownloadBundle, }: {
3
+ config: DaemonConfig | null;
4
+ report: DiagnosticsReport | null;
5
+ supportBundle: SupportBundle | null;
6
+ supportBundlePending: string | null;
7
+ instructionStatus: InstructionStatus | null;
8
+ loading: boolean;
9
+ error: string | null;
10
+ onRefresh: () => void;
11
+ onCreateBundle: () => void;
12
+ onDownloadBundle: () => void;
13
+ }): import("react").JSX.Element;
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import Icon from "@rightkit/agent-ui-core/components/Icon";
4
+ import ReadinessCard from "../../ReadinessCard.js";
5
+ import { ENABLE_READINESS_PANEL, getReadiness } from "@rightkit/agent-ui-core/lib/daemon";
6
+ import { DiagnosticsStat, diagnosticsLabel, diagnosticsStatusClass, OfflinePanel } from "./shared.js";
7
+ export default function DiagnosticsTab({ config, report, supportBundle, supportBundlePending, instructionStatus, loading, error, onRefresh, onCreateBundle, onDownloadBundle, }) {
8
+ const [readinessSnapshot, setReadinessSnapshot] = useState(null);
9
+ useEffect(() => {
10
+ if (!ENABLE_READINESS_PANEL || !config) {
11
+ setReadinessSnapshot(null);
12
+ return;
13
+ }
14
+ let cancelled = false;
15
+ getReadiness(config)
16
+ .then((snapshot) => {
17
+ if (!cancelled)
18
+ setReadinessSnapshot(snapshot);
19
+ })
20
+ .catch(() => {
21
+ if (!cancelled)
22
+ setReadinessSnapshot(null);
23
+ });
24
+ return () => {
25
+ cancelled = true;
26
+ };
27
+ }, [config]);
28
+ return (_jsxs("section", { className: "flex flex-col gap-4 p-6 max-w-[980px]", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "text-[16px] font-bold text-text", children: "Diagnostics" }), _jsx("p", { className: "text-[12px] text-text-3 truncate", children: report
29
+ ? `Verdict: ${diagnosticsLabel(report.verdict)}`
30
+ : "Runtime readiness has not been loaded" })] }), _jsxs("button", { type: "button", className: "inline-flex items-center gap-2 h-8 px-3 rounded-lg border border-line bg-transparent text-text-2 text-[13px] cursor-pointer hover:bg-panel hover:text-text disabled:opacity-40", disabled: loading, onClick: onRefresh, children: [_jsx(Icon, { name: "activity" }), loading ? "Refreshing" : "Refresh"] })] }), error ? _jsx(OfflinePanel, { title: "Diagnostics unavailable.", action: error }) : null, readinessSnapshot ? _jsx(ReadinessCard, { snapshot: readinessSnapshot }) : null, _jsxs("div", { className: "rounded-xl border border-line bg-panel overflow-hidden", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 px-4 py-3 border-b border-line", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h4", { className: "text-[13px] font-semibold text-text", children: "Support bundle" }), _jsx("p", { className: "text-[12px] text-text-3 truncate", children: supportBundle
31
+ ? `${supportBundle.bundleId} · ${supportBundle.byteLength} bytes`
32
+ : "No bundle created this session" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { type: "button", className: "inline-flex items-center gap-2 h-8 px-3 rounded-lg border border-line bg-transparent text-text-2 text-[13px] cursor-pointer hover:bg-panel-2 hover:text-text disabled:opacity-40", disabled: supportBundlePending !== null, onClick: onCreateBundle, children: [_jsx(Icon, { name: "activity" }), supportBundlePending === "create" ? "Creating" : "Create bundle"] }), _jsxs("button", { type: "button", className: "inline-flex items-center gap-2 h-8 px-3 rounded-lg border border-line bg-transparent text-text-2 text-[13px] cursor-pointer hover:bg-panel-2 hover:text-text disabled:opacity-40", disabled: !supportBundle || supportBundlePending !== null, onClick: onDownloadBundle, children: [_jsx(Icon, { name: "download" }), supportBundlePending === "download" ? "Downloading" : "Download"] })] })] }), supportBundle ? (_jsxs("div", { className: "flex flex-col gap-3 px-4 py-3", children: [_jsxs("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-3", children: [_jsx(DiagnosticsStat, { label: "Crash reports", value: String(supportBundle.crashReports) }), _jsx(DiagnosticsStat, { label: "Native artifacts", value: String(supportBundle.nativeArtifacts) }), _jsx(DiagnosticsStat, { label: "Log events", value: String(supportBundle.logEvents) })] }), _jsx("span", { className: "text-[12px] text-text-3", children: "Redacted ZIP of crash reports and a summary. Nothing is uploaded." })] })) : null] }), _jsx("div", { className: "grid grid-cols-1 xl:grid-cols-2 gap-3", children: report?.checks.map((check) => (_jsx("div", { className: "flex items-start justify-between gap-3 p-4 rounded-xl border border-line bg-panel", children: _jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("strong", { className: "text-[13px] text-text truncate", children: check.label }), _jsx("span", { className: `px-2 py-0.5 rounded-full text-[11px] border ${diagnosticsStatusClass(check.status)}`, children: diagnosticsLabel(check.status) })] }), _jsx("span", { className: "text-[12px] text-text-2", children: check.detail }), check.fix ? _jsx("span", { className: "text-[12px] text-text-3", children: check.fix }) : null] }) }, check.id))) }), instructionStatus ? (_jsxs("div", { className: "rounded-xl border border-line bg-panel overflow-hidden", children: [_jsx("div", { className: "flex items-center justify-between gap-3 px-4 py-3 border-b border-line", children: _jsxs("div", { className: "min-w-0", children: [_jsx("h4", { className: "text-[13px] font-semibold text-text", children: "Instruction sources" }), _jsxs("p", { className: "text-[12px] text-text-3 truncate", children: [instructionStatus.fileCount, " files \u00B7 ", instructionStatus.composedBytes, " composed bytes"] })] }) }), instructionStatus.files.length ? (_jsx("div", { className: "divide-y divide-line", children: instructionStatus.files.map((file) => {
33
+ const filters = [
34
+ ...file.globs.map((glob) => `glob:${glob}`),
35
+ ...file.paths.map((path) => `path:${path}`),
36
+ ];
37
+ return (_jsxs("div", { className: "grid grid-cols-[86px_1fr_110px] gap-3 px-4 py-3 text-[12px]", children: [_jsx("span", { className: "text-text-2 capitalize", children: file.scope }), _jsx("span", { className: "text-text truncate", title: file.path, children: file.path }), _jsxs("span", { className: "text-text-3 text-right", children: [file.bodyLines, " lines"] }), filters.length ? (_jsx("span", { className: "col-start-2 col-span-2 text-text-3 truncate", children: filters.join(" · ") })) : null] }, `${file.scope}-${file.path}`));
38
+ }) })) : (_jsx("div", { className: "px-4 py-5 text-[12px] text-text-3", children: "No instruction files were discovered for this workspace." }))] })) : null, !report && !error ? (_jsx(OfflinePanel, { title: "No diagnostics loaded.", action: "Refresh to load daemon readiness checks." })) : null] }));
39
+ }
@@ -0,0 +1,29 @@
1
+ import type { BackendDoctorReport, CoreSandboxSettings, CoreSandboxTier, DiagnosticsReport, ExecutionBackendRegistry, ExecutionNetworkDefault } from "@rightkit/agent-ui-core/lib/types";
2
+ export default function ExecutionBackendsTab({ registry, diagnostics, sandboxSettings, doctorReports, pendingId, error, workspaceRoot, onRefresh, onDoctor, onSetDefault, onSetEnabled, onSaveResourceLimits, onSaveNetworkProfile, onSaveNetworkProfileDefinition, onDeleteNetworkProfileDefinition, onSaveSandboxTier, }: {
3
+ registry: ExecutionBackendRegistry | null;
4
+ diagnostics: DiagnosticsReport | null;
5
+ sandboxSettings: CoreSandboxSettings | null;
6
+ doctorReports: Record<string, BackendDoctorReport>;
7
+ pendingId: string | null;
8
+ error: string | null;
9
+ workspaceRoot: string;
10
+ onRefresh: () => void;
11
+ onDoctor: (backendId: string) => void;
12
+ onSetDefault: (backendId: string) => void;
13
+ onSetEnabled: (backendId: string, enabled: boolean) => void;
14
+ onSaveResourceLimits: (backendId: string, limits: {
15
+ cpu?: number | null;
16
+ memoryMb?: number | null;
17
+ diskMb?: number | null;
18
+ }) => void;
19
+ onSaveNetworkProfile: (backendId: string, networkProfile: string | null) => void;
20
+ onSaveSandboxTier: (tier: CoreSandboxTier) => void;
21
+ onSaveNetworkProfileDefinition: (profileId: string, body: {
22
+ name?: string;
23
+ default?: ExecutionNetworkDefault;
24
+ allowHosts?: string[];
25
+ allowPrivateNetworks?: boolean;
26
+ denyPrivateNetworks?: boolean;
27
+ }) => void;
28
+ onDeleteNetworkProfileDefinition: (profileId: string) => void;
29
+ }): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import Icon from "@rightkit/agent-ui-core/components/Icon";
3
+ import { OfflinePanel } from "./shared.js";
4
+ import { CoreSandboxTierPanel } from "./execution/CoreSandboxTierPanel.js";
5
+ import { ExecutionBackendList } from "./execution/ExecutionBackendList.js";
6
+ import { ExecutionNetworkProfilesPanel } from "./execution/ExecutionNetworkProfilesPanel.js";
7
+ import { RemoteStatusCard } from "./execution/RemoteStatusCard.js";
8
+ export default function ExecutionBackendsTab({ registry, diagnostics, sandboxSettings, doctorReports, pendingId, error, workspaceRoot, onRefresh, onDoctor, onSetDefault, onSetEnabled, onSaveResourceLimits, onSaveNetworkProfile, onSaveNetworkProfileDefinition, onDeleteNetworkProfileDefinition, onSaveSandboxTier, }) {
9
+ const backends = registry?.backends ?? [];
10
+ const defaultBackend = registry?.defaultBackend ?? "local";
11
+ const profiles = registry?.networkProfiles ?? [];
12
+ return (_jsxs("section", { className: "flex flex-col gap-5 p-6", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [_jsx("h3", { className: "text-[16px] font-bold text-text", children: "Execution" }), _jsxs("p", { className: "text-[13px] text-text-2 truncate", children: ["Default backend ", defaultBackend, " \u00B7 ", workspaceRoot || "workspace not selected"] })] }), _jsxs("button", { type: "button", className: "inline-flex items-center gap-2 h-9 px-4 rounded-lg border border-line bg-transparent text-text-2 text-[13px] cursor-pointer hover:bg-panel hover:text-text disabled:opacity-40", disabled: pendingId === "list", onClick: onRefresh, children: [_jsx(Icon, { name: "refresh" }), pendingId === "list" ? "Refreshing" : "Refresh"] })] }), error ? _jsx(OfflinePanel, { title: "Execution backends unavailable.", action: error }) : null, _jsx(CoreSandboxTierPanel, { report: diagnostics, settings: sandboxSettings, pending: pendingId === "sandbox-tier", onSaveTier: onSaveSandboxTier }), registry ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "grid grid-cols-1 xl:grid-cols-3 gap-3 max-w-[980px]", children: [_jsx(RemoteStatusCard, { title: "Default backend", value: defaultBackend, status: "pass", detail: "New sessions inherit this execution target unless a request overrides it." }), _jsx(RemoteStatusCard, { title: "Network profiles", value: `${profiles.length} profile${profiles.length === 1 ? "" : "s"}`, status: profiles.length > 0 ? "pass" : "warn", detail: profiles.map((profile) => profile.id).join(", ") }), _jsx(RemoteStatusCard, { title: "Enabled backends", value: `${backends.filter((backend) => backend.enabled).length}/${backends.length}`, status: backends.some((backend) => backend.enabled) ? "pass" : "block", detail: "Local execution is the lean-launch path; disabled entries stay visible for diagnostics." })] }), _jsx(ExecutionNetworkProfilesPanel, { profiles: profiles, pendingId: pendingId, workspaceRoot: workspaceRoot, onSaveDefinition: onSaveNetworkProfileDefinition, onDeleteDefinition: onDeleteNetworkProfileDefinition }), _jsx(ExecutionBackendList, { backends: backends, defaultBackend: defaultBackend, doctorReports: doctorReports, pendingId: pendingId, networkProfiles: profiles, onDoctor: onDoctor, onSetDefault: onSetDefault, onSetEnabled: onSetEnabled, onSaveResourceLimits: onSaveResourceLimits, onSaveNetworkProfile: onSaveNetworkProfile })] })) : (_jsx(OfflinePanel, { title: "Execution backend registry has not loaded.", action: "Refresh after the local engine is connected." }))] }));
13
+ }
@@ -0,0 +1,20 @@
1
+ import { licenseSection } from "@rightkit/settings-ui/standard";
2
+ import { type LicenseView } from "@rightkit/agent-ui-core/state/license";
3
+ import type { UpdateState } from "@rightkit/agent-ui-core/state/updates";
4
+ /**
5
+ * The licence section (status, activate, deactivate, verify) is `@rightkit/settings-ui`'s
6
+ * `licenseSection` over the licence client (`state/license`); `SettingsModal` renders it above this
7
+ * tab. What stays here is the host app own: the Apple link and sync panels, the update controls with
8
+ * the install-consent card, and the unlocked-feature list. A change the section makes reaches the
9
+ * app through the owner's change event (`useLicenseState` restarts the daemon for it).
10
+ */
11
+ export declare const licenseTabSection: ReturnType<typeof licenseSection>;
12
+ export default function LicenseTab({ license, actionPending, latestVersion, updateState, error, onCheckForUpdate, onInstallUpdate, }: {
13
+ license: LicenseView | null;
14
+ actionPending: "check" | "install" | null;
15
+ latestVersion: string;
16
+ updateState: UpdateState;
17
+ error: string | null;
18
+ onCheckForUpdate: () => void;
19
+ onInstallUpdate: () => void | Promise<void>;
20
+ }): import("react").JSX.Element;
@@ -0,0 +1,66 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useReducer, useState } from "react";
3
+ import { deriveUpdateOverlay, createUpdateConsent } from "@rightkit/app-update";
4
+ import { UpdateConsentCard, updateOverlayText } from "@rightkit/app-update/react";
5
+ import { licenseSection } from "@rightkit/settings-ui/standard";
6
+ import { useUpdateStatus } from "@rightkit/agent-ui-hooks/hooks/useUpdateStatus";
7
+ import { isLicensed, licenseClient } from "@rightkit/agent-ui-core/state/license";
8
+ import { notifyProBridgeAfterActivation, suppressProBridgeConsumption } from "@rightkit/agent-ui-core/state/proBridge";
9
+ import AppleSyncPanel from "./AppleSyncPanel.js";
10
+ import LinkComputerPanel from "./LinkComputerPanel.js";
11
+ /**
12
+ * The licence section (status, activate, deactivate, verify) is `@rightkit/settings-ui`'s
13
+ * `licenseSection` over the licence client (`state/license`); `SettingsModal` renders it above this
14
+ * tab. What stays here is the host app own: the Apple link and sync panels, the update controls with
15
+ * the install-consent card, and the unlocked-feature list. A change the section makes reaches the
16
+ * app through the owner's change event (`useLicenseState` restarts the daemon for it).
17
+ */
18
+ export const licenseTabSection = licenseSection({
19
+ client: licenseClient,
20
+ // Suppress bridge consumption BEFORE the seat is freed, so a launch cannot instantly
21
+ // re-activate this device from the shared bridge.
22
+ beforeDeactivate: () => suppressProBridgeConsumption(true),
23
+ // An explicit activation clears bridge suppression and, if the user opted in, publishes this
24
+ // device's activation for their other Apple devices. Best effort: never affects the licence.
25
+ onChange: (view) => {
26
+ if (isLicensed(view))
27
+ void notifyProBridgeAfterActivation().catch(() => undefined);
28
+ },
29
+ labels: {
30
+ sectionLabel: "License",
31
+ statusLabel: "License",
32
+ searchStatus: "License status",
33
+ searchActivate: "Activate license key",
34
+ keyTitle: "License key",
35
+ keyHint: "Enter a purchase key.",
36
+ keyAria: "License key",
37
+ keyPlaceholder: "License key",
38
+ freeDetail: "Free tier. No license key is active on this device.",
39
+ },
40
+ ids: { licenseKey: "settings-license-key" },
41
+ });
42
+ export default function LicenseTab({ license, actionPending, latestVersion, updateState, error, onCheckForUpdate, onInstallUpdate, }) {
43
+ const active = isLicensed(license);
44
+ const updateModel = deriveUpdateOverlay(useUpdateStatus());
45
+ const updateLabel = updateOverlayText(updateModel).title || "Idle";
46
+ // Install needs its own approval through the published consent controller; the card shows only while pending or failed.
47
+ const [consent] = useState(() => createUpdateConsent());
48
+ const [, rerender] = useReducer((n) => n + 1, 0);
49
+ const requestInstall = () => {
50
+ consent.request("install");
51
+ rerender();
52
+ };
53
+ const allowInstall = async () => {
54
+ await consent.allowOnce(() => onInstallUpdate());
55
+ rerender();
56
+ };
57
+ const denyInstall = () => {
58
+ consent.deny();
59
+ rerender();
60
+ };
61
+ const features = license?.features ?? [];
62
+ const busy = actionPending !== null;
63
+ return (_jsxs("div", { className: "flex flex-col gap-4 p-6 max-w-5xl", children: [_jsx(LinkComputerPanel, { active: active }), _jsx(AppleSyncPanel, {}), _jsxs("div", { className: "rounded-lg border border-line bg-panel p-4", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 flex-wrap", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-[14px] font-semibold text-text", children: "Updates" }), _jsx("p", { className: "text-[12px] text-text-3", children: latestVersion
64
+ ? `Latest found: ${latestVersion}`
65
+ : "Repair patches are free; feature updates require Pro." }), _jsx("p", { className: "text-[12px] text-text-3", children: updateLabel })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", className: "inline-flex items-center h-8 px-3 rounded-lg border border-line bg-transparent text-text-2 text-[13px] cursor-pointer hover:bg-panel-2 hover:text-text disabled:opacity-40", disabled: busy, onClick: onCheckForUpdate, children: actionPending === "check" ? "Checking" : "Check" }), _jsx("button", { type: "button", className: "inline-flex items-center h-8 px-3 rounded-lg border-0 bg-accent text-on-accent font-semibold text-[13px] cursor-pointer disabled:border disabled:border-line disabled:bg-panel-2 disabled:text-text-3 hover:opacity-90", disabled: busy || (updateState !== "patch-available" && updateState !== "update-available"), onClick: requestInstall, children: actionPending === "install" ? "Installing" : "Install" })] })] }), error ? _jsx("div", { className: "mt-3 text-[12px] text-danger", children: error }) : null, _jsx(UpdateConsentCard, { state: consent.state(), version: latestVersion || undefined, onAllow: () => void allowInstall(), onDeny: denyInstall })] }), _jsxs("div", { className: "rounded-lg border border-line bg-panel p-4", children: [_jsx("h3", { className: "text-[14px] font-semibold text-text", children: "Features" }), _jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: features.length > 0 ? (features.map((feature) => (_jsx("span", { className: "inline-flex items-center h-7 px-2 rounded-md border border-line bg-bg text-[12px] text-text-2", children: feature }, feature)))) : (_jsx("span", { className: "text-[12px] text-text-3", children: "Free tier features only" })) })] })] }));
66
+ }
@@ -0,0 +1,6 @@
1
+ /** Windows only: redeem the one-time code an entitled Apple device shows, so
2
+ * this computer gets its own license without typing a key. Hidden once a
3
+ * license is active, and everywhere that is not Windows. */
4
+ export default function LinkComputerPanel({ active }: {
5
+ active: boolean;
6
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { licenseErrorMessage } from "@rightkit/agent-ui-core/state/license";
4
+ import { releasePlatform } from "@rightkit/agent-ui-core/state/platform";
5
+ import { redeemWindowsLinkCode } from "@rightkit/agent-ui-core/state/proBridge";
6
+ /** Windows only: redeem the one-time code an entitled Apple device shows, so
7
+ * this computer gets its own license without typing a key. Hidden once a
8
+ * license is active, and everywhere that is not Windows. */
9
+ export default function LinkComputerPanel({ active }) {
10
+ const platform = releasePlatform();
11
+ const [code, setCode] = useState("");
12
+ const [busy, setBusy] = useState(false);
13
+ const [error, setError] = useState(null);
14
+ const [linked, setLinked] = useState(false);
15
+ if (platform !== "windows" || (active && !linked))
16
+ return null;
17
+ async function onLink() {
18
+ const trimmed = code.trim();
19
+ if (!trimmed || busy)
20
+ return;
21
+ setBusy(true);
22
+ setError(null);
23
+ try {
24
+ await redeemWindowsLinkCode(trimmed);
25
+ setCode("");
26
+ setLinked(true);
27
+ }
28
+ catch (err) {
29
+ setError(licenseErrorMessage(err, "Could not link this computer"));
30
+ }
31
+ finally {
32
+ setBusy(false);
33
+ }
34
+ }
35
+ return (_jsxs("div", { className: "rounded-lg border border-line bg-panel p-4", "data-testid": "link-computer-panel", children: [_jsx("h3", { className: "text-[14px] font-semibold text-text", children: "Link from an Apple device" }), _jsx("p", { className: "text-[12px] text-text-3", children: "Enter the one-time code shown on your Apple device where Pro is active. Codes expire in minutes and work once. No license key is shared." }), _jsxs("div", { className: "mt-4 flex flex-col md:flex-row gap-2", children: [_jsx("input", { "aria-label": "Link code", className: "min-w-0 flex-1 h-9 px-3 rounded-lg border border-line bg-bg text-text text-[13px] outline-none focus:border-accent", value: code, onChange: (event) => setCode(event.target.value.toUpperCase()), onKeyDown: (event) => {
36
+ if (event.key === "Enter")
37
+ void onLink();
38
+ }, placeholder: "Code from your Apple device", autoComplete: "off", spellCheck: false, disabled: busy }), _jsx("button", { type: "button", className: "inline-flex items-center justify-center h-9 px-4 rounded-lg border-0 bg-accent text-on-accent font-semibold text-[13px] cursor-pointer disabled:border disabled:border-line disabled:bg-panel-2 disabled:text-text-3 hover:opacity-90", disabled: busy || !code.trim(), onClick: () => void onLink(), children: busy ? "Linking" : "Link this computer" })] }), linked ? (_jsx("div", { className: "mt-3 text-[12px] text-text-3", children: "This computer is linked." })) : null, error ? _jsx("div", { className: "mt-3 text-[12px] text-danger", children: error }) : null] }));
39
+ }
@@ -0,0 +1,11 @@
1
+ import type { LspStatusView, LspWorkspaceServer } from "@rightkit/agent-ui-core/lib/types";
2
+ export default function LspTab({ status, draft, pendingId, error, workspaceRoot, onDraft, onRefresh, onSave, }: {
3
+ status: LspStatusView | null;
4
+ draft: LspWorkspaceServer[];
5
+ pendingId: string | null;
6
+ error: string | null;
7
+ workspaceRoot: string;
8
+ onDraft: (draft: LspWorkspaceServer[]) => void;
9
+ onRefresh: () => void;
10
+ onSave: () => void;
11
+ }): import("react").JSX.Element;
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import Icon from "@rightkit/agent-ui-core/components/Icon";
3
+ import { OfflinePanel } from "./shared.js";
4
+ import { hostAppName } from "../../../appName.js";
5
+ export default function LspTab({ status, draft, pendingId, error, workspaceRoot, onDraft, onRefresh, onSave, }) {
6
+ function updateServer(index, patch) {
7
+ onDraft(draft.map((server, i) => (i === index ? { ...server, ...patch } : server)));
8
+ }
9
+ function addServer() {
10
+ onDraft([
11
+ ...draft,
12
+ {
13
+ language: "rust",
14
+ extensions: ["rs"],
15
+ serverPath: "rust-analyzer",
16
+ serverArgs: [],
17
+ },
18
+ ]);
19
+ }
20
+ function removeServer(index) {
21
+ onDraft(draft.filter((_, i) => i !== index));
22
+ }
23
+ return (_jsxs("section", { className: "flex flex-col gap-5 p-6", children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsxs("div", { className: "flex flex-col gap-1 flex-1 min-w-0", children: [_jsx("h3", { className: "text-[16px] font-bold text-text", children: "LSP" }), _jsx("p", { className: "text-[13px] text-text-2 truncate", children: status?.configPath ||
24
+ (workspaceRoot
25
+ ? `${workspaceRoot}/.coderight/lsp.json`
26
+ : "Select a workspace to configure language servers.") })] }), _jsxs("button", { type: "button", className: "inline-flex items-center gap-2 h-9 px-4 rounded-lg border border-line bg-transparent text-text-2 text-[13px] cursor-pointer hover:bg-panel hover:text-text", onClick: onRefresh, children: [_jsx(Icon, { name: "refresh" }), " Refresh"] })] }), error ? _jsx(OfflinePanel, { title: "LSP unavailable.", action: error }) : null, status ? (_jsx("div", { className: "flex flex-col divide-y divide-line border border-line rounded-xl overflow-hidden", children: status.servers.map((server) => (_jsxs("article", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_90px_90px] items-center gap-4 px-4 py-3", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("strong", { className: "block text-[13px] font-semibold text-text truncate", children: server.language }), _jsx("span", { className: "block text-[11px] text-text-3 truncate", children: server.extensions.join(", ") || "no extensions" })] }), _jsx("code", { className: "text-[11px] font-mono text-text-3 truncate", children: server.effectivePath || "local symbol fallback" }), _jsx("code", { className: `text-[11px] font-mono ${server.available ? "text-accent-2" : "text-text-3"}`, children: server.source }), _jsx("code", { className: "text-[11px] font-mono text-text-3", children: server.available ? "ready" : "fallback" })] }, server.language))) })) : (_jsx(OfflinePanel, { title: "No LSP status loaded.", action: "Open a workspace, then refresh LSP status." })), _jsxs("div", { className: "flex flex-col gap-3 border border-line rounded-xl p-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("h4", { className: "text-[14px] font-bold text-text", children: "Workspace servers" }), _jsx("p", { className: "text-[12px] text-text-3 truncate", children: "Configured servers override PATH discovery for matching languages." })] }), _jsxs("button", { type: "button", className: "inline-flex items-center gap-2 h-8 px-3 rounded-lg border border-line bg-transparent text-text-2 text-[12px] cursor-pointer hover:bg-panel hover:text-text", onClick: addServer, children: [_jsx(Icon, { name: "plus" }), " Add"] }), _jsxs("button", { type: "button", className: "inline-flex items-center gap-2 h-8 px-3 rounded-lg border-0 bg-accent text-on-accent font-semibold text-[12px] cursor-pointer hover:opacity-90 disabled:border disabled:border-line disabled:bg-panel-2 disabled:text-text-3", disabled: pendingId === "save" || !workspaceRoot.trim(), onClick: onSave, children: [_jsx(Icon, { name: "settings" }), " Save"] })] }), draft.length > 0 ? (_jsx("div", { className: "flex flex-col gap-3", children: draft.map((server, index) => (_jsxs("div", { className: "grid grid-cols-[120px_150px_minmax(0,1fr)_minmax(0,1fr)_auto] gap-3 items-end", children: [_jsxs("label", { className: "flex flex-col gap-1 text-[13px] text-text-2", children: ["Language", _jsx("input", { className: "h-9 px-3 rounded-lg border border-line bg-panel text-text text-[13px] outline-none", value: server.language, onChange: (e) => updateServer(index, { language: e.target.value }) })] }), _jsxs("label", { className: "flex flex-col gap-1 text-[13px] text-text-2", children: ["Extensions", _jsx("input", { className: "h-9 px-3 rounded-lg border border-line bg-panel text-text text-[13px] outline-none", value: server.extensions.join(","), onChange: (e) => updateServer(index, {
27
+ extensions: e.target.value
28
+ .split(",")
29
+ .map((ext) => ext.trim())
30
+ .filter(Boolean),
31
+ }) })] }), _jsxs("label", { className: "flex flex-col gap-1 text-[13px] text-text-2", children: ["Server path", _jsx("input", { className: "h-9 px-3 rounded-lg border border-line bg-panel text-text text-[13px] outline-none", value: server.serverPath, onChange: (e) => updateServer(index, { serverPath: e.target.value }) })] }), _jsxs("label", { className: "flex flex-col gap-1 text-[13px] text-text-2", children: ["Args", _jsx("input", { className: "h-9 px-3 rounded-lg border border-line bg-panel text-text text-[13px] outline-none", value: server.serverArgs.join(" "), onChange: (e) => updateServer(index, {
32
+ serverArgs: e.target.value.trim() ? e.target.value.trim().split(/\s+/) : [],
33
+ }) })] }), _jsx("button", { type: "button", className: "inline-flex items-center justify-center h-9 w-9 rounded-lg border border-line bg-transparent text-text-2 cursor-pointer hover:bg-panel hover:text-danger", onClick: () => removeServer(index), title: "Remove server", children: _jsx(Icon, { name: "trash", size: 14 }) })] }, `${server.language}:${server.serverPath}:${server.extensions.join(",")}:${server.serverArgs.join(" ")}`))) })) : (_jsx(OfflinePanel, { title: "No workspace LSP overrides.", action: `${hostAppName()} will use PATH discovery and the local symbol fallback.` }))] })] }));
34
+ }
@@ -0,0 +1,7 @@
1
+ import type { DaemonConfig } from "@rightkit/agent-ui-core/lib/types/settings-plugins";
2
+ interface MemoryTabProps {
3
+ config: DaemonConfig | null;
4
+ workspaceRoot: string;
5
+ }
6
+ export default function MemoryTab({ config, workspaceRoot }: MemoryTabProps): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from "react";
3
+ import { useMemoryFiles } from "@rightkit/agent-ui-hooks/hooks/useMemoryFiles";
4
+ function saveOutcomeMessage(outcome) {
5
+ switch (outcome.kind) {
6
+ case "saved":
7
+ return "Saved";
8
+ case "stale":
9
+ return "File changed remotely. Re-read or keep your draft.";
10
+ case "forbidden":
11
+ case "unsupported":
12
+ return outcome.reason;
13
+ case "missing":
14
+ return "CLAUDE.md no longer exists.";
15
+ }
16
+ }
17
+ export default function MemoryTab({ config, workspaceRoot }) {
18
+ const memory = useMemoryFiles(config, workspaceRoot);
19
+ const [confirmLeave, setConfirmLeave] = useState(false);
20
+ const [saveState, setSaveState] = useState(null);
21
+ const [saving, setSaving] = useState(false);
22
+ const previousWorkspace = useRef(workspaceRoot);
23
+ useEffect(() => {
24
+ const beforeUnload = (event) => {
25
+ if (!memory.dirty)
26
+ return;
27
+ event.preventDefault();
28
+ event.returnValue = "";
29
+ };
30
+ window.addEventListener("beforeunload", beforeUnload);
31
+ return () => window.removeEventListener("beforeunload", beforeUnload);
32
+ }, [memory.dirty]);
33
+ useEffect(() => {
34
+ if (previousWorkspace.current !== workspaceRoot && memory.dirty) {
35
+ setConfirmLeave(true);
36
+ setSaveState("Workspace changed; local draft is preserved until you choose.");
37
+ }
38
+ previousWorkspace.current = workspaceRoot;
39
+ }, [workspaceRoot, memory.dirty]);
40
+ const save = async () => {
41
+ setSaving(true);
42
+ try {
43
+ setSaveState(saveOutcomeMessage(await memory.save()));
44
+ }
45
+ finally {
46
+ setSaving(false);
47
+ }
48
+ };
49
+ if (!config || !workspaceRoot.trim()) {
50
+ return (_jsxs("section", { className: "flex max-w-[720px] flex-col gap-2 p-6", children: [_jsx("h3", { className: "text-[16px] font-bold text-text", children: "Project memory" }), _jsx("p", { className: "text-[12px] text-text-3", children: "Open a connected workspace to edit its existing CLAUDE.md." })] }));
51
+ }
52
+ if (memory.status === "loading" || memory.status === "idle") {
53
+ return _jsx("section", { className: "p-6 text-sm text-text-3", children: "Loading CLAUDE.md\u2026" });
54
+ }
55
+ if (!memory.response) {
56
+ return (_jsxs("section", { className: "flex max-w-[720px] flex-col gap-2 p-6", children: [_jsx("h3", { className: "text-[16px] font-bold text-text", children: "Project memory" }), _jsx("p", { role: "alert", className: "text-[12px] text-danger", children: memory.reason ?? "CLAUDE.md is unavailable." })] }));
57
+ }
58
+ if (memory.response.kind !== "file") {
59
+ const unavailableReason = memory.response.kind === "missing"
60
+ ? "Project-root CLAUDE.md does not exist. Create it in the workspace before editing."
61
+ : (memory.response.reason ?? "Existing project-root CLAUDE.md is not readable.");
62
+ return (_jsxs("section", { className: "flex max-w-[720px] flex-col gap-2 p-6", children: [_jsx("h3", { className: "text-[16px] font-bold text-text", children: "Project memory" }), _jsx("p", { role: "status", className: "text-[12px] text-text-3", children: unavailableReason })] }));
63
+ }
64
+ return (_jsxs("section", { className: "flex min-h-0 max-w-[900px] flex-1 flex-col gap-3 p-6", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-[16px] font-bold text-text", children: "Project memory" }), _jsxs("p", { className: "text-[12px] text-text-3", children: [memory.path, " \u00B7 edits existing project-root file only"] })] }), memory.dirty ? _jsx("span", { className: "text-[11px] text-warning", children: "Unsaved changes" }) : null] }), memory.status === "error" ? (_jsx("p", { role: "alert", className: "text-[12px] text-danger", children: memory.reason ?? "Latest disk read failed; local content is preserved." })) : null, memory.workspaceMismatch ? (_jsxs("p", { role: "alert", className: "text-[12px] text-warning", children: ["Draft belongs to ", memory.draftWorkspaceRoot, ". Switch back or Re-read to discard before saving in this workspace."] })) : null, memory.remoteConflict ? (_jsxs("div", { role: "alert", className: "flex flex-wrap items-center gap-2 rounded-md border border-warning/40 bg-warning/10 p-3 text-[12px] text-text-2", children: [_jsx("span", { children: "CLAUDE.md changed on disk." }), _jsx("button", { type: "button", className: "rounded border border-line px-2 py-1", onClick: () => void memory.reRead(), children: "Re-read" }), _jsx("button", { type: "button", className: "rounded border border-line px-2 py-1", onClick: () => void memory.keepLocal(), children: "Keep local" })] })) : null, _jsx("textarea", { "aria-label": "Project CLAUDE.md", className: "min-h-[360px] flex-1 resize-y rounded-md border border-line bg-panel p-3 font-mono text-[12px] text-text outline-none focus:border-accent", value: memory.content, onChange: (event) => memory.edit(event.currentTarget.value) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", className: "rounded-md bg-accent px-3 py-2 text-[12px] font-semibold text-on-accent disabled:opacity-40", disabled: !memory.dirty || memory.workspaceMismatch || saving, onClick: () => void save(), children: saving ? "Saving…" : "Save" }), _jsx("button", { type: "button", className: "rounded-md border border-line px-3 py-2 text-[12px]", disabled: !memory.dirty, onClick: () => setConfirmLeave(true), children: "Re-read" }), saveState ? (_jsx("span", { role: "status", className: "text-[11px] text-text-3", children: saveState })) : null] }), confirmLeave ? (_jsxs("div", { role: "dialog", "aria-label": "Discard draft confirmation", className: "rounded-md border border-warning/40 bg-warning/10 p-3 text-[12px] text-text-2", children: [_jsx("p", { children: "Re-read and discard local changes?" }), _jsxs("div", { className: "mt-2 flex gap-2", children: [_jsx("button", { type: "button", className: "rounded border border-line px-2 py-1", onClick: () => {
65
+ setConfirmLeave(false);
66
+ void memory.reRead();
67
+ }, children: "Re-read" }), _jsx("button", { type: "button", className: "rounded border border-line px-2 py-1", onClick: () => setConfirmLeave(false), children: "Keep local" })] })] })) : null] }));
68
+ }
@@ -0,0 +1,10 @@
1
+ import type { DaemonConfig, OrchestrationSettings } from "@rightkit/agent-ui-core/lib/types";
2
+ interface ProvidersTabProps {
3
+ settings: OrchestrationSettings | null;
4
+ config?: DaemonConfig | null;
5
+ sessionId?: string | null;
6
+ onLoginCliProvider?: (provider: string) => void;
7
+ onRefreshAttestations?: () => void;
8
+ }
9
+ export default function ProvidersTab({ settings, config, sessionId, onLoginCliProvider, }: ProvidersTabProps): import("react").JSX.Element;
10
+ export {};