@fias/plugin-dev-harness 1.3.0 → 1.3.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/dist/server/static/harness.css +0 -58
- package/dist/server/static/harness.html +7 -20
- package/dist/server/static/harness.js +6 -162
- package/dist/server/static/static/harness.css +390 -0
- package/dist/server/static/static/harness.html +66 -0
- package/dist/server/static/static/harness.js +706 -0
- package/package.json +2 -2
|
@@ -37,28 +37,6 @@ body {
|
|
|
37
37
|
color: #a78bfa;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
/* Environment selector */
|
|
41
|
-
.env-selector {
|
|
42
|
-
background: #27272a;
|
|
43
|
-
color: #a1a1aa;
|
|
44
|
-
border: 1px solid #3f3f46;
|
|
45
|
-
border-radius: 4px;
|
|
46
|
-
padding: 3px 8px;
|
|
47
|
-
font-size: 11px;
|
|
48
|
-
font-weight: 600;
|
|
49
|
-
cursor: pointer;
|
|
50
|
-
outline: none;
|
|
51
|
-
text-transform: uppercase;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.env-selector:hover {
|
|
55
|
-
border-color: #52525b;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.env-selector:focus {
|
|
59
|
-
border-color: #a78bfa;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
40
|
.mode-badge {
|
|
63
41
|
padding: 3px 10px;
|
|
64
42
|
border-radius: 4px;
|
|
@@ -215,12 +193,6 @@ body {
|
|
|
215
193
|
cursor: not-allowed;
|
|
216
194
|
}
|
|
217
195
|
|
|
218
|
-
.btn-full {
|
|
219
|
-
width: 100%;
|
|
220
|
-
padding: 10px 16px;
|
|
221
|
-
margin-bottom: 12px;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
196
|
.btn-secondary {
|
|
225
197
|
background: transparent;
|
|
226
198
|
color: #a1a1aa;
|
|
@@ -235,36 +207,6 @@ body {
|
|
|
235
207
|
background: #3f3f46;
|
|
236
208
|
}
|
|
237
209
|
|
|
238
|
-
.btn-link {
|
|
239
|
-
background: none;
|
|
240
|
-
border: none;
|
|
241
|
-
color: #a78bfa;
|
|
242
|
-
cursor: pointer;
|
|
243
|
-
font-size: 12px;
|
|
244
|
-
padding: 0;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
.btn-link:hover {
|
|
248
|
-
text-decoration: underline;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
.modal-divider {
|
|
252
|
-
display: flex;
|
|
253
|
-
align-items: center;
|
|
254
|
-
gap: 12px;
|
|
255
|
-
margin: 12px 0;
|
|
256
|
-
color: #6b7280;
|
|
257
|
-
font-size: 12px;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
.modal-divider::before,
|
|
261
|
-
.modal-divider::after {
|
|
262
|
-
content: '';
|
|
263
|
-
flex: 1;
|
|
264
|
-
height: 1px;
|
|
265
|
-
background: #3f3f46;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
210
|
/* Plugin status overlay */
|
|
269
211
|
.plugin-status {
|
|
270
212
|
flex: 1;
|
|
@@ -10,10 +10,6 @@
|
|
|
10
10
|
<div class="toolbar">
|
|
11
11
|
<div class="toolbar-left">
|
|
12
12
|
<span class="logo">Fias Arche Dev</span>
|
|
13
|
-
<select id="env-selector" class="env-selector">
|
|
14
|
-
<option value="staging">STAGING</option>
|
|
15
|
-
<option value="production">PRODUCTION</option>
|
|
16
|
-
</select>
|
|
17
13
|
<button id="mode-badge" class="mode-badge mode-mock" title="Click to switch mode">MOCK ⇆</button>
|
|
18
14
|
</div>
|
|
19
15
|
<div class="toolbar-right">
|
|
@@ -27,23 +23,14 @@
|
|
|
27
23
|
<div id="login-modal" class="modal-overlay" style="display: none">
|
|
28
24
|
<div class="modal">
|
|
29
25
|
<h3>Connect to FIAS</h3>
|
|
30
|
-
<p>
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
<p id="login-popup-hint" class="modal-hint" style="display:none">
|
|
34
|
-
Popup blocked? <a id="login-popup-link" href="#" target="_blank" style="color:#a78bfa">Open login page manually</a>
|
|
35
|
-
</p>
|
|
36
|
-
<div class="modal-divider"><span>or</span></div>
|
|
37
|
-
<button id="login-manual-toggle" class="btn-link">Enter API key manually</button>
|
|
38
|
-
</div>
|
|
39
|
-
<div id="login-manual-section" style="display:none">
|
|
40
|
-
<input id="login-input" type="password" class="modal-input" placeholder="fias_sk_..." autocomplete="off" />
|
|
41
|
-
<div class="modal-actions">
|
|
42
|
-
<button id="login-cancel" class="btn-secondary">Cancel</button>
|
|
43
|
-
<button id="login-submit" class="btn-primary">Save & Connect</button>
|
|
44
|
-
</div>
|
|
45
|
-
</div>
|
|
26
|
+
<p>Enter your API key to enable live mode with real AI responses.</p>
|
|
27
|
+
<p class="modal-hint">Get an API key from your FIAS platform account settings.</p>
|
|
28
|
+
<input id="login-input" type="password" class="modal-input" placeholder="fias_sk_..." autocomplete="off" />
|
|
46
29
|
<div id="login-error" class="modal-error" style="display: none"></div>
|
|
30
|
+
<div class="modal-actions">
|
|
31
|
+
<button id="login-cancel" class="btn-secondary">Cancel</button>
|
|
32
|
+
<button id="login-submit" class="btn-primary">Save & Connect</button>
|
|
33
|
+
</div>
|
|
47
34
|
</div>
|
|
48
35
|
</div>
|
|
49
36
|
<div id="plugin-status" class="plugin-status">
|
|
@@ -26,21 +26,12 @@
|
|
|
26
26
|
var loginError = document.getElementById('login-error');
|
|
27
27
|
var loginSubmit = document.getElementById('login-submit');
|
|
28
28
|
var loginCancel = document.getElementById('login-cancel');
|
|
29
|
-
var envSelector = document.getElementById('env-selector');
|
|
30
|
-
var loginPopupBtn = document.getElementById('login-popup-btn');
|
|
31
|
-
var loginPopupHint = document.getElementById('login-popup-hint');
|
|
32
|
-
var loginPopupLink = document.getElementById('login-popup-link');
|
|
33
|
-
var loginManualToggle = document.getElementById('login-manual-toggle');
|
|
34
|
-
var loginManualSection = document.getElementById('login-manual-section');
|
|
35
|
-
var loginPopupSection = document.getElementById('login-popup-section');
|
|
36
29
|
|
|
37
30
|
var messageCount = 0;
|
|
38
31
|
var currentTheme = 'dark';
|
|
39
32
|
var currentMode = 'mock';
|
|
40
|
-
var currentEnvironment = 'staging';
|
|
41
33
|
var hasCredentials = false;
|
|
42
34
|
var cachedConfig = null;
|
|
43
|
-
var authPollInterval = null;
|
|
44
35
|
|
|
45
36
|
/** Permission requirements per bridge call type (matches production) */
|
|
46
37
|
var PERMISSION_MAP = {
|
|
@@ -71,10 +62,8 @@
|
|
|
71
62
|
cachedConfig = config;
|
|
72
63
|
currentTheme = config.mockTheme || 'dark';
|
|
73
64
|
currentMode = config.mode || 'mock';
|
|
74
|
-
currentEnvironment = config.environment || 'staging';
|
|
75
65
|
hasCredentials = config.hasCredentials || false;
|
|
76
66
|
|
|
77
|
-
envSelector.value = currentEnvironment;
|
|
78
67
|
updateThemeBadge();
|
|
79
68
|
updateModeBadge();
|
|
80
69
|
|
|
@@ -149,42 +138,6 @@
|
|
|
149
138
|
}
|
|
150
139
|
});
|
|
151
140
|
|
|
152
|
-
// Environment selector
|
|
153
|
-
envSelector.addEventListener('change', function () {
|
|
154
|
-
fetch('/api/environment', {
|
|
155
|
-
method: 'POST',
|
|
156
|
-
headers: { 'Content-Type': 'application/json' },
|
|
157
|
-
body: JSON.stringify({ environment: envSelector.value }),
|
|
158
|
-
})
|
|
159
|
-
.then(function (r) {
|
|
160
|
-
return r.json();
|
|
161
|
-
})
|
|
162
|
-
.then(function (data) {
|
|
163
|
-
currentEnvironment = data.environment;
|
|
164
|
-
currentMode = data.mode;
|
|
165
|
-
hasCredentials = data.hasCredentials;
|
|
166
|
-
updateModeBadge();
|
|
167
|
-
|
|
168
|
-
if (currentMode === 'live') {
|
|
169
|
-
creditBalance.style.display = 'inline';
|
|
170
|
-
fetchCredits();
|
|
171
|
-
} else {
|
|
172
|
-
creditBalance.style.display = 'none';
|
|
173
|
-
creditBalance.textContent = '';
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
logMessage(
|
|
177
|
-
'info',
|
|
178
|
-
'Environment: ' +
|
|
179
|
-
currentEnvironment.toUpperCase() +
|
|
180
|
-
(hasCredentials ? '' : ' (not authenticated)'),
|
|
181
|
-
);
|
|
182
|
-
})
|
|
183
|
-
.catch(function (err) {
|
|
184
|
-
logMessage('error', err.message);
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
|
|
188
141
|
function switchMode(newMode) {
|
|
189
142
|
fetch('/api/mode', {
|
|
190
143
|
method: 'POST',
|
|
@@ -223,19 +176,15 @@
|
|
|
223
176
|
|
|
224
177
|
function showLoginModal() {
|
|
225
178
|
loginModal.style.display = 'flex';
|
|
226
|
-
|
|
227
|
-
loginManualSection.style.display = 'none';
|
|
228
|
-
loginPopupHint.style.display = 'none';
|
|
179
|
+
loginInput.value = '';
|
|
229
180
|
loginError.style.display = 'none';
|
|
230
|
-
|
|
231
|
-
loginPopupBtn.textContent = 'Sign in with FIAS';
|
|
181
|
+
loginInput.focus();
|
|
232
182
|
}
|
|
233
183
|
|
|
234
184
|
function hideLoginModal() {
|
|
235
185
|
loginModal.style.display = 'none';
|
|
236
186
|
loginInput.value = '';
|
|
237
187
|
loginError.style.display = 'none';
|
|
238
|
-
stopAuthPolling();
|
|
239
188
|
}
|
|
240
189
|
|
|
241
190
|
loginCancel.addEventListener('click', hideLoginModal);
|
|
@@ -244,13 +193,6 @@
|
|
|
244
193
|
if (e.target === loginModal) hideLoginModal();
|
|
245
194
|
});
|
|
246
195
|
|
|
247
|
-
// Toggle to manual key entry
|
|
248
|
-
loginManualToggle.addEventListener('click', function () {
|
|
249
|
-
loginPopupSection.style.display = 'none';
|
|
250
|
-
loginManualSection.style.display = 'block';
|
|
251
|
-
loginInput.focus();
|
|
252
|
-
});
|
|
253
|
-
|
|
254
196
|
loginInput.addEventListener('keydown', function (e) {
|
|
255
197
|
if (e.key === 'Enter') submitLogin();
|
|
256
198
|
if (e.key === 'Escape') hideLoginModal();
|
|
@@ -258,39 +200,6 @@
|
|
|
258
200
|
|
|
259
201
|
loginSubmit.addEventListener('click', submitLogin);
|
|
260
202
|
|
|
261
|
-
// Popup-based login
|
|
262
|
-
loginPopupBtn.addEventListener('click', function () {
|
|
263
|
-
loginPopupBtn.disabled = true;
|
|
264
|
-
loginPopupBtn.textContent = 'Opening...';
|
|
265
|
-
|
|
266
|
-
fetch('/api/auth/start', { method: 'POST' })
|
|
267
|
-
.then(function (r) {
|
|
268
|
-
return r.json();
|
|
269
|
-
})
|
|
270
|
-
.then(function (data) {
|
|
271
|
-
var popup = window.open(data.authUrl, 'fias-auth', 'width=500,height=650');
|
|
272
|
-
|
|
273
|
-
if (!popup || popup.closed) {
|
|
274
|
-
// Popup was blocked — show fallback link
|
|
275
|
-
loginPopupHint.style.display = 'block';
|
|
276
|
-
loginPopupLink.href = data.authUrl;
|
|
277
|
-
loginPopupBtn.disabled = false;
|
|
278
|
-
loginPopupBtn.textContent = 'Sign in with FIAS';
|
|
279
|
-
} else {
|
|
280
|
-
loginPopupBtn.textContent = 'Waiting for sign-in...';
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// Start polling as fallback (works even if popup can't postMessage)
|
|
284
|
-
startAuthPolling();
|
|
285
|
-
})
|
|
286
|
-
.catch(function (err) {
|
|
287
|
-
loginError.textContent = err.message;
|
|
288
|
-
loginError.style.display = 'block';
|
|
289
|
-
loginPopupBtn.disabled = false;
|
|
290
|
-
loginPopupBtn.textContent = 'Sign in with FIAS';
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
|
|
294
203
|
function submitLogin() {
|
|
295
204
|
var apiKey = loginInput.value.trim();
|
|
296
205
|
if (!apiKey) {
|
|
@@ -332,57 +241,11 @@
|
|
|
332
241
|
});
|
|
333
242
|
}
|
|
334
243
|
|
|
335
|
-
// Auth polling — fallback for popup blocked or postMessage unavailable
|
|
336
|
-
function startAuthPolling() {
|
|
337
|
-
if (authPollInterval) return;
|
|
338
|
-
authPollInterval = setInterval(function () {
|
|
339
|
-
fetch('/api/config')
|
|
340
|
-
.then(function (r) {
|
|
341
|
-
return r.json();
|
|
342
|
-
})
|
|
343
|
-
.then(function (config) {
|
|
344
|
-
if (config.hasCredentials && !hasCredentials) {
|
|
345
|
-
hasCredentials = true;
|
|
346
|
-
stopAuthPolling();
|
|
347
|
-
hideLoginModal();
|
|
348
|
-
logMessage('info', 'Authenticated for ' + currentEnvironment.toUpperCase());
|
|
349
|
-
switchMode('live');
|
|
350
|
-
}
|
|
351
|
-
})
|
|
352
|
-
.catch(function () {});
|
|
353
|
-
}, 2000);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function stopAuthPolling() {
|
|
357
|
-
if (authPollInterval) {
|
|
358
|
-
clearInterval(authPollInterval);
|
|
359
|
-
authPollInterval = null;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
244
|
// ────────────────────────────────────────────────────────────────
|
|
364
245
|
// Message Handling
|
|
365
246
|
// ────────────────────────────────────────────────────────────────
|
|
366
247
|
|
|
367
248
|
window.addEventListener('message', function (event) {
|
|
368
|
-
// Handle auth callback from popup
|
|
369
|
-
if (event.data && event.data.type === 'auth_callback') {
|
|
370
|
-
stopAuthPolling();
|
|
371
|
-
if (event.data.success) {
|
|
372
|
-
hasCredentials = true;
|
|
373
|
-
hideLoginModal();
|
|
374
|
-
logMessage('info', 'Authenticated for ' + currentEnvironment.toUpperCase());
|
|
375
|
-
switchMode('live');
|
|
376
|
-
} else {
|
|
377
|
-
loginError.textContent = event.data.error || 'Authentication failed';
|
|
378
|
-
loginError.style.display = 'block';
|
|
379
|
-
}
|
|
380
|
-
loginPopupBtn.disabled = false;
|
|
381
|
-
loginPopupBtn.textContent = 'Sign in with FIAS';
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
// Handle plugin iframe messages
|
|
386
249
|
if (event.source !== iframe.contentWindow) return;
|
|
387
250
|
|
|
388
251
|
var data = event.data;
|
|
@@ -556,51 +419,32 @@
|
|
|
556
419
|
var SPACING = { xs: '4px', sm: '8px', md: '16px', lg: '24px', xl: '32px' };
|
|
557
420
|
var FONTS = { body: SYSTEM_FONTS, heading: SYSTEM_FONTS, mono: MONO_FONTS };
|
|
558
421
|
|
|
559
|
-
var COMPONENTS = {
|
|
560
|
-
borderRadius: '0.5rem',
|
|
561
|
-
buttonRadius: '0.375rem',
|
|
562
|
-
cardRadius: '0.5rem',
|
|
563
|
-
inputRadius: '0.375rem',
|
|
564
|
-
shadowSm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
565
|
-
shadowMd: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',
|
|
566
|
-
shadowLg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)',
|
|
567
|
-
borderWidth: '1px',
|
|
568
|
-
};
|
|
569
|
-
|
|
570
422
|
function getTheme() {
|
|
571
423
|
if (currentTheme === 'light') {
|
|
572
424
|
return {
|
|
573
425
|
mode: 'light',
|
|
574
426
|
colors: {
|
|
575
|
-
primary: '#171717',
|
|
576
|
-
secondary: '#e5e5e5', accent: '#2563eb',
|
|
427
|
+
primary: '#171717', secondary: '#e5e5e5',
|
|
577
428
|
background: '#ffffff', surface: '#fafafa',
|
|
578
|
-
card: '#ffffff', cardText: '#0a0a0a',
|
|
579
429
|
text: '#0a0a0a', textSecondary: '#737373',
|
|
580
|
-
muted: '#f5f5f5', mutedText: '#a3a3a3',
|
|
581
430
|
border: '#e5e5e5',
|
|
582
|
-
error: '#dc2626', warning: '#d97706', success: '#16a34a',
|
|
431
|
+
error: '#dc2626', warning: '#d97706', success: '#16a34a',
|
|
583
432
|
},
|
|
584
433
|
spacing: SPACING,
|
|
585
434
|
fonts: FONTS,
|
|
586
|
-
components: COMPONENTS,
|
|
587
435
|
};
|
|
588
436
|
}
|
|
589
437
|
return {
|
|
590
438
|
mode: 'dark',
|
|
591
439
|
colors: {
|
|
592
|
-
primary: '#ffffff',
|
|
593
|
-
secondary: '#1f1f1f', accent: '#3b82f6',
|
|
440
|
+
primary: '#ffffff', secondary: '#1f1f1f',
|
|
594
441
|
background: '#0a0a0a', surface: '#171717',
|
|
595
|
-
card: '#141414', cardText: '#ffffff',
|
|
596
442
|
text: '#ffffff', textSecondary: '#a6a6a6',
|
|
597
|
-
muted: '#1e1e1e', mutedText: '#737373',
|
|
598
443
|
border: '#2e2e2e',
|
|
599
|
-
error: '#ef4444', warning: '#f59e0b', success: '#22c55e',
|
|
444
|
+
error: '#ef4444', warning: '#f59e0b', success: '#22c55e',
|
|
600
445
|
},
|
|
601
446
|
spacing: SPACING,
|
|
602
447
|
fonts: FONTS,
|
|
603
|
-
components: COMPONENTS,
|
|
604
448
|
};
|
|
605
449
|
}
|
|
606
450
|
|