@elevasis/ui 2.30.0 → 2.31.0

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 (109) hide show
  1. package/dist/{CoreAuthKitInner-QC62UHTZ.js → CoreAuthKitInner-KSEGSB67.js} +1 -1
  2. package/dist/api/index.js +3 -3
  3. package/dist/app/index.d.ts +122 -1
  4. package/dist/app/index.js +7 -7
  5. package/dist/auth/context.js +1 -1
  6. package/dist/auth/index.js +1 -1
  7. package/dist/charts/index.js +4 -4
  8. package/dist/{chunk-T5Z7G2J2.js → chunk-3BAPR3KA.js} +1 -1
  9. package/dist/{chunk-4VQ2PXMI.js → chunk-3FV6HBXS.js} +4 -4
  10. package/dist/{chunk-2DIYILF7.js → chunk-542WPQU2.js} +2 -2
  11. package/dist/{chunk-SBCIB5TZ.js → chunk-5LJAEZMA.js} +5 -5
  12. package/dist/{chunk-T2PAD63Y.js → chunk-7HMCB26R.js} +1 -1
  13. package/dist/chunk-7KC4P3AU.js +357 -0
  14. package/dist/{chunk-AKOD52HS.js → chunk-CQZ3DNQY.js} +4 -3
  15. package/dist/{chunk-I2KLQ2HA.js → chunk-DZTG5IAC.js} +7 -1
  16. package/dist/{chunk-JCGD4GM6.js → chunk-GRDLB6LM.js} +1 -0
  17. package/dist/{chunk-JKTPRYGV.js → chunk-HQGF4ATG.js} +9 -55
  18. package/dist/{chunk-SKXXT3E2.js → chunk-HYNYEBHM.js} +4 -4
  19. package/dist/{chunk-6EFVZV6X.js → chunk-JKSUN5GN.js} +718 -64
  20. package/dist/{chunk-LRZFLK2F.js → chunk-L2NVFLXU.js} +3 -3
  21. package/dist/{chunk-6WXDE5LZ.js → chunk-L3BVJWML.js} +1 -1
  22. package/dist/{chunk-3MDNBHVB.js → chunk-MVFCLZSK.js} +690 -221
  23. package/dist/{chunk-HYLERWRO.js → chunk-ND42LPY4.js} +6 -6
  24. package/dist/{chunk-CLUP5H3C.js → chunk-O2QOPJI5.js} +360 -126
  25. package/dist/{chunk-X2SUMO3P.js → chunk-P55BJZZW.js} +2 -1
  26. package/dist/{chunk-4FZYEEPK.js → chunk-Q6OYNEGR.js} +5 -5
  27. package/dist/{chunk-4SY6BTVZ.js → chunk-QDEETKYT.js} +4 -1
  28. package/dist/{chunk-IKQ42WHU.js → chunk-QHEWXU7I.js} +1 -1
  29. package/dist/chunk-R2XR4FCV.js +48 -0
  30. package/dist/chunk-R66W5UDG.js +26 -0
  31. package/dist/{chunk-3GV5NHSS.js → chunk-SHQXMW4F.js} +39 -211
  32. package/dist/{chunk-A7B7HLDF.js → chunk-T3IPHEYJ.js} +1889 -301
  33. package/dist/{chunk-7E3FUTND.js → chunk-TOIXUWR6.js} +1 -1
  34. package/dist/{chunk-NITGGYH2.js → chunk-TVRQ6AQI.js} +1 -1
  35. package/dist/{chunk-CN2HC4D4.js → chunk-UFTM5SZZ.js} +2 -2
  36. package/dist/{chunk-KVJ3LFH2.js → chunk-VNFR57DF.js} +4 -24
  37. package/dist/{chunk-P5WYW2GI.js → chunk-Y4FWCG7Y.js} +150 -305
  38. package/dist/components/chat/index.js +1 -1
  39. package/dist/components/index.d.ts +205 -11
  40. package/dist/components/index.js +38 -35
  41. package/dist/components/navigation/index.js +1 -1
  42. package/dist/execution/index.d.ts +2 -1
  43. package/dist/execution/index.js +1 -1
  44. package/dist/features/auth/index.d.ts +121 -0
  45. package/dist/features/auth/index.js +1 -1
  46. package/dist/features/clients/index.css +611 -0
  47. package/dist/features/clients/index.d.ts +86 -0
  48. package/dist/features/clients/index.js +719 -0
  49. package/dist/features/crm/index.d.ts +148 -2
  50. package/dist/features/crm/index.js +18 -16
  51. package/dist/features/dashboard/index.d.ts +36 -1
  52. package/dist/features/dashboard/index.js +14 -14
  53. package/dist/features/delivery/index.d.ts +121 -0
  54. package/dist/features/delivery/index.js +18 -16
  55. package/dist/features/knowledge/index.js +43 -20
  56. package/dist/features/lead-gen/index.d.ts +17 -11
  57. package/dist/features/lead-gen/index.js +19 -17
  58. package/dist/features/monitoring/index.js +17 -16
  59. package/dist/features/monitoring/requests/index.js +14 -13
  60. package/dist/features/operations/index.d.ts +38 -2
  61. package/dist/features/operations/index.js +22 -21
  62. package/dist/features/seo/index.js +1 -1
  63. package/dist/features/settings/index.d.ts +121 -0
  64. package/dist/features/settings/index.js +16 -15
  65. package/dist/graph/index.js +1 -1
  66. package/dist/hooks/delivery/index.d.ts +140 -0
  67. package/dist/hooks/delivery/index.js +3 -3
  68. package/dist/hooks/index.d.ts +583 -19
  69. package/dist/hooks/index.js +12 -12
  70. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +82 -1
  71. package/dist/hooks/operations/command-view/utils/transformCommandViewData.js +1 -1
  72. package/dist/hooks/published.d.ts +583 -19
  73. package/dist/hooks/published.js +12 -12
  74. package/dist/index.d.ts +680 -21
  75. package/dist/index.js +13 -13
  76. package/dist/initialization/index.d.ts +121 -0
  77. package/dist/initialization/index.js +1 -1
  78. package/dist/knowledge/index.d.ts +97 -1
  79. package/dist/knowledge/index.js +1692 -1039
  80. package/dist/layout/index.d.ts +6 -0
  81. package/dist/layout/index.js +4 -4
  82. package/dist/organization/index.js +1 -1
  83. package/dist/profile/index.d.ts +121 -0
  84. package/dist/profile/index.js +1 -1
  85. package/dist/provider/ElevasisServiceContext.js +1 -1
  86. package/dist/provider/index.d.ts +218 -2
  87. package/dist/provider/index.js +10 -10
  88. package/dist/provider/published.d.ts +218 -2
  89. package/dist/provider/published.js +7 -7
  90. package/dist/router/context.js +1 -1
  91. package/dist/router/index.js +1 -1
  92. package/dist/sse/index.js +1 -1
  93. package/dist/supabase/index.d.ts +232 -0
  94. package/dist/supabase/index.js +1 -1
  95. package/dist/test-utils/index.js +3 -3
  96. package/dist/test-utils/setup-integration.js +1 -1
  97. package/dist/test-utils/setup.js +2 -2
  98. package/dist/theme/index.js +4 -4
  99. package/dist/theme/presets/index.js +2 -2
  100. package/dist/typeform/index.js +1 -1
  101. package/dist/typeform/schemas.js +1 -1
  102. package/dist/types/index.d.ts +204 -1
  103. package/dist/utils/index.d.ts +36 -1
  104. package/dist/utils/index.js +2 -2
  105. package/dist/vite/index.js +3 -3
  106. package/dist/vite-plugin-knowledge/index.js +2 -2
  107. package/dist/zustand/index.js +1 -1
  108. package/package.json +13 -4
  109. /package/dist/{chunk-HXZQWMKE.js → chunk-XQHZBA65.js} +0 -0
@@ -1,10 +1,10 @@
1
1
  import { observabilityKeys } from './chunk-6YT4IKJ7.js';
2
- import { showApiErrorNotification, showSuccessNotification, projectKeys, noteKeys, taskKeys, milestoneKeys } from './chunk-T2PAD63Y.js';
2
+ import { showApiErrorNotification, showSuccessNotification, projectKeys, noteKeys, taskKeys, milestoneKeys } from './chunk-7HMCB26R.js';
3
3
  import { useSupabase } from './chunk-BRXELOHC.js';
4
- import { useNotificationAdapter, deriveActions } from './chunk-AKOD52HS.js';
5
4
  import { useOptionalElevasisFeatures } from './chunk-6IXOKUBC.js';
