aidevops 3.25.0 → 3.26.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.
- package/README.md +1 -1
- package/VERSION +1 -1
- package/aidevops.sh +1 -1
- package/package.json +1 -1
- package/packages/gui-web/src/AppNavigation.tsx +37 -20
- package/packages/gui-web/src/AppWorkspace.tsx +96 -12
- package/packages/gui-web/src/styles.css +69 -20
- package/setup.sh +1 -1
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ The result: an AI operations platform that manages projects across every busines
|
|
|
58
58
|
[](https://github.com/marcusquinn)
|
|
59
59
|
|
|
60
60
|
<!-- Release & Version Info -->
|
|
61
|
-
[](https://github.com/marcusquinn/aidevops/releases)
|
|
62
62
|
[](https://www.npmjs.com/package/aidevops)
|
|
63
63
|
[](https://github.com/marcusquinn/homebrew-tap)
|
|
64
64
|
[](https://github.com/marcusquinn/aidevops)
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.26.0
|
package/aidevops.sh
CHANGED
package/package.json
CHANGED
|
@@ -221,14 +221,14 @@ function ConversationSidebar({ conversationMode, selectedLocalRepoIndex, setConv
|
|
|
221
221
|
{conversationMode === "people" ? <PeopleChannelList /> : <>
|
|
222
222
|
<button className="new-session-button" disabled title="Creating sessions needs an audited OpenCode write route." type="button">{text.newSession}</button>
|
|
223
223
|
<section className="repo-session-selector" aria-label={text.localRepoSelector}>
|
|
224
|
-
<
|
|
225
|
-
<
|
|
226
|
-
<
|
|
227
|
-
<select onChange={(event) => setSelectedLocalRepoIndex(Number.parseInt(event.currentTarget.value, 10))} value={Math.min(selectedLocalRepoIndex, Math.max(0, repos.length - 1))}>
|
|
224
|
+
<span className="repo-selector-heading" id="local-repo-selector-label">{text.localRepos}</span>
|
|
225
|
+
<div className="selector-with-stepper repo-selector-row">
|
|
226
|
+
<button aria-label="Previous local repo" className="selector-step-button" disabled={!canSelectPreviousRepo} onClick={() => setSelectedLocalRepoIndex(Math.max(0, selectedLocalRepoIndex - 1))} type="button"><FiChevronLeft aria-hidden="true" /></button>
|
|
227
|
+
<select aria-labelledby="local-repo-selector-label" onChange={(event) => setSelectedLocalRepoIndex(Number.parseInt(event.currentTarget.value, 10))} value={Math.min(selectedLocalRepoIndex, Math.max(0, repos.length - 1))}>
|
|
228
228
|
{repos.length === 0 ? <option value={0}>No local repos</option> : repos.map((repo, index) => <option key={repo.path_ref} value={index}>{repo.name}</option>)}
|
|
229
229
|
</select>
|
|
230
|
-
|
|
231
|
-
|
|
230
|
+
<button aria-label="Next local repo" className="selector-step-button" disabled={!canSelectNextRepo} onClick={() => setSelectedLocalRepoIndex(Math.min(repos.length - 1, selectedLocalRepoIndex + 1))} type="button"><FiChevronRight aria-hidden="true" /></button>
|
|
231
|
+
</div>
|
|
232
232
|
</section>
|
|
233
233
|
<section className="sidebar-group session-history-list">
|
|
234
234
|
<h2>{text.sessionHistory}</h2>
|
|
@@ -386,8 +386,20 @@ function SidebarFooter({ accentHue, fontPreference, fontSizePreference, setAccen
|
|
|
386
386
|
const [appearanceOpen, setAppearanceOpen] = useState(true);
|
|
387
387
|
const AppearanceChevron = appearanceOpen ? FiChevronDown : FiChevronUp;
|
|
388
388
|
const selectedFontFamily = fontFamilyForPreference(fontPreference);
|
|
389
|
+
const fontIndex = Math.max(0, fontOptions.findIndex((option) => option.value === fontPreference));
|
|
389
390
|
const fontSizeIndex = Math.max(0, fontSizeOptions.findIndex((option) => option.value === fontSizePreference));
|
|
391
|
+
const canSelectPreviousFont = fontIndex > 0;
|
|
392
|
+
const canSelectNextFont = fontIndex < fontOptions.length - 1;
|
|
390
393
|
const [hueInput, setHueInput] = useState(() => String(accentHue));
|
|
394
|
+
const setFontByIndex = (index: number) => {
|
|
395
|
+
const nextFont = fontOptions[index]?.value;
|
|
396
|
+
|
|
397
|
+
if (nextFont === undefined) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
setFontPreference(nextFont);
|
|
402
|
+
};
|
|
391
403
|
const updateAccentHue = (value: number) => {
|
|
392
404
|
if (!Number.isFinite(value)) {
|
|
393
405
|
return;
|
|
@@ -486,20 +498,25 @@ function SidebarFooter({ accentHue, fontPreference, fontSizePreference, setAccen
|
|
|
486
498
|
{fontSizeOptions.map((option) => <span className={option.value === fontSizePreference ? "active" : ""} key={option.value}>{option.label}</span>)}
|
|
487
499
|
</div>
|
|
488
500
|
</div>
|
|
489
|
-
<
|
|
490
|
-
<span>{text.font}</span>
|
|
491
|
-
<
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
501
|
+
<div className="font-control">
|
|
502
|
+
<span id="appearance-font-selector-label">{text.font}</span>
|
|
503
|
+
<div className="selector-with-stepper font-selector-row">
|
|
504
|
+
<button aria-label="Previous font" className="selector-step-button" disabled={!canSelectPreviousFont} onClick={() => setFontByIndex(fontIndex - 1)} type="button"><FiChevronLeft aria-hidden="true" /></button>
|
|
505
|
+
<select
|
|
506
|
+
aria-labelledby="appearance-font-selector-label"
|
|
507
|
+
onChange={(event) => setFontPreference(event.currentTarget.value as FontPreference)}
|
|
508
|
+
style={{ fontFamily: selectedFontFamily }}
|
|
509
|
+
value={fontPreference}
|
|
510
|
+
>
|
|
511
|
+
{fontOptions.map((option) => (
|
|
512
|
+
<option key={option.value} style={{ fontFamily: option.fontFamily }} value={option.value}>
|
|
513
|
+
{option.label}
|
|
514
|
+
</option>
|
|
515
|
+
))}
|
|
516
|
+
</select>
|
|
517
|
+
<button aria-label="Next font" className="selector-step-button" disabled={!canSelectNextFont} onClick={() => setFontByIndex(fontIndex + 1)} type="button"><FiChevronRight aria-hidden="true" /></button>
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
503
520
|
</div>
|
|
504
521
|
: null}
|
|
505
522
|
</section>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* jshint esversion: 11 */
|
|
2
|
-
import { type ReactElement, type ReactNode, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { type ReactElement, type ReactNode, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { FiBell, FiChevronLeft, FiChevronRight, FiCommand, FiCpu, FiGlobe, FiHash, FiLogOut, FiMessageSquare, FiSearch, FiSettings, FiShield, FiUser } from "react-icons/fi";
|
|
4
4
|
import type { GuiFileRootId, GuiStatusData } from "../../gui-shared/src";
|
|
5
5
|
import { SurfaceGlyph } from "./AppNavigation";
|
|
@@ -54,6 +54,7 @@ function WorkspaceHeader({ activeItem, activeSectionLabel, activeSurface, canGoB
|
|
|
54
54
|
status: GuiStatusData;
|
|
55
55
|
}): ReactElement {
|
|
56
56
|
const [assistantOpen, setAssistantOpen] = useState(false);
|
|
57
|
+
const [commandInitialQuery, setCommandInitialQuery] = useState("");
|
|
57
58
|
const [commandOpen, setCommandOpen] = useState(false);
|
|
58
59
|
const [notificationsOpen, setNotificationsOpen] = useState(false);
|
|
59
60
|
const [profileOpen, setProfileOpen] = useState(false);
|
|
@@ -64,6 +65,14 @@ function WorkspaceHeader({ activeItem, activeSectionLabel, activeSurface, canGoB
|
|
|
64
65
|
const openCommandPalette = (event: KeyboardEvent) => {
|
|
65
66
|
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
|
|
66
67
|
event.preventDefault();
|
|
68
|
+
setCommandInitialQuery("");
|
|
69
|
+
setCommandOpen(true);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (event.key === "/" && !isEditableShortcutTarget(event.target)) {
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
setCommandInitialQuery("/");
|
|
67
76
|
setCommandOpen(true);
|
|
68
77
|
}
|
|
69
78
|
};
|
|
@@ -92,16 +101,18 @@ function WorkspaceHeader({ activeItem, activeSectionLabel, activeSurface, canGoB
|
|
|
92
101
|
<h1>{activeItem.label}</h1>
|
|
93
102
|
</div>
|
|
94
103
|
</div>
|
|
95
|
-
<div className="header-
|
|
104
|
+
<div className="header-center-controls">
|
|
96
105
|
<div className="sidebar-history-controls workspace-history-controls">
|
|
97
106
|
<button aria-label="Previous surface" disabled={!canGoBack} onClick={goBack} type="button"><FiChevronLeft /></button>
|
|
98
107
|
<button aria-label="Next surface" disabled={!canGoForward} onClick={goForward} type="button"><FiChevronRight /></button>
|
|
99
108
|
</div>
|
|
100
|
-
<button className="workspace-search command-trigger" onClick={() => setCommandOpen(true)} type="button">
|
|
109
|
+
<button className="workspace-search command-trigger" onClick={() => { setCommandInitialQuery(""); setCommandOpen(true); }} type="button">
|
|
101
110
|
<FiSearch aria-hidden="true" />
|
|
102
111
|
<span>⌘K</span>
|
|
103
112
|
<strong>{text.searchPlaceholder}</strong>
|
|
104
113
|
</button>
|
|
114
|
+
</div>
|
|
115
|
+
<div className="header-actions">
|
|
105
116
|
<div className="header-action-menu">
|
|
106
117
|
<button aria-expanded={notificationsOpen} aria-label="Open notifications" className="header-icon-button" onClick={() => { setNotificationsOpen((current) => !current); setProfileOpen(false); }} type="button">
|
|
107
118
|
<FiBell aria-hidden="true" />
|
|
@@ -120,11 +131,19 @@ function WorkspaceHeader({ activeItem, activeSectionLabel, activeSurface, canGoB
|
|
|
120
131
|
</div>
|
|
121
132
|
</div>
|
|
122
133
|
{assistantOpen ? <AssistantPanel activeSurface={activeSurface} userName={userName} /> : null}
|
|
123
|
-
{commandOpen ? <CommandPalette close={() => setCommandOpen(false)} openSurface={openSurface} /> : null}
|
|
134
|
+
{commandOpen ? <CommandPalette close={() => setCommandOpen(false)} initialQuery={commandInitialQuery} openSurface={openSurface} status={status} /> : null}
|
|
124
135
|
</header>
|
|
125
136
|
);
|
|
126
137
|
}
|
|
127
138
|
|
|
139
|
+
function isEditableShortcutTarget(target: EventTarget | null): boolean {
|
|
140
|
+
if (!(target instanceof HTMLElement)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return target.isContentEditable || ["INPUT", "SELECT", "TEXTAREA"].includes(target.tagName);
|
|
145
|
+
}
|
|
146
|
+
|
|
128
147
|
function NotificationsMenu({ openSurface }: { openSurface: (surface: SurfaceId) => void }): ReactElement {
|
|
129
148
|
return (
|
|
130
149
|
<div className="popover-menu notifications-menu" role="menu">
|
|
@@ -216,14 +235,79 @@ function AssistantPanel({ activeSurface, userName }: { activeSurface: SurfaceId;
|
|
|
216
235
|
);
|
|
217
236
|
}
|
|
218
237
|
|
|
219
|
-
|
|
220
|
-
|
|
238
|
+
interface CommandPaletteItem {
|
|
239
|
+
description: string;
|
|
240
|
+
icon: SurfaceNavItem["icon"];
|
|
241
|
+
id: string;
|
|
242
|
+
label: string;
|
|
243
|
+
searchText: string;
|
|
244
|
+
surface: SurfaceId;
|
|
245
|
+
tag: string;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const slashCommandItems: CommandPaletteItem[] = [
|
|
249
|
+
{ id: "slash-add-device", label: "/add-device", description: "Start device pairing setup", icon: "device", searchText: "/add-device add device pair machine", surface: "devices", tag: "Command" },
|
|
250
|
+
{ id: "slash-add-local-repo", label: "/add-local-repo", description: "Add a local repository path", icon: "folder", searchText: "/add-local-repo add local repo git", surface: "git", tag: "Command" },
|
|
251
|
+
{ id: "slash-add-remote-repo", label: "/add-remote-repo", description: "Register a remote repository", icon: "git", searchText: "/add-remote-repo add remote repo", surface: "projects", tag: "Command" },
|
|
252
|
+
{ id: "slash-add-secret", label: "/add-secret", description: "Add a protected secret reference", icon: "shield", searchText: "/add-secret add secret vault", surface: "security", tag: "Command" },
|
|
253
|
+
{ id: "slash-add-ai-provider", label: "/add-ai-provider", description: "Connect an AI provider account", icon: "users", searchText: "/add-ai-provider add ai provider oauth", surface: "aiProviders", tag: "Command" },
|
|
254
|
+
];
|
|
255
|
+
|
|
256
|
+
const plannedChannelItems: CommandPaletteItem[] = [
|
|
257
|
+
{ id: "channel-devops", label: "#devops", description: "Chat channel for aidevops operations", icon: "message", searchText: "#devops devops channel chat", surface: "messagingAccounts", tag: "Channel" },
|
|
258
|
+
{ id: "channel-comms", label: "#comms", description: "Chat channel for communications", icon: "message", searchText: "#comms comms channel chat", surface: "messagingAccounts", tag: "Channel" },
|
|
259
|
+
];
|
|
260
|
+
|
|
261
|
+
function CommandPalette({ close, initialQuery, openSurface, status }: { close: () => void; initialQuery: string; openSurface: (surface: SurfaceId) => void; status: GuiStatusData }): ReactElement {
|
|
262
|
+
const [query, setQuery] = useState(initialQuery);
|
|
263
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
221
264
|
const matches = useMemo(() => {
|
|
222
265
|
const normalizedQuery = query.trim().toLowerCase();
|
|
223
|
-
|
|
224
|
-
|
|
266
|
+
const surfaceItems: CommandPaletteItem[] = orderedNavItems.map((item) => ({
|
|
267
|
+
description: item.description,
|
|
268
|
+
icon: item.icon,
|
|
269
|
+
id: `surface-${item.id}`,
|
|
270
|
+
label: item.label,
|
|
271
|
+
searchText: `${item.label} ${item.description}`,
|
|
272
|
+
surface: item.id,
|
|
273
|
+
tag: "Surface",
|
|
274
|
+
}));
|
|
275
|
+
const sessionItems: CommandPaletteItem[] = status.opencode_sessions.sessions.map((session) => ({
|
|
276
|
+
description: `AI session in ${session.repo_path_ref}`,
|
|
277
|
+
icon: "terminal",
|
|
278
|
+
id: `session-${session.id_ref}`,
|
|
279
|
+
label: `#${session.title}`,
|
|
280
|
+
searchText: `#${session.title} ${session.title} ${session.repo_path_ref} ${session.agent} ${session.model}`,
|
|
281
|
+
surface: "git",
|
|
282
|
+
tag: "AI session",
|
|
283
|
+
}));
|
|
284
|
+
const directMessageItems: CommandPaletteItem[] = [{
|
|
285
|
+
description: "Direct message thread placeholder",
|
|
286
|
+
icon: "users",
|
|
287
|
+
id: "dm-local-user",
|
|
288
|
+
label: `@${status.machine.username || "local-user"}`,
|
|
289
|
+
searchText: `@${status.machine.username || "local-user"} direct message dm person local user`,
|
|
290
|
+
surface: "messagingAccounts",
|
|
291
|
+
tag: "Direct message",
|
|
292
|
+
}];
|
|
293
|
+
const items = [...surfaceItems, ...sessionItems, ...plannedChannelItems, ...directMessageItems, ...slashCommandItems];
|
|
294
|
+
const prefix = normalizedQuery.charAt(0);
|
|
295
|
+
const scopedItems = prefix === "/"
|
|
296
|
+
? slashCommandItems
|
|
297
|
+
: prefix === "@"
|
|
298
|
+
? directMessageItems
|
|
299
|
+
: prefix === "#"
|
|
300
|
+
? [...sessionItems, ...plannedChannelItems]
|
|
301
|
+
: items;
|
|
302
|
+
|
|
303
|
+
return scopedItems
|
|
304
|
+
.filter((item) => normalizedQuery.length === 0 || item.searchText.toLowerCase().includes(normalizedQuery))
|
|
225
305
|
.slice(0, 8);
|
|
226
|
-
}, [query]);
|
|
306
|
+
}, [query, status.machine.username, status.opencode_sessions.sessions]);
|
|
307
|
+
|
|
308
|
+
useEffect(() => {
|
|
309
|
+
inputRef.current?.focus();
|
|
310
|
+
}, []);
|
|
227
311
|
|
|
228
312
|
useEffect(() => {
|
|
229
313
|
const closeOnEscape = (event: KeyboardEvent) => {
|
|
@@ -242,14 +326,14 @@ function CommandPalette({ close, openSurface }: { close: () => void; openSurface
|
|
|
242
326
|
<section aria-label="Command palette" className="command-palette">
|
|
243
327
|
<label className="command-input-row">
|
|
244
328
|
<FiSearch aria-hidden="true" />
|
|
245
|
-
<input onChange={(event) => setQuery(event.currentTarget.value)} placeholder="Search commands
|
|
329
|
+
<input ref={inputRef} onChange={(event) => setQuery(event.currentTarget.value)} placeholder="Search commands, #sessions, #channels, @people, or /actions" value={query} />
|
|
246
330
|
</label>
|
|
247
331
|
<ul>
|
|
248
332
|
{matches.map((item) => (
|
|
249
333
|
<li key={item.id}>
|
|
250
|
-
<button onClick={() => openSurface(item.
|
|
334
|
+
<button onClick={() => openSurface(item.surface)} type="button">
|
|
251
335
|
<span className="surface-icon" aria-hidden="true"><SurfaceGlyph icon={item.icon} /></span>
|
|
252
|
-
<span><strong>{item.label}</strong><small>{item.description}</small></span>
|
|
336
|
+
<span><strong>{item.label}</strong><small>{item.tag} · {item.description}</small></span>
|
|
253
337
|
</button>
|
|
254
338
|
</li>
|
|
255
339
|
))}
|
|
@@ -211,6 +211,7 @@ code {
|
|
|
211
211
|
.theme-control-heading,
|
|
212
212
|
.appearance-panel-tab,
|
|
213
213
|
.header-title,
|
|
214
|
+
.header-center-controls,
|
|
214
215
|
.header-actions,
|
|
215
216
|
.workspace-search,
|
|
216
217
|
.version-pill,
|
|
@@ -377,42 +378,65 @@ code {
|
|
|
377
378
|
}
|
|
378
379
|
|
|
379
380
|
.repo-session-selector {
|
|
380
|
-
|
|
381
|
+
display: grid;
|
|
382
|
+
gap: 7px;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.selector-with-stepper {
|
|
386
|
+
align-items: center;
|
|
381
387
|
display: grid;
|
|
382
388
|
gap: 8px;
|
|
383
389
|
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
384
390
|
}
|
|
385
391
|
|
|
386
|
-
.repo-session-selector button
|
|
392
|
+
.repo-session-selector .selector-step-button,
|
|
393
|
+
.selector-step-button {
|
|
387
394
|
align-items: center;
|
|
388
395
|
background: var(--surface-muted);
|
|
389
396
|
border: 1px solid var(--border);
|
|
390
397
|
border-radius: 999px;
|
|
391
398
|
color: var(--text-secondary);
|
|
392
399
|
display: inline-flex;
|
|
393
|
-
height:
|
|
400
|
+
height: 40px;
|
|
394
401
|
justify-content: center;
|
|
395
|
-
width: 34px;
|
|
396
402
|
}
|
|
397
403
|
|
|
398
|
-
.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
min-width: 0;
|
|
404
|
+
.selector-step-button {
|
|
405
|
+
padding: 0;
|
|
406
|
+
width: 40px;
|
|
402
407
|
}
|
|
403
408
|
|
|
404
|
-
.
|
|
409
|
+
.selector-step-button:hover:not(:disabled),
|
|
410
|
+
.selector-step-button:focus-visible {
|
|
411
|
+
border-color: color-mix(in srgb, var(--accent) 40%, transparent);
|
|
412
|
+
color: var(--accent);
|
|
413
|
+
outline: none;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.selector-step-button svg {
|
|
417
|
+
height: 18px;
|
|
418
|
+
stroke-width: 2.5;
|
|
419
|
+
width: 18px;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
.repo-selector-heading {
|
|
405
423
|
color: var(--text-muted);
|
|
406
424
|
font-size: 0.72rem;
|
|
407
425
|
font-weight: 900;
|
|
426
|
+
text-align: center;
|
|
408
427
|
text-transform: uppercase;
|
|
409
428
|
}
|
|
410
429
|
|
|
430
|
+
.repo-selector-row {
|
|
431
|
+
align-items: center;
|
|
432
|
+
}
|
|
433
|
+
|
|
411
434
|
.repo-session-selector select {
|
|
412
435
|
background: var(--surface-muted);
|
|
413
436
|
border: 1px solid var(--border);
|
|
414
437
|
border-radius: 10px;
|
|
415
438
|
color: var(--text-primary);
|
|
439
|
+
min-height: 40px;
|
|
416
440
|
min-width: 0;
|
|
417
441
|
padding: 8px;
|
|
418
442
|
}
|
|
@@ -754,11 +778,16 @@ code {
|
|
|
754
778
|
border: 1px solid var(--border);
|
|
755
779
|
border-radius: 12px;
|
|
756
780
|
color: var(--text-primary);
|
|
781
|
+
min-height: 40px;
|
|
757
782
|
min-width: 0;
|
|
758
783
|
padding: 9px 10px;
|
|
759
784
|
width: 100%;
|
|
760
785
|
}
|
|
761
786
|
|
|
787
|
+
.font-selector-row {
|
|
788
|
+
align-items: center;
|
|
789
|
+
}
|
|
790
|
+
|
|
762
791
|
.app-inset {
|
|
763
792
|
display: grid;
|
|
764
793
|
grid-template-rows: auto minmax(0, 1fr);
|
|
@@ -770,9 +799,9 @@ code {
|
|
|
770
799
|
background: color-mix(in srgb, var(--surface-elevated) 94%, transparent);
|
|
771
800
|
border-bottom: 1px solid var(--border);
|
|
772
801
|
display: flex;
|
|
773
|
-
gap:
|
|
774
|
-
min-height:
|
|
775
|
-
padding:
|
|
802
|
+
gap: 12px;
|
|
803
|
+
min-height: 54px;
|
|
804
|
+
padding: 8px 14px;
|
|
776
805
|
position: sticky;
|
|
777
806
|
top: 0;
|
|
778
807
|
z-index: 2;
|
|
@@ -780,7 +809,7 @@ code {
|
|
|
780
809
|
|
|
781
810
|
.header-title {
|
|
782
811
|
flex: 0 0 auto;
|
|
783
|
-
gap:
|
|
812
|
+
gap: 8px;
|
|
784
813
|
min-width: 0;
|
|
785
814
|
}
|
|
786
815
|
|
|
@@ -788,12 +817,14 @@ code {
|
|
|
788
817
|
color: var(--text-muted);
|
|
789
818
|
font-size: 0.76rem;
|
|
790
819
|
font-weight: 900;
|
|
820
|
+
line-height: 1.15;
|
|
791
821
|
margin: 0;
|
|
792
822
|
text-transform: uppercase;
|
|
793
823
|
}
|
|
794
824
|
|
|
795
825
|
.header-title h1 {
|
|
796
826
|
font-size: 1rem;
|
|
827
|
+
line-height: 1.15;
|
|
797
828
|
margin: 0;
|
|
798
829
|
}
|
|
799
830
|
|
|
@@ -809,15 +840,25 @@ code {
|
|
|
809
840
|
align-items: center;
|
|
810
841
|
color: var(--accent);
|
|
811
842
|
display: inline-flex;
|
|
812
|
-
height:
|
|
843
|
+
height: 32px;
|
|
813
844
|
justify-content: center;
|
|
814
|
-
width:
|
|
845
|
+
width: 32px;
|
|
815
846
|
}
|
|
816
847
|
|
|
817
848
|
.workspace-surface-icon svg {
|
|
818
|
-
height:
|
|
849
|
+
height: 23px;
|
|
819
850
|
stroke-width: 2.2;
|
|
820
|
-
width:
|
|
851
|
+
width: 23px;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.header-center-controls {
|
|
855
|
+
gap: 10px;
|
|
856
|
+
left: 50%;
|
|
857
|
+
max-width: min(560px, 48vw);
|
|
858
|
+
min-width: 0;
|
|
859
|
+
position: absolute;
|
|
860
|
+
transform: translateX(-50%);
|
|
861
|
+
width: min(560px, 48vw);
|
|
821
862
|
}
|
|
822
863
|
|
|
823
864
|
.header-actions {
|
|
@@ -840,7 +881,7 @@ code {
|
|
|
840
881
|
|
|
841
882
|
.command-trigger {
|
|
842
883
|
justify-content: flex-start;
|
|
843
|
-
max-width:
|
|
884
|
+
max-width: none;
|
|
844
885
|
}
|
|
845
886
|
|
|
846
887
|
.command-trigger strong {
|
|
@@ -1024,12 +1065,11 @@ code {
|
|
|
1024
1065
|
}
|
|
1025
1066
|
|
|
1026
1067
|
.command-palette-backdrop {
|
|
1027
|
-
align-items:
|
|
1068
|
+
align-items: center;
|
|
1028
1069
|
background: rgb(0 0 0 / 28%);
|
|
1029
1070
|
display: flex;
|
|
1030
1071
|
inset: 0;
|
|
1031
1072
|
justify-content: center;
|
|
1032
|
-
padding-top: 12vh;
|
|
1033
1073
|
position: fixed;
|
|
1034
1074
|
z-index: 20;
|
|
1035
1075
|
}
|
|
@@ -1052,6 +1092,7 @@ code {
|
|
|
1052
1092
|
max-width: min(680px, calc(100vw - 32px));
|
|
1053
1093
|
padding: 14px;
|
|
1054
1094
|
position: relative;
|
|
1095
|
+
transform: translateY(-2vh);
|
|
1055
1096
|
width: 100%;
|
|
1056
1097
|
}
|
|
1057
1098
|
|
|
@@ -2071,12 +2112,20 @@ code {
|
|
|
2071
2112
|
}
|
|
2072
2113
|
|
|
2073
2114
|
.workspace-header,
|
|
2115
|
+
.header-center-controls,
|
|
2074
2116
|
.header-actions,
|
|
2075
2117
|
.split-heading {
|
|
2076
2118
|
align-items: stretch;
|
|
2077
2119
|
flex-direction: column;
|
|
2078
2120
|
}
|
|
2079
2121
|
|
|
2122
|
+
.header-center-controls {
|
|
2123
|
+
max-width: none;
|
|
2124
|
+
position: static;
|
|
2125
|
+
transform: none;
|
|
2126
|
+
width: 100%;
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2080
2129
|
.workspace-search {
|
|
2081
2130
|
min-width: 0;
|
|
2082
2131
|
width: 100%;
|
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.
|
|
15
|
+
# Version: 3.26.0
|
|
16
16
|
#
|
|
17
17
|
# Quick Install:
|
|
18
18
|
# npm install -g aidevops && aidevops update (recommended)
|