@nexus-ai-fs/tui 0.9.18

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 (193) hide show
  1. package/README.md +30 -0
  2. package/package.json +48 -0
  3. package/src/app.tsx +349 -0
  4. package/src/index.tsx +137 -0
  5. package/src/opentui-env.d.ts +61 -0
  6. package/src/panels/access/access-panel.tsx +597 -0
  7. package/src/panels/access/alert-list.tsx +77 -0
  8. package/src/panels/access/constraint-creator.tsx +128 -0
  9. package/src/panels/access/constraint-list.tsx +72 -0
  10. package/src/panels/access/credential-list.tsx +68 -0
  11. package/src/panels/access/delegation-chain-view.tsx +110 -0
  12. package/src/panels/access/delegation-completer.tsx +120 -0
  13. package/src/panels/access/delegation-creator.tsx +237 -0
  14. package/src/panels/access/delegation-list.tsx +74 -0
  15. package/src/panels/access/fraud-score-view.tsx +94 -0
  16. package/src/panels/access/manifest-creator.tsx +167 -0
  17. package/src/panels/access/manifest-list.tsx +105 -0
  18. package/src/panels/access/namespace-config-view.tsx +525 -0
  19. package/src/panels/access/permission-checker.tsx +231 -0
  20. package/src/panels/agents/agent-status-view.tsx +196 -0
  21. package/src/panels/agents/agents-panel.tsx +493 -0
  22. package/src/panels/agents/delegation-list.tsx +154 -0
  23. package/src/panels/agents/inbox-view.tsx +96 -0
  24. package/src/panels/agents/trajectories-tab.tsx +40 -0
  25. package/src/panels/api-console/api-console-panel.tsx +189 -0
  26. package/src/panels/api-console/codegen-viewer.tsx +36 -0
  27. package/src/panels/api-console/codegen.ts +112 -0
  28. package/src/panels/api-console/endpoint-list.tsx +57 -0
  29. package/src/panels/api-console/request-builder.tsx +69 -0
  30. package/src/panels/api-console/response-viewer.tsx +54 -0
  31. package/src/panels/connectors/available-tab.tsx +357 -0
  32. package/src/panels/connectors/connector-row.tsx +121 -0
  33. package/src/panels/connectors/connectors-panel.tsx +88 -0
  34. package/src/panels/connectors/error-parser.ts +116 -0
  35. package/src/panels/connectors/mounted-tab.tsx +179 -0
  36. package/src/panels/connectors/skills-tab.tsx +235 -0
  37. package/src/panels/connectors/template-generator.ts +211 -0
  38. package/src/panels/connectors/write-tab.tsx +514 -0
  39. package/src/panels/events/audit-tab.tsx +69 -0
  40. package/src/panels/events/audit-trail.tsx +75 -0
  41. package/src/panels/events/connector-detail.tsx +49 -0
  42. package/src/panels/events/connector-list.tsx +73 -0
  43. package/src/panels/events/connectors-tab.tsx +92 -0
  44. package/src/panels/events/event-replay.tsx +80 -0
  45. package/src/panels/events/events-panel.tsx +414 -0
  46. package/src/panels/events/events-tab.tsx +212 -0
  47. package/src/panels/events/lock-list.tsx +54 -0
  48. package/src/panels/events/locks-tab.tsx +103 -0
  49. package/src/panels/events/mcl-replay.tsx +77 -0
  50. package/src/panels/events/mcl-tab.tsx +83 -0
  51. package/src/panels/events/operations-tab-wrapper.tsx +62 -0
  52. package/src/panels/events/operations-tab.tsx +41 -0
  53. package/src/panels/events/replay-tab.tsx +76 -0
  54. package/src/panels/events/secrets-audit.tsx +64 -0
  55. package/src/panels/events/secrets-tab.tsx +75 -0
  56. package/src/panels/events/subscription-list.tsx +54 -0
  57. package/src/panels/events/subscriptions-tab.tsx +82 -0
  58. package/src/panels/files/file-aspects.tsx +93 -0
  59. package/src/panels/files/file-editor.tsx +160 -0
  60. package/src/panels/files/file-explorer-keybindings.ts +468 -0
  61. package/src/panels/files/file-explorer-panel.tsx +545 -0
  62. package/src/panels/files/file-lineage.tsx +163 -0
  63. package/src/panels/files/file-list-item.tsx +28 -0
  64. package/src/panels/files/file-metadata.tsx +62 -0
  65. package/src/panels/files/file-preview.tsx +108 -0
  66. package/src/panels/files/file-schema.tsx +89 -0
  67. package/src/panels/files/file-tree-node.tsx +44 -0
  68. package/src/panels/files/file-tree.tsx +169 -0
  69. package/src/panels/files/share-links-tab.tsx +33 -0
  70. package/src/panels/files/uploads-tab.tsx +45 -0
  71. package/src/panels/payments/approval-list.tsx +83 -0
  72. package/src/panels/payments/balance-card.tsx +43 -0
  73. package/src/panels/payments/budget-card.tsx +70 -0
  74. package/src/panels/payments/payments-panel.tsx +451 -0
  75. package/src/panels/payments/policy-list.tsx +64 -0
  76. package/src/panels/payments/reservation-list.tsx +78 -0
  77. package/src/panels/payments/transaction-list.tsx +103 -0
  78. package/src/panels/payments/transfer-form.tsx +109 -0
  79. package/src/panels/search/column-search.tsx +79 -0
  80. package/src/panels/search/knowledge-view.tsx +100 -0
  81. package/src/panels/search/memory-list.tsx +197 -0
  82. package/src/panels/search/playbook-list.tsx +77 -0
  83. package/src/panels/search/rlm-answer-view.tsx +105 -0
  84. package/src/panels/search/search-panel.tsx +405 -0
  85. package/src/panels/search/search-results.tsx +116 -0
  86. package/src/panels/stack/stack-panel.tsx +474 -0
  87. package/src/panels/versions/conflicts-tab.tsx +59 -0
  88. package/src/panels/versions/entry-detail.tsx +89 -0
  89. package/src/panels/versions/transaction-actions.tsx +34 -0
  90. package/src/panels/versions/transaction-list.tsx +90 -0
  91. package/src/panels/versions/versions-panel.tsx +276 -0
  92. package/src/panels/workflows/execution-list.tsx +102 -0
  93. package/src/panels/workflows/scheduler-view.tsx +135 -0
  94. package/src/panels/workflows/workflow-list.tsx +88 -0
  95. package/src/panels/workflows/workflows-panel.tsx +295 -0
  96. package/src/panels/zones/brick-detail.tsx +136 -0
  97. package/src/panels/zones/brick-list.tsx +56 -0
  98. package/src/panels/zones/cache-tab.tsx +118 -0
  99. package/src/panels/zones/drift-view.tsx +97 -0
  100. package/src/panels/zones/mcp-mounts-tab.tsx +38 -0
  101. package/src/panels/zones/memories-tab.tsx +37 -0
  102. package/src/panels/zones/reindex-status.tsx +84 -0
  103. package/src/panels/zones/workspaces-tab.tsx +37 -0
  104. package/src/panels/zones/zone-list.tsx +73 -0
  105. package/src/panels/zones/zones-panel.tsx +559 -0
  106. package/src/services/command-runner.ts +303 -0
  107. package/src/shared/accessibility-announcements.ts +44 -0
  108. package/src/shared/action-registry.ts +466 -0
  109. package/src/shared/brick-states.ts +91 -0
  110. package/src/shared/command-palette.ts +35 -0
  111. package/src/shared/components/announcement-bar.tsx +30 -0
  112. package/src/shared/components/app-confirm-dialog.tsx +29 -0
  113. package/src/shared/components/breadcrumb.tsx +21 -0
  114. package/src/shared/components/brick-gate.tsx +60 -0
  115. package/src/shared/components/command-output.tsx +95 -0
  116. package/src/shared/components/command-palette.tsx +97 -0
  117. package/src/shared/components/confirm-dialog.tsx +61 -0
  118. package/src/shared/components/diff-viewer.tsx +219 -0
  119. package/src/shared/components/empty-state.tsx +36 -0
  120. package/src/shared/components/error-bar.tsx +60 -0
  121. package/src/shared/components/error-boundary.tsx +53 -0
  122. package/src/shared/components/help-overlay.tsx +99 -0
  123. package/src/shared/components/identity-switcher.tsx +168 -0
  124. package/src/shared/components/loading-indicator.tsx +40 -0
  125. package/src/shared/components/pagination-bar.tsx +68 -0
  126. package/src/shared/components/pre-connection-screen.tsx +398 -0
  127. package/src/shared/components/scroll-indicator.tsx +46 -0
  128. package/src/shared/components/side-nav-utils.ts +68 -0
  129. package/src/shared/components/side-nav.tsx +287 -0
  130. package/src/shared/components/spinner.tsx +26 -0
  131. package/src/shared/components/status-bar.tsx +117 -0
  132. package/src/shared/components/styled-text.tsx +72 -0
  133. package/src/shared/components/sub-tab-bar-utils.ts +100 -0
  134. package/src/shared/components/sub-tab-bar.tsx +40 -0
  135. package/src/shared/components/tab-bar-utils.ts +36 -0
  136. package/src/shared/components/tab-bar.tsx +50 -0
  137. package/src/shared/components/text-input.tsx +73 -0
  138. package/src/shared/components/tooltip.tsx +53 -0
  139. package/src/shared/components/virtual-list.tsx +93 -0
  140. package/src/shared/components/welcome-screen.tsx +111 -0
  141. package/src/shared/hooks/use-api.ts +10 -0
  142. package/src/shared/hooks/use-brick-available.ts +42 -0
  143. package/src/shared/hooks/use-confirm.ts +66 -0
  144. package/src/shared/hooks/use-connection-state.ts +67 -0
  145. package/src/shared/hooks/use-copy.ts +31 -0
  146. package/src/shared/hooks/use-fresh-server.ts +62 -0
  147. package/src/shared/hooks/use-keyboard.ts +58 -0
  148. package/src/shared/hooks/use-list-navigation.ts +106 -0
  149. package/src/shared/hooks/use-swr.ts +117 -0
  150. package/src/shared/hooks/use-tab-fallback.ts +32 -0
  151. package/src/shared/hooks/use-text-input.ts +113 -0
  152. package/src/shared/hooks/use-visible-tabs.ts +61 -0
  153. package/src/shared/lib/circular-buffer.ts +82 -0
  154. package/src/shared/lib/clipboard.ts +14 -0
  155. package/src/shared/nav-items.ts +73 -0
  156. package/src/shared/navigation.ts +110 -0
  157. package/src/shared/status-breadcrumb.ts +74 -0
  158. package/src/shared/syntax-style.ts +3 -0
  159. package/src/shared/tab-visibility.ts +15 -0
  160. package/src/shared/text-style.ts +23 -0
  161. package/src/shared/theme.ts +179 -0
  162. package/src/shared/utils/format-size.ts +20 -0
  163. package/src/shared/utils/format-text.ts +10 -0
  164. package/src/shared/utils/format-time.ts +72 -0
  165. package/src/shared/utils/lru-cache.ts +75 -0
  166. package/src/stores/access-store-types.ts +154 -0
  167. package/src/stores/access-store.ts +674 -0
  168. package/src/stores/agents-store.ts +404 -0
  169. package/src/stores/announcement-store.ts +46 -0
  170. package/src/stores/api-console-store.ts +476 -0
  171. package/src/stores/connectors-store.ts +434 -0
  172. package/src/stores/create-api-action.ts +140 -0
  173. package/src/stores/delegation-store.ts +300 -0
  174. package/src/stores/error-store.ts +102 -0
  175. package/src/stores/events-store.ts +163 -0
  176. package/src/stores/files-store.ts +630 -0
  177. package/src/stores/first-run-store.ts +34 -0
  178. package/src/stores/global-store.ts +255 -0
  179. package/src/stores/infra-store.ts +461 -0
  180. package/src/stores/knowledge-store.ts +358 -0
  181. package/src/stores/lineage-store.ts +126 -0
  182. package/src/stores/mcp-store.ts +147 -0
  183. package/src/stores/payments-store.ts +545 -0
  184. package/src/stores/search-store-types.ts +155 -0
  185. package/src/stores/search-store.ts +656 -0
  186. package/src/stores/share-link-store.ts +151 -0
  187. package/src/stores/stack-store.ts +352 -0
  188. package/src/stores/ui-store.ts +161 -0
  189. package/src/stores/upload-store.ts +131 -0
  190. package/src/stores/versions-store.ts +355 -0
  191. package/src/stores/workflows-store.ts +402 -0
  192. package/src/stores/workspace-store.ts +185 -0
  193. package/src/stores/zones-store.ts +378 -0
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Global application state: connection, navigation, config.
3
+ */
4
+
5
+ import { create } from "zustand";
6
+ import type { NexusClientOptions } from "@nexus-ai-fs/api-client";
7
+ import { FetchClient, resolveConfig } from "@nexus-ai-fs/api-client";
8
+ import { categorizeError } from "./create-api-action.js";
9
+ import { useErrorStore } from "./error-store.js";
10
+
11
+ export type ConnectionStatus = "disconnected" | "connecting" | "connected" | "error";
12
+
13
+ export type PanelId =
14
+ | "files"
15
+ | "versions"
16
+ | "agents"
17
+ | "zones"
18
+ | "access"
19
+ | "payments"
20
+ | "search"
21
+ | "workflows"
22
+ | "infrastructure"
23
+ | "console";
24
+
25
+ /** Response from GET /api/v2/features */
26
+ export interface FeaturesResponse {
27
+ readonly profile: string;
28
+ readonly mode: string;
29
+ readonly enabled_bricks: readonly string[];
30
+ readonly disabled_bricks: readonly string[];
31
+ readonly version: string | null;
32
+ readonly rate_limit_enabled: boolean;
33
+ }
34
+
35
+ /** Response from GET /auth/me */
36
+ export interface UserInfo {
37
+ readonly user_id: string;
38
+ readonly email: string;
39
+ readonly username: string | null;
40
+ readonly display_name: string | null;
41
+ readonly avatar_url: string | null;
42
+ readonly is_global_admin: boolean;
43
+ readonly primary_auth_method: string | null;
44
+ }
45
+
46
+ export interface GlobalState {
47
+ // Connection
48
+ readonly connectionStatus: ConnectionStatus;
49
+ readonly connectionError: string | null;
50
+ readonly config: NexusClientOptions;
51
+ readonly client: FetchClient | null;
52
+
53
+ // Navigation
54
+ readonly activePanel: PanelId;
55
+ readonly panelHistory: readonly PanelId[];
56
+
57
+ // Identity display
58
+ readonly serverVersion: string | null;
59
+ readonly zoneId: string | null;
60
+ readonly uptime: number | null;
61
+ readonly userInfo: UserInfo | null;
62
+
63
+ // Features (from GET /api/v2/features)
64
+ readonly enabledBricks: readonly string[];
65
+ readonly profile: string | null;
66
+ readonly mode: string | null;
67
+ readonly featuresLoaded: boolean;
68
+ readonly featuresLastFetched: number;
69
+
70
+ // Actions
71
+ readonly initConfig: (overrides?: Partial<NexusClientOptions>) => void;
72
+ readonly testConnection: () => Promise<void>;
73
+ readonly setActivePanel: (panel: PanelId) => void;
74
+ readonly setConnectionStatus: (status: ConnectionStatus, error?: string) => void;
75
+ readonly setServerInfo: (info: { version?: string; zoneId?: string; uptime?: number }) => void;
76
+ readonly setIdentity: (identity: { agentId?: string; subject?: string; zoneId?: string }) => void;
77
+ readonly setFeatures: (features: FeaturesResponse) => void;
78
+ readonly refreshFeatures: () => Promise<void>;
79
+ }
80
+
81
+ export const useGlobalStore = create<GlobalState>((set, get) => ({
82
+ // Initial state
83
+ connectionStatus: "disconnected",
84
+ connectionError: null,
85
+ config: resolveConfig(),
86
+ client: null,
87
+ activePanel: "files",
88
+ panelHistory: [],
89
+ serverVersion: null,
90
+ zoneId: null,
91
+ uptime: null,
92
+ userInfo: null,
93
+ enabledBricks: [],
94
+ profile: null,
95
+ mode: null,
96
+ featuresLoaded: false,
97
+ featuresLastFetched: 0,
98
+
99
+ initConfig: (overrides) => {
100
+ const config = resolveConfig({ transformKeys: false, ...overrides });
101
+ const client = new FetchClient(config);
102
+ set({ config, client, connectionStatus: client ? "connecting" : "disconnected" });
103
+
104
+ if (client) {
105
+ get().testConnection();
106
+ }
107
+ },
108
+
109
+ testConnection: async () => {
110
+ const client = get().client;
111
+ if (!client) {
112
+ set({ connectionStatus: "disconnected", connectionError: null, userInfo: null });
113
+ return;
114
+ }
115
+
116
+ set({ connectionStatus: "connecting", connectionError: null });
117
+
118
+ try {
119
+ // Consolidated connection check (Decision 5A): health + features + auth in one flow
120
+ let [health, features, userInfo] = await Promise.all([
121
+ client.get<{ status?: string; uptime_seconds?: number }>(
122
+ "/healthz/ready",
123
+ ).catch(() => null),
124
+ client.get<FeaturesResponse>("/api/v2/features").catch(() => null),
125
+ client.get<UserInfo>("/auth/me").catch(() => null),
126
+ ]);
127
+
128
+ // Auto-discovery: if health check fails, scan common ports to find the server.
129
+ // Only probe when running interactively (not in tests) — probing creates real
130
+ // HTTP connections that cause test timeouts.
131
+ if (!health && typeof process !== "undefined" && process.stdout?.isTTY) {
132
+ const configuredUrl = get().config.baseUrl ?? "";
133
+ const hostname = configuredUrl.replace(/:\d+$/, "").replace(/^https?:\/\//, "");
134
+ const protocol = configuredUrl.startsWith("https") ? "https" : "http";
135
+ const PROBE_PORTS = [2026, 2027, 2042, 2043, 8080, 2122];
136
+
137
+ for (const port of PROBE_PORTS) {
138
+ if (configuredUrl.includes(`:${port}`)) continue;
139
+ try {
140
+ const probeUrl = `${protocol}://${hostname || "localhost"}:${port}`;
141
+ const probeClient = new FetchClient({ ...get().config, baseUrl: probeUrl, timeout: 3000, maxRetries: 0 });
142
+ const probeHealth = await probeClient.get<{ status?: string; uptime_seconds?: number }>(
143
+ "/healthz/ready",
144
+ ).catch(() => null);
145
+ if (probeHealth) {
146
+ const newConfig = resolveConfig({ transformKeys: false, baseUrl: probeUrl });
147
+ const newClient = new FetchClient(newConfig);
148
+ [health, features, userInfo] = await Promise.all([
149
+ Promise.resolve(probeHealth),
150
+ newClient.get<FeaturesResponse>("/api/v2/features").catch(() => null),
151
+ newClient.get<UserInfo>("/auth/me").catch(() => null),
152
+ ]);
153
+ set({ config: newConfig, client: newClient });
154
+ break;
155
+ }
156
+ } catch {
157
+ // probe failed, try next port
158
+ }
159
+ }
160
+ }
161
+
162
+ if (!health) {
163
+ throw new Error("Server health check failed");
164
+ }
165
+
166
+ // Note: zoneId is not set here — no health/readiness endpoint provides it.
167
+ // The old /api/v2/bricks/health never returned zone_id either (its response
168
+ // was { total, active, failed, bricks }). zoneId is set via setIdentity()
169
+ // when the user explicitly configures a zone, or defaults to "root".
170
+ set({
171
+ serverVersion: features?.version ?? get().serverVersion,
172
+ uptime: health.uptime_seconds ?? get().uptime,
173
+ });
174
+ if (features) {
175
+ get().setFeatures(features);
176
+ }
177
+
178
+ set({ connectionStatus: "connected", connectionError: null, userInfo });
179
+ } catch (err) {
180
+ const message = err instanceof Error ? err.message : "Connection test failed";
181
+ set({
182
+ connectionStatus: "error",
183
+ connectionError: message,
184
+ userInfo: null,
185
+ });
186
+ useErrorStore.getState().pushError({ message, category: categorizeError(message), source: "global" });
187
+ }
188
+ },
189
+
190
+ setActivePanel: (panel) => {
191
+ const current = get().activePanel;
192
+ if (current === panel) return;
193
+ set((state) => ({
194
+ activePanel: panel,
195
+ panelHistory: [...state.panelHistory.slice(-9), current],
196
+ }));
197
+ // Re-fetch features on panel switch (Decision 3A)
198
+ get().refreshFeatures();
199
+ },
200
+
201
+ setConnectionStatus: (status, error) => {
202
+ set({ connectionStatus: status, connectionError: error ?? null });
203
+ },
204
+
205
+ setServerInfo: (info) => {
206
+ set({
207
+ serverVersion: info.version ?? get().serverVersion,
208
+ zoneId: info.zoneId ?? get().zoneId,
209
+ uptime: info.uptime ?? get().uptime,
210
+ });
211
+ },
212
+
213
+ setIdentity: (identity) => {
214
+ const currentConfig = get().config;
215
+ // Use explicit values from identity, allowing empty string → undefined to clear fields
216
+ const config: NexusClientOptions = {
217
+ ...currentConfig,
218
+ agentId: "agentId" in identity ? identity.agentId : currentConfig.agentId,
219
+ subject: "subject" in identity ? identity.subject : currentConfig.subject,
220
+ zoneId: "zoneId" in identity ? identity.zoneId : currentConfig.zoneId,
221
+ };
222
+ const client = new FetchClient(config);
223
+ set({ config, client });
224
+ },
225
+
226
+ setFeatures: (features) => {
227
+ set({
228
+ enabledBricks: features.enabled_bricks ?? [],
229
+ profile: features.profile ?? null,
230
+ mode: features.mode ?? null,
231
+ featuresLoaded: true,
232
+ featuresLastFetched: Date.now(),
233
+ });
234
+ },
235
+
236
+ refreshFeatures: async () => {
237
+ const { client, featuresLastFetched } = get();
238
+ if (!client) return;
239
+ // TTL: skip if fetched within the last 10 seconds (Decision 13A)
240
+ if (Date.now() - featuresLastFetched < 10_000) return;
241
+ try {
242
+ const features = await client.get<{
243
+ profile: string;
244
+ mode: string;
245
+ enabled_bricks: string[];
246
+ disabled_bricks: string[];
247
+ version: string | null;
248
+ rate_limit_enabled: boolean;
249
+ }>("/api/v2/features");
250
+ get().setFeatures(features);
251
+ } catch {
252
+ // Non-critical: use last known state
253
+ }
254
+ },
255
+ }));