@wrongstack/webui 1.0.26 → 1.0.27

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 (86) hide show
  1. package/dist/assets/{AgentRosterView-udJ14GYq.js → AgentRosterView-BJ-1SQOm.js} +1 -1
  2. package/dist/assets/{AnalyticsDashboard-DwF-0cUA.js → AnalyticsDashboard-FYrD8BFQ.js} +1 -1
  3. package/dist/assets/{AudienceMemoryPanel-DpBGeZv_.js → AudienceMemoryPanel-BghMZicW.js} +1 -1
  4. package/dist/assets/{ChangesView-BfM0T_aS.js → ChangesView-B3uQtZGR.js} +1 -1
  5. package/dist/assets/{ChimeraReviewsView-Q_5C4DU1.js → ChimeraReviewsView-CBRbTHGM.js} +1 -1
  6. package/dist/assets/{ChronicleDashboard-D6LnZzhy.js → ChronicleDashboard-B1E-_u64.js} +1 -1
  7. package/dist/assets/{CodeEditor-DonrWH9u.js → CodeEditor-CbcWuMGV.js} +1 -1
  8. package/dist/assets/{CodeMap-Dxtc378S.js → CodeMap-WOfveRTG.js} +1 -1
  9. package/dist/assets/{CronJobsPanel-Cn2PQO_p.js → CronJobsPanel-DOFA5WVq.js} +1 -1
  10. package/dist/assets/{DeadCodeScanPanel-Mc5py-kJ.js → DeadCodeScanPanel-4ToPZX7e.js} +1 -1
  11. package/dist/assets/{DebugDashboard-D0LRcT4J.js → DebugDashboard-DAsNHSpG.js} +1 -1
  12. package/dist/assets/{DesignGalleryView-DAD-wRUc.js → DesignGalleryView-Dd5YnKhs.js} +1 -1
  13. package/dist/assets/{GoalView-CqeSw0tK.js → GoalView-BaDGAXuQ.js} +1 -1
  14. package/dist/assets/{KanbanView-V-bkFftp.js → KanbanView-CG8bVhpR.js} +1 -1
  15. package/dist/assets/{MailboxDetailView-CTEjap3r.js → MailboxDetailView-COxz-eEJ.js} +1 -1
  16. package/dist/assets/{MemoryDrawer-RCduY0FV.js → MemoryDrawer-4lDXuHCi.js} +1 -1
  17. package/dist/assets/{MemoryManager-B-p6-Bic.js → MemoryManager-DQlnpch1.js} +1 -1
  18. package/dist/assets/{ProcessMonitor-B9tpPo4r.js → ProcessMonitor-BUjfYqG3.js} +1 -1
  19. package/dist/assets/{PromptJournalView-DVNqlac9.js → PromptJournalView-o2dmPrwg.js} +1 -1
  20. package/dist/assets/{ProviderTestView-mmfpnAbZ.js → ProviderTestView-5wNbI46L.js} +1 -1
  21. package/dist/assets/{QueuePanel-BB9qozjm.js → QueuePanel-DP9D99DX.js} +1 -1
  22. package/dist/assets/{RefreshDebugView-CCCWzq29.js → RefreshDebugView-CB7_a_TI.js} +1 -1
  23. package/dist/assets/{RepositoryHistoryView-RQVRkkUU.js → RepositoryHistoryView-C_zpYLY6.js} +1 -1
  24. package/dist/assets/{RequirementIntakeView-D_JRhgzW.js → RequirementIntakeView-CahKEHJn.js} +1 -1
  25. package/dist/assets/{SageTabs--k2hQTvl.js → SageTabs-5Z2PR11S.js} +2 -2
  26. package/dist/assets/{SddFlowGraph-DKrrRXKy.js → SddFlowGraph-DSoWnlIt.js} +1 -1
  27. package/dist/assets/{SddHub-B5XO56oY.js → SddHub-0q2EpwYz.js} +2 -2
  28. package/dist/assets/{SessionInspectView-j3VJwXNi.js → SessionInspectView-CbDFR_tP.js} +1 -1
  29. package/dist/assets/{SessionList-CCVHBseu.js → SessionList-DhQK7JnP.js} +1 -1
  30. package/dist/assets/{SessionsDashboard-DsM7sXQw.js → SessionsDashboard-DNLDczSd.js} +1 -1
  31. package/dist/assets/{SetupScreen-DeuR8Y8S.js → SetupScreen-C-hpHQQ9.js} +1 -1
  32. package/dist/assets/{SkillDetailView-BeZyGIpW.js → SkillDetailView-Bir-Kdm4.js} +1 -1
  33. package/dist/assets/TechStackView-CJ3Abnwg.js +2 -0
  34. package/dist/assets/{TerminalPanel-BVJ5w-5R.js → TerminalPanel-8WHNTeQK.js} +1 -1
  35. package/dist/assets/{activity-BS2aW_NN.js → activity-B9WjS_Cz.js} +1 -1
  36. package/dist/assets/{activity-Cd0qM2Hx.js → activity-BB7AHL0U.js} +1 -1
  37. package/dist/assets/{activity-CR2KFruY.js → activity-Bd0XmdqX.js} +1 -1
  38. package/dist/assets/{activity-fI3Jy_jD.js → activity-BvmJte2K.js} +1 -1
  39. package/dist/assets/{activity-bBAOetvE.js → activity-DOEbDWqw.js} +1 -1
  40. package/dist/assets/{activity-DyXRoY2s.js → activity-beTxIN7V.js} +1 -1
  41. package/dist/assets/{activity-t6fUmVjo.js → activity-t-0KDhv5.js} +1 -1
  42. package/dist/assets/{chat-store-uzGtJfDz.js → chat-store-BMwP_sS0.js} +1 -1
  43. package/dist/assets/{common-DvjdaRhB.js → common-2kj0c3pG.js} +1 -1
  44. package/dist/assets/{common-D0QL7rwb.js → common-BAvh8XBp.js} +1 -1
  45. package/dist/assets/{common-opV6EoLd.js → common-CKwGvEQD.js} +1 -1
  46. package/dist/assets/{common-DJRPtYAt.js → common-CUd7l34J.js} +1 -1
  47. package/dist/assets/{common-BtyQBZBN.js → common-DmS4Wp1i.js} +1 -1
  48. package/dist/assets/common-PC103akE.js +1 -0
  49. package/dist/assets/{common-Bjl7V12m.js → common-zatZ4s-Z.js} +1 -1
  50. package/dist/assets/config-store-Cb4iyhGv.js +21 -0
  51. package/dist/assets/i18n-CzTjKT4L.js +3 -0
  52. package/dist/assets/{index-B4ELbNoz.js → index-Ci22AODp.js} +82 -81
  53. package/dist/assets/index-DfU9PQg8.css +1 -0
  54. package/dist/assets/{roster-ws-szSqUkqP.js → roster-ws-D-DCMdrg.js} +1 -1
  55. package/dist/assets/{settings-ClDQ01ie.js → settings-7W0ofid0.js} +1 -1
  56. package/dist/assets/{settings-BfNJfO4z.js → settings-BAArGYGW.js} +1 -1
  57. package/dist/assets/{settings-BMHZcBqe.js → settings-Btyr_M2v.js} +1 -1
  58. package/dist/assets/{settings-Dl_QM2QZ.js → settings-BwL_DVmc.js} +1 -1
  59. package/dist/assets/{settings-Da3EIcna.js → settings-C7ybAkyi.js} +1 -1
  60. package/dist/assets/{settings-BQ5J8WXE.js → settings-CgtL8eYb.js} +1 -1
  61. package/dist/assets/{settings-DD31lC4f.js → settings-D57Fd8Z8.js} +1 -1
  62. package/dist/assets/{stores-Cx52UOxM.js → stores-Svlibwo5.js} +2 -2
  63. package/dist/components/MessageBubble/FailedRunContinue.d.ts +7 -3
  64. package/dist/components/TechStackView/AnalyzeControls.d.ts +25 -0
  65. package/dist/components/TechStackView/RemediationTab.d.ts +20 -0
  66. package/dist/components/TechStackView/TrendsTab.d.ts +17 -0
  67. package/dist/hooks/ws-handlers/chat-handlers.d.ts +12 -0
  68. package/dist/hooks/ws-handlers/mcp-status-handlers.d.ts +6 -0
  69. package/dist/hooks/ws-handlers/techstack-handlers.d.ts +7 -0
  70. package/dist/index.html +7 -7
  71. package/dist/index.js +2639 -1487
  72. package/dist/stores/index.d.ts +1 -1
  73. package/dist/stores/local-prefs-defaults.d.ts +2 -1
  74. package/dist/stores/provider-quota-store.d.ts +5 -0
  75. package/dist/stores/techstack-store.d.ts +140 -1
  76. package/dist/stores/types.d.ts +5 -0
  77. package/dist/types/client-message.d.ts +3 -3
  78. package/dist/types/jev.d.ts +2 -0
  79. package/dist/types/server-message-mcp.d.ts +2 -0
  80. package/dist/types/server-message-system.d.ts +11 -0
  81. package/package.json +10 -9
  82. package/dist/assets/TechStackView-CpSMRQE0.js +0 -2
  83. package/dist/assets/common-DPPTV3yw.js +0 -1
  84. package/dist/assets/config-store-P5_updTQ.js +0 -21
  85. package/dist/assets/i18n-t7rIS4DB.js +0 -3
  86. package/dist/assets/index-qdrakcnP.css +0 -1
@@ -48,7 +48,7 @@ export { memorySessionSnapshots, useSessionStore } from './session-store.js';
48
48
  export { isTabBusy, MAX_OPEN_TABS, slotOf, summarizeTab, type TabSummary, useSessionTabStore, } from './session-tab-store.js';
49
49
  export { type SideEffectEntry, useSideEffectStore } from './side-effect-store.js';
50
50
  export { type BoardTaskItem, type BoardTaskStatus, type SpecColumn, type SpecDetail, type SpecListItem, useSpecsStore, } from './specs-store.js';
