arc-1 0.9.19 → 0.9.20
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 +7 -4
- package/dist/adt/errors.d.ts.map +1 -1
- package/dist/adt/errors.js +186 -25
- package/dist/adt/errors.js.map +1 -1
- package/dist/cache/cache.d.ts +25 -0
- package/dist/cache/cache.d.ts.map +1 -1
- package/dist/cache/cache.js.map +1 -1
- package/dist/cache/caching-layer.d.ts +31 -2
- package/dist/cache/caching-layer.d.ts.map +1 -1
- package/dist/cache/caching-layer.js +102 -2
- package/dist/cache/caching-layer.js.map +1 -1
- package/dist/cache/memory.d.ts +2 -1
- package/dist/cache/memory.d.ts.map +1 -1
- package/dist/cache/memory.js +46 -0
- package/dist/cache/memory.js.map +1 -1
- package/dist/cache/sqlite.d.ts +2 -1
- package/dist/cache/sqlite.d.ts.map +1 -1
- package/dist/cache/sqlite.js +54 -0
- package/dist/cache/sqlite.js.map +1 -1
- package/dist/handlers/context.d.ts.map +1 -1
- package/dist/handlers/context.js +27 -4
- package/dist/handlers/context.js.map +1 -1
- package/dist/handlers/object-types.d.ts +1 -1
- package/dist/handlers/object-types.d.ts.map +1 -1
- package/dist/handlers/object-types.js +10 -2
- package/dist/handlers/object-types.js.map +1 -1
- package/dist/handlers/read.d.ts.map +1 -1
- package/dist/handlers/read.js +4 -1
- package/dist/handlers/read.js.map +1 -1
- package/dist/handlers/schemas.d.ts +12 -4
- package/dist/handlers/schemas.d.ts.map +1 -1
- package/dist/handlers/schemas.js +2 -0
- package/dist/handlers/schemas.js.map +1 -1
- package/dist/handlers/tool-registry.d.ts +4 -4
- package/dist/handlers/tool-registry.d.ts.map +1 -1
- package/dist/handlers/tool-registry.js +4 -0
- package/dist/handlers/tool-registry.js.map +1 -1
- package/dist/handlers/tools.d.ts.map +1 -1
- package/dist/handlers/tools.js +29 -23
- package/dist/handlers/tools.js.map +1 -1
- package/dist/handlers/write/create.d.ts.map +1 -1
- package/dist/handlers/write/create.js +89 -4
- package/dist/handlers/write/create.js.map +1 -1
- package/dist/plugins/manifest-interpreter.d.ts.map +1 -1
- package/dist/plugins/manifest-interpreter.js +3 -1
- package/dist/plugins/manifest-interpreter.js.map +1 -1
- package/dist/public/testing.d.ts +2 -1
- package/dist/public/testing.d.ts.map +1 -1
- package/dist/public/testing.js +13 -0
- package/dist/public/testing.js.map +1 -1
- package/dist/public/types.d.ts +2 -2
- package/dist/public/types.d.ts.map +1 -1
- package/dist/public/ui/app.js +1044 -0
- package/dist/public/ui/arc-mark.svg +5 -0
- package/dist/public/ui/index.html +43 -0
- package/dist/public/ui/styles.css +563 -0
- package/dist/server/config.d.ts.map +1 -1
- package/dist/server/config.js +73 -0
- package/dist/server/config.js.map +1 -1
- package/dist/server/http.d.ts +2 -1
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +22 -1
- package/dist/server/http.js.map +1 -1
- package/dist/server/plugin-loader.d.ts.map +1 -1
- package/dist/server/plugin-loader.js +1 -1
- package/dist/server/plugin-loader.js.map +1 -1
- package/dist/server/safe-http-client.d.ts +12 -6
- package/dist/server/safe-http-client.d.ts.map +1 -1
- package/dist/server/safe-http-client.js +84 -15
- package/dist/server/safe-http-client.js.map +1 -1
- package/dist/server/server.d.ts +1 -1
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +28 -3
- package/dist/server/server.js.map +1 -1
- package/dist/server/types.d.ts +16 -0
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +4 -0
- package/dist/server/types.js.map +1 -1
- package/dist/server/ui-log-buffer.d.ts +29 -0
- package/dist/server/ui-log-buffer.d.ts.map +1 -0
- package/dist/server/ui-log-buffer.js +72 -0
- package/dist/server/ui-log-buffer.js.map +1 -0
- package/dist/server/ui-state.d.ts +32 -0
- package/dist/server/ui-state.d.ts.map +1 -0
- package/dist/server/ui-state.js +230 -0
- package/dist/server/ui-state.js.map +1 -0
- package/dist/server/ui.d.ts +20 -0
- package/dist/server/ui.d.ts.map +1 -0
- package/dist/server/ui.js +275 -0
- package/dist/server/ui.js.map +1 -0
- package/package.json +13 -9
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="ARC-1">
|
|
2
|
+
<rect width="64" height="64" rx="12" fill="#111827"/>
|
|
3
|
+
<path d="M16 44 28 18h8l12 26h-8l-2.4-5.8H26.3L24 44h-8Zm13-12.3h6l-3-7.5-3 7.5Z" fill="#f8fafc"/>
|
|
4
|
+
<path d="M47 18h5v26h-5V18Z" fill="#38bdf8"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>ARC-1 Console</title>
|
|
7
|
+
<link rel="icon" href="./arc-mark.svg" type="image/svg+xml" />
|
|
8
|
+
<link rel="stylesheet" href="./styles.css" />
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<header class="topbar">
|
|
12
|
+
<div class="brand">
|
|
13
|
+
<img src="./arc-mark.svg" alt="" width="32" height="32" />
|
|
14
|
+
<div>
|
|
15
|
+
<h1>ARC-1 Console</h1>
|
|
16
|
+
<p id="subtitle">Read-only runtime view</p>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="auth">
|
|
20
|
+
<input id="token" type="password" autocomplete="off" spellcheck="false" placeholder="Admin bearer token" />
|
|
21
|
+
<button id="save-token" type="button">Set</button>
|
|
22
|
+
<button id="clear-token" type="button" class="ghost">Clear</button>
|
|
23
|
+
</div>
|
|
24
|
+
</header>
|
|
25
|
+
|
|
26
|
+
<main>
|
|
27
|
+
<nav class="tabs" aria-label="Console views">
|
|
28
|
+
<button type="button" data-tab="overview" class="active">Overview</button>
|
|
29
|
+
<button type="button" data-tab="config">Config</button>
|
|
30
|
+
<button type="button" data-tab="safety">Safety</button>
|
|
31
|
+
<button type="button" data-tab="features">Features</button>
|
|
32
|
+
<button type="button" data-tab="cache">Cache</button>
|
|
33
|
+
<button type="button" data-tab="logs">Logs</button>
|
|
34
|
+
<button type="button" data-tab="docs">Docs</button>
|
|
35
|
+
</nav>
|
|
36
|
+
|
|
37
|
+
<section id="status" class="status" hidden></section>
|
|
38
|
+
<section id="content" class="content" aria-live="polite"></section>
|
|
39
|
+
</main>
|
|
40
|
+
|
|
41
|
+
<script src="./app.js" type="module"></script>
|
|
42
|
+
</body>
|
|
43
|
+
</html>
|
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color-scheme: light;
|
|
3
|
+
--bg: #f6f7f9;
|
|
4
|
+
--surface: #ffffff;
|
|
5
|
+
--surface-2: #eef2f6;
|
|
6
|
+
--text: #1f2937;
|
|
7
|
+
--muted: #64748b;
|
|
8
|
+
--line: #d8dee6;
|
|
9
|
+
--accent: #0f766e;
|
|
10
|
+
--accent-2: #2563eb;
|
|
11
|
+
--accent-3: #7c3aed;
|
|
12
|
+
--info: #0369a1;
|
|
13
|
+
--danger: #b91c1c;
|
|
14
|
+
--warn: #b45309;
|
|
15
|
+
--ok: #047857;
|
|
16
|
+
--mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
|
|
17
|
+
--sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
* {
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
body {
|
|
25
|
+
margin: 0;
|
|
26
|
+
background: var(--bg);
|
|
27
|
+
color: var(--text);
|
|
28
|
+
font-family: var(--sans);
|
|
29
|
+
font-size: 14px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.topbar {
|
|
33
|
+
min-height: 64px;
|
|
34
|
+
display: flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
justify-content: space-between;
|
|
37
|
+
gap: 16px;
|
|
38
|
+
padding: 12px 20px;
|
|
39
|
+
background: var(--surface);
|
|
40
|
+
border-bottom: 1px solid var(--line);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.brand {
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
gap: 12px;
|
|
47
|
+
min-width: 220px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.brand img {
|
|
51
|
+
flex: 0 0 auto;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
h1 {
|
|
55
|
+
margin: 0;
|
|
56
|
+
font-size: 18px;
|
|
57
|
+
line-height: 1.2;
|
|
58
|
+
font-weight: 700;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
h2 {
|
|
62
|
+
margin: 0 0 12px;
|
|
63
|
+
font-size: 16px;
|
|
64
|
+
line-height: 1.3;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
h3 {
|
|
68
|
+
margin: 16px 0 8px;
|
|
69
|
+
font-size: 14px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
p {
|
|
73
|
+
margin: 0;
|
|
74
|
+
color: var(--muted);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
main {
|
|
78
|
+
width: min(1380px, 100%);
|
|
79
|
+
margin: 0 auto;
|
|
80
|
+
padding: 16px 20px 28px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.auth {
|
|
84
|
+
display: grid;
|
|
85
|
+
grid-template-columns: minmax(180px, 320px) 54px 64px;
|
|
86
|
+
gap: 8px;
|
|
87
|
+
align-items: center;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
button,
|
|
91
|
+
input,
|
|
92
|
+
select {
|
|
93
|
+
min-height: 34px;
|
|
94
|
+
border: 1px solid var(--line);
|
|
95
|
+
background: var(--surface);
|
|
96
|
+
color: var(--text);
|
|
97
|
+
border-radius: 6px;
|
|
98
|
+
font: inherit;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
button {
|
|
102
|
+
padding: 0 12px;
|
|
103
|
+
cursor: pointer;
|
|
104
|
+
background: #12312f;
|
|
105
|
+
color: #ffffff;
|
|
106
|
+
border-color: #12312f;
|
|
107
|
+
font-weight: 600;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
button.ghost,
|
|
111
|
+
.tabs button {
|
|
112
|
+
color: var(--text);
|
|
113
|
+
background: var(--surface);
|
|
114
|
+
border-color: var(--line);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
button:hover,
|
|
118
|
+
button:focus-visible {
|
|
119
|
+
outline: 2px solid color-mix(in srgb, var(--accent-2) 35%, transparent);
|
|
120
|
+
outline-offset: 1px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
input,
|
|
124
|
+
select {
|
|
125
|
+
padding: 0 10px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.tabs {
|
|
129
|
+
display: flex;
|
|
130
|
+
gap: 6px;
|
|
131
|
+
flex-wrap: wrap;
|
|
132
|
+
margin-bottom: 12px;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.tabs button {
|
|
136
|
+
min-width: 92px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.tabs button.active {
|
|
140
|
+
color: #ffffff;
|
|
141
|
+
background: var(--accent);
|
|
142
|
+
border-color: var(--accent);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.status {
|
|
146
|
+
margin-bottom: 12px;
|
|
147
|
+
padding: 10px 12px;
|
|
148
|
+
border: 1px solid var(--line);
|
|
149
|
+
border-left: 4px solid var(--warn);
|
|
150
|
+
background: #fff7ed;
|
|
151
|
+
border-radius: 6px;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.content {
|
|
155
|
+
display: grid;
|
|
156
|
+
gap: 14px;
|
|
157
|
+
min-width: 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.panel {
|
|
161
|
+
min-width: 0;
|
|
162
|
+
overflow: hidden;
|
|
163
|
+
background: var(--surface);
|
|
164
|
+
border: 1px solid var(--line);
|
|
165
|
+
border-radius: 8px;
|
|
166
|
+
padding: 14px;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.grid {
|
|
170
|
+
display: grid;
|
|
171
|
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
172
|
+
gap: 10px;
|
|
173
|
+
min-width: 0;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.metric {
|
|
177
|
+
min-height: 78px;
|
|
178
|
+
display: grid;
|
|
179
|
+
align-content: center;
|
|
180
|
+
gap: 4px;
|
|
181
|
+
background: var(--surface-2);
|
|
182
|
+
border: 1px solid var(--line);
|
|
183
|
+
border-left-width: 4px;
|
|
184
|
+
border-radius: 6px;
|
|
185
|
+
min-width: 0;
|
|
186
|
+
padding: 10px 12px;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.metric.ok {
|
|
190
|
+
border-color: #a7f3d0;
|
|
191
|
+
border-left-color: var(--ok);
|
|
192
|
+
background: #ecfdf5;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.metric.info {
|
|
196
|
+
border-color: #bae6fd;
|
|
197
|
+
border-left-color: var(--info);
|
|
198
|
+
background: #f0f9ff;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.metric.accent {
|
|
202
|
+
border-color: #c4b5fd;
|
|
203
|
+
border-left-color: var(--accent-3);
|
|
204
|
+
background: #f5f3ff;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.metric.warn {
|
|
208
|
+
border-color: #fed7aa;
|
|
209
|
+
border-left-color: var(--warn);
|
|
210
|
+
background: #fff7ed;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.metric.error {
|
|
214
|
+
border-color: #fecaca;
|
|
215
|
+
border-left-color: var(--danger);
|
|
216
|
+
background: #fef2f2;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.metric strong {
|
|
220
|
+
font-size: 20px;
|
|
221
|
+
line-height: 1.2;
|
|
222
|
+
overflow-wrap: anywhere;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.metric span {
|
|
226
|
+
min-width: 0;
|
|
227
|
+
overflow-wrap: anywhere;
|
|
228
|
+
color: var(--muted);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.chart-grid {
|
|
232
|
+
display: grid;
|
|
233
|
+
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
|
234
|
+
gap: 12px;
|
|
235
|
+
min-width: 0;
|
|
236
|
+
margin-top: 12px;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.chart {
|
|
240
|
+
min-width: 0;
|
|
241
|
+
padding: 10px;
|
|
242
|
+
border: 1px solid var(--line);
|
|
243
|
+
border-radius: 6px;
|
|
244
|
+
background: #fbfcfe;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.chart h3 {
|
|
248
|
+
margin-top: 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.bar-row {
|
|
252
|
+
display: grid;
|
|
253
|
+
grid-template-columns: minmax(94px, 34%) minmax(80px, 1fr) 42px;
|
|
254
|
+
gap: 8px;
|
|
255
|
+
align-items: center;
|
|
256
|
+
min-height: 26px;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.bar-label,
|
|
260
|
+
.bar-value {
|
|
261
|
+
min-width: 0;
|
|
262
|
+
overflow: hidden;
|
|
263
|
+
color: var(--muted);
|
|
264
|
+
font-size: 12px;
|
|
265
|
+
text-overflow: ellipsis;
|
|
266
|
+
white-space: nowrap;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.bar-value {
|
|
270
|
+
color: var(--text);
|
|
271
|
+
font-variant-numeric: tabular-nums;
|
|
272
|
+
text-align: right;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.bar-track {
|
|
276
|
+
height: 10px;
|
|
277
|
+
overflow: hidden;
|
|
278
|
+
border-radius: 999px;
|
|
279
|
+
background: var(--surface-2);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.bar-fill {
|
|
283
|
+
height: 100%;
|
|
284
|
+
min-width: 4px;
|
|
285
|
+
border-radius: inherit;
|
|
286
|
+
background: var(--info);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.bar-fill.ok {
|
|
290
|
+
background: var(--ok);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.bar-fill.info {
|
|
294
|
+
background: var(--accent-2);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.bar-fill.accent {
|
|
298
|
+
background: var(--accent-3);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.bar-fill.warn {
|
|
302
|
+
background: var(--warn);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.bar-fill.error {
|
|
306
|
+
background: var(--danger);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.status-grid {
|
|
310
|
+
display: grid;
|
|
311
|
+
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
|
|
312
|
+
gap: 8px;
|
|
313
|
+
margin-bottom: 12px;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.status-item {
|
|
317
|
+
display: flex;
|
|
318
|
+
min-width: 0;
|
|
319
|
+
align-items: center;
|
|
320
|
+
justify-content: space-between;
|
|
321
|
+
gap: 8px;
|
|
322
|
+
padding: 9px 10px;
|
|
323
|
+
border: 1px solid var(--line);
|
|
324
|
+
border-left-width: 4px;
|
|
325
|
+
border-radius: 6px;
|
|
326
|
+
background: #fbfcfe;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.status-item.ok {
|
|
330
|
+
border-color: #bbf7d0;
|
|
331
|
+
border-left-color: var(--ok);
|
|
332
|
+
background: #f0fdf4;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.status-item.info {
|
|
336
|
+
border-color: #bae6fd;
|
|
337
|
+
border-left-color: var(--info);
|
|
338
|
+
background: #f0f9ff;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.status-item.warn {
|
|
342
|
+
border-color: #fed7aa;
|
|
343
|
+
border-left-color: var(--warn);
|
|
344
|
+
background: #fff7ed;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.status-item.error {
|
|
348
|
+
border-color: #fecaca;
|
|
349
|
+
border-left-color: var(--danger);
|
|
350
|
+
background: #fef2f2;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.status-item > span:first-child {
|
|
354
|
+
min-width: 0;
|
|
355
|
+
overflow: hidden;
|
|
356
|
+
color: var(--muted);
|
|
357
|
+
text-overflow: ellipsis;
|
|
358
|
+
white-space: nowrap;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.filters {
|
|
362
|
+
display: grid;
|
|
363
|
+
grid-template-columns: repeat(5, minmax(120px, 1fr));
|
|
364
|
+
gap: 8px;
|
|
365
|
+
align-items: end;
|
|
366
|
+
min-width: 0;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
label {
|
|
370
|
+
display: grid;
|
|
371
|
+
gap: 4px;
|
|
372
|
+
color: var(--muted);
|
|
373
|
+
font-size: 12px;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.table-wrap {
|
|
377
|
+
max-width: 100%;
|
|
378
|
+
min-width: 0;
|
|
379
|
+
overflow-x: auto;
|
|
380
|
+
border: 1px solid var(--line);
|
|
381
|
+
border-radius: 6px;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
table {
|
|
385
|
+
width: 100%;
|
|
386
|
+
border-collapse: collapse;
|
|
387
|
+
min-width: 720px;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
th,
|
|
391
|
+
td {
|
|
392
|
+
padding: 8px 10px;
|
|
393
|
+
border-bottom: 1px solid var(--line);
|
|
394
|
+
overflow-wrap: anywhere;
|
|
395
|
+
text-align: left;
|
|
396
|
+
vertical-align: top;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
th {
|
|
400
|
+
background: var(--surface-2);
|
|
401
|
+
color: #334155;
|
|
402
|
+
font-weight: 700;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
tr:last-child td {
|
|
406
|
+
border-bottom: 0;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
code,
|
|
410
|
+
.mono {
|
|
411
|
+
font-family: var(--mono);
|
|
412
|
+
font-size: 12px;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.pill {
|
|
416
|
+
display: inline-flex;
|
|
417
|
+
align-items: center;
|
|
418
|
+
min-height: 22px;
|
|
419
|
+
padding: 0 8px;
|
|
420
|
+
border-radius: 999px;
|
|
421
|
+
background: var(--surface-2);
|
|
422
|
+
border: 1px solid var(--line);
|
|
423
|
+
font-size: 12px;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.pill.ok {
|
|
427
|
+
color: var(--ok);
|
|
428
|
+
background: #ecfdf5;
|
|
429
|
+
border-color: #bbf7d0;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.pill.warn {
|
|
433
|
+
color: var(--warn);
|
|
434
|
+
background: #fff7ed;
|
|
435
|
+
border-color: #fed7aa;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.pill.info {
|
|
439
|
+
color: var(--info);
|
|
440
|
+
background: #f0f9ff;
|
|
441
|
+
border-color: #bae6fd;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.pill.accent {
|
|
445
|
+
color: var(--accent-3);
|
|
446
|
+
background: #f5f3ff;
|
|
447
|
+
border-color: #ddd6fe;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.pill.error {
|
|
451
|
+
color: var(--danger);
|
|
452
|
+
background: #fef2f2;
|
|
453
|
+
border-color: #fecaca;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.detail-chips {
|
|
457
|
+
display: flex;
|
|
458
|
+
flex-wrap: wrap;
|
|
459
|
+
gap: 6px;
|
|
460
|
+
max-width: 100%;
|
|
461
|
+
min-width: 0;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.detail-chip {
|
|
465
|
+
display: inline-flex;
|
|
466
|
+
flex: 0 1 auto;
|
|
467
|
+
min-width: 0;
|
|
468
|
+
max-width: 100%;
|
|
469
|
+
align-items: center;
|
|
470
|
+
gap: 5px;
|
|
471
|
+
padding: 3px 7px;
|
|
472
|
+
border: 1px solid var(--line);
|
|
473
|
+
border-radius: 999px;
|
|
474
|
+
background: #f8fafc;
|
|
475
|
+
color: var(--text);
|
|
476
|
+
font-size: 12px;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.detail-chip span {
|
|
480
|
+
flex: 0 0 auto;
|
|
481
|
+
color: var(--muted);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.detail-chip strong {
|
|
485
|
+
flex: 1 1 auto;
|
|
486
|
+
min-width: 0;
|
|
487
|
+
overflow-wrap: anywhere;
|
|
488
|
+
font-weight: 600;
|
|
489
|
+
white-space: normal;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
.detail-chip.ok {
|
|
493
|
+
border-color: #bbf7d0;
|
|
494
|
+
background: #ecfdf5;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.detail-chip.info {
|
|
498
|
+
border-color: #bae6fd;
|
|
499
|
+
background: #f0f9ff;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.detail-chip.warn {
|
|
503
|
+
border-color: #fed7aa;
|
|
504
|
+
background: #fff7ed;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.detail-chip.error {
|
|
508
|
+
border-color: #fecaca;
|
|
509
|
+
background: #fef2f2;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.kv {
|
|
513
|
+
display: grid;
|
|
514
|
+
grid-template-columns: minmax(140px, 260px) minmax(0, 1fr);
|
|
515
|
+
border-top: 1px solid var(--line);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
.kv div {
|
|
519
|
+
padding: 7px 8px;
|
|
520
|
+
border-bottom: 1px solid var(--line);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.kv div:nth-child(odd) {
|
|
524
|
+
color: var(--muted);
|
|
525
|
+
background: #fafafa;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
pre {
|
|
529
|
+
margin: 0;
|
|
530
|
+
white-space: pre-wrap;
|
|
531
|
+
word-break: break-word;
|
|
532
|
+
font: 12px/1.45 var(--mono);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
a {
|
|
536
|
+
color: var(--accent-2);
|
|
537
|
+
text-decoration: none;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
a:hover {
|
|
541
|
+
text-decoration: underline;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
@media (max-width: 760px) {
|
|
545
|
+
.topbar {
|
|
546
|
+
align-items: stretch;
|
|
547
|
+
flex-direction: column;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.auth,
|
|
551
|
+
.filters {
|
|
552
|
+
grid-template-columns: 1fr;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
main {
|
|
556
|
+
padding: 12px;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.tabs button {
|
|
560
|
+
min-width: 0;
|
|
561
|
+
flex: 1 1 96px;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,KAAK,EAAE,YAAY,EAAiB,YAAY,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,KAAK,EAAE,YAAY,EAAiB,YAAY,EAAyB,MAAM,YAAY,CAAC;AAGnG;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,kFAAkF;IAClF,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/B;AAED,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CA2E1D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA4BjF;AAoED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CAAE,CAsb7G;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAEtD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAgFzD"}
|
package/dist/server/config.js
CHANGED
|
@@ -124,6 +124,21 @@ export function parseApiKeys(raw) {
|
|
|
124
124
|
}
|
|
125
125
|
return entries;
|
|
126
126
|
}
|
|
127
|
+
function parseUiMode(raw, transport) {
|
|
128
|
+
const value = raw.trim().toLowerCase();
|
|
129
|
+
if (value === '')
|
|
130
|
+
return 'off';
|
|
131
|
+
if (['0', 'false', 'no', 'off'].includes(value))
|
|
132
|
+
return 'off';
|
|
133
|
+
if (['local', 'sidecar'].includes(value))
|
|
134
|
+
return 'local';
|
|
135
|
+
if (['web', 'http', 'server'].includes(value))
|
|
136
|
+
return 'web';
|
|
137
|
+
if (['1', 'true', 'yes', 'on'].includes(value)) {
|
|
138
|
+
return transport === 'stdio' ? 'local' : 'web';
|
|
139
|
+
}
|
|
140
|
+
throw new Error('Invalid ARC1_UI value: expected off, local, web, true, or false');
|
|
141
|
+
}
|
|
127
142
|
/** Map of legacy env-var names → human-readable migration hint. */
|
|
128
143
|
const LEGACY_ENV_VARS = {
|
|
129
144
|
SAP_READ_ONLY: 'Replaced by SAP_ALLOW_WRITES (inverted). Set SAP_ALLOW_WRITES=true to enable writes.',
|
|
@@ -184,6 +199,18 @@ export function resolveConfig(args) {
|
|
|
184
199
|
}
|
|
185
200
|
return undefined;
|
|
186
201
|
};
|
|
202
|
+
const getOptionalFlagValue = (name) => {
|
|
203
|
+
const prefix = `--${name}=`;
|
|
204
|
+
for (let i = 0; i < args.length; i++) {
|
|
205
|
+
if (args[i] === `--${name}`) {
|
|
206
|
+
const next = args[i + 1];
|
|
207
|
+
return next && !next.startsWith('--') ? next : 'true';
|
|
208
|
+
}
|
|
209
|
+
if (args[i]?.startsWith(prefix))
|
|
210
|
+
return args[i].slice(prefix.length);
|
|
211
|
+
}
|
|
212
|
+
return undefined;
|
|
213
|
+
};
|
|
187
214
|
// An empty flag/env value (a cleared install-dialog field, or a shell-expanded unset $VAR) is
|
|
188
215
|
// treated as "not provided" and falls through to the default instead of overriding it with "".
|
|
189
216
|
// This stops non-empty defaults (e.g. SAP_CLIENT=100, SAP_LANGUAGE=EN) from being silently
|
|
@@ -283,6 +310,33 @@ export function resolveConfig(args) {
|
|
|
283
310
|
config.httpAddr = `${addrHost}:${parsedPort}`;
|
|
284
311
|
sources.httpAddr = getFlag('port') !== undefined ? { flag: '--port' } : { env: 'ARC1_PORT' };
|
|
285
312
|
}
|
|
313
|
+
// ── Read-only Admin UI ────────────────────────────────────────────
|
|
314
|
+
const uiFlag = getOptionalFlagValue('ui');
|
|
315
|
+
const uiEnv = process.env.ARC1_UI;
|
|
316
|
+
if (uiFlag !== undefined) {
|
|
317
|
+
config.uiMode = parseUiMode(uiFlag, config.transport);
|
|
318
|
+
sources.uiMode = { flag: '--ui' };
|
|
319
|
+
}
|
|
320
|
+
else if (uiEnv !== undefined && uiEnv !== '') {
|
|
321
|
+
config.uiMode = parseUiMode(uiEnv, config.transport);
|
|
322
|
+
sources.uiMode = { env: 'ARC1_UI' };
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
config.uiMode = 'off';
|
|
326
|
+
sources.uiMode = 'default';
|
|
327
|
+
}
|
|
328
|
+
config.uiAddr = resolveStr('ui-addr', 'ARC1_UI_ADDR', DEFAULT_CONFIG.uiAddr, 'uiAddr');
|
|
329
|
+
const uiPortOverride = getFlag('ui-port') ?? process.env.ARC1_UI_PORT;
|
|
330
|
+
if (uiPortOverride) {
|
|
331
|
+
const parsedPort = Number.parseInt(uiPortOverride, 10);
|
|
332
|
+
if (Number.isNaN(parsedPort) || parsedPort < 1 || parsedPort > 65535) {
|
|
333
|
+
throw new Error(`Invalid UI port '${uiPortOverride}': must be a number between 1 and 65535`);
|
|
334
|
+
}
|
|
335
|
+
const addrHost = config.uiAddr.includes(':') ? config.uiAddr.split(':')[0] : '127.0.0.1';
|
|
336
|
+
config.uiAddr = `${addrHost}:${parsedPort}`;
|
|
337
|
+
sources.uiAddr = getFlag('ui-port') !== undefined ? { flag: '--ui-port' } : { env: 'ARC1_UI_PORT' };
|
|
338
|
+
}
|
|
339
|
+
config.uiOpen = resolveBool('ui-open', 'ARC1_UI_OPEN', false, 'uiOpen');
|
|
286
340
|
// ── Safety (positive opt-ins) ──────────────────────────────────────
|
|
287
341
|
config.allowWrites = resolveBool('allow-writes', 'SAP_ALLOW_WRITES', false, 'allowWrites');
|
|
288
342
|
config.allowDataPreview = resolveBool('allow-data-preview', 'SAP_ALLOW_DATA_PREVIEW', false, 'allowDataPreview');
|
|
@@ -429,6 +483,9 @@ export function resolveConfig(args) {
|
|
|
429
483
|
.filter(Boolean);
|
|
430
484
|
// Opt-in: let plugin tools execute ABAP console classes (ctx.run.classRun). Also needs allowWrites.
|
|
431
485
|
config.allowPluginExecute = resolveBool('allow-plugin-execute', 'SAP_ALLOW_PLUGIN_EXECUTE', false, 'allowPluginExecute');
|
|
486
|
+
// Opt-in: let plugin tools write (ctx.http.post/put/delete) to non-ADT (OData/ICF) paths. Also
|
|
487
|
+
// needs allowWrites; ADT object writes are always refused (no package gate on this raw surface).
|
|
488
|
+
config.allowPluginRawWrites = resolveBool('allow-plugin-raw-writes', 'SAP_ALLOW_PLUGIN_RAW_WRITES', false, 'allowPluginRawWrites');
|
|
432
489
|
// ── Lint ───────────────────────────────────────────────────────────
|
|
433
490
|
config.abaplintConfig = resolveOptionalStr('abaplint-config', 'SAP_ABAPLINT_CONFIG', 'abaplintConfig');
|
|
434
491
|
config.lintBeforeWrite = resolveBool('lint-before-write', 'SAP_LINT_BEFORE_WRITE', true, 'lintBeforeWrite');
|
|
@@ -556,5 +613,21 @@ export function validateConfig(config) {
|
|
|
556
613
|
if (config.dcrSigningSecret && !config.xsuaaAuth) {
|
|
557
614
|
console.error('[warn] ARC1_DCR_SIGNING_SECRET is set but SAP_XSUAA_AUTH=false — the secret is unused. Unset it to reduce attack surface, or enable XSUAA OAuth proxy mode (SAP_XSUAA_AUTH=true).');
|
|
558
615
|
}
|
|
616
|
+
if (config.transport === 'stdio' && config.uiMode === 'web') {
|
|
617
|
+
throw new Error('ARC1_UI=web requires SAP_TRANSPORT=http-streamable. Use ARC1_UI=local for stdio clients.');
|
|
618
|
+
}
|
|
619
|
+
const hasAdminApiKey = config.apiKeys?.some((entry) => entry.profile === 'admin') ?? false;
|
|
620
|
+
if (config.uiMode === 'web' && !(hasAdminApiKey || config.oidcIssuer || config.xsuaaAuth)) {
|
|
621
|
+
throw new Error('ARC1_UI=web requires HTTP authentication: set ARC1_API_KEYS with an admin key, SAP_OIDC_ISSUER/SAP_OIDC_AUDIENCE, or SAP_XSUAA_AUTH=true.');
|
|
622
|
+
}
|
|
623
|
+
if (config.uiMode === 'local' && !isLoopbackAddr(config.uiAddr)) {
|
|
624
|
+
throw new Error(`ARC1_UI=local must bind to a loopback address, got '${config.uiAddr}'. Use ARC1_UI=web with HTTP transport for network-exposed deployments.`);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
function isLoopbackAddr(addr) {
|
|
628
|
+
if (/^\d+$/.test(addr))
|
|
629
|
+
return true;
|
|
630
|
+
const host = addr.includes(':') ? addr.split(':')[0] : addr;
|
|
631
|
+
return host === 'localhost' || host === '::1' || host.startsWith('127.') || host === '';
|
|
559
632
|
}
|
|
560
633
|
//# sourceMappingURL=config.js.map
|