6
- import { HTTP_HEADERS } from './chunk-7E3FUTND.js';
7
- import { ResourceTypeSchema, NonEmptyStringSchema, OriginResourceTypeSchema, UuidSchema, CredentialNameSchema, STALE_TIME_DEFAULT, REFETCH_INTERVAL_DASHBOARD, STALE_TIME_MONITORING, getTimeRangeDates, REFETCH_INTERVAL_RUNNING, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, STALE_TIME_ADMIN, APIClientError, GC_TIME_MEDIUM, GC_TIME_SHORT } from './chunk-HXZQWMKE.js';
5
+ import { useNotificationAdapter, deriveActions } from './chunk-CQZ3DNQY.js';
6
+ import { HTTP_HEADERS } from './chunk-TOIXUWR6.js';
7
+ import { ResourceTypeSchema, NonEmptyStringSchema, OriginResourceTypeSchema, UuidSchema, CredentialNameSchema, STALE_TIME_DEFAULT, REFETCH_INTERVAL_DASHBOARD, STALE_TIME_MONITORING, getTimeRangeDates, REFETCH_INTERVAL_RUNNING, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, STALE_TIME_ADMIN, APIClientError, GC_TIME_MEDIUM, GC_TIME_SHORT } from './chunk-XQHZBA65.js';
8
8
  import { useStableAccessToken } from './chunk-VKIZUUPM.js';
9
9
  import { useInitialization } from './chunk-533DUEQY.js';
10
10
  import { useOrganization } from './chunk-DD3CCMCZ.js';
@@ -29,7 +29,8 @@ var PERMISSIONS = {
29
29
  OPERATIONS_READ: "operations.read",
30
30
  OPERATIONS_MANAGE: "operations.manage",
31
31
  ACQUISITION_MANAGE: "acquisition.manage",
32
- PROJECTS_MANAGE: "projects.manage"
32
+ PROJECTS_MANAGE: "projects.manage",
33
+ CLIENTS_MANAGE: "clients.manage"
33
34
  };
