aidevops 3.29.40 → 3.30.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.
@@ -0,0 +1,51 @@
1
+ import { type ReactElement, useEffect, useState } from "react";
2
+
3
+ export interface ScreenshotCapturedDetail {
4
+ path: string;
5
+ url: string;
6
+ }
7
+
8
+ interface WebKitExternalLinkWindow extends Window {
9
+ webkit?: {
10
+ messageHandlers?: {
11
+ externalLink?: {
12
+ postMessage: (href: string) => void;
13
+ };
14
+ };
15
+ };
16
+ }
17
+
18
+ export function ScreenshotCaptureNotification({ notification, onDismiss }: { notification: ScreenshotCapturedDetail; onDismiss: () => void }): ReactElement {
19
+ const revealScreenshot = () => {
20
+ const webkit = (window as WebKitExternalLinkWindow).webkit;
21
+ webkit?.messageHandlers?.externalLink?.postMessage(notification.url);
22
+ };
23
+
24
+ return (
25
+ <div className="screenshot-capture-notification" role="status">
26
+ <div>
27
+ <strong>Screenshot captured</strong>
28
+ <span>Saved to <button onClick={revealScreenshot} type="button">{notification.path}</button>; path copied to clipboard.</span>
29
+ </div>
30
+ <button aria-label="Dismiss screenshot notification" onClick={onDismiss} type="button">×</button>
31
+ </div>
32
+ );
33
+ }
34
+
35
+ export function ScreenshotCaptureNotificationHost(): ReactElement | null {
36
+ const [screenshotNotification, setScreenshotNotification] = useState<ScreenshotCapturedDetail | undefined>();
37
+
38
+ useEffect(() => {
39
+ const showScreenshotNotification = (event: Event) => {
40
+ const detail = (event as CustomEvent<Partial<ScreenshotCapturedDetail>>).detail;
41
+ if (detail !== undefined && typeof detail.path === "string" && typeof detail.url === "string") {
42
+ setScreenshotNotification({ path: detail.path, url: detail.url });
43
+ }
44
+ };
45
+
46
+ window.addEventListener("aidevops:screenshot-captured", showScreenshotNotification);
47
+ return () => window.removeEventListener("aidevops:screenshot-captured", showScreenshotNotification);
48
+ }, []);
49
+
50
+ return screenshotNotification ? <ScreenshotCaptureNotification notification={screenshotNotification} onDismiss={() => setScreenshotNotification(undefined)} /> : null;
51
+ }
@@ -148,6 +148,13 @@ export interface InventorySurfaceConfig {
148
148
  title: string;
149
149
  }
150
150
 
151
+ export interface ChatPrimitiveStackDecision {
152
+ adopt: string[];
153
+ defer: string[];
154
+ foundation: string;
155
+ owner: "local_vite_shell";
156
+ }
157
+
151
158
  export type SurfaceRecordCounts = Partial<Record<SurfaceId, number>>;
152
159
 