51
- export { type TechStackCoverage, type TechStackDependency, type TechStackEvidence, type TechStackFinding, type TechStackFindingAction, type TechStackFindingSeverity, type TechStackFindingType, type TechStackJobKind, type TechStackJobStatus, type TechStackJobView, type TechStackProgress, type TechStackSnapshot, type TechStackWorkspace, useTechStackStore, } from './techstack-store.js';
51
+ export { type TechStackAnalyzeDepth, type TechStackApplyPlanResult, type TechStackCoverage, type TechStackDependency, type TechStackEvidence, type TechStackFinding, type TechStackFindingAction, type TechStackFindingSeverity, type TechStackFindingType, type TechStackJobKind, type TechStackJobStatus, type TechStackJobView, type TechStackModelInfo, type TechStackProgress, type TechStackSnapshot, type TechStackTrendPoint, type TechStackTrendReport, type TechStackUpgradePlan, type TechStackUpgradePlanItem, type TechStackWorkspace, useTechStackStore, } from './techstack-store.js';
52
52
  export { bucketSuccessRatio, LEADER_AGENT_KEY, sessionInFlight, type ToolStatsBucket, type ToolStatsDelegation, type ToolStatsSession, useToolStatsStore, } from './tool-stats-store.js';
53
53
  export type { AgentTranscriptEntry, AgentTranscriptKind, BrainDecisionData, ChatMessage, ChatMessageAttachment, CouncilDecisionData, CouncilSeatVote, FleetTimelineEvent, SessionHistoryEntry, SessionInfo, SubagentEvent, SubagentView, ToolExecution, } from './types.js';
54
54
  export type { Activity, DockSection, InspectorTab, WorkDashboardTab } from './ui-store.js';
