aidevops 3.29.6 → 3.29.7
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/InventorySurfaces.tsx +74 -21
- package/packages/gui-web/src/styles.css +212 -27
- 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.29.
|
|
1
|
+
3.29.7
|
package/aidevops.sh
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { GuiAppActionId, GuiAppActionJobSummary, GuiManagedAppSummary, GuiResponseEnvelope, GuiStatusData } from "@aidevops/gui-shared";
|
|
2
2
|
import { type Dispatch, type ReactElement, type SetStateAction, useEffect, useState } from "react";
|
|
3
|
-
import { FiDownload, FiExternalLink, FiRefreshCw, FiRepeat, FiTrash2 } from "react-icons/fi";
|
|
3
|
+
import { FiChevronDown, FiDownload, FiExternalLink, FiRefreshCw, FiRepeat, FiTrash2 } from "react-icons/fi";
|
|
4
4
|
import type { InventoryColumn } from "./app-model";
|
|
5
5
|
import { installationRows, text } from "./app-model";
|
|
6
6
|
|
|
@@ -13,9 +13,17 @@ let draftRowCounter = 0;
|
|
|
13
13
|
|
|
14
14
|
export function AppsSurface({ status }: { status: GuiStatusData }): ReactElement {
|
|
15
15
|
const [selectedJobId, setSelectedJobId] = useState<string | null>(null);
|
|
16
|
+
const [expandedAppIds, setExpandedAppIds] = useState<Set<string>>(() => new Set(status.managed_apps.length > 0 ? [status.managed_apps[0].id] : []));
|
|
16
17
|
const [jobs, setJobs] = useState<Record<string, GuiAppActionJobSummary>>({});
|
|
17
18
|
const selectedJob = selectedJobId === null ? null : jobs[selectedJobId] ?? null;
|
|
18
19
|
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (status.managed_apps.length === 0) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
setExpandedAppIds((current) => current.size === 0 ? new Set([status.managed_apps[0].id]) : current);
|
|
25
|
+
}, [status.managed_apps]);
|
|
26
|
+
|
|
19
27
|
useEffect(() => {
|
|
20
28
|
if (selectedJob === null || selectedJob.status !== "running") {
|
|
21
29
|
return undefined;
|
|
@@ -37,28 +45,51 @@ export function AppsSurface({ status }: { status: GuiStatusData }): ReactElement
|
|
|
37
45
|
</div>
|
|
38
46
|
<div className="managed-app-list">
|
|
39
47
|
{status.managed_apps.map((app) => (
|
|
40
|
-
<
|
|
48
|
+
<ManagedAppPanel
|
|
49
|
+
app={app}
|
|
50
|
+
expanded={expandedAppIds.has(app.id)}
|
|
51
|
+
job={jobForApp(app.id, jobs, selectedJob)}
|
|
52
|
+
key={app.id}
|
|
53
|
+
onJob={(job) => {
|
|
54
|
+
setJobs((current) => ({ ...current, [job.id]: job }));
|
|
55
|
+
setSelectedJobId(job.id);
|
|
56
|
+
setExpandedAppIds((current) => toggledAppIds(current, app.id, true));
|
|
57
|
+
}}
|
|
58
|
+
onToggle={() => setExpandedAppIds((current) => toggledAppIds(current, app.id))}
|
|
59
|
+
/>
|
|
41
60
|
))}
|
|
42
61
|
</div>
|
|
43
|
-
|
|
62
|
+
<p className="empty-state compact-notice">Install/update actions run as allowlisted background jobs and stream inside each app panel. xterm.js with a node-pty bridge is the right next step for full TUI apps such as OpenCode; this view starts with non-interactive command logs.</p>
|
|
44
63
|
</section>
|
|
45
64
|
);
|
|
46
65
|
}
|
|
47
66
|
|
|
48
|
-
function
|
|
67
|
+
function ManagedAppPanel({ app, expanded, job, onJob, onToggle }: { app: GuiManagedAppSummary; expanded: boolean; job: GuiAppActionJobSummary | null; onJob: (job: GuiAppActionJobSummary) => void; onToggle: () => void }): ReactElement {
|
|
49
68
|
return (
|
|
50
|
-
<article className="managed-app-
|
|
51
|
-
<
|
|
52
|
-
<
|
|
53
|
-
<
|
|
54
|
-
<
|
|
55
|
-
<
|
|
56
|
-
</
|
|
57
|
-
<
|
|
58
|
-
<
|
|
59
|
-
<
|
|
69
|
+
<article className={expanded ? "managed-app-card expanded" : "managed-app-card"}>
|
|
70
|
+
<button aria-expanded={expanded} className="managed-app-summary" data-tooltip={`${expanded ? "Collapse" : "Expand"} ${app.name} controls`} onClick={onToggle} type="button">
|
|
71
|
+
<span className="managed-app-title-block">
|
|
72
|
+
<span className="eyebrow">{app.category}</span>
|
|
73
|
+
<strong>{app.name}</strong>
|
|
74
|
+
<span>{app.description}</span>
|
|
75
|
+
</span>
|
|
76
|
+
<span className="managed-app-summary-meta">
|
|
77
|
+
<SummaryChip label="Status" value={app.status} />
|
|
78
|
+
<SummaryChip label="Installed" value={app.installed_version} />
|
|
79
|
+
<SummaryChip label="Latest" value={app.latest_version} />
|
|
80
|
+
<FiChevronDown aria-hidden="true" className="managed-app-chevron" />
|
|
81
|
+
</span>
|
|
82
|
+
</button>
|
|
83
|
+
{expanded ? <div className="managed-app-body">
|
|
84
|
+
<div className="managed-app-toolbar">
|
|
85
|
+
<div className="managed-app-links">
|
|
86
|
+
<OriginLink href={app.origin_website_url} label={text.website} />
|
|
87
|
+
<OriginLink href={app.origin_repo_url} label="Repo" />
|
|
88
|
+
</div>
|
|
89
|
+
<div className="managed-app-actions">
|
|
90
|
+
{app.actions.map((action) => <AppActionButton action={action.id} app={app} disabled={!action.enabled} key={action.id} onJob={onJob} commandPreview={action.command_preview} />)}
|
|
91
|
+
</div>
|
|
60
92
|
</div>
|
|
61
|
-
</div>
|
|
62
93
|
<div className="managed-app-details">
|
|
63
94
|
<ToggleSwitch checked={app.aidevops_install} label="setup installs" />
|
|
64
95
|
<ToggleSwitch checked={app.aidevops_update} label="update maintains" />
|
|
@@ -67,19 +98,22 @@ function ManagedAppRow({ app, onJob }: { app: GuiManagedAppSummary; onJob: (job:
|
|
|
67
98
|
<AppMeta label={text.path} value={app.install_path_ref} />
|
|
68
99
|
<AppMeta label="Status" value={app.status} />
|
|
69
100
|
</div>
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
</div>
|
|
101
|
+
{job ? <AppActionTerminal job={job} /> : <p className="empty-state compact-notice">No recent command output for this app. Run an action to open this app's terminal log.</p>}
|
|
102
|
+
</div> : null}
|
|
73
103
|
</article>
|
|
74
104
|
);
|
|
75
105
|
}
|
|
76
106
|
|
|
107
|
+
function SummaryChip({ label, value }: { label: string; value: string }): ReactElement {
|
|
108
|
+
return <span className="managed-summary-chip"><small>{label}</small><span>{value}</span></span>;
|
|
109
|
+
}
|
|
110
|
+
|
|
77
111
|
function OriginLink({ href, label }: { href: string; label: string }): ReactElement {
|
|
78
112
|
if (href.length === 0) {
|
|
79
113
|
return <span className="origin-missing">{label}: source pending</span>;
|
|
80
114
|
}
|
|
81
115
|
|
|
82
|
-
return <a href={href} rel="noreferrer" target="_blank">{label} <FiExternalLink aria-hidden="true" /></a>;
|
|
116
|
+
return <a data-tooltip={`Open ${label.toLowerCase()} destination`} href={href} rel="noreferrer" target="_blank">{label} <FiExternalLink aria-hidden="true" /></a>;
|
|
83
117
|
}
|
|
84
118
|
|
|
85
119
|
function ToggleSwitch({ checked, label }: { checked: boolean; label: string }): ReactElement {
|
|
@@ -90,7 +124,7 @@ function AppMeta({ label, value }: { label: string; value: string }): ReactEleme
|
|
|
90
124
|
return <span className="app-meta"><small>{label}</small><strong>{value}</strong></span>;
|
|
91
125
|
}
|
|
92
126
|
|
|
93
|
-
function AppActionButton({ action, app, disabled, onJob
|
|
127
|
+
function AppActionButton({ action, app, commandPreview, disabled, onJob }: { action: GuiAppActionId; app: GuiManagedAppSummary; commandPreview: string; disabled: boolean; onJob: (job: GuiAppActionJobSummary) => void }): ReactElement {
|
|
94
128
|
const icon = action === "install" ? <FiDownload /> : action === "update" ? <FiRefreshCw /> : action === "reinstall" ? <FiRepeat /> : <FiTrash2 />;
|
|
95
129
|
|
|
96
130
|
async function runAction(): Promise<void> {
|
|
@@ -106,7 +140,7 @@ function AppActionButton({ action, app, disabled, onJob, title }: { action: GuiA
|
|
|
106
140
|
onJob(envelope.data);
|
|
107
141
|
}
|
|
108
142
|
|
|
109
|
-
return <button aria-label={`${action} ${app.name}`} className="app-action-button" disabled={disabled} onClick={() => void runAction()}
|
|
143
|
+
return <button aria-label={`${action} ${app.name}`} className={action === "remove" ? "app-action-button remove" : "app-action-button"} data-tooltip={commandPreview} disabled={disabled} onClick={() => void runAction()} type="button">{icon}<span>{action}</span></button>;
|
|
110
144
|
}
|
|
111
145
|
|
|
112
146
|
function AppActionTerminal({ job }: { job: GuiAppActionJobSummary }): ReactElement {
|
|
@@ -127,6 +161,25 @@ async function refreshJob(jobId: string, setJobs: Dispatch<SetStateAction<Record
|
|
|
127
161
|
setJobs((current) => ({ ...current, [envelope.data.id]: envelope.data }));
|
|
128
162
|
}
|
|
129
163
|
|
|
164
|
+
function jobForApp(appId: string, jobs: Record<string, GuiAppActionJobSummary>, selectedJob: GuiAppActionJobSummary | null): GuiAppActionJobSummary | null {
|
|
165
|
+
if (selectedJob?.app_id === appId) {
|
|
166
|
+
return selectedJob;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return Object.values(jobs).reverse().find((job) => job.app_id === appId) ?? null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function toggledAppIds(current: Set<string>, appId: string, forceOpen = false): Set<string> {
|
|
173
|
+
const next = new Set(current);
|
|
174
|
+
if (forceOpen || !next.has(appId)) {
|
|
175
|
+
next.add(appId);
|
|
176
|
+
} else {
|
|
177
|
+
next.delete(appId);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return next;
|
|
181
|
+
}
|
|
182
|
+
|
|
130
183
|
export function InstallationSurface(): ReactElement {
|
|
131
184
|
return (
|
|
132
185
|
<section className="panel" aria-label={text.installation}>
|
|
@@ -1869,38 +1869,122 @@ code {
|
|
|
1869
1869
|
}
|
|
1870
1870
|
|
|
1871
1871
|
.managed-app-list {
|
|
1872
|
-
|
|
1873
|
-
border: 1px solid var(--border);
|
|
1874
|
-
border-radius: 16px;
|
|
1872
|
+
gap: 12px;
|
|
1875
1873
|
margin-bottom: 12px;
|
|
1874
|
+
overflow: visible;
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
.managed-app-card {
|
|
1878
|
+
background:
|
|
1879
|
+
linear-gradient(135deg, color-mix(in srgb, var(--accent) 7%, transparent), transparent 34%),
|
|
1880
|
+
var(--surface-muted);
|
|
1881
|
+
border: 1px solid var(--border);
|
|
1882
|
+
border-radius: 18px;
|
|
1883
|
+
box-shadow: inset 0 1px 0 rgb(255 255 255 / 7%);
|
|
1884
|
+
overflow: visible;
|
|
1876
1885
|
}
|
|
1877
1886
|
|
|
1878
|
-
.managed-app-
|
|
1887
|
+
.managed-app-card.expanded {
|
|
1888
|
+
border-color: color-mix(in srgb, var(--accent) 32%, var(--border));
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
.managed-app-summary {
|
|
1892
|
+
align-items: center;
|
|
1893
|
+
background: transparent;
|
|
1894
|
+
border: 0;
|
|
1895
|
+
color: var(--text-primary);
|
|
1879
1896
|
display: grid;
|
|
1880
|
-
gap:
|
|
1881
|
-
grid-template-columns: minmax(
|
|
1882
|
-
padding:
|
|
1897
|
+
gap: 16px;
|
|
1898
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
1899
|
+
padding: 16px;
|
|
1900
|
+
text-align: left;
|
|
1901
|
+
width: 100%;
|
|
1883
1902
|
}
|
|
1884
1903
|
|
|
1885
|
-
.managed-app-
|
|
1886
|
-
|
|
1904
|
+
.managed-app-summary:hover,
|
|
1905
|
+
.managed-app-summary:focus-visible {
|
|
1906
|
+
background: color-mix(in srgb, var(--accent) 7%, transparent);
|
|
1907
|
+
outline: none;
|
|
1887
1908
|
}
|
|
1888
1909
|
|
|
1889
|
-
.managed-app-
|
|
1890
|
-
.managed-app-main > div,
|
|
1910
|
+
.managed-app-title-block,
|
|
1891
1911
|
.app-meta {
|
|
1892
1912
|
display: grid;
|
|
1893
|
-
gap:
|
|
1913
|
+
gap: 7px;
|
|
1894
1914
|
min-width: 0;
|
|
1895
1915
|
}
|
|
1896
1916
|
|
|
1897
|
-
.managed-app-
|
|
1898
|
-
|
|
1899
|
-
|
|
1917
|
+
.managed-app-title-block strong {
|
|
1918
|
+
font-size: clamp(1.12rem, 2vw, 1.4rem);
|
|
1919
|
+
letter-spacing: -0.04em;
|
|
1920
|
+
line-height: 1.15;
|
|
1900
1921
|
}
|
|
1901
1922
|
|
|
1902
|
-
.managed-app-
|
|
1923
|
+
.managed-app-title-block > span:last-child {
|
|
1903
1924
|
color: var(--text-secondary);
|
|
1925
|
+
max-width: 72ch;
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
.managed-app-summary-meta {
|
|
1929
|
+
align-items: center;
|
|
1930
|
+
display: flex;
|
|
1931
|
+
flex-wrap: wrap;
|
|
1932
|
+
gap: 8px;
|
|
1933
|
+
justify-content: end;
|
|
1934
|
+
min-width: min(420px, 38vw);
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
.managed-summary-chip {
|
|
1938
|
+
background: color-mix(in srgb, var(--surface-elevated) 92%, transparent);
|
|
1939
|
+
border: 1px solid var(--border);
|
|
1940
|
+
border-radius: 999px;
|
|
1941
|
+
display: inline-grid;
|
|
1942
|
+
gap: 1px;
|
|
1943
|
+
min-width: 118px;
|
|
1944
|
+
padding: 7px 11px;
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
.managed-summary-chip small {
|
|
1948
|
+
color: var(--text-muted);
|
|
1949
|
+
font-size: 0.66rem;
|
|
1950
|
+
font-weight: 900;
|
|
1951
|
+
line-height: 1;
|
|
1952
|
+
text-transform: uppercase;
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
.managed-summary-chip span {
|
|
1956
|
+
color: var(--text-primary);
|
|
1957
|
+
font-size: 0.84rem;
|
|
1958
|
+
font-weight: 800;
|
|
1959
|
+
max-width: 18ch;
|
|
1960
|
+
overflow: hidden;
|
|
1961
|
+
text-overflow: ellipsis;
|
|
1962
|
+
white-space: nowrap;
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
.managed-app-chevron {
|
|
1966
|
+
color: var(--accent);
|
|
1967
|
+
flex: 0 0 auto;
|
|
1968
|
+
transition: transform 180ms ease;
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
.managed-app-card.expanded .managed-app-chevron {
|
|
1972
|
+
transform: rotate(180deg);
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
.managed-app-body {
|
|
1976
|
+
border-top: 1px solid var(--border);
|
|
1977
|
+
display: grid;
|
|
1978
|
+
gap: 14px;
|
|
1979
|
+
padding: 0 16px 16px;
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
.managed-app-toolbar {
|
|
1983
|
+
align-items: start;
|
|
1984
|
+
display: grid;
|
|
1985
|
+
gap: 12px;
|
|
1986
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
1987
|
+
padding-top: 14px;
|
|
1904
1988
|
}
|
|
1905
1989
|
|
|
1906
1990
|
.managed-app-links,
|
|
@@ -1911,6 +1995,10 @@ code {
|
|
|
1911
1995
|
gap: 8px;
|
|
1912
1996
|
}
|
|
1913
1997
|
|
|
1998
|
+
.managed-app-actions {
|
|
1999
|
+
justify-content: end;
|
|
2000
|
+
}
|
|
2001
|
+
|
|
1914
2002
|
.managed-app-links a,
|
|
1915
2003
|
.origin-missing {
|
|
1916
2004
|
align-items: center;
|
|
@@ -1921,18 +2009,28 @@ code {
|
|
|
1921
2009
|
font-size: 0.78rem;
|
|
1922
2010
|
font-weight: 800;
|
|
1923
2011
|
gap: 4px;
|
|
2012
|
+
max-width: 100%;
|
|
1924
2013
|
padding: 6px 9px;
|
|
2014
|
+
position: relative;
|
|
1925
2015
|
text-decoration: none;
|
|
1926
2016
|
}
|
|
1927
2017
|
|
|
2018
|
+
.managed-app-links a:hover,
|
|
2019
|
+
.managed-app-links a:focus-visible {
|
|
2020
|
+
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
|
2021
|
+
border-color: color-mix(in srgb, var(--accent) 48%, var(--border));
|
|
2022
|
+
color: var(--accent);
|
|
2023
|
+
outline: none;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
1928
2026
|
.origin-missing {
|
|
1929
2027
|
color: var(--text-muted);
|
|
1930
2028
|
}
|
|
1931
2029
|
|
|
1932
2030
|
.managed-app-details {
|
|
1933
2031
|
display: grid;
|
|
1934
|
-
gap:
|
|
1935
|
-
grid-template-columns: repeat(
|
|
2032
|
+
gap: 10px;
|
|
2033
|
+
grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
|
|
1936
2034
|
}
|
|
1937
2035
|
|
|
1938
2036
|
.managed-toggle,
|
|
@@ -1941,7 +2039,8 @@ code {
|
|
|
1941
2039
|
border: 1px solid var(--border);
|
|
1942
2040
|
border-radius: 12px;
|
|
1943
2041
|
min-width: 0;
|
|
1944
|
-
|
|
2042
|
+
min-height: 64px;
|
|
2043
|
+
padding: 10px 12px;
|
|
1945
2044
|
}
|
|
1946
2045
|
|
|
1947
2046
|
.managed-toggle {
|
|
@@ -1987,30 +2086,68 @@ code {
|
|
|
1987
2086
|
.app-meta strong {
|
|
1988
2087
|
color: var(--text-primary);
|
|
1989
2088
|
font-size: 0.84rem;
|
|
2089
|
+
line-height: 1.35;
|
|
1990
2090
|
overflow-wrap: anywhere;
|
|
2091
|
+
word-break: break-word;
|
|
1991
2092
|
}
|
|
1992
2093
|
|
|
1993
2094
|
.app-action-button {
|
|
1994
2095
|
align-items: center;
|
|
1995
|
-
|
|
2096
|
+
background: color-mix(in srgb, var(--accent) 16%, var(--surface-elevated));
|
|
2097
|
+
border: 1px solid color-mix(in srgb, var(--accent) 48%, var(--border));
|
|
2098
|
+
border-radius: 999px;
|
|
2099
|
+
color: var(--accent);
|
|
1996
2100
|
display: inline-flex;
|
|
1997
|
-
|
|
2101
|
+
gap: 7px;
|
|
2102
|
+
min-height: 42px;
|
|
1998
2103
|
justify-content: center;
|
|
1999
|
-
padding: 0;
|
|
2000
|
-
|
|
2104
|
+
padding: 0 12px;
|
|
2105
|
+
position: relative;
|
|
2106
|
+
transition: background 140ms ease, border-color 140ms ease, color 140ms ease, transform 140ms ease;
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
.app-action-button span {
|
|
2110
|
+
font-size: 0.7rem;
|
|
2111
|
+
font-weight: 900;
|
|
2112
|
+
text-transform: uppercase;
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
.app-action-button:hover,
|
|
2116
|
+
.app-action-button:focus-visible {
|
|
2117
|
+
background: var(--accent);
|
|
2118
|
+
border-color: var(--accent);
|
|
2119
|
+
color: var(--bg-primary);
|
|
2120
|
+
outline: none;
|
|
2121
|
+
transform: translateY(-1px);
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
.app-action-button.remove {
|
|
2125
|
+
background: color-mix(in srgb, #ef4444 12%, var(--surface-elevated));
|
|
2126
|
+
border-color: color-mix(in srgb, #ef4444 45%, var(--border));
|
|
2127
|
+
color: #ff8a8a;
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
.app-action-button.remove:hover,
|
|
2131
|
+
.app-action-button.remove:focus-visible {
|
|
2132
|
+
background: #ef4444;
|
|
2133
|
+
border-color: #ef4444;
|
|
2134
|
+
color: white;
|
|
2001
2135
|
}
|
|
2002
2136
|
|
|
2003
2137
|
.app-action-button:disabled {
|
|
2004
2138
|
color: var(--text-muted);
|
|
2005
2139
|
cursor: not-allowed;
|
|
2006
2140
|
opacity: 0.45;
|
|
2141
|
+
transform: none;
|
|
2007
2142
|
}
|
|
2008
2143
|
|
|
2009
2144
|
.app-terminal {
|
|
2010
|
-
background:
|
|
2145
|
+
background:
|
|
2146
|
+
linear-gradient(180deg, rgb(255 255 255 / 4%), transparent),
|
|
2147
|
+
#050806;
|
|
2011
2148
|
border: 1px solid var(--border);
|
|
2012
2149
|
border-radius: 16px;
|
|
2013
|
-
color: var(--
|
|
2150
|
+
color: color-mix(in srgb, var(--accent) 78%, white);
|
|
2014
2151
|
overflow: hidden;
|
|
2015
2152
|
}
|
|
2016
2153
|
|
|
@@ -2018,16 +2155,57 @@ code {
|
|
|
2018
2155
|
align-items: center;
|
|
2019
2156
|
border-bottom: 1px solid var(--border);
|
|
2020
2157
|
display: flex;
|
|
2158
|
+
gap: 12px;
|
|
2021
2159
|
justify-content: space-between;
|
|
2022
2160
|
padding: 10px 12px;
|
|
2023
2161
|
}
|
|
2024
2162
|
|
|
2163
|
+
.app-terminal header span {
|
|
2164
|
+
color: var(--text-muted);
|
|
2165
|
+
text-align: right;
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2025
2168
|
.app-terminal pre {
|
|
2026
2169
|
margin: 0;
|
|
2027
|
-
max-height:
|
|
2170
|
+
max-height: 240px;
|
|
2028
2171
|
overflow: auto;
|
|
2029
2172
|
padding: 12px;
|
|
2030
2173
|
white-space: pre-wrap;
|
|
2174
|
+
word-break: break-word;
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
[data-tooltip] {
|
|
2178
|
+
position: relative;
|
|
2179
|
+
}
|
|
2180
|
+
|
|
2181
|
+
[data-tooltip]::after {
|
|
2182
|
+
background: color-mix(in srgb, var(--surface-elevated) 94%, black);
|
|
2183
|
+
border: 1px solid color-mix(in srgb, var(--accent) 36%, var(--border));
|
|
2184
|
+
border-radius: 10px;
|
|
2185
|
+
bottom: calc(100% + 8px);
|
|
2186
|
+
box-shadow: 0 18px 46px rgb(0 0 0 / 38%);
|
|
2187
|
+
color: var(--text-primary);
|
|
2188
|
+
content: attr(data-tooltip);
|
|
2189
|
+
font-size: 0.72rem;
|
|
2190
|
+
font-weight: 700;
|
|
2191
|
+
left: 50%;
|
|
2192
|
+
line-height: 1.35;
|
|
2193
|
+
max-width: min(320px, 72vw);
|
|
2194
|
+
opacity: 0;
|
|
2195
|
+
padding: 8px 10px;
|
|
2196
|
+
pointer-events: none;
|
|
2197
|
+
position: absolute;
|
|
2198
|
+
text-align: left;
|
|
2199
|
+
transform: translate(-50%, 4px);
|
|
2200
|
+
transition: opacity 140ms ease, transform 140ms ease;
|
|
2201
|
+
width: max-content;
|
|
2202
|
+
z-index: 40;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
[data-tooltip]:hover::after,
|
|
2206
|
+
[data-tooltip]:focus-visible::after {
|
|
2207
|
+
opacity: 1;
|
|
2208
|
+
transform: translate(-50%, 0);
|
|
2031
2209
|
}
|
|
2032
2210
|
|
|
2033
2211
|
.data-row,
|
|
@@ -2715,9 +2893,16 @@ code {
|
|
|
2715
2893
|
grid-template-columns: 1fr;
|
|
2716
2894
|
}
|
|
2717
2895
|
|
|
2718
|
-
.managed-app-
|
|
2896
|
+
.managed-app-summary,
|
|
2897
|
+
.managed-app-toolbar {
|
|
2719
2898
|
grid-template-columns: 1fr;
|
|
2720
2899
|
}
|
|
2900
|
+
|
|
2901
|
+
.managed-app-summary-meta,
|
|
2902
|
+
.managed-app-actions {
|
|
2903
|
+
justify-content: start;
|
|
2904
|
+
min-width: 0;
|
|
2905
|
+
}
|
|
2721
2906
|
}
|
|
2722
2907
|
|
|
2723
2908
|
@media (max-width: 980px) {
|
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.
|
|
15
|
+
# Version: 3.29.7
|
|
16
16
|
#
|
|
17
17
|
# Quick Install:
|
|
18
18
|
# npm install -g aidevops && aidevops update (recommended)
|