153
160
  export const text = {
@@ -278,6 +285,8 @@ export const text = {
278
285
  workersIntro: "Pulse & Workers brings worker sessions, event streams, outcomes, resources, and systemic fixes into one observability console so attention goes to exceptions, bottlenecks, and reusable improvements instead of raw noise.",
279
286
  theme: "Theme",
280
287
  appearance: "Appearance",
288
+ approvalExecutionDeferred: "Approval execution is deferred until audited approval tooling exists.",
289
+ devOpsCard: "DevOps card",
281
290
  hue: "Hue",
282
291
  reset: "Reset",
283
292
  showBorders: "Show borders",
@@ -286,6 +295,8 @@ export const text = {
286
295
  fontSize: "Font size",
287
296
  truncated: "Preview truncated for safety.",
288
297
  update: "Update",
298
+ tamboGenUiReadOnly: "Tambo GenUI · read-only",
299
+ unsupportedDevOpsCard: "Unsupported DevOps card",
289
300
  vault: "Vault",
290
301
  vaultAudit: "Audit Logs",
291
302
  vaultBackups: "Backups & Recovery",
@@ -315,6 +326,13 @@ export const DEFAULT_CONTRAST: ContrastPreference = "low";
315
326
  export const DEFAULT_FONT: FontPreference = "Inter";
316
327
  export const DEFAULT_FONT_SIZE: FontSizePreference = "xs";
317
328
 
329
+ export const chatPrimitiveStackDecision: ChatPrimitiveStackDecision = {
330
+ owner: "local_vite_shell",
331
+ foundation: "Turbostarter AI patterns supply persistence, AI SDK transport, model selection, attachments, tool/reasoning panels, sharing, and session actions behind audited routes.",
332
+ adopt: ["MessageScroller", "Message", "Bubble", "Attachment", "Marker"],
333
+ defer: ["Tambo ordinary chat persistence", "Tambo channel transport", "React Joyride as chat infrastructure", "Next.js route ownership"],
334
+ };
335
+
318
336
  export const contrastOptions: ContrastOption[] = [
319
337
  { value: "low", label: "Low" },
320
338
  { value: "medium", label: "Medium" },
@@ -368,7 +386,7 @@ export const navGroups: SurfaceNavGroup[] = [
368
386
  mode: "devops",
369
387
  items: [
370
388
  plannedNavItem("aiSessions", text.aiSessions, "AI chat and OpenCode sessions", "terminal"),
371
- plannedNavItem("workers", text.workers, "Pulse, worker sessions, outcomes, and resources", "activity"),
389
+ { id: "workers", label: text.workers, description: "Pulse, worker sessions, outcomes, and resources", icon: "activity" },
372
390
  { id: "git", label: text.localRepos, description: "~/Git explorer", icon: "folder" },
373
391
  plannedNavItem("repos", text.repos, "Unified local and remote repo context", "git"),
374
392
  { id: "projects", label: text.projects, description: "repos.json summary", icon: "git" },
@@ -104,9 +104,11 @@ function normalizeStatusEnvelope(envelope: GuiResponseEnvelope<Partial<GuiStatus
104
104
  ...data.pulse_workers,
105
105
  kpis: data.pulse_workers?.kpis ?? statusFixture.pulse_workers.kpis,
106
106
  attention: data.pulse_workers?.attention ?? statusFixture.pulse_workers.attention,
107
+ insights: data.pulse_workers?.insights ?? statusFixture.pulse_workers.insights,
107
108
  filters: { ...statusFixture.pulse_workers.filters, ...data.pulse_workers?.filters },
108
109
  charts: data.pulse_workers?.charts ?? statusFixture.pulse_workers.charts,
109
110
  events: data.pulse_workers?.events ?? statusFixture.pulse_workers.events,
111
+ actions: data.pulse_workers?.actions ?? statusFixture.pulse_workers.actions,
110
112
  },
111
113
  capabilities: data.capabilities ?? statusFixture.capabilities,
112
114
  secrets: data.secrets ?? statusFixture.secrets,
@@ -50,10 +50,10 @@
50
50
  --bg-primary: #0a0a0a;
51
51
  --bg-secondary: #111111;
52
52
  --bg-tertiary: #1a1a1a;
53
- --border: color-mix(in srgb, rgb(255 255 255 / 11%) 76%, rgb(255 255 255 / 30%));
54
- --border-hover: color-mix(in srgb, rgb(255 255 255 / 22%) 74%, rgb(255 255 255 / 40%));
53
+ --border: color-mix(in srgb, rgb(255 255 255 / 15%) 78%, rgb(255 255 255 / 32%));
54
+ --border-hover: color-mix(in srgb, rgb(255 255 255 / 28%) 76%, rgb(255 255 255 / 44%));
55
55
  --code-bg: hsl(var(--accent-hue) 18% 6%);
56
- --glass-panel-shadow: inset 0 1px 0 rgb(255 255 255 / 10%), inset 0 -1px 0 rgb(0 0 0 / 24%), var(--shadow-soft);
56
+ --glass-panel-shadow: inset 0 1px 0 rgb(255 255 255 / 13%), inset 0 -1px 0 rgb(0 0 0 / 28%), var(--shadow-soft);
57
57
  --notification-error-bg: rgb(255 123 114 / 13%);
58
58
  --notification-error-fg: #ff7b72;
59
59
  --notification-info-bg: rgb(88 166 255 / 13%);
@@ -62,7 +62,7 @@
62
62
  --notification-success-fg: #56d364;
63
63
  --notification-warning-bg: rgb(210 153 34 / 15%);
64
64
  --notification-warning-fg: #d29922;
65
- --shadow-soft: 0 24px 80px rgb(0 0 0 / 40%);
65
+ --shadow-soft: 0 26px 84px rgb(0 0 0 / 46%);
66
66
  --surface-elevated: #151515;
67
67
  --surface-muted: #202020;
68
68
  --success-bg: hsl(var(--accent-hue) 74% 66% / 12%);
@@ -88,8 +88,10 @@
88
88
  --bg-primary: #050505;
89
89
  --bg-secondary: #0b0b0b;
90
90
  --bg-tertiary: #141414;
91
- --border: color-mix(in srgb, rgb(255 255 255 / 22%) 78%, rgb(255 255 255 / 44%));
92
- --border-hover: color-mix(in srgb, rgb(255 255 255 / 36%) 80%, rgb(255 255 255 / 52%));
91
+ --border: color-mix(in srgb, rgb(255 255 255 / 24%) 80%, rgb(255 255 255 / 44%));
92
+ --border-hover: color-mix(in srgb, rgb(255 255 255 / 38%) 82%, rgb(255 255 255 / 52%));
93
+ --glass-panel-shadow: inset 0 1px 0 rgb(255 255 255 / 14%), inset 0 -1px 0 rgb(0 0 0 / 30%), var(--shadow-soft);
94
+ --shadow-soft: 0 28px 88px rgb(0 0 0 / 52%);
93
95
  --surface-elevated: #101010;
94
96
  --surface-muted: #181818;
95
97
  --text-muted: rgb(255 255 255 / 58%);
@@ -205,13 +207,36 @@ body {
205
207
  background:
206
208
  radial-gradient(ellipse at top left, color-mix(in srgb, var(--accent) 16%, transparent) 0%, transparent 36%),
207
209
  var(--bg-secondary);
210
+ background-attachment: fixed;
211
+ background-repeat: no-repeat;
208
212
  color: var(--text-primary);
209
213
  font-family: var(--font-family-app);
210
214
  line-height: 1.6;
211
215
  margin: 0;
216
+ min-height: 100vh;
212
217
  font-size: var(--font-size-app);
213
218
  }
214
219
 
220
+ :root[data-theme="dark"] body {
221
+ background-image:
222
+ radial-gradient(ellipse 78% 64% at top left,
223
+ hsl(var(--accent-hue) 96% 22% / 62%) 0%,
224
+ hsl(var(--accent-hue) 92% 18% / 34%) 34%,
225
+ transparent 58%),
226
+ radial-gradient(ellipse 72% 62% at bottom right,
227
+ hsl(var(--accent-hue) 90% 16% / 38%) 0%,
228
+ hsl(var(--accent-hue) 84% 12% / 20%) 38%,
229
+ transparent 66%),
230
+ radial-gradient(ellipse 66% 54% at bottom left,
231
+ hsl(var(--accent-hue) 90% 15% / 30%) 0%,
232
+ hsl(var(--accent-hue) 80% 11% / 16%) 38%,
233
+ transparent 68%),
234
+ linear-gradient(135deg,
235
+ color-mix(in srgb, hsl(var(--accent-hue) 92% 16%) 44%, var(--bg-secondary)) 0%,
236
+ color-mix(in srgb, hsl(var(--accent-hue) 80% 12%) 14%, var(--bg-secondary)) 48%,
237
+ color-mix(in srgb, var(--accent) 6%, var(--bg-primary)) 100%);
238
+ }
239
+
215
240
  button,
216
241
  input,
217
242
  select {
@@ -273,6 +298,68 @@ code {
273
298
  z-index: 20;
274
299
  }
275
300
 
301
+ .screenshot-capture-notification {
302
+ align-items: center;
303
+ background: color-mix(in srgb, var(--surface-elevated) 94%, transparent);
304
+ border: 1px solid var(--border-accent);
305
+ border-radius: 999px;
306
+ box-shadow: var(--glass-panel-shadow);
307
+ color: var(--text-secondary);
308
+ display: flex;
309
+ gap: 12px;
310
+ left: 50%;
311
+ max-width: min(720px, calc(100vw - 48px));
312
+ padding: 8px 10px 8px 14px;
313
+ position: fixed;
314
+ top: calc(var(--desktop-titlebar-height) + 10px);
315
+ transform: translateX(-50%);
316
+ z-index: 40;
317
+ }
318
+
319
+ .screenshot-capture-notification > div {
320
+ display: grid;
321
+ gap: 1px;
322
+ min-width: 0;
323
+ }
324
+
325
+ .screenshot-capture-notification strong {
326
+ color: var(--text-primary);
327
+ font-size: 0.78rem;
328
+ line-height: 1.2;
329
+ }
330
+
331
+ .screenshot-capture-notification span {
332
+ font-size: 0.74rem;
333
+ line-height: 1.25;
334
+ overflow: hidden;
335
+ text-overflow: ellipsis;
336
+ white-space: nowrap;
337
+ }
338
+
339
+ .screenshot-capture-notification button {
340
+ background: transparent;
341
+ border: 0;
342
+ color: var(--accent);
343
+ font: inherit;
344
+ padding: 0;
345
+ text-decoration: underline;
346
+ }
347
+
348
+ .screenshot-capture-notification > button {
349
+ align-items: center;
350
+ background: var(--surface-muted);
351
+ border: 1px solid transparent;
352
+ border-radius: 999px;
353
+ color: var(--text-secondary);
354
+ display: inline-flex;
355
+ flex: 0 0 auto;
356
+ font-size: 1rem;
357
+ height: 24px;
358
+ justify-content: center;
359
+ line-height: 1;
360
+ width: 24px;
361
+ }
362
+
276
363
  .machine-rail,
277
364
  .app-sidebar,
278
365
  .app-inset {
@@ -1721,7 +1808,7 @@ code {
1721
1808
 
1722
1809
  .hero-panel {
1723
1810
  background:
1724
- linear-gradient(135deg, color-mix(in srgb, var(--accent) 16%, transparent), transparent 58%),
1811
+ linear-gradient(135deg, color-mix(in srgb, var(--accent) 11%, transparent), transparent 58%),
1725
1812
  var(--surface-elevated);
1726
1813
  padding: clamp(24px, 5vw, 42px);
1727
1814
  }
@@ -1849,7 +1936,7 @@ code {
1849
1936
 
1850
1937
  .notifications-hero {
1851
1938
  background:
1852
- linear-gradient(135deg, var(--notification-bg, color-mix(in srgb, var(--accent) 12%, transparent)), transparent 62%),
1939
+ linear-gradient(135deg, var(--notification-bg, color-mix(in srgb, var(--accent) 10%, transparent)), transparent 62%),
1853
1940
  var(--surface-elevated);
1854
1941
  }
1855
1942
 
@@ -2228,7 +2315,7 @@ code {
2228
2315
 
2229
2316
  .pulse-hero {
2230
2317
  background:
2231
- linear-gradient(135deg, color-mix(in srgb, var(--accent) 18%, transparent), transparent 64%),
2318
+ linear-gradient(135deg, color-mix(in srgb, var(--accent) 12%, transparent), transparent 64%),
2232
2319
  var(--surface-elevated);
2233
2320
  }
2234
2321
 
@@ -3149,8 +3236,8 @@ button.managed-toggle:focus-visible {
3149
3236
  .recommended-app-card:hover,
3150
3237
  .recommended-app-card:focus-within {
3151
3238
  background:
3152
- linear-gradient(135deg, color-mix(in srgb, var(--accent) 16%, transparent), transparent 46%),
3153
- color-mix(in srgb, var(--accent) 7%, var(--surface-muted));
3239
+ linear-gradient(135deg, color-mix(in srgb, var(--accent) 11%, transparent), transparent 42%),
3240
+ color-mix(in srgb, var(--accent) 5%, var(--surface-muted));
3154
3241
  border-color: var(--border-accent);
3155
3242
  box-shadow: 0 18px 46px color-mix(in srgb, var(--accent) 10%, transparent);
3156
3243
  transform: translateY(-1px);
package/setup.sh CHANGED
@@ -12,7 +12,7 @@ shopt -s inherit_errexit 2>/dev/null || true
12
12
  # AI Assistant Server Access Framework Setup Script
13
13
  # Helps developers set up the framework for their infrastructure
14
14
  #
15
- # Version: 3.29.40
15
+ # Version: 3.30.0
16
16
  #
17
17
  # Quick Install:
18
18
  # npm install -g aidevops && aidevops update (recommended)