@@ -162,6 +162,7 @@ export interface LocalPrefs {
162
162
  featureMemory: boolean;
163
163
  featureSkills: boolean;
164
164
  featureModelsRegistry: boolean;
165
+ featureToolCoach: boolean;
165
166
  indexOnStart: boolean;
166
167
  /** Per-plugin enabled/disabled state. Keys are plugin names (e.g. "wstack-chimera"). */
167
168
  pluginsEnabled: Record<string, boolean>;
@@ -269,7 +270,7 @@ export interface LocalPrefs {
269
270
  chimeraModel: string;
270
271
  /** Maximum number of files considered per review (default 15). */
271
272
  chimeraMaxFiles: number;
272
- /** Master enable for `wstack-auto-review`. Defaults to false (matches plugin: `cfg.enabled === true`). */
273
+ /** Master enable for `wstack-auto-review`. Defaults to true (matches plugin: `cfg.enabled !== false`). */
273
274
  autoReviewEnabled: boolean;
274
275
  /** Override provider id for the review subagent. Empty = resolve via fallbackProfile/effective chain. */
275
276
  autoReviewProvider: string;
@@ -24,6 +24,11 @@ export interface QuotaWindow {
24
24
  windowMinutes?: number | undefined;
25
25
  /** Absolute reset time in epoch **seconds**. */
26
26
  resetsAt?: number | undefined;
27
+ /**
28
+ * When the last hour's pace fills the window (epoch **seconds**). Set by the
29
+ * server only when that lands before `resetsAt`.
30
+ */
31
+ exhaustsAt?: number | undefined;
27
32
  }
28
33
  export interface QuotaCredits {
29
34
  hasCredits: boolean;
@@ -1,6 +1,12 @@
1
1
  export type TechStackCoverage = 'full' | 'partial' | 'unsupported';
2
2
  export type TechStackJobKind = 'inventory' | 'analyze';
3
3
  export type TechStackJobStatus = 'idle' | 'queued' | 'discovering' | 'inventorying' | 'enriching' | 'researching' | 'synthesizing' | 'completed' | 'failed' | 'cancelled';
4
+ /**
5
+ * Pipeline depth the user picked for the next `analyze` run.
6
+ * Mirrors `AnalyzeDepth` on the engine; defaults to `'full'` for parity with
7
+ * the pre-feature one-click Analyze button.
8
+ */
9
+ export type TechStackAnalyzeDepth = 'inventory' | 'enrich' | 'full';
4
10
  export interface TechStackEvidence {
5
11
  readonly kind: string;
6
12
  readonly source: string;
@@ -62,6 +68,96 @@ export interface TechStackFinding {
62
68
  readonly breakingRisk?: string | undefined;
63
69
  readonly evidence: readonly TechStackEvidence[];
64
70
  }
71
+ /**
72
+ * One item in a remediation upgrade plan.
73
+ *
74
+ * Mirrors `UpgradePlanItem` server-side (`packages/techstack/src/remediation.ts`).
75
+ * `executable` is true when the engine can drive the change through the
76
+ * permission-gated `language_package` tool — false for ecosystems that need
77
+ * a manual command (ruby, dart, maven, gradle, swift, elixir, c/cpp). The UI
78
+ * uses this to render an "Apply" button vs. a "Copy command" card.
79
+ */
80
+ export interface TechStackUpgradePlanItem {
81
+ readonly dependencyName: string;
82
+ readonly ecosystem: string;
83
+ readonly workspaceId: string;
84
+ readonly currentVersion?: string | undefined;
85
+ readonly targetVersion?: string | undefined;
86
+ readonly action: TechStackFindingAction;
87
+ readonly severity: TechStackFindingSeverity;
88
+ readonly rationale: string;
89
+ readonly breakingRisk?: string | undefined;
90
+ readonly suggestedCommand?: string | undefined;
91
+ readonly executable: boolean;
92
+ }
93
+ export interface TechStackUpgradePlan {
94
+ readonly snapshotId: string;
95
+ readonly generatedAt: string;
96
+ readonly warning: string;
97
+ readonly summary: {
98
+ readonly total: number;
99
+ readonly patch: number;
100
+ readonly minor: number;
101
+ readonly major: number;
102
+ readonly replace: number;
103
+ readonly remove: number;
104
+ readonly investigate: number;
105
+ };
106
+ readonly items: readonly TechStackUpgradePlanItem[];
107
+ }
108
+ export interface TechStackApplyPlanResult {
109
+ readonly dryRun: boolean;
110
+ readonly items: ReadonlyArray<{
111
+ readonly dependencyName: string;
112
+ readonly status: 'planned' | 'skipped' | 'applied' | 'failed';
113
+ readonly detail?: string | undefined;
114
+ }>;
115
+ }
116
+ /**
117
+ * Single point on the cross-snapshot trend curve.
118
+ *
119
+ * Server-side: `TrendReport` in `packages/techstack/src/trend.ts`. The full
120
+ * report is heavier than what the page needs day-to-day, so the WebUI view
121
+ * uses the lightweight shape surfaced by `GET /api/techstack/trends`.
122
+ */
123
+ export interface TechStackTrendPoint {
124
+ readonly snapshotId: string;
125
+ readonly createdAt: string;
126
+ readonly dependencies: number;
127
+ readonly outdated: number;
128
+ readonly vulnerable: number;
129
+ }
130
+ export interface TechStackTrendReport {
131
+ readonly snapshots: number;
132
+ readonly vulnerabilityHalfLifeMs?: number | undefined;
133
+ readonly points: readonly TechStackTrendPoint[];
134
+ readonly dependencies: ReadonlyArray<{
135
+ readonly key: string;
136
+ readonly name: string;
137
+ readonly ecosystem: string;
138
+ readonly currentVersion?: string | undefined;
139
+ readonly lockedVersionAgeMs: number;
140
+ readonly versionChanges: number;
141
+ }>;
142
+ }
143
+ /**
144
+ * Lightweight description of the LLM available for AI-assisted runs.
145
+ * Mirrors the `GET /api/techstack/models` response. When `available` is false
146
+ * the model picker is disabled — there is no point letting the user pick a
147
+ * model when none can answer.
148
+ */
149
+ export interface TechStackModelInfo {
150
+ readonly available: boolean;
151
+ readonly provider: string | null;
152
+ readonly model: string | null;
153
+ readonly candidates: ReadonlyArray<{
154
+ readonly id: string;
155
+ }>;
156
+ readonly capabilities: {
157
+ readonly structuredOutput: boolean;
158
+ readonly jsonMode: boolean;
159
+ };
160
+ }
65
161
  export interface TechStackSnapshot {
66
162
  readonly id: string;
67
163
  readonly projectId: string;
@@ -85,6 +181,10 @@ export interface TechStackJobView {
85
181
  readonly status: TechStackJobStatus;
86
182
  readonly progress: TechStackProgress | null;
87
183
  readonly error: string | null;
184
+ /** Pipeline depth the job will run / is running. */
185
+ readonly depth?: TechStackAnalyzeDepth;
186
+ /** Model id the user picked for the LLM research stage. */
187
+ readonly model?: string;
88
188
  }
89
189
  interface TechStackState {
90
190
  snapshot: TechStackSnapshot | null;
@@ -94,15 +194,54 @@ interface TechStackState {
94
194
  activeJob: TechStackJobView | null;
95
195
  lastWorkspaceId: string | null;
96
196
  reportId: string | null;
197
+ /** Next analyze options. Persisted in-memory so a refresh keeps them. */
198
+ selectedDepth: TechStackAnalyzeDepth;
199
+ selectedModel: string | null;
200
+ /** `null` until the user opens the TechStack page (the page lazy-loads the list). */
201
+ availableModels: TechStackModelInfo | null;
202
+ /** Plan from `GET /api/techstack/remediation`. `null` when not yet fetched. */
203
+ remediationPlan: TechStackUpgradePlan | null;
204
+ remediationPreview: TechStackApplyPlanResult | null;
205
+ remediationLoading: boolean;
206
+ remediationError: string | null;
207
+ /** Cross-snapshot trend report. `null` when not yet fetched. */
208
+ trend: TechStackTrendReport | null;
209
+ trendLoading: boolean;
210
+ trendError: string | null;
211
+ /** Streaming deep-dive partials, keyed by dependency id. */
212
+ deepDivePartial: {
213
+ dependencyId: string;
214
+ status: 'researching';
215
+ completed: number;
216
+ total: number;
217
+ } | null;
97
218
  setSnapshot: (snapshot: TechStackSnapshot | null, stale?: boolean) => void;
98
219
  setLoading: (loading: boolean) => void;
99
220
  setError: (error: string | null) => void;
100
- jobStarted: (jobId: string, kind: TechStackJobKind) => void;
221
+ jobStarted: (jobId: string, kind: TechStackJobKind, options?: {
222
+ depth?: TechStackAnalyzeDepth;
223
+ model?: string;
224
+ }) => void;
101
225
  jobProgress: (jobId: string, progress: TechStackProgress) => void;
102
226
  jobFailed: (jobId: string, error: string) => void;
103
227
  jobCancelled: (jobId: string) => void;
104
228
  workspaceCompleted: (workspaceId: string) => void;
105
229
  reportReady: (reportId: string) => void;
230
+ setSelectedDepth: (depth: TechStackAnalyzeDepth) => void;
231
+ setSelectedModel: (model: string | null) => void;
232
+ setAvailableModels: (models: TechStackModelInfo) => void;
233
+ setRemediation: (plan: TechStackUpgradePlan, preview: TechStackApplyPlanResult) => void;
234
+ setRemediationLoading: (loading: boolean) => void;
235
+ setRemediationError: (error: string | null) => void;
236
+ setTrend: (trend: TechStackTrendReport) => void;
237
+ setTrendLoading: (loading: boolean) => void;
238
+ setTrendError: (error: string | null) => void;
239
+ setDeepDivePartial: (partial: {
240
+ dependencyId: string;
241
+ status: 'researching';
242
+ completed: number;
243
+ total: number;
244
+ } | null) => void;
106
245
  clear: () => void;
107
246
  }
108
247
  export declare const useTechStackStore: import("zustand").UseBoundStore<import("zustand").StoreApi<TechStackState>>;
@@ -95,6 +95,11 @@ export interface ChatMessage {
95
95
  * most recent start and would leave earlier ones stuck on "Running...". */
96
96
  toolUseId?: string | undefined;
97
97
  isError?: boolean | undefined;
98
+ /** Set on the error bubble of a run a provider killed on a retryable
99
+ * failure (overload, dropped connection, 5xx): the one error the Continue
100
+ * countdown may auto-fire for, in `auto` autonomy. Every other error —
101
+ * loop guard, iteration limit, auth, bad request — keeps a manual button. */
102
+ autoContinue?: boolean | undefined;
98
103
  timestamp: number;
99
104
  usage?: Usage | undefined;
100
105
  streaming?: boolean | undefined;
@@ -353,7 +353,7 @@ export type WSClientMessageCore = WSUserMessage | WSPromptQueueClientMessage
353
353
  worktrees?: boolean | undefined;
354
354
  /** Split non-atomic tasks before dispatch (planning-time decompose). */
355
355
  planDecompose?: boolean | undefined;
356
- };
356
+ } & SessionScopedPayload;
357
357
  } | {
358
358
  type: 'sdd.run.from_graph';
359
359
  payload: {
@@ -364,7 +364,7 @@ export type WSClientMessageCore = WSUserMessage | WSPromptQueueClientMessage
364
364
  fallbackModels?: string[] | undefined;
365
365
  worktrees?: boolean | undefined;
366
366
  planDecompose?: boolean | undefined;
367
- };
367
+ } & SessionScopedPayload;
368
368
  } | {
369
369
  type: 'sdd.run.from_spec';
370
370
  payload: {
@@ -375,7 +375,7 @@ export type WSClientMessageCore = WSUserMessage | WSPromptQueueClientMessage
375
375
  fallbackModels?: string[] | undefined;
376
376
  worktrees?: boolean | undefined;
377
377
  planDecompose?: boolean | undefined;
378
- };
378
+ } & SessionScopedPayload;
379
379
  } | {
380
380
  type: 'abort';
381
381
  payload: SessionScopedPayload;
@@ -7,6 +7,8 @@ export interface JevSettings {
7
7
  requestTimeoutMs: number;
8
8
  keySource: string;
9
9
  features: Record<string, boolean>;
10
+ /** Full request/response recording in the log file. Never sent to this view. */
11
+ logContent?: boolean;
10
12
  contextStrategy?: 'hybrid' | 'intelligent' | 'selective';
11
13
  recallTurnContext?: boolean;
12
14
  readiness?: Record<string, {
@@ -122,9 +122,11 @@ export type WSMcpServerMessage = {
122
122
  };
123
123
  } | {
124
124
  type: 'mcp.server.disconnected';
125
+ /** `terminal`: connect/reconnect exhausted; only `/mcp restart` brings it back. */
125
126
  payload: {
126
127
  name: string;
127
128
  reason: string;
129
+ terminal?: boolean | undefined;
128
130
  };
129
131
  } | {
130
132
  type: 'mcp.server.error';
@@ -126,6 +126,17 @@ export type WSSystemMiscServerMessage = {
126
126
  payload: {
127
127
  jobId: string;
128
128
  kind: 'inventory' | 'analyze';
129
+ /** Pipeline depth the job will run. Optional for legacy producers. */
130
+ depth?: 'inventory' | 'enrich' | 'full';
131
+ /** Model id the user picked for the LLM research stage. */
132
+ model?: string;
133
+ };
134
+ } | {
135
+ type: 'techstack.research.partial';
136
+ payload: {
137
+ dependencyId: string;
138
+ completed: number;
139
+ total: number;
129
140
  };
130
141
  } | {
131
142
  type: 'techstack.job.progress';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/webui",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "license": "MIT",
5
5
  "description": "Browser-based WebUI for WrongStack — React + Vite frontend. The WebSocket backend lives in the separate @wrongstack/webui-server package (extracted in PR #018b to remove the CLI -> @wrongstack/webui/server cross-package edge).",
6
6
  "keywords": [
@@ -87,12 +87,12 @@
87
87
  "@radix-ui/react-tabs": "^1.1.21",
88
88
  "@tanstack/react-virtual": "^3.14.12",
89
89
  "@uiw/react-textarea-code-editor": "^3.1.1",
90
- "@wrongstack/core": "1.0.26",
91
- "@wrongstack/kanban": "1.0.26",
92
- "@wrongstack/plugins": "1.0.26",
93
- "@wrongstack/providers": "1.0.26",
94
- "@wrongstack/tools": "1.0.26",
95
- "@wrongstack/webui-protocol": "1.0.26",
90
+ "@wrongstack/core": "1.0.27",
91
+ "@wrongstack/kanban": "1.0.27",
92
+ "@wrongstack/plugins": "1.0.27",
93
+ "@wrongstack/providers": "1.0.27",
94
+ "@wrongstack/tools": "1.0.27",
95
+ "@wrongstack/webui-protocol": "1.0.27",
96
96
  "@xterm/addon-fit": "^0.11.0",
97
97
  "@xterm/xterm": "^6.0.0",
98
98
  "@xyflow/react": "^12.11.6",
@@ -128,8 +128,8 @@
128
128
  "@types/ws": "^8.18.1",
129
129
  "@vitejs/plugin-react": "^6.1.1",
130
130
  "@vitest/coverage-v8": "^5.0.0",
131
- "@wrongstack/sdd": "1.0.26",
132
- "@wrongstack/webui-server": "1.0.26",
131
+ "@wrongstack/sdd": "1.0.27",
132
+ "@wrongstack/webui-server": "1.0.27",
133
133
  "jsdom": "^30.0.1",
134
134
  "tailwindcss": "^4.3.3",
135
135
  "typescript": "^7.0.2",
@@ -141,6 +141,7 @@
141
141
  "build": "vite build && node ../../scripts/build-package.mjs",
142
142
  "typecheck": "tsc --noEmit",
143
143
  "test": "vitest run",
144
+ "test:at-mention-browser": "node tests/at-mention-browser-smoke.mjs",
144
145
  "test:user-input-browser": "node tests/user-input-browser-smoke.mjs",
145
146
  "test:page-scroll-browser": "node tests/page-scroll-browser-smoke.mjs",
146
147
  "test:watch": "vitest",
@@ -1,2 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{i as t,t as n}from"./react-core-wiHys0m2.js";import{Dn as r,Fr as i,Gi as a,Ja as o,Mt as s,Oi as c,Q as l,Ri as u,Rn as d,Vn as f,Xi as ee,_i as p,da as m,fa as h,fn as g,go as _,hn as v,ia as y,jt as b,mi as x,mr as te,qa as S,sr as ne,tn as C,uo as w,wo as T,yn as re}from"./vendor-BfBvt432.js";import"./i18n-t7rIS4DB.js";import{t as E}from"./utils-B21Devim.js";import{n as D}from"./stores-Cx52UOxM.js";import{t as O}from"./button-UuKTnoM-.js";import{t as k}from"./input-DMnC2O7-.js";import{A,G as j,K as ie,U as ae,W as oe,k as se}from"./index-B4ELbNoz.js";var M=e(t(),1),N=n(),P={current:{labelKey:`activity:techStackStatus.current`,badge:`border-success/35 bg-success/10 text-success`,dot:`bg-success`,weight:0},update_available_safe:{labelKey:`activity:techStackStatus.update_available_safe`,badge:`border-info/35 bg-info/10 text-info`,dot:`bg-info`,weight:30},update_available_breaking:{labelKey:`activity:techStackStatus.update_available_breaking`,badge:`border-warning/35 bg-warning/10 text-warning`,dot:`bg-warning`,weight:50},vulnerable:{labelKey:`activity:techStackStatus.vulnerable`,badge:`border-destructive/45 bg-destructive/15 text-destructive`,dot:`bg-destructive`,weight:100},deprecated:{labelKey:`activity:techStackStatus.deprecated`,badge:`border-destructive/35 bg-destructive/10 text-destructive`,dot:`bg-destructive`,weight:70},yanked:{labelKey:`activity:techStackStatus.yanked`,badge:`border-destructive/45 bg-destructive/15 text-destructive`,dot:`bg-destructive`,weight:80},unmaintained_suspected:{labelKey:`activity:techStackStatus.unmaintained_suspected`,badge:`border-warning/35 bg-warning/10 text-warning`,dot:`bg-warning`,weight:60},blocked_by_constraints:{labelKey:`activity:techStackStatus.blocked_by_constraints`,badge:`border-warning/30 bg-warning/5 text-warning`,dot:`bg-warning`,weight:40},private_or_unresolved:{labelKey:`activity:techStackStatus.private_or_unresolved`,badge:`border-border/70 bg-muted text-muted-foreground`,dot:`bg-muted-foreground`,weight:10},local_path:{labelKey:`activity:techStackStatus.local_path`,badge:`border-border/70 bg-muted text-muted-foreground`,dot:`bg-muted-foreground`,weight:5},git_dependency:{labelKey:`activity:techStackStatus.git_dependency`,badge:`border-border/70 bg-muted text-muted-foreground`,dot:`bg-muted-foreground`,weight:5},unsupported:{labelKey:`activity:techStackStatus.unsupported`,badge:`border-border/70 bg-muted text-muted-foreground`,dot:`bg-muted-foreground`,weight:5},unknown:{labelKey:`activity:techStackStatus.unknown`,badge:`border-border/70 bg-muted text-muted-foreground`,dot:`bg-muted-foreground`,weight:20}},ce={labelKey:`activity:techStackStatus.unknown`,badge:`border-border/70 bg-muted text-muted-foreground`,dot:`bg-muted-foreground`,weight:0};function F(e){return P[e]??ce}var le={npm:{label:`npm / Node.js`,icon:ne},python:{label:`Python`,icon:h},rust:{label:`Rust`,icon:v},go:{label:`Go`,icon:d},dotnet:{label:`.NET`,icon:te},php:{label:`PHP`,icon:C},dart:{label:`Dart / Flutter`,icon:y},maven:{label:`Maven`,icon:_},gradle:{label:`Gradle`,icon:o},ruby:{label:`Ruby`,icon:x},swift:{label:`Swift`,icon:b},elixir:{label:`Elixir`,icon:C},cpp:{label:`C / C++`,icon:m}},ue={labelKey:`activity:techStackStatus.unknown`};function I(e,t){let n=L(e);return n.labelKey?t(n.labelKey):n.label??e}function L(e){return le[e]??ue}function R({ecosystem:e,className:t=`size-3.5 shrink-0`}){let n=L(e);if(!n.icon)return null;let r=n.icon;return(0,N.jsx)(r,{className:t})}function de(e){return F(e.status).weight>=50}var fe=[`critical`,`high`,`medium`,`low`,`info`],z={critical:{labelKey:`activity:techStackSeverity.critical`,badge:`border-destructive/45 bg-destructive/15 text-destructive`},high:{labelKey:`activity:techStackSeverity.high`,badge:`border-destructive/35 bg-destructive/10 text-destructive`},medium:{labelKey:`activity:techStackSeverity.medium`,badge:`border-warning/35 bg-warning/10 text-warning`},low:{labelKey:`activity:techStackSeverity.low`,badge:`border-info/35 bg-info/10 text-info`},info:{labelKey:`activity:techStackSeverity.info`,badge:`border-border/70 bg-muted text-muted-foreground`}},B={none:`activity:techStackAction.none`,upgrade_patch:`activity:techStackAction.upgrade_patch`,upgrade_minor:`activity:techStackAction.upgrade_minor`,upgrade_major:`activity:techStackAction.upgrade_major`,replace:`activity:techStackAction.replace`,remove:`activity:techStackAction.remove`,investigate:`activity:techStackAction.investigate`},V={full:{labelKey:`activity:techStackCoverage.full`,badge:`border-success/35 bg-success/10 text-success`,noteKey:void 0},partial:{labelKey:`activity:techStackCoverage.partial`,badge:`border-warning/35 bg-warning/10 text-warning`,noteKey:`activity:techStackCoverage.partialNote`},unsupported:{labelKey:`activity:techStackCoverage.unsupported`,badge:`border-border/70 bg-muted text-muted-foreground`,noteKey:`activity:techStackCoverage.unsupportedNote`}};function H(e){return V[e]??V.unsupported}function U(e){if(!e)return null;let t=/^\D*(\d+)/.exec(e);if(!t?.[1])return null;let n=Number(t[1]);return Number.isFinite(n)?n:null}function W(e){let t=U(e.locked??e.installed??e.requested),n=U(e.latestStable);if(t===null||n===null||n<=t)return{majorsBehind:0,label:null};let r=n-t;return{majorsBehind:r,label:`${r} major${r===1?``:`s`} behind`}}function G(e){return e.locked??e.installed??e.requested??null}function K(e){return e.confidence<1}function q({className:e,children:t}){return(0,N.jsx)(`span`,{className:E(`inline-flex shrink-0 items-center gap-1 border px-1.5 py-0.5 text-[10px] font-medium`,e),children:t})}function J({label:e,value:t,hint:n,tone:r=`default`}){let i={default:`text-foreground`,success:`text-success`,warning:`text-warning`,info:`text-info`,destructive:`text-destructive`}[r];return(0,N.jsxs)(`div`,{className:`border border-border/70 bg-card/55 px-3 py-2.5 shadow-[inset_0_1px_0_hsl(var(--foreground)/0.035)]`,children:[(0,N.jsx)(`p`,{className:`text-[9px] font-bold uppercase tracking-[0.16em] text-muted-foreground`,children:e}),(0,N.jsxs)(`div`,{className:`mt-1 flex items-end justify-between gap-2`,children:[(0,N.jsx)(`p`,{className:E(`font-mono text-xl font-bold tabular-nums`,i),children:t}),(0,N.jsx)(`p`,{className:`truncate text-[9px] text-muted-foreground`,children:n})]})]})}function Y(e,t){let n,r,i;if(t===`json`)n=JSON.stringify(e,null,2),r=`techstack.json`,i=`application/json`;else if(t===`spdx`){let t={spdxVersion:`SPDX-2.3`,dataLicense:`CC0-1.0`,SPDXID:`SPDXRef-DOCUMENT`,name:`TechStack-SBOM-${e.projectId}`,documentNamespace:`https://wrongstack.dev/spdx/${e.id}`,creationInfo:{created:e.createdAt,creators:[`Tool: WrongStack TechStack Engine`]},packages:e.dependencies.map((e,t)=>({name:e.name,SPDXID:`SPDXRef-Package-${t}`,versionInfo:e.locked??e.requested,downloadLocation:e.purl?`https://purl.io/${e.purl}`:`NOASSERTION`,licenseConcluded:e.license??`NOASSERTION`}))};n=JSON.stringify(t,null,2),r=`techstack-sbom-spdx.json`,i=`application/json`}else if(t===`cyclonedx`){let t={bomFormat:`CycloneDX`,specVersion:`1.5`,version:1,metadata:{timestamp:e.createdAt,tools:[{name:`WrongStack TechStack Engine`,version:e.adapterVersion}]},components:e.dependencies.map(e=>({type:`library`,name:e.name,version:e.locked??e.requested,...e.purl?{purl:e.purl}:{},...e.license?{licenses:[{license:{id:e.license}}]}:{}}))};n=JSON.stringify(t,null,2),r=`techstack-sbom-cyclonedx.json`,i=`application/json`}else{let t=[`# TechStack Report`,``,`**Generated:** ${e.createdAt}`,`**Target:** ${e.targetRoot}`,`**Fingerprint:** ${e.fingerprint}`,`**Workspaces:** ${e.workspaces.length}`,`**Dependencies:** ${e.dependencies.length}`,`**Findings:** ${e.findings.length}`,`**Coverage:** ${e.coverage}`,``];if(e.workspaces.length>0){t.push(`## Workspaces`,``,`| Workspace | Ecosystem | Coverage | Deps |`,`|---|---|---|---|`);for(let n of e.workspaces){let r=e.dependencies.filter(e=>e.workspaceId===n.id).length;t.push(`| ${n.relativeRoot} | ${n.ecosystem} | ${n.coverage} | ${r} |`)}t.push(``)}if(e.findings.length>0){t.push(`## Findings`,``);let n=new Map;for(let t of e.findings)n.set(t.severity,[...n.get(t.severity)??[],t]);for(let r of[`critical`,`high`,`medium`,`low`,`info`]){let i=n.get(r);if(i?.length){t.push(`### ${r.charAt(0).toUpperCase()+r.slice(1)} (${i.length})`,``);for(let n of i){let r=e.dependencies.find(e=>e.id===n.dependencyId);t.push(`- **${r?.name??n.dependencyId}** — ${n.type} — ${n.rationale}`)}t.push(``)}}}if(e.dependencies.length>0){t.push(`## Dependencies`,``,`| Name | Ecosystem | Status | Locked | Latest |`,`|---|---|---|---|---|`);for(let n of e.dependencies)t.push(`| ${n.name} | ${n.ecosystem} | ${n.status} | ${n.locked??`—`} | ${n.latestStable??`—`} |`)}n=t.join(`
2
- `),r=`techstack-report.md`,i=`text/markdown`}let a=new Blob([n],{type:i}),o=URL.createObjectURL(a),s=document.createElement(`a`);s.href=o,s.download=r,s.click(),URL.revokeObjectURL(o)}function pe({dependency:e,findings:t,deepDive:n,onDeepDive:r,onBack:o,coverage:s}){let{t:c}=T(),l=F(e.status),u=G(e),d=W(e),f=s?H(s).noteKey:void 0;return(0,N.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col`,children:[(0,N.jsxs)(`header`,{className:`shrink-0 border-b border-border/70 bg-card/45 p-3`,children:[(0,N.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,N.jsx)(O,{variant:`ghost`,size:`icon`,onClick:o,"aria-label":c(`activity:techStack.backToDependencyList`),className:`shrink-0 md:hidden`,children:(0,N.jsx)(w,{className:`size-4`})}),(0,N.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,N.jsx)(`h2`,{className:`min-w-0 truncate font-mono text-sm font-bold text-foreground`,children:e.name}),(0,N.jsx)(q,{className:l.badge,children:c(l.labelKey)})]}),(0,N.jsxs)(`p`,{className:`mt-0.5 truncate text-[10px] text-muted-foreground`,children:[I(e.ecosystem,c),` ·`,` `,e.direct?`direct`:`transitive`,` · `,e.scope,` ·`,` `,e.sourceType,f&&(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(`span`,{"aria-hidden":`true`,children:` · `}),(0,N.jsx)(`span`,{className:`text-warning`,children:c(f)})]})]})]})]}),(0,N.jsxs)(`div`,{className:`mt-2 flex flex-wrap items-baseline gap-2 font-mono text-xs`,children:[(0,N.jsx)(`span`,{className:`text-foreground`,children:u??`—`}),e.latestStable&&e.latestStable!==u&&(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(`span`,{className:`text-muted-foreground`,children:`→`}),(0,N.jsx)(`span`,{className:`text-info`,children:e.latestStable})]}),d.label&&(0,N.jsxs)(`span`,{className:`text-[10px] text-warning`,children:[`(`,d.label,`)`]})]})]}),(0,N.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-auto p-3`,children:[(0,N.jsxs)(`dl`,{className:`grid grid-cols-2 gap-px border border-border/70 bg-border/60`,children:[(0,N.jsx)(X,{label:c(`activity:techStack.constraint`),value:e.requested??`—`,mono:!0}),(0,N.jsx)(X,{label:c(`activity:techStack.locked`),value:e.locked??`—`,mono:!0}),(0,N.jsx)(X,{label:c(`activity:techStack.latestStable`),value:e.latestStable??`—`,mono:!0}),(0,N.jsx)(X,{label:c(`activity:techStack.license`),value:e.license??`—`}),e.wanted&&(0,N.jsx)(X,{label:c(`activity:techStack.wanted`),value:e.wanted,mono:!0}),e.resolvable&&(0,N.jsx)(X,{label:c(`activity:techStack.resolvable`),value:e.resolvable,mono:!0}),e.purl&&(0,N.jsx)(X,{label:c(`activity:techStack.purl`),value:e.purl,mono:!0}),(0,N.jsx)(X,{label:c(`activity:techStack.registryFlags`),value:[e.deprecated&&`deprecated`,e.yanked&&`yanked`].filter(Boolean).join(`, `)||`none`})]}),(0,N.jsxs)(`section`,{className:`mt-4`,children:[(0,N.jsxs)(`div`,{className:`mb-1.5 flex flex-wrap items-center justify-between gap-2`,children:[(0,N.jsx)(`h3`,{className:`text-[9px] font-bold uppercase tracking-[0.16em] text-muted-foreground`,children:c(`activity:techStack.findings`)}),(0,N.jsxs)(O,{variant:`outline`,size:`sm`,onClick:()=>r(e),disabled:n.status===`loading`,className:`h-7 text-[10px]`,children:[n.status===`loading`?(0,N.jsx)(i,{className:`size-3 animate-spin`}):(0,N.jsx)(g,{className:`size-3`}),n.status===`loading`?`Researching…`:`Deep dive`]})]}),n.status===`error`&&n.error&&(0,N.jsx)(`p`,{role:`alert`,className:`mb-1.5 text-[10px] text-destructive`,children:n.error}),t.length===0?(0,N.jsx)(`p`,{className:`text-[11px] text-muted-foreground`,children:c(`activity:techStack.nothingFlaggedRunADeepDive`)}):(0,N.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:t.map(e=>(0,N.jsxs)(`div`,{className:`border border-border/70 bg-card/40 p-2`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,N.jsx)(q,{className:z[e.severity].badge,children:c(z[e.severity].labelKey)}),(0,N.jsx)(q,{className:`border-border/70 bg-muted text-muted-foreground`,children:B[e.action]?c(B[e.action]):e.action}),K(e)&&(0,N.jsxs)(q,{className:`border-info/35 bg-info/10 text-info`,children:[(0,N.jsx)(g,{className:`size-2.5`}),`AI · `,Math.round(e.confidence*100),`%`]})]}),(0,N.jsx)(`p`,{className:`mt-1 text-[11px] leading-relaxed text-muted-foreground`,children:e.rationale}),e.breakingRisk&&(0,N.jsx)(`p`,{className:`mt-1 border-l-2 border-warning/40 pl-2 text-[10px] leading-relaxed text-warning`,children:e.breakingRisk})]},e.id))})]}),(0,N.jsxs)(`section`,{className:`mt-4`,children:[(0,N.jsx)(`h3`,{className:`mb-1.5 text-[9px] font-bold uppercase tracking-[0.16em] text-muted-foreground`,children:c(`activity:techStack.evidence`)}),e.evidence.length===0?(0,N.jsx)(`p`,{className:`text-[11px] text-muted-foreground`,children:c(`activity:techStack.noEvidenceRecorded`)}):(0,N.jsx)(`ul`,{className:`flex flex-col gap-1`,children:e.evidence.map((t,n)=>(0,N.jsxs)(`li`,{className:`border border-border/70 bg-card/40 p-2`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,N.jsx)(q,{className:`border-border/70 bg-muted text-muted-foreground`,children:t.kind}),(0,N.jsx)(`span`,{className:`font-mono text-[9px] text-muted-foreground`,children:new Date(t.retrievedAt).toLocaleString()})]}),t.source.startsWith(`http`)?(0,N.jsxs)(`a`,{href:t.source,target:`_blank`,rel:`noreferrer noopener`,className:`mt-1 flex min-w-0 items-center gap-1 truncate text-[10px] text-info underline-offset-2 hover:underline`,children:[(0,N.jsx)(`span`,{className:`truncate`,children:t.source}),(0,N.jsx)(a,{className:`size-2.5 shrink-0`})]}):(0,N.jsx)(`p`,{className:`mt-1 truncate font-mono text-[10px] text-muted-foreground`,children:t.source}),t.detail&&(0,N.jsx)(`p`,{className:`mt-0.5 text-[10px] leading-relaxed text-muted-foreground`,children:t.detail})]},`${e.id}-evidence-${n}`))})]})]})]})}function X({label:e,value:t,mono:n}){return(0,N.jsxs)(`div`,{className:`bg-card/55 px-2.5 py-1.5`,children:[(0,N.jsx)(`dt`,{className:`text-[9px] font-bold uppercase tracking-[0.14em] text-muted-foreground`,children:e}),(0,N.jsx)(`dd`,{className:E(`mt-0.5 truncate text-[11px] text-foreground`,n&&`font-mono`),children:t})]})}var me=`grid grid-cols-[minmax(0,2.2fr)_minmax(0,1.6fr)_minmax(0,1.1fr)] gap-2`;function he({dependencies:e,selectedId:t,hasDependencies:n,coverageByWorkspaceId:r,onSelect:i}){let{t:a}=T(),o=A(e,30);return e.length===0?(0,N.jsx)(`div`,{className:`flex flex-1 items-center justify-center p-8 text-center`,children:(0,N.jsx)(`p`,{className:`max-w-xs text-xs text-muted-foreground`,children:n?`No dependencies match the current filters.`:`No dependencies inventoried yet. Run a scan to populate the inventory.`})}):(0,N.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col`,children:[(0,N.jsxs)(`div`,{className:E(me,`shrink-0 border-b border-border/70 bg-card/45 px-3 py-1.5 text-[9px] font-bold uppercase tracking-[0.14em] text-muted-foreground`),children:[(0,N.jsx)(`span`,{children:a(`activity:techStack.package`)}),(0,N.jsx)(`span`,{children:a(`activity:techStack.installedLatest`)}),(0,N.jsx)(`span`,{children:a(`activity:techStack.status`)})]}),(0,N.jsx)(`div`,{className:`min-h-0 flex-1`,children:(0,N.jsx)(l,{className:`h-full`,"aria-label":a(`activity:techStack.dependencies`),children:o.pageItems.map(e=>(0,N.jsx)(ge,{dependency:e,selected:e.id===t,coverage:r?.get(e.workspaceId),onSelect:i},e.id))})}),(0,N.jsx)(se,{page:o.page,pageSize:o.pageSize,totalItems:o.totalItems,onPageChange:o.setPage,itemLabel:`dependencies`})]})}function ge({dependency:e,selected:t,coverage:n,onSelect:r}){let{t:i}=T(),a=F(e.status),o=G(e),s=W(e),c=n?H(n).noteKey:void 0;return(0,N.jsxs)(`button`,{type:`button`,onClick:()=>r(e),"aria-current":t,className:E(me,`w-full items-center border-b border-border/40 px-3 py-2 text-left transition-colors hover:bg-accent/40`,t&&`bg-accent/60`),children:[(0,N.jsxs)(`div`,{className:`min-w-0`,children:[(0,N.jsxs)(`div`,{className:`flex min-w-0 items-center gap-1.5`,children:[(0,N.jsx)(`span`,{className:E(`size-1.5 shrink-0`,a.dot),"aria-hidden":`true`}),(0,N.jsx)(`span`,{className:`truncate font-mono text-xs text-foreground`,children:e.name})]}),(0,N.jsxs)(`p`,{className:`mt-0.5 truncate text-[10px] text-muted-foreground`,children:[(0,N.jsx)(R,{ecosystem:e.ecosystem,className:`mr-0.5 inline-block size-3 align-text-bottom`}),I(e.ecosystem,i),` · `,e.direct?`direct`:`transitive`,` · `,e.scope,c&&(0,N.jsxs)(N.Fragment,{children:[` · `,(0,N.jsx)(`span`,{className:`text-warning`,children:i(c)})]})]})]}),(0,N.jsxs)(`div`,{className:`min-w-0`,children:[(0,N.jsxs)(`div`,{className:`flex min-w-0 items-baseline gap-1.5 font-mono text-[11px]`,children:[(0,N.jsx)(`span`,{className:`truncate text-foreground`,children:o??`—`}),e.latestStable&&e.latestStable!==o&&(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(`span`,{className:`shrink-0 text-muted-foreground`,children:`→`}),(0,N.jsx)(`span`,{className:`truncate text-info`,children:e.latestStable})]})]}),s.label?(0,N.jsx)(`p`,{className:`mt-0.5 truncate text-[10px] text-warning`,children:s.label}):e.requested&&(0,N.jsx)(`p`,{className:`mt-0.5 truncate font-mono text-[10px] text-muted-foreground`,children:e.requested})]}),(0,N.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-1`,children:[(0,N.jsx)(q,{className:a.badge,children:i(a.labelKey)}),e.deprecated&&(0,N.jsx)(q,{className:`border-destructive/35 bg-destructive/10 text-destructive`,children:`dep`}),e.yanked&&(0,N.jsx)(q,{className:`border-destructive/45 bg-destructive/15 text-destructive`,children:`yank`})]})]})}function _e({findings:e,dependenciesById:t,onSelectDependency:n}){let{t:r}=T(),i=A(e,20);if(e.length===0)return(0,N.jsx)(`div`,{className:`flex flex-1 items-center justify-center p-8 text-center`,children:(0,N.jsxs)(`p`,{className:`max-w-sm text-xs text-muted-foreground`,children:[r(`activity:techStack.noFindingsRun`),` `,(0,N.jsx)(`span`,{className:`font-mono text-foreground`,children:r(`activity:techStack.analyze`)}),` `,r(`activity:techStack.toCheckVersionsAndAdvisoriesAgainst`)]})});let a=fe.map(e=>[e,i.pageItems.filter(t=>t.severity===e)]).filter(([,e])=>e.length>0);return(0,N.jsxs)(`div`,{className:`flex min-h-0 flex-1 flex-col`,children:[(0,N.jsx)(`div`,{className:`min-h-0 flex-1 overflow-auto p-3`,children:(0,N.jsx)(`div`,{className:`flex flex-col gap-4`,children:a.map(([e,i])=>(0,N.jsxs)(`section`,{children:[(0,N.jsxs)(`div`,{className:`mb-1.5 flex items-center gap-2`,children:[(0,N.jsx)(q,{className:z[e].badge,children:r(z[e].labelKey)}),(0,N.jsx)(`span`,{className:`font-mono text-[10px] tabular-nums text-muted-foreground`,children:i.length})]}),(0,N.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:i.map(e=>(0,N.jsx)(ve,{finding:e,dependency:t.get(e.dependencyId),onSelectDependency:n},e.id))})]},e))})}),(0,N.jsx)(se,{page:i.page,pageSize:i.pageSize,totalItems:i.totalItems,onPageChange:i.setPage,itemLabel:`findings`})]})}function ve({finding:e,dependency:t,onSelectDependency:n}){let{t:r}=T(),i=K(e);return(0,N.jsxs)(`div`,{className:`border border-border/70 bg-card/40 p-2.5`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:[(0,N.jsx)(`button`,{type:`button`,onClick:()=>n(e.dependencyId),className:`min-w-0 truncate font-mono text-xs text-foreground underline-offset-2 hover:underline`,children:t?.name??e.dependencyId}),(0,N.jsx)(q,{className:`border-border/70 bg-muted text-muted-foreground`,children:B[e.action]?r(B[e.action]):e.action}),i&&(0,N.jsxs)(q,{className:`border-info/35 bg-info/10 text-info`,children:[(0,N.jsx)(g,{className:`size-2.5`}),`AI · `,Math.round(e.confidence*100),`%`]})]}),(0,N.jsx)(`p`,{className:`mt-1.5 text-[11px] leading-relaxed text-muted-foreground`,children:e.rationale}),e.breakingRisk&&(0,N.jsx)(`p`,{className:`mt-1 border-l-2 border-warning/40 pl-2 text-[10px] leading-relaxed text-warning`,children:e.breakingRisk}),e.evidence.length>0&&(0,N.jsx)(`ul`,{className:E(`mt-1.5 flex flex-col gap-0.5`),children:e.evidence.slice(0,4).map((t,n)=>(0,N.jsx)(`li`,{className:`min-w-0 truncate text-[10px]`,children:t.source.startsWith(`http`)?(0,N.jsx)(`a`,{href:t.source,target:`_blank`,rel:`noreferrer noopener`,className:`text-info underline-offset-2 hover:underline`,children:t.detail??t.source}):(0,N.jsx)(`span`,{className:`text-muted-foreground`,children:t.detail??t.source})},`${e.id}-${n}`))})]})}function ye({searchQuery:e,ecosystemFilter:t,statusFilter:n,directOnly:i,sort:a,hasFilters:o,ecosystems:c,statuses:l,visibleCount:u,totalCount:d,onSearchChange:f,onEcosystemFilterChange:ee,onStatusFilterChange:m,onToggleDirectOnly:h,onSortChange:g,onClearFilters:_}){let{t:v}=T();return(0,N.jsxs)(`div`,{className:`shrink-0 space-y-2 border-b border-border/70 bg-card/45 p-3`,children:[(0,N.jsxs)(`div`,{className:`flex gap-2`,children:[(0,N.jsxs)(`div`,{className:`relative min-w-0 flex-1`,children:[(0,N.jsx)(r,{className:`pointer-events-none absolute left-3 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground`}),(0,N.jsx)(k,{"aria-label":v(`activity:techStack.searchDependencies`),value:e,onChange:e=>f(e.target.value),placeholder:v(`activity:techStack.searchByPackageName`),className:`h-10 min-w-0 bg-background pl-9 pr-8 text-xs`}),e&&(0,N.jsx)(`button`,{type:`button`,"aria-label":v(`activity:techStack.clearSearch`),onClick:()=>f(``),className:`absolute right-2 top-1/2 -translate-y-1/2 p-1 text-muted-foreground hover:text-foreground`,children:(0,N.jsx)(s,{className:`size-3.5`})})]}),(0,N.jsx)(O,{variant:i?`default`:`outline`,size:`sm`,onClick:h,"aria-pressed":i,title:v(`activity:techStack.showOnlyDependenciesThisProjectDeclaresItself`),className:`shrink-0`,children:v(`activity:techStack.directOnly`)}),o&&(0,N.jsx)(O,{variant:`ghost`,size:`icon`,onClick:_,"aria-label":v(`activity:techStack.clearAllFilters`),title:v(`activity:techStack.clearAllFilters`),className:`shrink-0`,children:(0,N.jsx)(p,{className:`size-4`})})]}),(0,N.jsxs)(`div`,{className:`grid gap-2 sm:grid-cols-3`,children:[(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`label`,{className:`sr-only`,htmlFor:`techstack-ecosystem-filter`,children:v(`activity:techStack.filterByEcosystem`)}),(0,N.jsxs)(`select`,{id:`techstack-ecosystem-filter`,value:t,onChange:e=>ee(e.target.value),className:`h-9 w-full min-w-0 border border-input bg-background px-2 text-xs`,children:[(0,N.jsx)(`option`,{value:`all`,children:v(`activity:techStack.allEcosystems`)}),c.map(([e,t])=>(0,N.jsxs)(`option`,{value:e,children:[I(e,v),` · `,t]},e))]})]}),(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`label`,{className:`sr-only`,htmlFor:`techstack-status-filter`,children:v(`activity:techStack.filterByStatus`)}),(0,N.jsxs)(`select`,{id:`techstack-status-filter`,value:n,onChange:e=>m(e.target.value),className:`h-9 w-full min-w-0 border border-input bg-background px-2 text-xs`,children:[(0,N.jsx)(`option`,{value:`all`,children:v(`activity:techStack.allStatuses`)}),l.map(([e,t])=>(0,N.jsxs)(`option`,{value:e,children:[v(F(e).labelKey),` · `,t]},e))]})]}),(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`label`,{className:`sr-only`,htmlFor:`techstack-sort`,children:v(`activity:techStack.sortDependencies`)}),(0,N.jsxs)(`select`,{id:`techstack-sort`,value:a,onChange:e=>g(e.target.value),className:`h-9 w-full min-w-0 border border-input bg-background px-2 text-xs`,children:[(0,N.jsx)(`option`,{value:`attention`,children:v(`activity:techStack.sortNeedsAttention`)}),(0,N.jsx)(`option`,{value:`drift`,children:v(`activity:techStack.sortMostOutOfDate`)}),(0,N.jsx)(`option`,{value:`name`,children:v(`activity:techStack.sortName`)})]})]})]}),(0,N.jsx)(`p`,{className:E(`text-[10px] text-muted-foreground`,o&&`text-info`),children:u===d?`${d} dependencies`:`${u} of ${d} dependencies`})]})}var be=[{id:`dependencies`,labelKey:`activity:techStack.tabDependencies`},{id:`findings`,labelKey:`activity:techStack.tabFindings`},{id:`workspaces`,labelKey:`activity:techStack.tabWorkspaces`},{id:`trends`,labelKey:`activity:techStack.tabTrends`},{id:`remediation`,labelKey:`activity:techStack.tabRemediation`}],Z=new Set([`npm`,`python`,`rust`,`go`,`php`,`dotnet`]);function Q(){let{t:e}=T(),t=D(e=>e.snapshot),n=D(e=>e.stale),r=D(e=>e.loading),a=D(e=>e.error),o=D(e=>e.activeJob),[l,d]=(0,M.useState)(`dependencies`),[p,m]=(0,M.useState)(``),[h,_]=(0,M.useState)(`all`),[y,b]=(0,M.useState)(`all`),[x,te]=(0,M.useState)(!1),[S,ne]=(0,M.useState)(`attention`),[C,w]=(0,M.useState)(null),[k,A]=(0,M.useState)([]),[se,P]=(0,M.useState)({status:`idle`,error:null}),[ce,le]=(0,M.useState)(null),[ue,I]=(0,M.useState)(null),[L,R]=(0,M.useState)(new Set),[fe,z]=(0,M.useState)(!1),B=(0,M.useCallback)(async()=>{let t=D.getState();t.setLoading(!0),t.setError(null);try{let e=await fetch(`/api/techstack/snapshot`);if(e.status===404){t.setSnapshot(null,!1);return}if(!e.ok)throw Error(`HTTP ${e.status}: ${e.statusText}`);let n=await e.json();t.setSnapshot(n.snapshot,n.stale)}catch(n){let r=n instanceof Error?n.message:String(n),i=/unexpected token/i.test(r)&&/<!doctype|<html/i.test(r);t.setError(i?e(`activity:techStack.snapshotUnavailable`,{defaultValue:`TechStack service unavailable — start the WebUI server to scan.`}):r)}},[e]),V=(0,M.useCallback)(async e=>{let t=D.getState();t.setLoading(!0),t.setError(null);try{let n=await fetch(`/api/techstack/${e}`,{method:`POST`}),r=await n.json();if(!n.ok||!r.jobId)throw Error(r.error??`HTTP ${n.status}: ${n.statusText}`);t.jobStarted(r.jobId,e)}catch(e){t.setError(e instanceof Error?e.message:String(e))}},[]),H=(0,M.useCallback)(async()=>{let e=D.getState().activeJob;if(e)try{let t=await fetch(`/api/techstack/jobs/${encodeURIComponent(e.id)}/cancel`,{method:`POST`});if(!t.ok)throw Error(`HTTP ${t.status}: ${t.statusText}`);D.getState().jobCancelled(e.id)}catch(e){D.getState().setError(e instanceof Error?e.message:String(e))}},[]),U=(0,M.useCallback)(async e=>{P({status:`loading`,error:null});try{let t=await fetch(`/api/techstack/deps/${encodeURIComponent(e.id)}/research`,{method:`POST`}),n=await t.json();if(!t.ok)throw Error(n.error??`HTTP ${t.status}`);A(n.findings??[]),P({status:`idle`,error:null})}catch(e){P({status:`error`,error:e instanceof Error?e.message:String(e)})}},[]);(0,M.useEffect)(()=>{B()},[B]),(0,M.useEffect)(()=>{(l===`trends`||l===`remediation`)&&fetch(`/api/techstack/${l===`trends`?`trends`:`remediation`}`).then(async e=>{let t=await e.json();if(!e.ok)throw Error(t.error??`HTTP ${e.status}`);t.trend&&le(t.trend),t.plan&&I(t.plan)}).catch(e=>D.getState().setError(e instanceof Error?e.message:String(e)))},[l,t?.id]);let G=(0,M.useCallback)(async()=>{if(L.size!==0){z(!0);try{let e=await fetch(`/api/techstack/remediation/apply`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({approvedItems:[...L]})}),t=await e.json();if(!e.ok)throw Error(t.error??`HTTP ${e.status}`);R(new Set),await V(`inventory`)}catch(e){D.getState().setError(e instanceof Error?e.message:String(e))}finally{z(!1)}}},[L,V]);(0,M.useEffect)(()=>{A([]),P({status:`idle`,error:null})},[t?.id]);let K=(0,M.useMemo)(()=>t?.dependencies??[],[t]),q=(0,M.useMemo)(()=>t?.findings??[],[t]),X=(0,M.useMemo)(()=>new Map(K.map(e=>[e.id,e])),[K]),me=(0,M.useMemo)(()=>Ee(K.map(e=>e.ecosystem)),[K]),ge=(0,M.useMemo)(()=>Ee(K.map(e=>e.status)),[K]),ve=(0,M.useMemo)(()=>new Map(t?.workspaces.map(e=>[e.id,e.coverage])??[]),[t]),Z=(0,M.useMemo)(()=>{let e=p.trim().toLowerCase(),t=[...K.filter(t=>!(e&&!t.name.toLowerCase().includes(e)||h!==`all`&&t.ecosystem!==h||y!==`all`&&t.status!==y||x&&!t.direct))];return S===`name`?t.sort((e,t)=>e.name.localeCompare(t.name)):S===`drift`?t.sort((e,t)=>W(t).majorsBehind-W(e).majorsBehind||e.name.localeCompare(t.name)):t.sort((e,t)=>F(t.status).weight-F(e.status).weight||Number(t.direct)-Number(e.direct)||e.name.localeCompare(t.name)),t},[K,p,h,y,x,S]),Q=C?X.get(C):void 0,De=(0,M.useMemo)(()=>Q?[...q.filter(e=>e.dependencyId===Q.id),...k.filter(e=>e.dependencyId===Q.id)]:[],[q,k,Q]),Oe=(0,M.useMemo)(()=>K.filter(de).length,[K]),ke=(0,M.useMemo)(()=>K.filter(e=>W(e).majorsBehind>0).length,[K]),Ae=(0,M.useMemo)(()=>K.filter(e=>e.status===`vulnerable`).length,[K]),je=p.trim()!==``||h!==`all`||y!==`all`||x,Me=(0,M.useCallback)(()=>{m(``),_(`all`),b(`all`),te(!1)},[]),$=!(!o||[`completed`,`failed`,`cancelled`].includes(o.status)),Ne=(0,M.useCallback)(e=>{w(e),d(`dependencies`)},[]);return(0,N.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,N.jsx)(`header`,{className:`shrink-0 border-b border-border/70 px-4 py-3`,children:(0,N.jsxs)(`div`,{className:`flex flex-wrap items-start gap-3`,children:[(0,N.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,N.jsx)(`h1`,{className:`text-base font-bold sm:text-lg`,children:e(`activity:techStack.techstack`)}),(0,N.jsx)(`span`,{className:`border border-info/35 bg-info/10 px-2 py-0.5 font-mono text-[9px] font-bold uppercase text-info`,children:t?e(`activity:techStack.workspaceCount`,{count:t.workspaces.length}):e(`activity:techStack.noScanYet`)}),n&&(0,N.jsx)(`span`,{className:`border border-warning/35 bg-warning/10 px-2 py-0.5 font-mono text-[9px] font-bold uppercase text-warning`,children:e(`activity:techStack.staleGt24h`)})]}),(0,N.jsx)(`p`,{className:`mt-0.5 truncate text-[10px] text-muted-foreground sm:text-xs`,children:t?e(`activity:techStack.scannedAt`,{root:t.targetRoot,when:new Date(t.createdAt).toLocaleString()}):e(`activity:techStack.scanHint`)})]}),(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,N.jsxs)(O,{variant:`outline`,size:`sm`,onClick:()=>void V(`inventory`),disabled:$,title:e(`activity:techStack.offlineReReadManifestsAndLockfiles`),children:[(0,N.jsx)(f,{className:E(`size-3.5`,$&&`animate-spin`)}),(0,N.jsx)(`span`,{className:`hidden sm:inline`,children:e(`activity:techStack.refresh`)})]}),(0,N.jsxs)(O,{size:`sm`,onClick:()=>void V(`analyze`),disabled:$,title:e(`activity:techStack.checkRegistriesAndAdvisoriesThenInterpretTheResultsWithTheModel`),children:[(0,N.jsx)(g,{className:`size-3.5`}),e(`activity:techStack.analyze`)]}),$&&(0,N.jsx)(O,{variant:`ghost`,size:`icon`,onClick:()=>void H(),"aria-label":e(`activity:techStack.cancelJob`),children:(0,N.jsx)(s,{className:`size-4`})}),(0,N.jsxs)(ae,{children:[(0,N.jsx)(ie,{asChild:!0,children:(0,N.jsx)(O,{variant:`ghost`,size:`icon`,disabled:!t,"aria-label":e(`activity:techStack.exportOptions`),title:e(`activity:techStack.exportOptions`),children:(0,N.jsx)(ee,{className:`size-4`})})}),(0,N.jsxs)(oe,{align:`end`,className:`w-60`,children:[(0,N.jsxs)(j,{onClick:()=>t&&Y(t,`json`),children:[(0,N.jsx)(u,{className:`mr-2 size-4`}),e(`activity:techStack.exportSnapshotAsJson`)]}),(0,N.jsxs)(j,{onClick:()=>t&&Y(t,`spdx`),children:[(0,N.jsx)(v,{className:`mr-2 size-4`}),e(`activity:techStack.exportSbomSpdx`)]}),(0,N.jsxs)(j,{onClick:()=>t&&Y(t,`cyclonedx`),children:[(0,N.jsx)(re,{className:`mr-2 size-4`}),e(`activity:techStack.exportSbomCycloneDx`)]}),(0,N.jsxs)(j,{onClick:()=>t&&Y(t,`md`),children:[(0,N.jsx)(c,{className:`mr-2 size-4`}),e(`activity:techStack.exportReportMd`)]})]})]})]})]})}),t&&(0,N.jsxs)(`div`,{className:`grid shrink-0 grid-cols-2 gap-px border-b border-border/70 bg-border/60 sm:grid-cols-4`,children:[(0,N.jsx)(J,{label:e(`activity:techStack.dependencies`),value:K.length,hint:`${Z.length} visible`}),(0,N.jsx)(J,{label:e(`activity:techStack.outdated`),value:ke,hint:e(`activity:techStack.majorsBehind`),tone:ke>0?`warning`:`success`}),(0,N.jsx)(J,{label:e(`activity:techStack.vulnerable`),value:Ae,hint:e(`activity:techStack.knownAdvisories`),tone:Ae>0?`destructive`:`success`}),(0,N.jsx)(J,{label:e(`activity:techStack.findings`),value:q.length,hint:`${Oe} need attention`,tone:q.length>0?`info`:`default`})]}),($||a)&&(0,N.jsxs)(`div`,{className:`shrink-0 border-b border-border/70 px-4 py-2`,"aria-live":`polite`,children:[$&&o&&(0,N.jsxs)(`div`,{role:`status`,className:`flex items-center gap-2 text-xs text-info`,children:[(0,N.jsx)(i,{className:`size-3.5 animate-spin`}),(0,N.jsx)(`span`,{className:`font-mono`,children:o.status}),o.progress&&(0,N.jsxs)(`span`,{className:`text-muted-foreground`,children:[o.progress.completed,`/`,o.progress.total]})]}),a&&(0,N.jsxs)(`div`,{role:`alert`,className:`flex items-center gap-2 text-xs text-destructive`,children:[(0,N.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:a}),(0,N.jsx)(`button`,{type:`button`,onClick:()=>void B(),className:`underline`,children:e(`activity:techStack.retry`)})]})]}),r&&!t?(0,N.jsx)(we,{}):t?(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(`nav`,{className:`flex shrink-0 gap-1 border-b border-border/70 px-2`,children:be.map(t=>(0,N.jsxs)(`button`,{type:`button`,onClick:()=>d(t.id),"aria-current":l===t.id,className:E(`border-b-2 px-3 py-2 text-xs font-medium transition-colors`,l===t.id?`border-primary text-foreground`:`border-transparent text-muted-foreground hover:text-foreground`),children:[e(t.labelKey),t.id===`findings`&&q.length>0&&(0,N.jsx)(`span`,{className:`ml-1.5 font-mono text-[10px] tabular-nums text-muted-foreground`,children:q.length})]},t.id))}),l===`dependencies`&&(0,N.jsxs)(`div`,{className:`grid min-h-0 flex-1 md:grid-cols-[minmax(340px,1fr)_minmax(0,1.15fr)]`,children:[(0,N.jsxs)(`section`,{className:E(`min-h-0 border-r border-border/70`,Q?`hidden md:flex md:flex-col`:`flex flex-col`),"aria-label":e(`activity:techStack.dependencyList`),children:[(0,N.jsx)(ye,{searchQuery:p,ecosystemFilter:h,statusFilter:y,directOnly:x,sort:S,hasFilters:je,ecosystems:me,statuses:ge,visibleCount:Z.length,totalCount:K.length,onSearchChange:m,onEcosystemFilterChange:_,onStatusFilterChange:b,onToggleDirectOnly:()=>te(e=>!e),onSortChange:ne,onClearFilters:Me}),(0,N.jsx)(he,{dependencies:Z,selectedId:C,hasDependencies:K.length>0,coverageByWorkspaceId:ve,onSelect:e=>w(e.id)})]}),(0,N.jsx)(`section`,{className:E(`min-h-0`,Q?`flex flex-col`:`hidden md:flex md:flex-col`),"aria-label":e(`activity:techStack.dependencyDetail`),children:Q?(0,N.jsx)(pe,{dependency:Q,findings:De,deepDive:se,onDeepDive:U,onBack:()=>w(null),coverage:ve.get(Q.workspaceId)}):(0,N.jsx)(`div`,{className:`flex flex-1 items-center justify-center p-8 text-center`,children:(0,N.jsx)(`p`,{className:`max-w-xs text-xs text-muted-foreground`,children:e(`activity:techStack.selectADependencyToSeeIts`)})})})]}),l===`findings`&&(0,N.jsx)(_e,{findings:q,dependenciesById:X,onSelectDependency:Ne}),l===`workspaces`&&(0,N.jsx)(Ce,{snapshot:t}),l===`trends`&&(0,N.jsx)(xe,{trend:ce}),l===`remediation`&&(0,N.jsx)(Se,{plan:ue,approved:L,applying:fe,onToggle:e=>R(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n}),onApply:()=>void G()})]}):(0,N.jsx)(Te,{onScan:()=>void V(`inventory`),disabled:$})]})}function xe({trend:e}){return e?(0,N.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-auto p-3`,children:[(0,N.jsxs)(`p`,{className:`mb-3 text-xs text-muted-foreground`,children:[e.snapshots,` snapshots`,e.vulnerabilityHalfLifeMs===void 0?``:` · vulnerability half-life ${(e.vulnerabilityHalfLifeMs/864e5).toFixed(1)} days`]}),(0,N.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:e.points.map(e=>(0,N.jsxs)(`div`,{className:`grid grid-cols-4 border border-border/70 bg-card/40 p-2 text-xs`,children:[(0,N.jsx)(`span`,{children:new Date(e.createdAt).toLocaleDateString()}),(0,N.jsxs)(`span`,{children:[e.dependencies,` deps`]}),(0,N.jsxs)(`span`,{className:`text-warning`,children:[e.outdated,` outdated`]}),(0,N.jsxs)(`span`,{className:`text-destructive`,children:[e.vulnerable,` vulnerable`]})]},e.snapshotId))})]}):(0,N.jsx)(we,{})}function Se({plan:e,approved:t,applying:n,onToggle:r,onApply:a}){let{t:o}=T();return e?(0,N.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-auto p-3`,children:[(0,N.jsxs)(`div`,{className:`mb-3 flex items-center justify-between gap-3`,children:[(0,N.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:e.warning}),(0,N.jsxs)(O,{size:`sm`,disabled:t.size===0||n,onClick:a,children:[n&&(0,N.jsx)(i,{className:`size-3.5 animate-spin`}),`Apply `,t.size>0?t.size:``]})]}),(0,N.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[e.items.map(e=>{let n=`${e.workspaceId}:${e.ecosystem}:${e.dependencyName}:${e.action}`,i=e.action===`replace`||e.action===`investigate`||!Z.has(e.ecosystem);return(0,N.jsxs)(`label`,{className:E(`flex gap-3 border border-border/70 bg-card/40 p-2.5`,i?`cursor-not-allowed opacity-65`:`cursor-pointer`),children:[(0,N.jsx)(`input`,{type:`checkbox`,disabled:i,checked:t.has(n),onChange:()=>r(n)}),(0,N.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,N.jsxs)(`span`,{className:`block font-mono text-xs`,children:[e.dependencyName,` · `,e.action]}),(0,N.jsxs)(`span`,{className:`block text-[10px] text-muted-foreground`,children:[e.currentVersion??`?`,` → `,e.targetVersion??`latest`,` · `,e.rationale]}),i&&(0,N.jsx)(`span`,{className:`block text-[10px] text-warning`,children:o(`activity:techStack.requiresAManualPackageChoice`)})]})]},n)}),e.items.length===0&&(0,N.jsx)(`p`,{className:`p-8 text-center text-xs text-muted-foreground`,children:o(`activity:techStack.noRemediationNeeded`)})]})]}):(0,N.jsx)(we,{})}function Ce({snapshot:e}){let{t}=T(),n=(0,M.useMemo)(()=>{let t=new Map;for(let n of e.dependencies)t.set(n.workspaceId,(t.get(n.workspaceId)??0)+1);return t},[e]);return e.workspaces.length===0?(0,N.jsx)(`div`,{className:`flex flex-1 items-center justify-center p-8`,children:(0,N.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:t(`activity:techStack.noWorkspacesDetected`)})}):(0,N.jsx)(`div`,{className:`min-h-0 flex-1 overflow-auto p-3`,children:(0,N.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:e.workspaces.map(e=>{let r=V[e.coverage];return(0,N.jsxs)(`div`,{className:`border border-border/70 bg-card/40 p-2.5`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,N.jsxs)(`div`,{className:`min-w-0`,children:[(0,N.jsx)(`p`,{className:`truncate font-mono text-xs text-foreground`,children:e.relativeRoot}),(0,N.jsxs)(`p`,{className:`mt-0.5 flex items-center gap-1 truncate text-[10px] text-muted-foreground`,children:[(0,N.jsx)(R,{ecosystem:e.ecosystem}),(0,N.jsx)(`span`,{children:I(e.ecosystem,t)}),e.packageManager?(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(`span`,{"aria-hidden":`true`,children:`·`}),(0,N.jsx)(`span`,{children:e.packageManager})]}):null,(0,N.jsx)(`span`,{"aria-hidden":`true`,children:`·`}),(0,N.jsxs)(`span`,{children:[n.get(e.id)??0,` deps`]})]})]}),(0,N.jsx)(`span`,{className:E(`shrink-0 border px-1.5 py-0.5 text-[10px] font-medium`,r.badge),children:t(r.labelKey)})]}),e.manifests.length>0&&(0,N.jsx)(`div`,{className:`mt-1.5 flex flex-wrap gap-1`,children:e.manifests.map(e=>(0,N.jsx)(`span`,{className:`border border-border/70 bg-background/45 px-1.5 py-0.5 font-mono text-[9px] text-muted-foreground`,children:e.split(/[/\\]/).pop()},e))})]},e.id)})})})}function we(){let{t:e}=T();return(0,N.jsx)(`div`,{className:`flex flex-1 items-center justify-center`,children:(0,N.jsxs)(`div`,{className:`flex flex-col items-center gap-2`,children:[(0,N.jsx)(i,{className:`size-5 animate-spin text-muted-foreground`}),(0,N.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:e(`activity:techStack.loadingSnapshot`)})]})})}function Te({onScan:e,disabled:t}){let{t:n}=T(),r=(0,M.useMemo)(()=>Object.values(le).map(e=>e.label??``).filter(Boolean).join(`, `),[]);return(0,N.jsx)(`div`,{className:`flex flex-1 items-center justify-center p-8`,children:(0,N.jsxs)(`div`,{className:`flex max-w-md flex-col items-center gap-3 text-center`,children:[(0,N.jsx)(`div`,{className:`flex size-14 items-center justify-center border border-info/25 bg-info/5 text-info`,children:(0,N.jsx)(S,{className:`size-6`})}),(0,N.jsx)(`h2`,{className:`text-sm font-semibold`,children:n(`activity:techStack.noInventoryYet`)}),(0,N.jsxs)(`p`,{className:`text-xs leading-relaxed text-muted-foreground`,children:[`TechStack reads every manifest and lockfile in the open project — `,r,` — and compares what you have against the upstream registries.`]}),(0,N.jsxs)(O,{size:`sm`,onClick:e,disabled:t,children:[(0,N.jsx)(f,{className:E(`size-3.5`,t&&`animate-spin`)}),n(`activity:techStack.scanThisProject`)]})]})})}function Ee(e){let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);return[...t.entries()].sort((e,t)=>t[1]-e[1]||e[0].localeCompare(t[0]))}export{Q as TechStackView};
@@ -1 +0,0 @@
1
- import{n as e}from"./rolldown-runtime-hePW80VL.js";var t=e({action:()=>n,confirm:()=>r,default:()=>l,error:()=>o,loadingNamed:()=>c,sparkline:()=>s,status:()=>i,time:()=>a}),n={ok:`OK`,cancel:`Cancel`,create:`Create`,save:`Save`,saved:`Saved`,close:`Close`,dismiss:`Dismiss`,yes:`Yes`,no:`No`,delete:`Delete`,remove:`Remove`,discard:`Discard`,add:`Add`,edit:`Edit`,rename:`Rename`,retry:`Retry`,reset:`Reset`,apply:`Apply`,confirm:`Confirm`,back:`Back`,next:`Next`,done:`Done`,refresh:`Refresh`,copy:`Copy`,copied:`Copied`,copyFailed:`Copy failed — clipboard access was blocked.`,open:`Open`,start:`Start`,stop:`Stop`,pause:`Pause`,resume:`Resume`,continue:`Continue`,clear:`Clear`,search:`Search`,loading:`Loading…`,saving:`Saving…`,searchPlaceholder:`Search…`,always:`Always`,deny:`Deny`,undo:`Undo`,all:`All`},r={approvalScope:`Remember approval for`,scopeExact:`This exact input and arguments`,scopeCommand:`This executable with any arguments`,scopeTool:`{{tool}} — any input`,scopeHint:`Used by Always for this project. Broad grants still require approval for destructive calls.`,title:`Approval required: {{tool}}`,descriptionEdit:`The agent wants to modify a file. Review the request below and decide whether to proceed.`,descriptionTool:`The agent wants to run this tool. Review the request below and decide whether to proceed.`,fileModification:`File modification`,toolExecution:`Tool execution`,riskSuffix:`{{risk}} risk`,command:`Command`,inputLabel:`Input:`,trustSuggestionTitle:`Trust pattern suggestion`,trustSuggestionHint:`Picking Always will whitelist matching calls for this project.`,yoloDestructiveNote:`YOLO is on. This prompt is still shown because the request was classified as destructive.`,brainCountdown:`Waiting for your approval · Brain takes over in {{time}}`,brainDeciding:`Time expired · Brain is deciding…`,skipApprovalsTitle:`Skip future approvals`,skipApprovalsHint:`Enable YOLO mode and the agent runs without asking. Destructive operations still ask for confirmation.`,enableYoloTitle:`Enable YOLO mode (auto-approve this and future non-destructive calls)`,enableYoloBtn:`Enable YOLO`,denyAlways:`Deny always`,denyAlwaysTitle:`Reject this and all future calls matching the pattern (d)`,noTitle:`Reject this single call (Esc / n)`,alwaysTitle:`Approve and remember the pattern for the project (a)`,yesTitle:`Approve this single call (y)`},i={connected:`Connected`,disconnected:`Disconnected`,notConnectedRetry:`Not connected to the server — try again once reconnected.`,connecting:`Connecting…`,reconnecting:`Reconnecting…`,ready:`Ready`,error:`Error`,offline:`Offline`,online:`Online`,live:`Live`,budgetWarning:`budget warning`,running:`Running`,inProgress:`In Progress`,working:`working`},a={justNow:`just now`,secondsAgo_one:`{{count}} second ago`,secondsAgo_other:`{{count}} seconds ago`,minutesAgo_one:`{{count}} minute ago`,minutesAgo_other:`{{count}} minutes ago`,hoursAgo_one:`{{count}} hour ago`,hoursAgo_other:`{{count}} hours ago`,daysAgo_one:`{{count}} day ago`,daysAgo_other:`{{count}} days ago`,compactSecondsAgo:`{{count}}s ago`,compactMinutesAgo:`{{count}}m ago`,compactHoursAgo:`{{count}}h ago`},o={title:`Something went wrong`,body:`A rendering error occurred. Your session is still active on the server — reloading will pick up where you left off.`,reload:`Reload page`,tryAgain:`Try again`,panelTitle:`{{name}} hit an error`},s={noActivity:`No activity`,noActivityYet:`No activity yet`,activityMax:`Activity sparkline: max {{count}} events`,activityPeak:`Activity sparkline — peak {{count}} events/bucket`},c=`Loading {{name}}…`,l={action:n,confirm:r,status:i,time:a,error:o,sparkline:s,loadingNamed:c};export{t as n,l as t};