aidevops 3.31.28 → 3.31.30

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.
package/README.md CHANGED
@@ -58,7 +58,7 @@ The result: an AI operations platform that manages projects across every busines
58
58
  [![Copyright](https://img.shields.io/badge/Copyright-Marcus%20Quinn%202025--2026-blue.svg)](https://github.com/marcusquinn)
59
59
 
60
60
  <!-- Release & Version Info -->
61
- [![Version](https://img.shields.io/badge/Version-3.31.28-blue.svg)](https://github.com/marcusquinn/aidevops/releases)
61
+ [![Version](https://img.shields.io/badge/Version-3.31.30-blue.svg)](https://github.com/marcusquinn/aidevops/releases)
62
62
  [![npm version](https://img.shields.io/npm/v/aidevops)](https://www.npmjs.com/package/aidevops)
63
63
  [![Homebrew](https://img.shields.io/badge/homebrew-marcusquinn%2Ftap-orange)](https://github.com/marcusquinn/homebrew-tap)
64
64
  [![GitHub repository](https://img.shields.io/badge/github-repository-181717.svg?logo=github)](https://github.com/marcusquinn/aidevops)
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.31.28
1
+ 3.31.30
package/aidevops.sh CHANGED
@@ -5,7 +5,7 @@
5
5
  # AI DevOps Framework CLI
6
6
  # Usage: aidevops <command> [options]
7
7
  #
8
- # Version: 3.31.28
8
+ # Version: 3.31.30
9
9
 
10
10
  set -euo pipefail
11
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidevops",
3
- "version": "3.31.28",
3
+ "version": "3.31.30",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -220,19 +220,68 @@ function actionById(actions: GuiPulseWorkerActionSummary[], id: GuiPulseWorkerAc
220
220
 
221
221
  function PulseChartPanel({ chart }: { chart: GuiPulseWorkerChartSeries }): ReactElement {
222
222
  const maxValue = Math.max(...chart.points.map((point) => point.value), 1);
223
+ const values = chart.points.map((point) => point.value);
224
+ const latestValue = values.at(-1) ?? 0;
225
+ const firstValue = values[0] ?? latestValue;
226
+ const trend = latestValue - firstValue;
227
+ const svgPaths = chartSvgPaths(values);
223
228
 
224
229
  return (
225
230
  <article className="planned-card pulse-chart-panel">
226
- <p className="eyebrow">Trends · day/week/month/year</p>
231
+ <p className="eyebrow">Trends · compact bars · day/week/month/year</p>
227
232
  <h3>{chart.label}</h3>
233
+ <div className="pulse-chart-meta">
234
+ <span><strong>{formatChartValue(latestValue, chart.unit)}</strong><small>Latest</small></span>
235
+ <span><strong>{trendSummary(trend, chart.unit)}</strong><small>Δ period</small></span>
236
+ </div>
228
237
  <div className="pulse-chart-placeholder" aria-label={`${chart.label} chart for day week month year buckets`} role="img">
229
- {chart.points.map((point) => <span key={`${chart.id}-${point.period}`} style={{ "--bar-height": `${Math.max(18, Math.round((point.value / maxValue) * 100))}%` } as CSSProperties}>{point.period}</span>)}
238
+ <svg aria-hidden="true" className="pulse-chart-sparkline" focusable="false" preserveAspectRatio="none" viewBox="0 0 100 48">
239
+ <path className="pulse-chart-area" d={svgPaths.area} />
240
+ <path className="pulse-chart-line" d={svgPaths.line} />
241
+ {svgPaths.points.map((point) => <circle className="pulse-chart-dot" cx={point.x} cy={point.y} key={`${chart.id}-dot-${point.x}`} r="1.6" />)}
242
+ </svg>
243
+ {chart.points.map((point) => <span data-value={formatChartValue(point.value, chart.unit)} key={`${chart.id}-${point.period}`} style={{ "--bar-height": `${Math.max(18, Math.round((point.value / maxValue) * 100))}%` } as CSSProperties} title={`${point.period_label}: ${formatChartValue(point.value, chart.unit)}`}>{point.period}</span>)}
230
244
  </div>
231
245
  <p>{chart.unit} · {chart.points.map((point) => `${point.period_label}: ${point.value}`).join(" · ")}</p>
232
246
  </article>
233
247
  );
234
248
  }
235
249
 
250
+ function chartSvgPaths(values: number[]): { line: string; area: string; points: Array<{ x: number; y: number }> } {
251
+ if (values.length === 0) {
252
+ return { line: "M0 24 L100 24", area: "M0 24 L100 24 L100 48 L0 48 Z", points: [] };
253
+ }
254
+
255
+ const max = Math.max(...values, 1);
256
+ const min = Math.min(...values, 0);
257
+ const height = 48;
258
+ const padding = 5;
259
+ const span = Math.max(max - min, 1);
260
+ const points = values.map((value, index) => {
261
+ const x = values.length <= 1 ? 50 : (index / (values.length - 1)) * 100;
262
+ const y = max === min ? height / 2 : padding + ((max - value) / span) * (height - padding * 2);
263
+ return { x: Math.round(x * 10) / 10, y: Math.round(y * 10) / 10 };
264
+ });
265
+ const line = points.map((point, index) => `${index === 0 ? "M" : "L"}${point.x} ${point.y}`).join(" ");
266
+ const first = points[0] ?? { x: 0, y: height / 2 };
267
+ const last = points.at(-1) ?? first;
268
+
269
+ return { line, area: `${line} L${last.x} ${height} L${first.x} ${height} Z`, points };
270
+ }
271
+
272
+ function formatChartValue(value: number, unit: GuiPulseWorkerChartSeries["unit"]): string {
273
+ if (unit === "percent") return `${value}%`;
274
+ if (unit === "cost_ref") return `$${value.toFixed(2)}`;
275
+ if (unit === "milliseconds") return `${Math.round(value)}ms`;
276
+ if (unit === "tokens") return `${new Intl.NumberFormat("en", { notation: "compact" }).format(value)} tokens`;
277
+ return new Intl.NumberFormat("en").format(value);
278
+ }
279
+
280
+ function trendSummary(delta: number, unit: GuiPulseWorkerChartSeries["unit"]): string {
281
+ const sign = delta > 0 ? "+" : "";
282
+ return `${sign}${formatChartValue(delta, unit)}`;
283
+ }
284
+
236
285
  function PulseDrilldownPanel({ event }: { event: PulseEvent | undefined }): ReactElement {
237
286
  if (event === undefined) {
238
287
  return (
@@ -72,6 +72,7 @@ export const recommendedApps = ([
72
72
  { name: "Nextcloud Talk", description: "Open source video calls, chat, and collaboration for Nextcloud.", websiteUrl: "https://nextcloud.com/talk/", repoUrl: "https://github.com/nextcloud/spreed", iosUrl: "https://apps.apple.com/us/app/nextcloud-talk/id1296825574", androidUrl: "https://play.google.com/store/apps/details?id=com.nextcloud.talk2&hl=en", os: ["ios", "android"], platforms: ["webapp"] },
73
73
  { name: "OBS Studio", description: "Open source video recording and live streaming.", websiteUrl: "https://obsproject.com/", alternativeToUrl: "https://alternativeto.net/software/open-broadcaster-software/", repoUrl: "https://github.com/obsproject/obs-studio", os: ["macos", "linux", "windows"], platforms: [] },
74
74
  { name: "ONLYOFFICE", description: "Office and document collaboration.", websiteUrl: "https://www.onlyoffice.com/", alternativeToUrl: "https://alternativeto.net/software/onlyoffice/", repoUrl: "https://github.com/ONLYOFFICE/", iosUrl: "https://apps.apple.com/us/app/onlyoffice-documents/id944896972", androidUrl: "https://play.google.com/store/apps/details?id=com.onlyoffice.documents", os: ["macos", "linux", "windows", "ios", "android"], platforms: ["webapp", "saas", "api"] },
75
+ { name: "OpenPanel", description: "Open source web and product analytics with privacy-first dashboards, funnels, retention, session replay, revenue, and MCP access.", websiteUrl: "https://openpanel.dev/", repoUrl: "https://github.com/Openpanel-dev/openpanel", os: ["linux"], platforms: ["webapp", "saas", "api"] },
75
76
  { name: "OpenScreen", description: "Open screen-sharing project.", websiteUrl: "https://github.com/getopenscreen/openscreen/releases", alternativeToUrl: "https://alternativeto.net/software/openscreen/", repoUrl: "https://github.com/getopenscreen/openscreen", os: ["macos", "linux", "windows"], platforms: [] },
76
77
  { name: "Osaurus", description: "AI app workspace.", websiteUrl: "https://osaurus.ai/", alternativeToUrl: "https://alternativeto.net/software/osaurus/", os: ["macos"], platforms: [] },
77
78
  { name: "Parallels Desktop", description: "Run Windows, Linux, and virtual machines on macOS.", websiteUrl: "https://www.parallels.com/products/desktop/", alternativeToUrl: "https://alternativeto.net/software/parallels-desktop/about/", os: ["macos"], platforms: [] },
@@ -2450,6 +2450,36 @@ code {
2450
2450
  line-height: 1;
2451
2451
  }
2452
2452
 
2453
+ .pulse-chart-meta {
2454
+ display: grid;
2455
+ gap: 8px;
2456
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2457
+ }
2458
+
2459
+ .pulse-chart-meta span {
2460
+ background: color-mix(in srgb, var(--accent) 9%, var(--surface-muted));
2461
+ border: 1px solid var(--border);
2462
+ border-radius: 14px;
2463
+ display: grid;
2464
+ gap: 2px;
2465
+ padding: 10px;
2466
+ }
2467
+
2468
+ .pulse-chart-meta strong {
2469
+ color: var(--accent);
2470
+ font-size: 1.08rem;
2471
+ letter-spacing: -0.04em;
2472
+ line-height: 1;
2473
+ }
2474
+
2475
+ .pulse-chart-meta small {
2476
+ color: var(--text-muted);
2477
+ font-size: 0.72rem;
2478
+ font-weight: 800;
2479
+ letter-spacing: 0.08em;
2480
+ text-transform: uppercase;
2481
+ }
2482
+
2453
2483
  .pulse-attention-panel,
2454
2484
  .pulse-chart-panel,
2455
2485
  .pulse-activity-panel,
@@ -2480,19 +2510,25 @@ code {
2480
2510
 
2481
2511
  .pulse-chart-placeholder {
2482
2512
  align-items: end;
2483
- background: var(--surface-muted);
2513
+ background:
2514
+ linear-gradient(180deg, transparent 24%, color-mix(in srgb, var(--border) 42%, transparent) 24% 25%, transparent 25% 49%, color-mix(in srgb, var(--border) 34%, transparent) 49% 50%, transparent 50% 74%, color-mix(in srgb, var(--border) 28%, transparent) 74% 75%, transparent 75%),
2515
+ radial-gradient(circle at 12% 18%, color-mix(in srgb, var(--accent) 20%, transparent), transparent 34%),
2516
+ var(--surface-muted);
2484
2517
  border: 1px solid var(--border);
2485
2518
  border-radius: 16px;
2486
2519
  display: grid;
2487
2520
  gap: 8px;
2488
- grid-template-columns: repeat(6, minmax(0, 1fr));
2521
+ grid-template-columns: repeat(auto-fit, minmax(46px, 1fr));
2489
2522
  min-height: 180px;
2523
+ overflow: hidden;
2490
2524
  padding: 14px;
2525
+ position: relative;
2491
2526
  }
2492
2527
 
2493
2528
  .pulse-chart-placeholder span {
2494
2529
  align-items: end;
2495
- background: color-mix(in srgb, var(--accent) 26%, transparent);
2530
+ background:
2531
+ linear-gradient(180deg, color-mix(in srgb, var(--accent) 52%, transparent), color-mix(in srgb, var(--accent) 18%, transparent));
2496
2532
  border: 1px solid var(--border-accent);
2497
2533
  border-radius: 12px 12px 4px 4px;
2498
2534
  color: var(--accent-strong);
@@ -2502,7 +2538,50 @@ code {
2502
2538
  justify-content: center;
2503
2539
  min-height: max(40px, var(--bar-height, calc(40px + var(--bar-index, 1) * 18px)));
2504
2540
  padding: 8px 4px;
2541
+ position: relative;
2505
2542
  text-transform: uppercase;
2543
+ z-index: 1;
2544
+ }
2545
+
2546
+ .pulse-chart-placeholder span::before {
2547
+ color: var(--text-secondary);
2548
+ content: attr(data-value);
2549
+ font-size: 0.68rem;
2550
+ font-weight: 800;
2551
+ left: 50%;
2552
+ position: absolute;
2553
+ top: -20px;
2554
+ transform: translateX(-50%);
2555
+ white-space: nowrap;
2556
+ }
2557
+
2558
+ .pulse-chart-sparkline {
2559
+ height: 48%;
2560
+ inset: 16px 12px auto;
2561
+ opacity: 0.88;
2562
+ pointer-events: none;
2563
+ position: absolute;
2564
+ width: calc(100% - 24px);
2565
+ z-index: 2;
2566
+ }
2567
+
2568
+ .pulse-chart-area {
2569
+ fill: color-mix(in srgb, var(--accent) 18%, transparent);
2570
+ stroke: none;
2571
+ }
2572
+
2573
+ .pulse-chart-line {
2574
+ fill: none;
2575
+ stroke: var(--accent);
2576
+ stroke-linecap: round;
2577
+ stroke-linejoin: round;
2578
+ stroke-width: 2.6;
2579
+ }
2580
+
2581
+ .pulse-chart-dot {
2582
+ fill: var(--surface-elevated);
2583
+ stroke: var(--accent);
2584
+ stroke-width: 1.4;
2506
2585
  }
2507
2586
 
2508
2587
  .pulse-chart-grid,
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.31.28
15
+ # Version: 3.31.30
16
16
  #
17
17
  # Quick Install:
18
18
  # npm install -g aidevops && aidevops update (recommended)