aidevops 3.29.28 → 3.29.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.29.28-blue.svg)](https://github.com/marcusquinn/aidevops/releases)
61
+ [![Version](https://img.shields.io/badge/Version-3.29.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.29.28
1
+ 3.29.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.29.28
8
+ # Version: 3.29.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.29.28",
3
+ "version": "3.29.30",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -79,47 +79,67 @@ function AppLogLink({ job }: { job: GuiAppActionJobSummary }): ReactElement {
79
79
  return <a className="app-meta app-log-link" href={`#app-job-${job.id}`}><small>Logs</small><strong>{job.action} · {job.status}</strong></a>;
80
80
  }
81
81
 
82
- function AppActionButton({ action, app, commandPreview, disabled, onJob }: { action: GuiAppActionId; app: GuiManagedAppSummary; commandPreview: string; disabled: boolean; onJob: (job: GuiAppActionJobSummary) => void }): ReactElement {
83
- const icon = action === "install" ? <FiDownload /> : action === "update" ? <FiRefreshCw /> : action === "reinstall" ? <FiRepeat /> : <FiTrash2 />;
84
- const [confirmOpen, setConfirmOpen] = useState(false);
82
+ function appActionIcon(action: GuiAppActionId): ReactElement {
83
+ const icons: Record<GuiAppActionId, ReactElement> = {
84
+ install: <FiDownload />,
85
+ reinstall: <FiRepeat />,
86
+ remove: <FiTrash2 />,
87
+ update: <FiRefreshCw />,
88
+ };
89
+
90
+ return icons[action];
91
+ }
85
92
 
86
- async function runAction(): Promise<void> {
87
- if (disabled) {
88
- return;
89
- }
93
+ function appActionButtonClass(action: GuiAppActionId): string {
94
+ return action === "remove" ? "app-action-button remove" : "app-action-button";
95
+ }
90
96
 
91
- try {
92
- const response = await fetch(`/api/apps/${encodeURIComponent(app.id)}/actions/${action}`, { method: "POST" });
93
- if (!response.ok) {
94
- console.error(`Failed to run ${action} for ${app.id}: ${response.status} ${response.statusText}`);
95
- return;
96
- }
97
+ function envelopeErrorSummary(envelope: Partial<GuiResponseEnvelope<GuiAppActionJobSummary>>): string {
98
+ return Array.isArray(envelope.errors) && envelope.errors.length > 0 ? envelope.errors.join("; ") : "unknown error";
99
+ }
97
100
 
101
+ async function requestAppActionJob(app: GuiManagedAppSummary, action: GuiAppActionId): Promise<GuiAppActionJobSummary | null> {
102
+ let job: GuiAppActionJobSummary | null = null;
103
+
104
+ try {
105
+ const response = await fetch(`/api/apps/${encodeURIComponent(app.id)}/actions/${action}`, { method: "POST" });
106
+ if (!response.ok) {
107
+ console.error(`Failed to run ${action} for ${app.id}: ${response.status} ${response.statusText}`);
108
+ } else {
98
109
  const envelope = await response.json() as Partial<GuiResponseEnvelope<GuiAppActionJobSummary>> | null;
99
110
  if (envelope === null || typeof envelope !== "object") {
100
111
  console.error(`Action ${action} for ${app.id} returned an invalid response envelope`);
101
- return;
112
+ } else if (envelope.ok !== true) {
113
+ console.error(`Action ${action} for ${app.id} returned an error envelope: ${envelopeErrorSummary(envelope)}`);
114
+ } else if (!("data" in envelope)) {
115
+ console.error(`Action ${action} for ${app.id} returned a response envelope without job data`);
116
+ } else {
117
+ job = envelope.data as GuiAppActionJobSummary;
102
118
  }
119
+ }
120
+ } catch (error) {
121
+ console.error(`Network error running ${action} for ${app.id}:`, error);
122
+ }
103
123
 
104
- if (envelope.ok !== true) {
105
- const errors = Array.isArray(envelope.errors) && envelope.errors.length > 0 ? envelope.errors.join("; ") : "unknown error";
106
- console.error(`Action ${action} for ${app.id} returned an error envelope: ${errors}`);
107
- return;
108
- }
124
+ return job;
125
+ }
109
126
 
110
- if (!("data" in envelope)) {
111
- console.error(`Action ${action} for ${app.id} returned a response envelope without job data`);
112
- return;
113
- }
127
+ function AppActionButton({ action, app, commandPreview, disabled, onJob }: { action: GuiAppActionId; app: GuiManagedAppSummary; commandPreview: string; disabled: boolean; onJob: (job: GuiAppActionJobSummary) => void }): ReactElement {
128
+ const [confirmOpen, setConfirmOpen] = useState(false);
129
+
130
+ async function runAction(): Promise<void> {
131
+ if (disabled) {
132
+ return;
133
+ }
114
134
 
115
- onJob(envelope.data as GuiAppActionJobSummary);
116
- } catch (error) {
117
- console.error(`Network error running ${action} for ${app.id}:`, error);
135
+ const job = await requestAppActionJob(app, action);
136
+ if (job !== null) {
137
+ onJob(job);
118
138
  }
119
139
  }
120
140
 
121
141
  return <>
122
- <button aria-label={`${action} ${app.name}`} className={action === "remove" ? "app-action-button remove" : "app-action-button"} data-tooltip={commandPreview} disabled={disabled} onClick={() => setConfirmOpen(true)} type="button">{icon}<span>{action}</span></button>
142
+ <button aria-label={`${action} ${app.name}`} className={appActionButtonClass(action)} data-tooltip={commandPreview} disabled={disabled} onClick={() => setConfirmOpen(true)} type="button">{appActionIcon(action)}<span>{action}</span></button>
123
143
  {confirmOpen ? <ConfirmActionModal action={action} app={app} commandPreview={commandPreview} close={() => setConfirmOpen(false)} confirm={() => { setConfirmOpen(false); void runAction(); }} /> : null}
124
144
  </>;
125
145
  }
@@ -134,7 +154,7 @@ function ConfirmActionModal({ action, app, close, commandPreview, confirm }: { a
134
154
  <code>{commandPreview}</code>
135
155
  <div className="confirm-modal-actions">
136
156
  <button className="secondary-action" onClick={close} type="button">Cancel</button>
137
- <button className={action === "remove" ? "app-action-button remove" : "app-action-button"} onClick={confirm} type="button">Confirm</button>
157
+ <button className={appActionButtonClass(action)} onClick={confirm} type="button">Confirm</button>
138
158
  </div>
139
159
  </section>
140
160
  </div>
@@ -137,6 +137,46 @@
137
137
  --glass-panel-shadow: var(--shadow-soft);
138
138
  }
139
139
 
140
+ :root[data-borders="hidden"] :where(
141
+ .machine-rail,
142
+ .app-sidebar,
143
+ .app-inset,
144
+ .desktop-status-bar,
145
+ .workspace-header,
146
+ button,
147
+ input,
148
+ select,
149
+ textarea,
150
+ [class*="badge"],
151
+ [class*="button"],
152
+ [class*="card"],
153
+ [class*="control"],
154
+ [class*="entry"],
155
+ [class*="item"],
156
+ [class*="menu"],
157
+ [class*="orb"],
158
+ [class*="panel"],
159
+ [class*="pill"],
160
+ [class*="preview"],
161
+ [class*="row"],
162
+ [class*="selector"],
163
+ [class*="surface"],
164
+ [class*="switch"],
165
+ [class*="tag"]
166
+ ) {
167
+ border-color: transparent !important;
168
+ }
169
+
170
+ :root[data-borders="hidden"] :where(
171
+ .github-notification-card,
172
+ .managed-app-card,
173
+ .notification-preview,
174
+ .status-dot,
175
+ .terminal-mark
176
+ ) {
177
+ box-shadow: none;
178
+ }
179
+
140
180
  *,
141
181
  *::before,
142
182
  *::after {
@@ -1136,7 +1176,7 @@ code {
1136
1176
 
1137
1177
  .notification-dot {
1138
1178
  background: var(--accent);
1139
- border: 2px solid var(--surface-elevated);
1179
+ border: 2px solid var(--border-accent);
1140
1180
  border-radius: 999px;
1141
1181
  height: 10px;
1142
1182
  position: absolute;
@@ -1192,7 +1232,7 @@ code {
1192
1232
  .notification-preview {
1193
1233
  background: var(--notification-bg, transparent);
1194
1234
  border: 1px solid var(--border);
1195
- border-left: 4px solid var(--notification-color, var(--accent));
1235
+ border-left: 4px solid var(--border-accent);
1196
1236
  border-radius: 12px;
1197
1237
  color: var(--text-secondary);
1198
1238
  cursor: pointer;
@@ -1204,7 +1244,7 @@ code {
1204
1244
 
1205
1245
  .notification-preview:hover,
1206
1246
  .notification-preview:focus-visible {
1207
- border-color: var(--notification-color, var(--accent));
1247
+ border-color: var(--border-accent);
1208
1248
  outline: none;
1209
1249
  }
1210
1250
 
@@ -1786,7 +1826,7 @@ code {
1786
1826
  .github-notification-card {
1787
1827
  background: var(--surface-elevated);
1788
1828
  border: 1px solid var(--border);
1789
- border-left: 5px solid var(--notification-color, var(--accent));
1829
+ border-left: 5px solid var(--border-accent);
1790
1830
  border-radius: 18px;
1791
1831
  box-shadow: var(--glass-panel-shadow);
1792
1832
  display: grid;
@@ -2457,7 +2497,7 @@ button.managed-toggle:focus-visible {
2457
2497
  .app-action-button:hover,
2458
2498
  .app-action-button:focus-visible {
2459
2499
  background: var(--accent);
2460
- border-color: var(--accent);
2500
+ border-color: var(--border-accent);
2461
2501
  color: var(--bg-primary);
2462
2502
  outline: none;
2463
2503
  transform: translateY(-1px);
@@ -2465,14 +2505,14 @@ button.managed-toggle:focus-visible {
2465
2505
 
2466
2506
  .app-action-button.remove {
2467
2507
  background: color-mix(in srgb, #ef4444 12%, var(--surface-elevated));
2468
- border-color: color-mix(in srgb, #ef4444 45%, var(--border));
2508
+ border-color: var(--border-danger);
2469
2509
  color: #ff8a8a;
2470
2510
  }
2471
2511
 
2472
2512
  .app-action-button.remove:hover,
2473
2513
  .app-action-button.remove:focus-visible {
2474
2514
  background: #ef4444;
2475
- border-color: #ef4444;
2515
+ border-color: var(--border-danger);
2476
2516
  color: white;
2477
2517
  }
2478
2518
 
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.28
15
+ # Version: 3.29.30
16
16
  #
17
17
  # Quick Install:
18
18
  # npm install -g aidevops && aidevops update (recommended)