aidevops 3.32.0 → 3.32.1

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
@@ -60,7 +60,7 @@ The result: an AI operations platform that manages projects across every busines
60
60
  [![Copyright](https://img.shields.io/badge/Copyright-Marcus%20Quinn%202025--2026-blue.svg)](https://github.com/marcusquinn)
61
61
 
62
62
  <!-- Release & Version Info -->
63
- [![Version](https://img.shields.io/badge/Version-3.32.0-blue.svg)](https://github.com/marcusquinn/aidevops/releases)
63
+ [![Version](https://img.shields.io/badge/Version-3.32.1-blue.svg)](https://github.com/marcusquinn/aidevops/releases)
64
64
  [![npm version](https://img.shields.io/npm/v/aidevops)](https://www.npmjs.com/package/aidevops)
65
65
  [![Homebrew](https://img.shields.io/badge/homebrew-marcusquinn%2Ftap-orange)](https://github.com/marcusquinn/homebrew-tap)
66
66
  [![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.32.0
1
+ 3.32.1
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.32.0
8
+ # Version: 3.32.1
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.32.0",
3
+ "version": "3.32.1",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -1,5 +1,5 @@
1
1
  import type { GuiResponseEnvelope, GuiStatusData } from "@aidevops/gui-shared";
2
- import { type KeyboardEvent as ReactKeyboardEvent, type MouseEvent as ReactMouseEvent, type ReactElement, useEffect, useState } from "react";
2
+ import { type KeyboardEvent as ReactKeyboardEvent, type MouseEvent as ReactMouseEvent, type ReactElement, useEffect, useRef, useState } from "react";
3
3
  import { MachineRail, Sidebar } from "./AppNavigation";
4
4
  import { Workspace } from "./AppWorkspace";
5
5
  import type { ContrastPreference, ConversationMode, FontPreference, FontSizePreference, ShellMode, SurfaceId, ThemePreference } from "./app-model";
@@ -108,6 +108,7 @@ export function App(): ReactElement {
108
108
  const [selectedLocalRepoIndex, setSelectedLocalRepoIndex] = useState(0);
109
109
  const [selectedSessionId, setSelectedSessionId] = useState<string | undefined>();
110
110
  const [vaultDialogIntent, setVaultDialogIntent] = useState<VaultDialogIntent | null>(null);
111
+ const hasPromptedVaultSetup = useRef(false);
111
112
  const [systemTheme, setSystemTheme] = useState<"light" | "dark">("light");
112
113
  const resolvedTheme = themePreference === "system" ? systemTheme : themePreference;
113
114
  const activeSurface: SurfaceId = navigation.entries[navigation.index] ?? "overview";
@@ -213,7 +214,8 @@ export function App(): ReactElement {
213
214
  }, [status.data.local_repos.repos.length]);
214
215
 
215
216
  useEffect(() => {
216
- if (!statusLoading && status.data.vault.readiness.setup_required) {
217
+ if (shouldPromptVaultSetup(statusLoading, status.data.vault.readiness.setup_required, hasPromptedVaultSetup.current)) {
218
+ hasPromptedVaultSetup.current = true;
217
219
  setVaultDialogIntent("setup");
218
220
  }
219
221
  }, [status.data.vault.readiness.setup_required, statusLoading]);
@@ -343,6 +345,10 @@ export function clampSidebarWidth(width: number): number {
343
345
  return Math.min(maxSidebarWidth, Math.max(minSidebarWidth, Math.round(width)));
344
346
  }
345
347
 
348
+ export function shouldPromptVaultSetup(statusLoading: boolean, setupRequired: boolean, hasPromptedVaultSetup: boolean): boolean {
349
+ return !statusLoading && setupRequired && !hasPromptedVaultSetup;
350
+ }
351
+
346
352
  function SidebarResizeHandle(): ReactElement {
347
353
  const [sidebarWidth, setSidebarWidth] = useState(() => readStoredSidebarWidth());
348
354
 
@@ -369,8 +369,8 @@ function SidebarItem({ activeSurface, item, onVaultRequest, recordCount, setActi
369
369
  {shouldShowCount ? <span className="surface-count">({recordCount})</span> : null}
370
370
  </span>
371
371
  </span>
372
- {vaultCollection ? <VaultPadlock collection={vaultCollection} compact vault={status.vault} /> : null}
373
372
  {item.badge ? <em>{item.badge}</em> : null}
373
+ {vaultCollection ? <VaultPadlock collection={vaultCollection} compact vault={status.vault} /> : null}
374
374
  </button>
375
375
  </li>
376
376
  );
@@ -51,7 +51,18 @@ export function VaultPassphraseModal({ intent, onClose, vault }: {
51
51
 
52
52
  return (
53
53
  <div className="vault-modal-backdrop" role="presentation">
54
- <section aria-label={title} aria-modal="true" className="vault-modal" role="dialog">
54
+ <form
55
+ aria-label={title}
56
+ aria-modal="true"
57
+ className="vault-modal"
58
+ onSubmit={(event) => {
59
+ event.preventDefault();
60
+ if (canContinue) {
61
+ continueFlow();
62
+ }
63
+ }}
64
+ role="dialog"
65
+ >
55
66
  <header className="vault-modal-header">
56
67
  <span className="vault-modal-icon" aria-hidden="true">{intent === "lock" ? <FiLock /> : <FiUnlock />}</span>
57
68
  <div>
@@ -62,10 +73,10 @@ export function VaultPassphraseModal({ intent, onClose, vault }: {
62
73
  {setupMode ? <SetupStep accepted={savedWarningAccepted} confirm={passphraseConfirm} match={setupPassphrasesMatch} onAcceptChange={setSavedWarningAccepted} onConfirmChange={setPassphraseConfirm} onPassphraseChange={setPassphrase} onUnlockPassphraseChange={setUnlockPassphrase} passphrase={passphrase} step={step} unlockMatch={finalPassphraseMatches} unlockPassphrase={unlockPassphrase} /> : <UnlockStep intent={intent} onUnlockPassphraseChange={setUnlockPassphrase} unlockPassphrase={unlockPassphrase} vault={vault} />}
63
74
  <footer className="vault-modal-actions">
64
75
  <button className="secondary-action" onClick={onClose} type="button">Cancel</button>
65
- <button className="primary-action" disabled={!canContinue} onClick={continueFlow} type="button">{setupMode && step < 2 ? "Continue" : actionLabel}</button>
76
+ <button className="primary-action" disabled={!canContinue} type="submit">{setupMode && step < 2 ? "Continue" : actionLabel}</button>
66
77
  </footer>
67
78
  <p className="vault-modal-footnote">Passphrases stay in this local dialog state only and are never shown in logs, issues, command arguments, or AI chat.</p>
68
- </section>
79
+ </form>
69
80
  </div>
70
81
  );
71
82
  }
@@ -239,10 +239,65 @@ body {
239
239
 
240
240
  button,
241
241
  input,
242
- select {
242
+ select,
243
+ textarea {
243
244
  font: inherit;
244
245
  }
245
246
 
247
+ :where(input:not([type="range"]):not([type="checkbox"]):not([type="radio"]):not([type="color"]), select, textarea) {
248
+ background:
249
+ linear-gradient(180deg, rgb(255 255 255 / 12%), rgb(255 255 255 / 0%)),
250
+ color-mix(in srgb, var(--surface-muted) 88%, var(--surface-elevated));
251
+ border: 1px solid color-mix(in srgb, var(--border) 86%, var(--surface-elevated));
252
+ border-radius: 12px;
253
+ box-shadow:
254
+ inset 0 1px 0 rgb(255 255 255 / 18%),
255
+ inset 0 -1px 0 rgb(0 0 0 / 8%),
256
+ 0 1px 2px rgb(0 0 0 / 8%);
257
+ color: var(--text-primary);
258
+ min-height: 38px;
259
+ padding: 8px 12px;
260
+ transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease, color 140ms ease;
261
+ }
262
+
263
+ :where(input:not([type="range"]):not([type="checkbox"]):not([type="radio"]):not([type="color"]), select, textarea)::placeholder {
264
+ color: color-mix(in srgb, var(--text-muted) 78%, transparent);
265
+ }
266
+
267
+ :where(input:not([type="range"]):not([type="checkbox"]):not([type="radio"]):not([type="color"]), select, textarea):hover:not(:disabled) {
268
+ border-color: var(--border-hover);
269
+ }
270
+
271
+ :where(input:not([type="range"]):not([type="checkbox"]):not([type="radio"]):not([type="color"]), select, textarea):focus-visible {
272
+ border-color: color-mix(in srgb, var(--accent) 58%, var(--border));
273
+ box-shadow:
274
+ 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent),
275
+ inset 0 1px 0 rgb(255 255 255 / 22%),
276
+ 0 1px 2px rgb(0 0 0 / 10%);
277
+ outline: none;
278
+ }
279
+
280
+ :where(input:not([type="range"]):not([type="checkbox"]):not([type="radio"]):not([type="color"]), select, textarea):disabled {
281
+ color: var(--text-secondary);
282
+ cursor: not-allowed;
283
+ opacity: 0.9;
284
+ }
285
+
286
+ select {
287
+ appearance: none;
288
+ background-image:
289
+ linear-gradient(45deg, transparent 50%, var(--text-muted) 50%),
290
+ linear-gradient(135deg, var(--text-muted) 50%, transparent 50%),
291
+ linear-gradient(180deg, rgb(255 255 255 / 12%), rgb(255 255 255 / 0%));
292
+ background-position:
293
+ calc(100% - 16px) 50%,
294
+ calc(100% - 11px) 50%,
295
+ 0 0;
296
+ background-repeat: no-repeat;
297
+ background-size: 5px 5px, 5px 5px, 100% 100%;
298
+ padding-right: 32px;
299
+ }
300
+
246
301
  button {
247
302
  cursor: pointer;
248
303
  }
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.32.0
15
+ # Version: 3.32.1
16
16
  #
17
17
  # Quick Install:
18
18
  # npm install -g aidevops && aidevops update (recommended)