34
35
  var PERMISSION_CATALOG = [
35
36
  {
@@ -81,6 +82,11 @@ var PERMISSION_CATALOG = [
81
82
  key: "projects.manage",
82
83
  description: "Create, update, and delete project records (prj_projects, prj_milestones, prj_tasks, prj_notes)",
83
84
  isOrgGrantable: false
85
+ },
86
+ {
87
+ key: "clients.manage",
88
+ description: "Create, update, and delete client hub records (clients, clt_* satellites)",
89
+ isOrgGrantable: false
84
90
  }
85
91
  ];
86
92
  new Set(PERMISSION_CATALOG.map((p) => p.key));
@@ -2342,18 +2348,41 @@ function useResourceExecutions({
2342
2348
  }
2343
2349
 
2344
2350
  // src/features/operations/organization-graph/commandViewVisualizationModes.ts
2351
+ var DEFAULT_CLUSTER_PARAMETERS = {
2352
+ zonePadding: 86,
2353
+ interZoneGap: 325
2354
+ };
2355
+ var DEFAULT_SWIMLANE_PARAMETERS = {
2356
+ laneHeight: 140,
2357
+ sortKey: "kind"
2358
+ };
2359
+ var DEFAULT_FOCUS_PARAMETERS = {
2360
+ depth: 2,
2361
+ radius: 390
2362
+ };
2363
+ var DEFAULT_NETWORK_PARAMETERS = {
2364
+ linkLength: 82,
2365
+ repulsion: 150
2366
+ };
2367
+ var DEFAULT_FORCE_PARAMETERS = {
2368
+ nodeRepulsion: 4500,
2369
+ idealEdgeLength: 80,
2370
+ gravity: 0.25
2371
+ };
2345
2372
  var COMMAND_VIEW_VISUALIZATION_MODES = [
2373
+ { label: "Explore", value: "explore" },
2346
2374
  { label: "Cluster", value: "cluster" },
2347
2375
  { label: "Swimlane", value: "swimlane" },
2348
2376
  { label: "Focus", value: "focus" },
2349
- { label: "Network", value: "network" }
2377
+ { label: "Network", value: "network" },
2378
+ { label: "Force", value: "force" }
2350
2379
  ];
2351
- var DEFAULT_COMMAND_VIEW_VISUALIZATION_MODE = "network";
2352
2380
  var DOMAIN_ORDER = [
2353
2381
  "operations",
2354
2382
  "runtime",
2355
2383
  "business",
2356
2384
  "delivery",
2385
+ "knowledge",
2357
2386
  "admin",
2358
2387
  "system",
2359
2388
  "platform",
@@ -2374,6 +2403,7 @@ var DOMAIN_KEYWORDS = {
2374
2403
  runtime: ["execution", "runner", "log", "session", "deploy", "webhook", "api key", "credential", "activity"],
2375
2404
  business: ["sales", "crm", "lead", "seo", "analytics", "cost", "account"],
2376
2405
  delivery: ["project", "task", "submission", "request", "design"],
2406
+ knowledge: [],
2377
2407
  admin: ["admin", "user", "organization", "notification", "archive"],
2378
2408
  system: ["setting", "appearance", "debug", "monitoring", "health"],
2379
2409
  platform: ["surface", "capability", "entity", "feature"],
@@ -2385,16 +2415,22 @@ function spread(index, count, spacing) {
2385
2415
  function getNodeSortValue(node) {
2386
2416
  return `${node.kind}:${node.label}:${node.id}`;
2387
2417
  }
2418
+ function getCommandViewNodeDomain(node) {
2419
+ return getNodeDomain(node);
2420
+ }
2388
2421
  function getNodeDomain(node) {
2389
- if (node.kind === "organization") {
2422
+ if (node.kind === "organization" || node.kind === "surface" || node.kind === "capability" || node.kind === "entity") {
2390
2423
  return "platform";
2391
2424
  }
2392
- if (node.kind !== "feature" && node.kind !== "resource") {
2393
- return "platform";
2425
+ if (node.kind === "knowledge") {
2426
+ return "knowledge";
2427
+ }
2428
+ if (node.kind === "stage") {
2429
+ return "business";
2394
2430
  }
2395
2431
  const searchable = `${node.id} ${node.sourceId ?? ""} ${node.featureId ?? ""} ${node.resourceType ?? ""} ${node.label}`.toLowerCase();
2396
2432
  for (const domain of DOMAIN_ORDER) {
2397
- if (domain === "other") {
2433
+ if (DOMAIN_KEYWORDS[domain].length === 0) {
2398
2434
  continue;
2399
2435
  }
2400
2436
  if (DOMAIN_KEYWORDS[domain].some((keyword) => searchable.includes(keyword))) {
@@ -2430,19 +2466,34 @@ function getNeighbors(graph, nodeId) {
2430
2466
  }
2431
2467
  return neighbors;
2432
2468
  }
2433
- function getClusterGraphPositions(graph) {
2469
+ var CLUSTER_ZONE_ORIGINS = {
2470
+ operations: { x: -520, y: -270, columns: 3, xGap: 188, yGap: 86 },
2471
+ runtime: { x: 130, y: -270, columns: 3, xGap: 188, yGap: 86 },
2472
+ business: { x: -520, y: 95, columns: 3, xGap: 188, yGap: 86 },
2473
+ delivery: { x: 130, y: 95, columns: 3, xGap: 188, yGap: 86 },
2474
+ knowledge: { x: 0, y: 605, columns: 4, xGap: 200, yGap: 86 },
2475
+ admin: { x: -520, y: 420, columns: 3, xGap: 188, yGap: 86 },
2476
+ system: { x: 130, y: 420, columns: 3, xGap: 188, yGap: 86 },
2477
+ platform: { x: 0, y: -520, columns: 4, xGap: 205, yGap: 90 },
2478
+ other: { x: 0, y: 800, columns: 6, xGap: 176, yGap: 78 }
2479
+ };
2480
+ function getClusterGraphPositions(graph, params) {
2434
2481
  const positions = /* @__PURE__ */ new Map();
2435
2482
  const groups = groupNodesByDomain(graph);
2436
- const zoneConfig = {
2437
- operations: { x: -520, y: -270, columns: 3, xGap: 188, yGap: 86 },
2438
- runtime: { x: 130, y: -270, columns: 3, xGap: 188, yGap: 86 },
2439
- business: { x: -520, y: 95, columns: 3, xGap: 188, yGap: 86 },
2440
- delivery: { x: 130, y: 95, columns: 3, xGap: 188, yGap: 86 },
2441
- admin: { x: -520, y: 420, columns: 3, xGap: 188, yGap: 86 },
2442
- system: { x: 130, y: 420, columns: 3, xGap: 188, yGap: 86 },
2443
- platform: { x: 0, y: -520, columns: 4, xGap: 205, yGap: 90 },
2444
- other: { x: 0, y: 710, columns: 6, xGap: 176, yGap: 78 }
2445
- };
2483
+ const zoneConfig = params === void 0 ? CLUSTER_ZONE_ORIGINS : (() => {
2484
+ const yGapScale = params.zonePadding / DEFAULT_CLUSTER_PARAMETERS.zonePadding;
2485
+ const yOriginScale = params.interZoneGap / DEFAULT_CLUSTER_PARAMETERS.interZoneGap;
2486
+ return Object.fromEntries(
2487
+ Object.entries(CLUSTER_ZONE_ORIGINS).map(([domain, cfg]) => [
2488
+ domain,
2489
+ {
2490
+ ...cfg,
2491
+ y: Math.round(cfg.y * yOriginScale),
2492
+ yGap: Math.round(cfg.yGap * yGapScale)
2493
+ }
2494
+ ])
2495
+ );
2496
+ })();
2446
2497
  for (const domain of DOMAIN_ORDER) {
2447
2498
  const nodes = groups.get(domain) ?? [];
2448
2499
  const zone = zoneConfig[domain];
@@ -2458,21 +2509,41 @@ function getClusterGraphPositions(graph) {
2458
2509
  }
2459
2510
  return positions;
2460
2511
  }
2461
- function getSwimlaneGraphPositions(graph) {
2512
+ var SWIMLANE_BASE_LANE_Y = {
2513
+ platform: -360,
2514
+ operations: -220,
2515
+ runtime: -80,
2516
+ business: 60,
2517
+ delivery: 200,
2518
+ knowledge: 340,
2519
+ admin: 480,
2520
+ system: 620,
2521
+ other: 760
2522
+ };
2523
+ function getSwimlaneGraphPositions(graph, params) {
2462
2524
  const positions = /* @__PURE__ */ new Map();
2463
- const groups = groupNodesByDomain(graph);
2464
- const laneY = {
2465
- platform: -360,
2466
- operations: -220,
2467
- runtime: -80,
2468
- business: 60,
2469
- delivery: 200,
2470
- admin: 340,
2471
- system: 480,
2472
- other: 620
2473
- };
2525
+ const rawGroups = groupNodesByDomain(graph);
2526
+ if (params !== void 0 && params.sortKey !== "kind") {
2527
+ for (const [, nodes] of rawGroups) {
2528
+ nodes.sort((left, right) => {
2529
+ if (params.sortKey === "domain") {
2530
+ return left.label.localeCompare(right.label);
2531
+ }
2532
+ return left.kind.localeCompare(right.kind) || left.label.localeCompare(right.label);
2533
+ });
2534
+ }
2535
+ }
2536
+ const laneY = params === void 0 ? SWIMLANE_BASE_LANE_Y : (() => {
2537
+ const scale = params.laneHeight / DEFAULT_SWIMLANE_PARAMETERS.laneHeight;
2538
+ return Object.fromEntries(
2539
+ Object.keys(SWIMLANE_BASE_LANE_Y).map((domain) => [
2540
+ domain,
2541
+ Math.round(SWIMLANE_BASE_LANE_Y[domain] * scale)
2542
+ ])
2543
+ );
2544
+ })();
2474
2545
  for (const domain of DOMAIN_ORDER) {
2475
- const nodes = groups.get(domain) ?? [];
2546
+ const nodes = rawGroups.get(domain) ?? [];
2476
2547
  const columns = Math.min(8, Math.max(1, Math.ceil(Math.sqrt(nodes.length) * 1.6)));
2477
2548
  for (const [index, node] of nodes.entries()) {
2478
2549
  const column = index % columns;
@@ -2486,7 +2557,7 @@ function getSwimlaneGraphPositions(graph) {
2486
2557
  }
2487
2558
  return positions;
2488
2559
  }
2489
- function getFocusGraphPositions(graph, selectedNodeId) {
2560
+ function getFocusGraphPositions(graph, selectedNodeId, params) {
2490
2561
  if (!selectedNodeId || !graph.nodes.some((node) => node.id === selectedNodeId)) {
2491
2562
  return getNetworkGraphPositions(graph);
2492
2563
  }
@@ -2501,6 +2572,10 @@ function getFocusGraphPositions(graph, selectedNodeId) {
2501
2572
  }
2502
2573
  }
2503
2574
  positions.set(selectedNodeId, { x: 0, y: 0 });
2575
+ const ring1RadiusX = params === void 0 ? 390 : params.radius;
2576
+ const ring1RadiusY = params === void 0 ? 210 : Math.round(params.radius * (210 / 390));
2577
+ const ring2RadiusX = params === void 0 ? 680 : Math.round(params.radius * (680 / 390));
2578
+ const ring2RadiusY = params === void 0 ? 360 : Math.round(params.radius * (360 / 390));
2504
2579
  const placeRing = (ids, radiusX, radiusY, yOffset = 0) => {
2505
2580
  ids.forEach((id, index) => {
2506
2581
  const angle = -Math.PI / 2 + index / Math.max(1, ids.length) * Math.PI * 2;
@@ -2510,8 +2585,11 @@ function getFocusGraphPositions(graph, selectedNodeId) {
2510
2585
  });
2511
2586
  });
2512
2587
  };
2513
- placeRing([...firstDegree].sort(), 390, 210);
2514
- placeRing([...secondDegree].sort(), 680, 360);
2588
+ placeRing([...firstDegree].sort(), ring1RadiusX, ring1RadiusY);
2589
+ const effectiveDepth = params === void 0 ? DEFAULT_FOCUS_PARAMETERS.depth : params.depth;
2590
+ if (effectiveDepth >= 2) {
2591
+ placeRing([...secondDegree].sort(), ring2RadiusX, ring2RadiusY);
2592
+ }
2515
2593
  const remaining = graph.nodes.filter((node) => !positions.has(node.id)).sort((left, right) => left.label.localeCompare(right.label));
2516
2594
  for (const [index, node] of remaining.entries()) {
2517
2595
  const column = index % 8;
@@ -2523,18 +2601,20 @@ function getFocusGraphPositions(graph, selectedNodeId) {
2523
2601
  }
2524
2602
  return positions;
2525
2603
  }
2526
- function getNetworkGraphPositions(graph) {
2604
+ function getNetworkGraphPositions(graph, params) {
2527
2605
  const positions = /* @__PURE__ */ new Map();
2528
2606
  const nodes = [...graph.nodes].sort((left, right) => {
2529
2607
  const degreeDelta = getNodeDegree(graph, right.id) - getNodeDegree(graph, left.id);
2530
2608
  return degreeDelta || left.label.localeCompare(right.label);
2531
2609
  });
2610
+ const baseRepulsion = params === void 0 ? 150 : params.repulsion;
2611
+ const linkLength = params === void 0 ? 82 : params.linkLength;
2532
2612
  for (const [index, node] of nodes.entries()) {
2533
2613
  if (index === 0) {
2534
2614
  positions.set(node.id, { x: 0, y: 0 });
2535
2615
  continue;
2536
2616
  }
2537
- const radius = 150 + Math.sqrt(index) * 82;
2617
+ const radius = baseRepulsion + Math.sqrt(index) * linkLength;
2538
2618
  const angle = index * 2.399963229728653;
2539
2619
  positions.set(node.id, {
2540
2620
  x: Math.cos(angle) * radius,
@@ -2543,13 +2623,183 @@ function getNetworkGraphPositions(graph) {
2543
2623
  }
2544
2624
  return positions;
2545
2625
  }
2546
- function getSpatialGraphPositions(graph) {
2547
- const positions = getSwimlaneGraphPositions(graph);
2548
- for (const [nodeId, position] of positions.entries()) {
2549
- const degree = getNodeDegree(graph, nodeId);
2550
- positions.set(nodeId, {
2551
- x: position.x + degree * 12,
2552
- y: position.y - degree * 8
2626
+ function getDefaultParameters(mode) {
2627
+ switch (mode) {
2628
+ case "swimlane":
2629
+ return { mode: "swimlane", ...DEFAULT_SWIMLANE_PARAMETERS };
2630
+ case "focus":
2631
+ return { mode: "focus", ...DEFAULT_FOCUS_PARAMETERS };
2632
+ case "network":
2633
+ return { mode: "network", ...DEFAULT_NETWORK_PARAMETERS };
2634
+ case "force":
2635
+ return { mode: "force", ...DEFAULT_FORCE_PARAMETERS };
2636
+ case "cluster":
2637
+ return { mode: "cluster", ...DEFAULT_CLUSTER_PARAMETERS, zonePadding: 110, interZoneGap: 400 };
2638
+ case "explore":
2639
+ return { mode: "explore" };
2640
+ }
2641
+ }
2642
+ var EXPLORE_ZONE_ORDER = [
2643
+ "platform",
2644
+ "operations",
2645
+ "runtime",
2646
+ "business",
2647
+ "delivery",
2648
+ "knowledge",
2649
+ "admin",
2650
+ "system",
2651
+ "other"
2652
+ ];
2653
+ var EXPLORE_ZONE_DISPLAY_NAME = {
2654
+ platform: "Platform",
2655
+ operations: "Operations",
2656
+ runtime: "Runtime",
2657
+ business: "Business",
2658
+ delivery: "Delivery",
2659
+ knowledge: "Knowledge",
2660
+ admin: "Admin",
2661
+ system: "System",
2662
+ other: "Other"
2663
+ };
2664
+ var EXPLORE_OM_ROOT_ID = "explore-om-root";
2665
+ function getExploreProjection() {
2666
+ const CENTROID_RADIUS = 340;
2667
+ const count = EXPLORE_ZONE_ORDER.length;
2668
+ const positions = /* @__PURE__ */ new Map();
2669
+ const syntheticNodes = [];
2670
+ const backboneEdges = [];
2671
+ syntheticNodes.push({
2672
+ id: EXPLORE_OM_ROOT_ID,
2673
+ kind: "organization",
2674
+ label: "Organization Model",
2675
+ isCentroid: "false",
2676
+ domainZone: null,
2677
+ zoneTint: null,
2678
+ isOmRoot: true
2679
+ });
2680
+ positions.set(EXPLORE_OM_ROOT_ID, { x: 0, y: 0 });
2681
+ for (const [index, zone] of EXPLORE_ZONE_ORDER.entries()) {
2682
+ const angle = -Math.PI / 2 + index / count * Math.PI * 2;
2683
+ const x = Math.cos(angle) * CENTROID_RADIUS;
2684
+ const y = Math.sin(angle) * CENTROID_RADIUS;
2685
+ const centroidId = `centroid:${zone}`;
2686
+ syntheticNodes.push({
2687
+ id: centroidId,
2688
+ kind: "centroid",
2689
+ label: EXPLORE_ZONE_DISPLAY_NAME[zone],
2690
+ isCentroid: "true",
2691
+ domainZone: zone,
2692
+ zoneTint: DOMAIN_ZONE_TINT_COLOR[zone] ?? null
2693
+ });
2694
+ positions.set(centroidId, { x, y });
2695
+ backboneEdges.push({ source: EXPLORE_OM_ROOT_ID, target: centroidId });
2696
+ }
2697
+ return { syntheticNodes, backboneEdges, positions };
2698
+ }
2699
+ function buildCommandViewGraphIndex(graph) {
2700
+ const nodesByDomain = /* @__PURE__ */ new Map();
2701
+ const nodeById = /* @__PURE__ */ new Map();
2702
+ const containsChildrenByParentId = /* @__PURE__ */ new Map();
2703
+ const containsParentIdsByChildId = /* @__PURE__ */ new Map();
2704
+ const childBearingNodeIds = /* @__PURE__ */ new Set();
2705
+ const degreeByNodeId = /* @__PURE__ */ new Map();
2706
+ for (const node of graph.nodes) {
2707
+ const zone = getNodeDomain(node);
2708
+ nodeById.set(node.id, node);
2709
+ degreeByNodeId.set(node.id, 0);
2710
+ const existing = nodesByDomain.get(zone);
2711
+ if (existing) {
2712
+ existing.push(node.id);
2713
+ } else {
2714
+ nodesByDomain.set(zone, [node.id]);
2715
+ }
2716
+ }
2717
+ for (const edge of graph.edges) {
2718
+ degreeByNodeId.set(edge.sourceId, (degreeByNodeId.get(edge.sourceId) ?? 0) + 1);
2719
+ degreeByNodeId.set(edge.targetId, (degreeByNodeId.get(edge.targetId) ?? 0) + 1);
2720
+ if (edge.kind !== "contains") continue;
2721
+ childBearingNodeIds.add(edge.sourceId);
2722
+ const children = containsChildrenByParentId.get(edge.sourceId);
2723
+ if (children) {
2724
+ children.push(edge.targetId);
2725
+ } else {
2726
+ containsChildrenByParentId.set(edge.sourceId, [edge.targetId]);
2727
+ }
2728
+ const parents = containsParentIdsByChildId.get(edge.targetId);
2729
+ if (parents) {
2730
+ parents.push(edge.sourceId);
2731
+ } else {
2732
+ containsParentIdsByChildId.set(edge.targetId, [edge.sourceId]);
2733
+ }
2734
+ }
2735
+ return {
2736
+ nodesByDomain,
2737
+ nodeById,
2738
+ containsChildrenByParentId,
2739
+ containsParentIdsByChildId,
2740
+ childBearingNodeIds,
2741
+ degreeByNodeId
2742
+ };
2743
+ }
2744
+ function getIndexedDomainNodeIds(graph, zone, lookup) {
2745
+ if (lookup instanceof Map) {
2746
+ return lookup.get(zone) ?? graph.nodes.filter((node) => getNodeDomain(node) === zone).map((node) => node.id);
2747
+ }
2748
+ return lookup?.nodesByDomain.get(zone) ?? graph.nodes.filter((node) => getNodeDomain(node) === zone).map((node) => node.id);
2749
+ }
2750
+ function getIndexedContainsChildIds(graph, parentId, lookup) {
2751
+ if (lookup && !(lookup instanceof Map)) {
2752
+ return lookup.containsChildrenByParentId.get(parentId) ?? [];
2753
+ }
2754
+ return graph.edges.filter((e) => e.kind === "contains" && e.sourceId === parentId).map((e) => e.targetId);
2755
+ }
2756
+ function getRadialFromAnchorProjection(graph, anchorId, anchorPos, level, lookup) {
2757
+ const RADIUS_BY_LEVEL = {
2758
+ 1: 260,
2759
+ 2: 170,
2760
+ 3: 110
2761
+ };
2762
+ const radius = RADIUS_BY_LEVEL[level] ?? 110;
2763
+ const positions = /* @__PURE__ */ new Map();
2764
+ let childIds;
2765
+ if (anchorId.startsWith("centroid:")) {
2766
+ const zone = anchorId.slice("centroid:".length);
2767
+ childIds = getIndexedDomainNodeIds(graph, zone, lookup);
2768
+ } else {
2769
+ childIds = getIndexedContainsChildIds(graph, anchorId, lookup);
2770
+ }
2771
+ const outwardAngle = anchorPos.x === 0 && anchorPos.y === 0 ? -Math.PI / 2 : Math.atan2(anchorPos.y, anchorPos.x);
2772
+ const NODE_SLOT = 92;
2773
+ const BASE_ARC = Math.PI / 2.5;
2774
+ const PREFERRED_ARC = Math.PI / 1.8;
2775
+ const MAX_ARC = Math.PI * 0.95;
2776
+ const n = childIds.length;
2777
+ let effectiveRadius = radius;
2778
+ let arcSpan;
2779
+ if (n <= 1) {
2780
+ arcSpan = BASE_ARC;
2781
+ } else {
2782
+ const minArcAtBase = n * NODE_SLOT / effectiveRadius;
2783
+ if (minArcAtBase <= BASE_ARC) {
2784
+ arcSpan = BASE_ARC;
2785
+ } else if (minArcAtBase <= PREFERRED_ARC) {
2786
+ arcSpan = minArcAtBase;
2787
+ } else {
2788
+ arcSpan = PREFERRED_ARC;
2789
+ effectiveRadius = Math.max(effectiveRadius, n * NODE_SLOT / PREFERRED_ARC);
2790
+ const MAX_RADIUS = radius * 2.4;
2791
+ if (effectiveRadius > MAX_RADIUS) {
2792
+ effectiveRadius = MAX_RADIUS;
2793
+ arcSpan = Math.min(MAX_ARC, n * NODE_SLOT / effectiveRadius);
2794
+ }
2795
+ }
2796
+ }
2797
+ for (const [index, childId] of childIds.entries()) {
2798
+ const t = n === 1 ? 0.5 : (index + 0.5) / n;
2799
+ const angle = outwardAngle - arcSpan / 2 + t * arcSpan;
2800
+ positions.set(childId, {
2801
+ x: anchorPos.x + Math.cos(angle) * effectiveRadius,
2802
+ y: anchorPos.y + Math.sin(angle) * effectiveRadius
2553
2803
  });
2554
2804
  }
2555
2805
  return positions;
@@ -2557,24 +2807,272 @@ function getSpatialGraphPositions(graph) {
2557
2807
  function getCommandViewGraphPositions({
2558
2808
  graph,
2559
2809
  visualizationMode,
2560
- selectedNodeId
2810
+ selectedNodeId,
2811
+ parameters,
2812
+ expandedNodeIds
2561
2813
  }) {
2562
2814
  switch (visualizationMode) {
2563
- case "swimlane":
2564
- return getSwimlaneGraphPositions(graph);
2565
- case "focus":
2566
- return getFocusGraphPositions(graph, selectedNodeId);
2567
- case "network":
2568
- return getNetworkGraphPositions(graph);
2569
- case "spatial":
2570
- return getSpatialGraphPositions(graph);
2815
+ case "swimlane": {
2816
+ const p = parameters?.mode === "swimlane" ? parameters : void 0;
2817
+ return getSwimlaneGraphPositions(graph, p);
2818
+ }
2819
+ case "focus": {
2820
+ const p = parameters?.mode === "focus" ? parameters : void 0;
2821
+ return getFocusGraphPositions(graph, selectedNodeId, p);
2822
+ }
2823
+ case "network": {
2824
+ const p = parameters?.mode === "network" ? parameters : void 0;
2825
+ return getNetworkGraphPositions(graph, p);
2826
+ }
2827
+ case "force":
2828
+ return /* @__PURE__ */ new Map();
2829
+ case "explore": {
2830
+ const { positions: explorePositions } = getExploreProjection();
2831
+ if (expandedNodeIds && expandedNodeIds.size > 0) {
2832
+ const graphIndex = buildCommandViewGraphIndex(graph);
2833
+ for (const nodeId of expandedNodeIds) {
2834
+ const isCentroid = nodeId.startsWith("centroid:");
2835
+ const level = isCentroid ? 1 : getExpandDepthForNode(graph, nodeId, expandedNodeIds, graphIndex);
2836
+ if (level >= 3) {
2837
+ continue;
2838
+ }
2839
+ const anchorPos = explorePositions.get(nodeId);
2840
+ if (!anchorPos) continue;
2841
+ const childPositions = getRadialFromAnchorProjection(graph, nodeId, anchorPos, level + 1, graphIndex);
2842
+ for (const [id, pos] of childPositions) {
2843
+ explorePositions.set(id, pos);
2844
+ }
2845
+ }
2846
+ }
2847
+ return explorePositions;
2848
+ }
2571
2849
  case "cluster":
2572
- default:
2573
- return getClusterGraphPositions(graph);
2850
+ default: {
2851
+ const p = parameters?.mode === "cluster" ? parameters : void 0;
2852
+ return getClusterGraphPositions(graph, p);
2853
+ }
2854
+ }
2855
+ }
2856
+ function getExpandDepthForNode(graph, nodeId, expandedNodeIds, graphIndex) {
2857
+ const node = graphIndex?.nodeById.get(nodeId) ?? graph.nodes.find((n) => n.id === nodeId);
2858
+ for (const expandedId of expandedNodeIds) {
2859
+ if (!expandedId.startsWith("centroid:")) continue;
2860
+ const zone = expandedId.slice("centroid:".length);
2861
+ const isDirectChild = node ? getNodeDomain(node) === zone : false;
2862
+ if (isDirectChild) return 2;
2863
+ }
2864
+ for (const expandedId of expandedNodeIds) {
2865
+ if (expandedId.startsWith("centroid:")) continue;
2866
+ const isContainsChild = getIndexedContainsChildIds(graph, expandedId, graphIndex).includes(nodeId);
2867
+ if (isContainsChild) return 3;
2574
2868
  }
2869
+ return 2;
2870
+ }
2871
+ function exploreNodeHasChildren(graph, nodeId, graphIndex) {
2872
+ if (nodeId.startsWith("centroid:")) return true;
2873
+ return graphIndex?.childBearingNodeIds.has(nodeId) ?? graph.edges.some((e) => e.kind === "contains" && e.sourceId === nodeId);
2874
+ }
2875
+ function findExploreParent(graph, childId, expandedNodeIds, graphIndex) {
2876
+ if (childId.startsWith("centroid:")) {
2877
+ return EXPLORE_OM_ROOT_ID;
2878
+ }
2879
+ for (const parentId2 of expandedNodeIds) {
2880
+ if (parentId2.startsWith("centroid:")) continue;
2881
+ const hasEdge = getIndexedContainsChildIds(graph, parentId2, graphIndex).includes(childId);
2882
+ if (hasEdge) return parentId2;
2883
+ }
2884
+ const childNode = graphIndex?.nodeById.get(childId) ?? graph.nodes.find((n) => n.id === childId);
2885
+ if (childNode) {
2886
+ const childCentroidId = `centroid:${getNodeDomain(childNode)}`;
2887
+ if (expandedNodeIds.has(childCentroidId)) {
2888
+ return childCentroidId;
2889
+ }
2890
+ }
2891
+ const parentId = graphIndex?.containsParentIdsByChildId.get(childId)?.[0];
2892
+ if (parentId) return parentId;
2893
+ const parentEdge = graph.edges.find((e) => e.kind === "contains" && e.targetId === childId);
2894
+ if (parentEdge) return parentEdge.sourceId;
2895
+ if (childNode) return `centroid:${getNodeDomain(childNode)}`;
2896
+ return null;
2897
+ }
2898
+ function getExploreFocusSet(graph, selectedId, expandedNodeIds, graphIndex) {
2899
+ const nodeIds = /* @__PURE__ */ new Set();
2900
+ const edgeIds = /* @__PURE__ */ new Set();
2901
+ nodeIds.add(EXPLORE_OM_ROOT_ID);
2902
+ if (selectedId === EXPLORE_OM_ROOT_ID) {
2903
+ return { nodeIds, edgeIds };
2904
+ }
2905
+ const ancestorChain = [selectedId];
2906
+ let cursor = selectedId;
2907
+ for (let i = 0; i < 8 && cursor !== EXPLORE_OM_ROOT_ID; i++) {
2908
+ if (cursor.startsWith("centroid:")) {
2909
+ ancestorChain.push(EXPLORE_OM_ROOT_ID);
2910
+ break;
2911
+ }
2912
+ const parentId = findExploreParent(graph, cursor, expandedNodeIds, graphIndex);
2913
+ if (!parentId) break;
2914
+ ancestorChain.push(parentId);
2915
+ cursor = parentId;
2916
+ }
2917
+ for (let i = 0; i < ancestorChain.length; i++) {
2918
+ nodeIds.add(ancestorChain[i]);
2919
+ if (i > 0) {
2920
+ const child = ancestorChain[i - 1];
2921
+ const parent = ancestorChain[i];
2922
+ if (parent === EXPLORE_OM_ROOT_ID && child.startsWith("centroid:")) {
2923
+ edgeIds.add(`backbone:${parent}:${child}`);
2924
+ } else {
2925
+ edgeIds.add(`expand:${parent}:${child}`);
2926
+ }
2927
+ }
2928
+ }
2929
+ if (expandedNodeIds.has(selectedId)) {
2930
+ const queue = [selectedId];
2931
+ while (queue.length > 0) {
2932
+ const id = queue.shift();
2933
+ let children;
2934
+ if (id.startsWith("centroid:")) {
2935
+ const zone = id.slice("centroid:".length);
2936
+ children = getIndexedDomainNodeIds(graph, zone, graphIndex);
2937
+ } else {
2938
+ children = getIndexedContainsChildIds(graph, id, graphIndex);
2939
+ }
2940
+ for (const c of children) {
2941
+ nodeIds.add(c);
2942
+ edgeIds.add(`expand:${id}:${c}`);
2943
+ if (expandedNodeIds.has(c)) queue.push(c);
2944
+ }
2945
+ }
2946
+ }
2947
+ return { nodeIds, edgeIds };
2948
+ }
2949
+ function getNextExpandedSetForToggle(graph, toggleId, currentExpanded, graphIndex) {
2950
+ if (currentExpanded.has(toggleId)) {
2951
+ return removeExpandedSubtree(graph, toggleId, currentExpanded, graphIndex);
2952
+ }
2953
+ const siblings = getSameParentExpandedSiblings(graph, toggleId, currentExpanded, graphIndex);
2954
+ let next = new Set(currentExpanded);
2955
+ for (const siblingId of siblings) {
2956
+ next = removeExpandedSubtree(graph, siblingId, next, graphIndex);
2957
+ }
2958
+ next.add(toggleId);
2959
+ return next;
2960
+ }
2961
+ function removeExpandedSubtree(graph, rootId, set, graphIndex) {
2962
+ const result = new Set(set);
2963
+ if (!result.has(rootId)) return result;
2964
+ result.delete(rootId);
2965
+ const queue = [rootId];
2966
+ while (queue.length > 0) {
2967
+ const id = queue.shift();
2968
+ let children;
2969
+ if (id.startsWith("centroid:")) {
2970
+ const zone = id.slice("centroid:".length);
2971
+ children = getIndexedDomainNodeIds(graph, zone, graphIndex);
2972
+ } else {
2973
+ children = getIndexedContainsChildIds(graph, id, graphIndex);
2974
+ }
2975
+ for (const c of children) {
2976
+ if (result.has(c)) {
2977
+ result.delete(c);
2978
+ queue.push(c);
2979
+ }
2980
+ }
2981
+ }
2982
+ return result;
2983
+ }
2984
+ function getSameParentExpandedSiblings(graph, nodeId, expandedSet, graphIndex) {
2985
+ if (nodeId.startsWith("centroid:")) {
2986
+ return Array.from(expandedSet).filter((id) => id !== nodeId && id.startsWith("centroid:"));
2987
+ }
2988
+ let parentId = null;
2989
+ const directParents = graphIndex?.containsParentIdsByChildId.get(nodeId) ?? graph.edges.filter((e) => e.kind === "contains" && e.targetId === nodeId).map((e) => e.sourceId);
2990
+ parentId = directParents.find((p) => expandedSet.has(p)) ?? null;
2991
+ if (!parentId) {
2992
+ const node = graphIndex?.nodeById.get(nodeId) ?? graph.nodes.find((n) => n.id === nodeId);
2993
+ if (node) {
2994
+ const centroidId = `centroid:${getNodeDomain(node)}`;
2995
+ if (expandedSet.has(centroidId)) parentId = centroidId;
2996
+ }
2997
+ }
2998
+ if (!parentId) return [];
2999
+ if (parentId.startsWith("centroid:")) {
3000
+ const zone = parentId.slice("centroid:".length);
3001
+ return Array.from(expandedSet).filter((id) => {
3002
+ if (id === nodeId || id.startsWith("centroid:")) return false;
3003
+ const n = graphIndex?.nodeById.get(id) ?? graph.nodes.find((nn) => nn.id === id);
3004
+ return n ? getNodeDomain(n) === zone : false;
3005
+ });
3006
+ }
3007
+ const childrenOfParent = new Set(getIndexedContainsChildIds(graph, parentId, graphIndex));
3008
+ return Array.from(expandedSet).filter((id) => id !== nodeId && childrenOfParent.has(id));
3009
+ }
3010
+ var DOMAIN_ZONE_TINT_COLOR = {
3011
+ operations: "#3b82a0",
3012
+ runtime: "#7c6ea8",
3013
+ business: "#3f8f7a",
3014
+ delivery: "#4b97a6",
3015
+ knowledge: "#6673a6",
3016
+ admin: "#7b838a",
3017
+ system: "#536b9a",
3018
+ platform: "#8d679b",
3019
+ other: "#6f757b"
3020
+ };
3021
+ var DOMAIN_DISPLAY_NAME = {
3022
+ operations: "Operations",
3023
+ runtime: "Runtime",
3024
+ business: "Business",
3025
+ delivery: "Delivery",
3026
+ knowledge: "Knowledge",
3027
+ admin: "Admin",
3028
+ system: "System",
3029
+ platform: "Platform",
3030
+ other: "Other"
3031
+ };
3032
+ function getCommandViewSwimlaneLaneLabels() {
3033
+ const laneY = {
3034
+ platform: -360,
3035
+ operations: -220,
3036
+ runtime: -80,
3037
+ business: 60,
3038
+ delivery: 200,
3039
+ knowledge: 340,
3040
+ admin: 480,
3041
+ system: 620,
3042
+ other: 760
3043
+ };
3044
+ return DOMAIN_ORDER.map((domain) => ({
3045
+ domain,
3046
+ text: DOMAIN_DISPLAY_NAME[domain],
3047
+ y: laneY[domain],
3048
+ x: 0
3049
+ }));
3050
+ }
3051
+ function getCommandViewClusterZoneLabels() {
3052
+ const zoneOrigins = {
3053
+ operations: { x: -520, y: -270 },
3054
+ runtime: { x: 130, y: -270 },
3055
+ business: { x: -520, y: 95 },
3056
+ delivery: { x: 130, y: 95 },
3057
+ knowledge: { x: 0, y: 605 },
3058
+ admin: { x: -520, y: 420 },
3059
+ system: { x: 130, y: 420 },
3060
+ platform: { x: 0, y: -520 },
3061
+ other: { x: 0, y: 800 }
3062
+ };
3063
+ return DOMAIN_ORDER.map((domain) => ({
3064
+ domain,
3065
+ text: DOMAIN_DISPLAY_NAME[domain],
3066
+ x: zoneOrigins[domain].x,
3067
+ y: zoneOrigins[domain].y
3068
+ }));
2575
3069
  }
2576
3070
 
2577
3071
  // src/hooks/operations/command-view/useCommandViewStore.ts
3072
+ var VALID_VISUALIZATION_MODES = new Set(
3073
+ COMMAND_VIEW_VISUALIZATION_MODES.map((entry) => entry.value)
3074
+ );
3075
+ var NEW_SESSION_VISUALIZATION_MODE = "explore";
2578
3076
  var DEFAULT_DIAGNOSTIC_CATEGORIES = ["diagnostic", "testing"];
2579
3077
  var useCommandViewStore = create()(
2580
3078
  persist(
@@ -2585,8 +3083,12 @@ var useCommandViewStore = create()(
2585
3083
  setShowIntegrations: (showIntegrations) => set({ showIntegrations }),
2586
3084
  fitViewOnFilter: true,
2587
3085
  setFitViewOnFilter: (fitViewOnFilter) => set({ fitViewOnFilter }),
2588
- visualizationMode: DEFAULT_COMMAND_VIEW_VISUALIZATION_MODE,
2589
- setVisualizationMode: (visualizationMode) => set({ visualizationMode }),
3086
+ // New sessions default to 'explore'; returning sessions get their stored mode via persist.
3087
+ visualizationMode: NEW_SESSION_VISUALIZATION_MODE,
3088
+ setVisualizationMode: (visualizationMode) => set({ visualizationMode, lastUsedVisualizationMode: visualizationMode }),
3089
+ lastUsedVisualizationMode: null,
3090
+ lastOpenBottomTab: null,
3091
+ setLastOpenBottomTab: (lastOpenBottomTab) => set({ lastOpenBottomTab }),
2590
3092
  selectedNodeId: null,
2591
3093
  setSelectedNodeId: (selectedNodeId) => set({ selectedNodeId }),
2592
3094
  resourcesHidden: true,
@@ -2599,7 +3101,29 @@ var useCommandViewStore = create()(
2599
3101
  clearRevealedIds: () => set({ revealedIds: /* @__PURE__ */ new Set() }),
2600
3102
  hasVisibilityInteraction: false,
2601
3103
  markVisibilityInteraction: () => set({ hasVisibilityInteraction: true }),
2602
- resetVisibilityInteraction: () => set({ hasVisibilityInteraction: false })
3104
+ resetVisibilityInteraction: () => set({ hasVisibilityInteraction: false }),
3105
+ expandedClusterDomains: [],
3106
+ toggleClusterDomain: (domain) => set((s) => ({
3107
+ expandedClusterDomains: s.expandedClusterDomains.includes(domain) ? s.expandedClusterDomains.filter((d) => d !== domain) : [...s.expandedClusterDomains, domain]
3108
+ })),
3109
+ setExpandedClusterDomains: (expandedClusterDomains) => set({ expandedClusterDomains }),
3110
+ expandedNodeIdsArray: [],
3111
+ expandedNodeIds: /* @__PURE__ */ new Set(),
3112
+ toggleNodeExpansion: (nodeId) => set((s) => {
3113
+ const currentSet = s.expandedNodeIds;
3114
+ const isCurrentlyExpanded = currentSet.has(nodeId);
3115
+ if (isCurrentlyExpanded) {
3116
+ const next2 = new Set(currentSet);
3117
+ next2.delete(nodeId);
3118
+ const nextArray2 = [...next2];
3119
+ return { expandedNodeIdsArray: nextArray2, expandedNodeIds: next2 };
3120
+ }
3121
+ const next = new Set(currentSet);
3122
+ next.add(nodeId);
3123
+ const nextArray = [...next];
3124
+ return { expandedNodeIdsArray: nextArray, expandedNodeIds: next };
3125
+ }),
3126
+ clearExpandedNodes: () => set({ expandedNodeIdsArray: [], expandedNodeIds: /* @__PURE__ */ new Set() })
2603
3127
  }),
2604
3128
  {
2605
3129
  name: "command-view-store",
@@ -2607,9 +3131,29 @@ var useCommandViewStore = create()(
2607
3131
  showIntegrations: s.showIntegrations,
2608
3132
  fitViewOnFilter: s.fitViewOnFilter,
2609
3133
  visualizationMode: s.visualizationMode,
3134
+ lastUsedVisualizationMode: s.lastUsedVisualizationMode,
2610
3135
  resourcesHidden: s.resourcesHidden,
2611
- diagnosticsHidden: s.diagnosticsHidden
2612
- })
3136
+ diagnosticsHidden: s.diagnosticsHidden,
3137
+ lastOpenBottomTab: s.lastOpenBottomTab,
3138
+ expandedClusterDomains: s.expandedClusterDomains
3139
+ }),
3140
+ // Guard against stale localStorage with an invalid mode name (e.g. old 'overview' → 'explore' rename).
3141
+ merge: (persisted, current) => {
3142
+ const stored = persisted;
3143
+ const storedMode = stored.visualizationMode;
3144
+ const storedLastUsed = stored.lastUsedVisualizationMode;
3145
+ const migratedMode = storedMode === "overview" ? "explore" : storedMode;
3146
+ const migratedLastUsed = storedLastUsed === "overview" ? "explore" : storedLastUsed;
3147
+ const { expandedZonesArray: _dropped, ...restStored } = stored;
3148
+ return {
3149
+ ...current,
3150
+ ...restStored,
3151
+ // If the stored mode is unrecognized (stale rename), fall back to new-session default.
3152
+ visualizationMode: migratedMode !== void 0 && VALID_VISUALIZATION_MODES.has(migratedMode) ? migratedMode : NEW_SESSION_VISUALIZATION_MODE,
3153
+ // Validate lastUsedVisualizationMode the same way.
3154
+ lastUsedVisualizationMode: migratedLastUsed !== void 0 && migratedLastUsed !== null && VALID_VISUALIZATION_MODES.has(migratedLastUsed) ? migratedLastUsed : current.lastUsedVisualizationMode
3155
+ };
3156
+ }
2613
3157
  }
2614
3158
  )
2615
3159
  );
@@ -4479,6 +5023,116 @@ function useDeleteRequest() {
4479
5023
  }
4480
5024
  });
4481
5025
  }
5026
+
5027
+ // src/hooks/clients/queryKeys.ts
5028
+ var clientsKeys = {
5029
+ all: ["clients"],
5030
+ lists: () => [...clientsKeys.all, "list"],
5031
+ list: (organizationId, filters) => [...clientsKeys.lists(), organizationId, filters],
5032
+ statuses: () => [...clientsKeys.all, "status"],
5033
+ status: (organizationId) => [...clientsKeys.statuses(), organizationId],
5034
+ details: () => [...clientsKeys.all, "detail"],
5035
+ detail: (organizationId, id) => [...clientsKeys.details(), organizationId, id]
5036
+ };
5037
+ function useClients(filters = {}) {
5038
+ const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
5039
+ return useQuery({
5040
+ queryKey: clientsKeys.list(workOSOrganizationId ?? void 0, filters),
5041
+ queryFn: async () => {
5042
+ const { status, search, limit, offset } = filters;
5043
+ const params = new URLSearchParams();
5044
+ if (status) params.set("status", status);
5045
+ if (search) params.set("search", search);
5046
+ if (limit !== void 0) params.set("limit", String(limit));
5047
+ if (offset !== void 0) params.set("offset", String(offset));
5048
+ const query = params.toString();
5049
+ return apiRequest(`/clients${query ? "?" + query : ""}`);
5050
+ },
5051
+ enabled: isReady
5052
+ });
5053
+ }
5054
+ function useClientStatus() {
5055
+ const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
5056
+ return useQuery({
5057
+ queryKey: clientsKeys.status(workOSOrganizationId ?? void 0),
5058
+ queryFn: async () => {
5059
+ return apiRequest("/clients/status");
5060
+ },
5061
+ enabled: isReady
5062
+ });
5063
+ }
5064
+ function useClient(clientId) {
5065
+ const { apiRequest, isReady, workOSOrganizationId } = useElevasisServices();
5066
+ return useQuery({
5067
+ queryKey: clientsKeys.detail(workOSOrganizationId ?? void 0, clientId),
5068
+ queryFn: async () => {
5069
+ return apiRequest(`/clients/${clientId}`);
5070
+ },
5071
+ enabled: isReady && !!clientId
5072
+ });
5073
+ }
5074
+ function useCreateClient() {
5075
+ const { apiRequest } = useElevasisServices();
5076
+ const queryClient = useQueryClient();
5077
+ return useMutation({
5078
+ mutationFn: async (data) => {
5079
+ return apiRequest("/clients", {
5080
+ method: "POST",
5081
+ body: JSON.stringify(data)
5082
+ });
5083
+ },
5084
+ onSuccess: () => {
5085
+ void queryClient.invalidateQueries({ queryKey: clientsKeys.lists() });
5086
+ void queryClient.invalidateQueries({ queryKey: clientsKeys.statuses() });
5087
+ },
5088
+ onError: (error) => {
5089
+ console.error("Failed to create client:", error);
5090
+ showApiErrorNotification(error);
5091
+ }
5092
+ });
5093
+ }
5094
+ function useUpdateClient() {
5095
+ const { apiRequest, workOSOrganizationId } = useElevasisServices();
5096
+ const queryClient = useQueryClient();
5097
+ return useMutation({
5098
+ mutationFn: async ({ clientId, updates }) => {
5099
+ return apiRequest(`/clients/${clientId}`, {
5100
+ method: "PATCH",
5101
+ body: JSON.stringify(updates)
5102
+ });
5103
+ },
5104
+ onSuccess: (_data, { clientId }) => {
5105
+ void queryClient.invalidateQueries({ queryKey: clientsKeys.lists() });
5106
+ void queryClient.invalidateQueries({
5107
+ queryKey: clientsKeys.detail(workOSOrganizationId ?? void 0, clientId)
5108
+ });
5109
+ void queryClient.invalidateQueries({ queryKey: clientsKeys.statuses() });
5110
+ },
5111
+ onError: (error) => {
5112
+ console.error("Failed to update client:", error);
5113
+ showApiErrorNotification(error);
5114
+ }
5115
+ });
5116
+ }
5117
+ function useDeleteClient() {
5118
+ const { apiRequest } = useElevasisServices();
5119
+ const queryClient = useQueryClient();
5120
+ return useMutation({
5121
+ mutationFn: async (clientId) => {
5122
+ await apiRequest(`/clients/${clientId}`, {
5123
+ method: "DELETE"
5124
+ });
5125
+ },
5126
+ onSuccess: () => {
5127
+ void queryClient.invalidateQueries({ queryKey: clientsKeys.lists() });
5128
+ void queryClient.invalidateQueries({ queryKey: clientsKeys.statuses() });
5129
+ },
5130
+ onError: (error) => {
5131
+ console.error("Failed to delete client:", error);
5132
+ showApiErrorNotification(error);
5133
+ }
5134
+ });
5135
+ }
4482
5136
  function useResourceErrors({ resourceId, timeRange, hasFailures }) {
4483
5137
  const { apiRequest, workOSOrganizationId, isReady } = useElevasisServices();
4484
5138
  return useQuery({
@@ -5206,4 +5860,4 @@ function useProjectRealtime(projectId) {
5206
5860
  });
5207
5861
  }
5208
5862
 
5209
- export { ApiKeyService, COMMAND_VIEW_VISUALIZATION_MODES, CredentialSchemas, CredentialService, DeploymentService, MEMBERSHIP_STATUS_COLORS, OperationsService, OrganizationMembershipService, WebhookEndpointService, acquisitionListKeys, collectResourceFilterFacets, companyKeys, contactKeys, dealKeys, dealNoteKeys, dealTaskKeys, executionsKeys, filterByDomainFilters, getCommandViewGraphPositions, getResourceFilterFacetIds, isSessionCapable, labelResourceFilterFacet, leadGenArtifactKeys, leadGenListCompanyKeys, leadGenListMemberKeys, operationsKeys, projectActivityKeys, requestsKeys, scheduleKeys, sessionsKeys, sortData, transformMembershipToTableRow, useActivateDeployment, useActivities, useActivitiesRealtime, useActivityFilters, useActivityTrend, useAddCompaniesToList, useAddContactsToList, useArchiveSession, useArchivedLogs, useArtifacts, useAssignRole, useBatchDelete, useBatchTelemetry, useBatchedResourcesHealth, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCheckpointTasks, useCommandQueue, useCommandQueueTotals, useCommandViewData, useCommandViewDomainFilters, useCommandViewStats, useCommandViewStore, useCompanies, useCompany, useCompanyFacets, useCompleteDealTask, useContact, useContacts, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateApiKey, useCreateArtifact, useCreateCompany, useCreateContact, useCreateCredential, useCreateDealNote, useCreateDealTask, useCreateList, useCreateOrgRole, useCreateSchedule, useCreateSession, useCreateWebhookEndpoint, useCredentials, useDashboardMetrics, useDeactivateDeployment, useDeactivateMembership, useDealDetail, useDealNotes, useDealTasks, useDealTasksDue, useDeals, useDealsLookup, useDealsSummary, useDeleteApiKey, useDeleteCompanies, useDeleteContacts, useDeleteCredential, useDeleteDeal, useDeleteDeployment, useDeleteExecution, useDeleteList, useDeleteOrgRole, useDeleteRequest, useDeleteSchedule, useDeleteSession, useDeleteTask, useDeleteWebhookEndpoint, useDeriveActions, useEffectivePermissions, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorNotification, useExecuteAction, useExecuteAsync, useExecuteResource, useExecution, useExecutionHealth, useExecutionLogSSE, useExecutionLogs, useExecutionLogsFilters, useExecutionPanelState, useExecutionSSE, useExecutions, useGetExecutionHistory, useGetSchedule, useHasPermission, useInFlightExecutions, useList, useListApiKeys, useListDeployments, useListExecutions, useListMember, useListMembers, useListProgress, useListRecords, useListSchedules, useListWebhookEndpoints, useLists, useListsTelemetry, useMarkAllAsRead, useMarkAsRead, useNotificationCount, useNotifications, useOrgRoles, useOrganizationMembers, useOrganizationPermissions, usePaginationState, usePatchTask, usePauseSchedule, usePermissionCatalog, useProjectActivities, useProjectRealtime, useReactivateMembership, useRecentExecutionsByResource, useRemoveCompaniesFromList, useRequest, useRequestsList, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResourceDefinition, useResourceErrors, useResourceExecutions, useResourceSearch, useResources, useResourcesDomainFilters, useResourcesHealth, useResumeSchedule, useRetryExecution, useRevokeRole, useSSEConnection, useScheduledTasks, useSession, useSessionExecution, useSessionExecutions, useSessionMessages, useSessionWebSocket, useSessions, useSortedData, useStatusFilter, useSubmitAction, useSuccessNotification, useTableSelection, useTableSort, useTestNotification, useTimeRangeDates, useTopFailingResources, useTransitionItem, useTransitionListCompany, useTransitionListMember, useTransitionState, useUnresolveError, useUnresolvedErrors, useUpdateAnchor, useUpdateApiKey, useUpdateCompany, useUpdateContact, useUpdateCredential, useUpdateList, useUpdateListConfig, useUpdateListStatus, useUpdateMemberConfig, useUpdateOrgRole, useUpdateRequestStatus, useUpdateSchedule, useUpdateWebhookEndpoint, useUserMemberships, useVerifyCredential, useVisibleResources, useWarningNotification, useWorkflowExecution };
5863
+ export { ApiKeyService, COMMAND_VIEW_VISUALIZATION_MODES, CredentialSchemas, CredentialService, DEFAULT_CLUSTER_PARAMETERS, DEFAULT_FOCUS_PARAMETERS, DEFAULT_FORCE_PARAMETERS, DEFAULT_NETWORK_PARAMETERS, DEFAULT_SWIMLANE_PARAMETERS, DOMAIN_ZONE_TINT_COLOR, DeploymentService, EXPLORE_OM_ROOT_ID, MEMBERSHIP_STATUS_COLORS, OperationsService, OrganizationMembershipService, WebhookEndpointService, acquisitionListKeys, buildCommandViewGraphIndex, clientsKeys, collectResourceFilterFacets, companyKeys, contactKeys, dealKeys, dealNoteKeys, dealTaskKeys, executionsKeys, exploreNodeHasChildren, filterByDomainFilters, getCommandViewClusterZoneLabels, getCommandViewGraphPositions, getCommandViewNodeDomain, getCommandViewSwimlaneLaneLabels, getDefaultParameters, getExploreFocusSet, getExploreProjection, getNextExpandedSetForToggle, getRadialFromAnchorProjection, getResourceFilterFacetIds, isSessionCapable, labelResourceFilterFacet, leadGenArtifactKeys, leadGenListCompanyKeys, leadGenListMemberKeys, operationsKeys, projectActivityKeys, requestsKeys, scheduleKeys, sessionsKeys, sortData, transformMembershipToTableRow, useActivateDeployment, useActivities, useActivitiesRealtime, useActivityFilters, useActivityTrend, useAddCompaniesToList, useAddContactsToList, useArchiveSession, useArchivedLogs, useArtifacts, useAssignRole, useBatchDelete, useBatchTelemetry, useBatchedResourcesHealth, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCheckpointTasks, useClient, useClientStatus, useClients, useCommandQueue, useCommandQueueTotals, useCommandViewData, useCommandViewDomainFilters, useCommandViewStats, useCommandViewStore, useCompanies, useCompany, useCompanyFacets, useCompleteDealTask, useContact, useContacts, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateApiKey, useCreateArtifact, useCreateClient, useCreateCompany, useCreateContact, useCreateCredential, useCreateDealNote, useCreateDealTask, useCreateList, useCreateOrgRole, useCreateSchedule, useCreateSession, useCreateWebhookEndpoint, useCredentials, useDashboardMetrics, useDeactivateDeployment, useDeactivateMembership, useDealDetail, useDealNotes, useDealTasks, useDealTasksDue, useDeals, useDealsLookup, useDealsSummary, useDeleteApiKey, useDeleteClient, useDeleteCompanies, useDeleteContacts, useDeleteCredential, useDeleteDeal, useDeleteDeployment, useDeleteExecution, useDeleteList, useDeleteOrgRole, useDeleteRequest, useDeleteSchedule, useDeleteSession, useDeleteTask, useDeleteWebhookEndpoint, useDeriveActions, useEffectivePermissions, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorNotification, useExecuteAction, useExecuteAsync, useExecuteResource, useExecution, useExecutionHealth, useExecutionLogSSE, useExecutionLogs, useExecutionLogsFilters, useExecutionPanelState, useExecutionSSE, useExecutions, useGetExecutionHistory, useGetSchedule, useHasPermission, useInFlightExecutions, useList, useListApiKeys, useListDeployments, useListExecutions, useListMember, useListMembers, useListProgress, useListRecords, useListSchedules, useListWebhookEndpoints, useLists, useListsTelemetry, useMarkAllAsRead, useMarkAsRead, useNotificationCount, useNotifications, useOrgRoles, useOrganizationMembers, useOrganizationPermissions, usePaginationState, usePatchTask, usePauseSchedule, usePermissionCatalog, useProjectActivities, useProjectRealtime, useReactivateMembership, useRecentExecutionsByResource, useRemoveCompaniesFromList, useRequest, useRequestsList, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResourceDefinition, useResourceErrors, useResourceExecutions, useResourceSearch, useResources, useResourcesDomainFilters, useResourcesHealth, useResumeSchedule, useRetryExecution, useRevokeRole, useSSEConnection, useScheduledTasks, useSession, useSessionExecution, useSessionExecutions, useSessionMessages, useSessionWebSocket, useSessions, useSortedData, useStatusFilter, useSubmitAction, useSuccessNotification, useTableSelection, useTableSort, useTestNotification, useTimeRangeDates, useTopFailingResources, useTransitionItem, useTransitionListCompany, useTransitionListMember, useTransitionState, useUnresolveError, useUnresolvedErrors, useUpdateAnchor, useUpdateApiKey, useUpdateClient, useUpdateCompany, useUpdateContact, useUpdateCredential, useUpdateList, useUpdateListConfig, useUpdateListStatus, useUpdateMemberConfig, useUpdateOrgRole, useUpdateRequestStatus, useUpdateSchedule, useUpdateWebhookEndpoint, useUserMemberships, useVerifyCredential, useVisibleResources, useWarningNotification, useWorkflowExecution };