aidevops 3.29.29 → 3.29.31

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.29-blue.svg)](https://github.com/marcusquinn/aidevops/releases)
61
+ [![Version](https://img.shields.io/badge/Version-3.29.31-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.29
1
+ 3.29.31
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.29
8
+ # Version: 3.29.31
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.29",
3
+ "version": "3.29.31",
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>
@@ -134,7 +134,7 @@
134
134
  --border-danger: transparent;
135
135
  --border-hover: transparent;
136
136
  --border-warning: transparent;
137
- --glass-panel-shadow: var(--shadow-soft);
137
+ --glass-panel-shadow: none;
138
138
  }
139
139
 
140
140
  :root[data-borders="hidden"] :where(
@@ -142,6 +142,10 @@
142
142
  .app-sidebar,
143
143
  .app-inset,
144
144
  .desktop-status-bar,
145
+ .app-global-tooltip,
146
+ .confirm-modal,
147
+ .loading-brand-overlay,
148
+ .popover-menu,
145
149
  .workspace-header,
146
150
  button,
147
151
  input,
@@ -151,30 +155,44 @@
151
155
  [class*="button"],
152
156
  [class*="card"],
153
157
  [class*="control"],
158
+ [class*="dot"],
154
159
  [class*="entry"],
155
160
  [class*="item"],
161
+ [class*="loading"],
162
+ [class*="mark"],
156
163
  [class*="menu"],
164
+ [class*="modal"],
157
165
  [class*="orb"],
158
166
  [class*="panel"],
159
167
  [class*="pill"],
168
+ [class*="popover"],
160
169
  [class*="preview"],
161
170
  [class*="row"],
162
171
  [class*="selector"],
163
172
  [class*="surface"],
164
173
  [class*="switch"],
165
- [class*="tag"]
174
+ [class*="tag"],
175
+ [class*="tooltip"]
166
176
  ) {
167
177
  border-color: transparent !important;
178
+ box-shadow: none !important;
179
+ outline-color: transparent !important;
168
180
  }
169
181
 
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;
182
+ :root[data-borders="hidden"] *,
183
+ :root[data-borders="hidden"] *::before,
184
+ :root[data-borders="hidden"] *::after {
185
+ border-color: transparent !important;
186
+ outline-color: transparent !important;
187
+ }
188
+
189
+ :root[data-borders="hidden"] [data-tooltip]::after {
190
+ border-color: transparent !important;
191
+ box-shadow: none !important;
192
+ }
193
+
194
+ :root[data-borders="hidden"] .desktop-status-bar span:not(.status-dot)::before {
195
+ color: transparent !important;
178
196
  }
179
197
 
180
198
  *,
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.29
15
+ # Version: 3.29.31
16
16
  #
17
17
  # Quick Install:
18
18
  # npm install -g aidevops && aidevops update (recommended)