agent-nuvira 2.7.0 → 2.7.2

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.
Files changed (114) hide show
  1. package/dist/agents/orchestrator.d.ts.map +1 -1
  2. package/dist/agents/orchestrator.js +17 -3
  3. package/dist/agents/orchestrator.js.map +1 -1
  4. package/dist/app.js +26 -0
  5. package/dist/cli/chat.d.ts.map +1 -1
  6. package/dist/cli/chat.js +108 -2
  7. package/dist/cli/chat.js.map +1 -1
  8. package/dist/config/auth.js +18 -0
  9. package/dist/config/jwt.js +24 -0
  10. package/dist/config/keys.js +14 -0
  11. package/dist/gateway/chat-store.d.ts +32 -5
  12. package/dist/gateway/chat-store.d.ts.map +1 -1
  13. package/dist/gateway/chat-store.js +52 -6
  14. package/dist/gateway/chat-store.js.map +1 -1
  15. package/dist/gateway/registry.d.ts.map +1 -1
  16. package/dist/gateway/registry.js +54 -10
  17. package/dist/gateway/registry.js.map +1 -1
  18. package/dist/inference/model-validator.d.ts.map +1 -1
  19. package/dist/inference/model-validator.js +11 -1
  20. package/dist/inference/model-validator.js.map +1 -1
  21. package/dist/inference/tool-call-utils.d.ts +31 -0
  22. package/dist/inference/tool-call-utils.d.ts.map +1 -1
  23. package/dist/inference/tool-call-utils.js +41 -0
  24. package/dist/inference/tool-call-utils.js.map +1 -1
  25. package/dist/learning/reasoning-trace.d.ts +5 -3
  26. package/dist/learning/reasoning-trace.d.ts.map +1 -1
  27. package/dist/learning/reasoning-trace.js +2 -2
  28. package/dist/learning/reasoning-trace.js.map +1 -1
  29. package/dist/middleware/auth.js +30 -0
  30. package/dist/nlu/conversation-gate.js +1 -1
  31. package/dist/nlu/conversation-gate.js.map +1 -1
  32. package/dist/nlu/entities.d.ts.map +1 -1
  33. package/dist/nlu/entities.js +12 -0
  34. package/dist/nlu/entities.js.map +1 -1
  35. package/dist/nlu/intent.d.ts.map +1 -1
  36. package/dist/nlu/intent.js +83 -15
  37. package/dist/nlu/intent.js.map +1 -1
  38. package/dist/passport.js +34 -0
  39. package/dist/routes/auth.js +42 -0
  40. package/dist/routes/user.js +31 -0
  41. package/dist/server.js +17 -0
  42. package/dist/tools/pipeline-tool.d.ts.map +1 -1
  43. package/dist/tools/pipeline-tool.js +14 -0
  44. package/dist/tools/pipeline-tool.js.map +1 -1
  45. package/dist/tools/release-sync.d.ts +52 -16
  46. package/dist/tools/release-sync.d.ts.map +1 -1
  47. package/dist/tools/release-sync.js +143 -79
  48. package/dist/tools/release-sync.js.map +1 -1
  49. package/dist/web-dashboard/src/App.js +85 -0
  50. package/dist/web-dashboard/src/admin-auth.test.js +186 -0
  51. package/dist/web-dashboard/src/ansi.js +23 -0
  52. package/dist/web-dashboard/src/ansi.test.js +31 -0
  53. package/dist/web-dashboard/src/api-admin-auth.test.js +172 -0
  54. package/dist/web-dashboard/src/api-admin.test.js +65 -0
  55. package/dist/web-dashboard/src/api-hub.test.js +117 -0
  56. package/dist/web-dashboard/src/api.js +1421 -0
  57. package/dist/web-dashboard/src/api.test.js +51 -0
  58. package/dist/web-dashboard/src/artifacts.js +128 -0
  59. package/dist/web-dashboard/src/artifacts.test.js +139 -0
  60. package/dist/web-dashboard/src/components/AdminPanel.js +567 -0
  61. package/dist/web-dashboard/src/components/AdminPanel.test.js +288 -0
  62. package/dist/web-dashboard/src/components/AgentHub.js +1580 -0
  63. package/dist/web-dashboard/src/components/AgentHub.test.js +343 -0
  64. package/dist/web-dashboard/src/components/BedrockOnboarding.js +320 -0
  65. package/dist/web-dashboard/src/components/BenchmarkCharts.js +228 -0
  66. package/dist/web-dashboard/src/components/ChatPage.js +1586 -0
  67. package/dist/web-dashboard/src/components/ChatPage.test.js +899 -0
  68. package/dist/web-dashboard/src/components/ContactsPage.js +141 -0
  69. package/dist/web-dashboard/src/components/CostDashboard.js +105 -0
  70. package/dist/web-dashboard/src/components/DAGView.js +477 -0
  71. package/dist/web-dashboard/src/components/DAGView.test.js +147 -0
  72. package/dist/web-dashboard/src/components/EnvVarEditor.js +138 -0
  73. package/dist/web-dashboard/src/components/EvalsPage.js +73 -0
  74. package/dist/web-dashboard/src/components/EvalsPage.test.js +120 -0
  75. package/dist/web-dashboard/src/components/ExecutionHistory.js +201 -0
  76. package/dist/web-dashboard/src/components/GatewayPage.js +40 -0
  77. package/dist/web-dashboard/src/components/GatewayPage.test.js +74 -0
  78. package/dist/web-dashboard/src/components/HealthPanel.js +68 -0
  79. package/dist/web-dashboard/src/components/HistoryBrowser.js +34 -0
  80. package/dist/web-dashboard/src/components/Layout.js +50 -0
  81. package/dist/web-dashboard/src/components/Markdown.js +152 -0
  82. package/dist/web-dashboard/src/components/Markdown.test.js +126 -0
  83. package/dist/web-dashboard/src/components/MarkdownZeroDep.js +237 -0
  84. package/dist/web-dashboard/src/components/MemoryPanel.js +81 -0
  85. package/dist/web-dashboard/src/components/ModelTimeline.js +298 -0
  86. package/dist/web-dashboard/src/components/ModelsPanel.js +1484 -0
  87. package/dist/web-dashboard/src/components/ModelsPanel.test.js +460 -0
  88. package/dist/web-dashboard/src/components/Overview.js +123 -0
  89. package/dist/web-dashboard/src/components/PhaseTimeline.js +359 -0
  90. package/dist/web-dashboard/src/components/PhaseTimeline.test.js +234 -0
  91. package/dist/web-dashboard/src/components/PlatformConfigSection.js +384 -0
  92. package/dist/web-dashboard/src/components/PlatformConfigSection.test.js +106 -0
  93. package/dist/web-dashboard/src/components/PlatformsPage.js +250 -0
  94. package/dist/web-dashboard/src/components/QuotaPanel.js +159 -0
  95. package/dist/web-dashboard/src/components/QuotaPanel.test.js +85 -0
  96. package/dist/web-dashboard/src/components/RequestsPanel.js +229 -0
  97. package/dist/web-dashboard/src/components/RequestsPanel.test.js +103 -0
  98. package/dist/web-dashboard/src/components/RoutingInsightsPanel.js +938 -0
  99. package/dist/web-dashboard/src/components/RoutingInsightsPanel.test.js +339 -0
  100. package/dist/web-dashboard/src/components/RoutingWalkthrough.js +408 -0
  101. package/dist/web-dashboard/src/components/RoutingWalkthrough.test.js +209 -0
  102. package/dist/web-dashboard/src/components/TaskConsole.js +119 -0
  103. package/dist/web-dashboard/src/components/TaskConsole.test.js +123 -0
  104. package/dist/web-dashboard/src/components/TasksPage.js +256 -0
  105. package/dist/web-dashboard/src/components/TasksPage.test.js +103 -0
  106. package/dist/web-dashboard/src/components/TracePanel.js +306 -0
  107. package/dist/web-dashboard/src/components/WhatsAppPanel.js +195 -0
  108. package/dist/web-dashboard/src/components/WhatsAppPanel.test.js +122 -0
  109. package/dist/web-dashboard/src/jsonOrNull.js +37 -0
  110. package/dist/web-dashboard/src/main.js +15 -0
  111. package/dist/web-dashboard/src/mask.js +11 -0
  112. package/dist/web-dashboard/vite.config.js +23 -0
  113. package/dist/web-dashboard/vitest.config.js +15 -0
  114. package/package.json +5 -3
@@ -0,0 +1,320 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = BedrockOnboarding;
4
+ const react_1 = require("react");
5
+ const api_1 = require("../api");
6
+ // ─── Constants ──────────────────────────────────────────────────────────────
7
+ const BEDROCK_REGIONS = [
8
+ { value: 'us-east-1', label: 'us-east-1 (N. Virginia) — most models' },
9
+ { value: 'us-west-2', label: 'us-west-2 (Oregon) — most models' },
10
+ { value: 'eu-west-1', label: 'eu-west-1 (Ireland) — EU coverage' },
11
+ { value: 'ap-southeast-1', label: 'ap-southeast-1 (Singapore)' },
12
+ { value: 'ap-northeast-1', label: 'ap-northeast-1 (Tokyo)' },
13
+ ];
14
+ const MODEL_FAMILIES = [
15
+ { name: 'Anthropic Claude', models: ['claude-haiku-4.5', 'claude-sonnet-4.6', 'claude-fable-5', 'claude-opus-4.6'], checked: true },
16
+ { name: 'Meta Llama', models: ['llama3-1-8b', 'llama3-1-70b', 'llama3-3-70b', 'llama4-scout', 'llama4-maverick'], checked: true },
17
+ { name: 'Mistral AI', models: ['mistral-large-3', 'devstral-2', 'ministral-3'], checked: false },
18
+ { name: 'DeepSeek', models: ['deepseek-v3.2', 'deepseek-r1'], checked: false },
19
+ { name: 'Amazon Nova', models: ['nova-pro', 'nova-lite'], checked: false },
20
+ { name: 'OpenAI on Bedrock', models: ['gpt-5.6-terra', 'gpt-oss-120b'], checked: false },
21
+ { name: 'Qwen', models: ['qwen3-coder-next', 'qwen3-32b'], checked: false },
22
+ { name: 'Google Gemma', models: ['gemma-3-12b'], checked: false },
23
+ { name: 'xAI', models: ['grok-4.6'], checked: false },
24
+ ];
25
+ // ─── Main Component ─────────────────────────────────────────────────────────
26
+ function BedrockOnboarding({ canWrite, sessionExpired }) {
27
+ const [status, setStatus] = (0, react_1.useState)(null);
28
+ const [probeResults, setProbeResults] = (0, react_1.useState)(null);
29
+ const [probing, setProbing] = (0, react_1.useState)(false);
30
+ const [step, setStep] = (0, react_1.useState)('overview');
31
+ const mounted = (0, react_1.useRef)(true);
32
+ // Setup wizard state
33
+ const [authMethod, setAuthMethod] = (0, react_1.useState)('bearer');
34
+ const [apiKey, setApiKey] = (0, react_1.useState)('');
35
+ const [accessKeyId, setAccessKeyId] = (0, react_1.useState)('');
36
+ const [secretAccessKey, setSecretAccessKey] = (0, react_1.useState)('');
37
+ const [region, setRegion] = (0, react_1.useState)('us-east-1');
38
+ const [selectedFamilies, setSelectedFamilies] = (0, react_1.useState)(MODEL_FAMILIES.filter(f => f.checked).map(f => f.name));
39
+ const [saving, setSaving] = (0, react_1.useState)(false);
40
+ const [saveResult, setSaveResult] = (0, react_1.useState)(null);
41
+ const refresh = (0, react_1.useCallback)(async () => {
42
+ const s = await api_1.dashboardAPI.getBedrockStatus();
43
+ if (mounted.current)
44
+ setStatus(s);
45
+ }, []);
46
+ (0, react_1.useEffect)(() => {
47
+ void refresh();
48
+ return () => { mounted.current = false; };
49
+ }, [refresh]);
50
+ const runProbe = async () => {
51
+ setProbing(true);
52
+ setProbeResults(null);
53
+ try {
54
+ const result = await api_1.dashboardAPI.probeBedrock(status?.region || 'us-east-1');
55
+ if (!mounted.current)
56
+ return;
57
+ if (result.ok && result.models) {
58
+ setProbeResults(result.models);
59
+ setStep('test');
60
+ }
61
+ }
62
+ catch {
63
+ // ignore
64
+ }
65
+ finally {
66
+ if (mounted.current)
67
+ setProbing(false);
68
+ }
69
+ };
70
+ const saveSetup = async () => {
71
+ setSaving(true);
72
+ setSaveResult(null);
73
+ try {
74
+ const envVars = { BEDROCK_REGION: region };
75
+ if (authMethod === 'bearer' && apiKey) {
76
+ envVars.AWS_BEARER_TOKEN = apiKey;
77
+ }
78
+ else if (authMethod === 'iam') {
79
+ if (accessKeyId)
80
+ envVars.AWS_ACCESS_KEY_ID = accessKeyId;
81
+ if (secretAccessKey)
82
+ envVars.AWS_SECRET_ACCESS_KEY = secretAccessKey;
83
+ }
84
+ const result = await api_1.dashboardAPI.setupBedrock(envVars);
85
+ if (!mounted.current)
86
+ return;
87
+ if (result.ok) {
88
+ setSaveResult({ kind: 'ok', text: '✅ Configuration saved! Running connectivity test…' });
89
+ setStep('overview');
90
+ await refresh();
91
+ // Auto-probe after save
92
+ setTimeout(() => void runProbe(), 500);
93
+ }
94
+ else {
95
+ setSaveResult({ kind: 'err', text: result.error || 'Save failed' });
96
+ }
97
+ }
98
+ catch {
99
+ if (mounted.current)
100
+ setSaveResult({ kind: 'err', text: 'Could not reach the dashboard server.' });
101
+ }
102
+ finally {
103
+ if (mounted.current)
104
+ setSaving(false);
105
+ }
106
+ };
107
+ if (status === null) {
108
+ return <div className="empty-state">Loading Bedrock status…</div>;
109
+ }
110
+ // ── Render ──────────────────────────────────────────────────────────────
111
+ return (<div className="bedrock-onboarding">
112
+ <h2 className="section-title">🟠 AWS Bedrock</h2>
113
+ <p className="admin-subtitle">
114
+ Bedrock gives you access to Claude, Llama, Mistral, DeepSeek, and more — all through a single AWS account.
115
+ Unlike other providers, Bedrock requires a <strong>region</strong>, <strong>AWS credentials</strong>, and explicit <strong>model access approval</strong>.
116
+ </p>
117
+
118
+ {saveResult ? (<div className={`admin-row-msg${saveResult.kind === 'ok' ? '' : ' admin-row-msg-err'}`}>{saveResult.text}</div>) : null}
119
+
120
+ {/* ── Status Bar ─────────────────────────────────────────────────── */}
121
+ <div className="bedrock-status-bar">
122
+ <div className="bedrock-status-item">
123
+ <span className={`status-dot ${status.configured ? 'connected' : 'reconnecting'}`}/>
124
+ <span>{status.configured ? 'Configured' : 'Not configured'}</span>
125
+ </div>
126
+ <div className="bedrock-status-item">
127
+ <span className="bedrock-status-label">Region:</span>
128
+ <code>{status.region}</code>
129
+ </div>
130
+ <div className="bedrock-status-item">
131
+ <span className="bedrock-status-label">Auth:</span>
132
+ <code>{status.authMethod === 'bearer' ? 'API Key' : status.authMethod === 'iam' ? 'IAM' : 'None'}</code>
133
+ </div>
134
+ <div className="bedrock-status-actions">
135
+ {canWrite ? (<button type="button" className="admin-refresh-btn" onClick={() => setStep(step === 'setup' ? 'overview' : 'setup')}>
136
+ {step === 'setup' ? '✕ Cancel' : '⚙ Setup Wizard'}
137
+ </button>) : null}
138
+ {status.configured ? (<button type="button" className="admin-refresh-btn" onClick={() => void runProbe()} disabled={probing}>
139
+ {probing ? '⏳ Probing…' : '🔍 Test Models'}
140
+ </button>) : null}
141
+ </div>
142
+ </div>
143
+
144
+ {/* ── Setup Wizard ──────────────────────────────────────────────── */}
145
+ {step === 'setup' && (<div className="bedrock-setup-wizard">
146
+ <h3 className="section-subtitle">🚀 Bedrock Setup Wizard</h3>
147
+
148
+ {/* Step 1: Auth Method */}
149
+ <div className="bedrock-wizard-step">
150
+ <h4>Step 1: Authentication</h4>
151
+ <div className="bedrock-auth-options">
152
+ <label className={`bedrock-auth-option ${authMethod === 'bearer' ? 'selected' : ''}`}>
153
+ <input type="radio" name="authMethod" checked={authMethod === 'bearer'} onChange={() => setAuthMethod('bearer')}/>
154
+ <div>
155
+ <strong>Bedrock API Key</strong>
156
+ <span>Simpler — get from Bedrock → Settings → API keys</span>
157
+ </div>
158
+ </label>
159
+ <label className={`bedrock-auth-option ${authMethod === 'iam' ? 'selected' : ''}`}>
160
+ <input type="radio" name="authMethod" checked={authMethod === 'iam'} onChange={() => setAuthMethod('iam')}/>
161
+ <div>
162
+ <strong>IAM Credentials</strong>
163
+ <span>Full AWS SDK auth — AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY</span>
164
+ </div>
165
+ </label>
166
+ </div>
167
+
168
+ {authMethod === 'bearer' ? (<div className="bedrock-wizard-fields">
169
+ <div className="bedrock-setup-hint">
170
+ <strong>How to get a Bedrock API key:</strong>
171
+ <ol>
172
+ <li>Open <a href="https://console.aws.amazon.com/bedrock/" target="_blank" rel="noopener noreferrer">AWS Bedrock Console</a></li>
173
+ <li>Go to <strong>Settings</strong> → <strong>API keys</strong></li>
174
+ <li>Create a new key and paste it below</li>
175
+ </ol>
176
+ </div>
177
+ <label className="hub-send-target">
178
+ <span className="admin-hint">Bedrock API Key (Bearer token)</span>
179
+ <input type="password" value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder="••••••••••••" autoComplete="off" spellCheck={false}/>
180
+ </label>
181
+ </div>) : (<div className="bedrock-wizard-fields">
182
+ <div className="bedrock-setup-hint">
183
+ <strong>IAM credentials</strong> give full AWS SDK access. Create an IAM user with Bedrock permissions.
184
+ </div>
185
+ <label className="hub-send-target">
186
+ <span className="admin-hint">AWS_ACCESS_KEY_ID</span>
187
+ <input type="text" value={accessKeyId} onChange={(e) => setAccessKeyId(e.target.value)} placeholder="AKIA..." autoComplete="off" spellCheck={false}/>
188
+ </label>
189
+ <label className="hub-send-target">
190
+ <span className="admin-hint">AWS_SECRET_ACCESS_KEY</span>
191
+ <input type="password" value={secretAccessKey} onChange={(e) => setSecretAccessKey(e.target.value)} placeholder="••••••••••••" autoComplete="off" spellCheck={false}/>
192
+ </label>
193
+ </div>)}
194
+ </div>
195
+
196
+ {/* Step 2: Region */}
197
+ <div className="bedrock-wizard-step">
198
+ <h4>Step 2: AWS Region</h4>
199
+ <p className="admin-hint">
200
+ Models vary by region. <strong>us-east-1</strong> and <strong>us-west-2</strong> have the most models.
201
+ ⚠️ Do NOT use eu-north-1 unless models are explicitly enabled there.
202
+ </p>
203
+ <select className="bedrock-region-select" value={region} onChange={(e) => setRegion(e.target.value)}>
204
+ {BEDROCK_REGIONS.map((r) => (<option key={r.value} value={r.value}>{r.label}</option>))}
205
+ </select>
206
+ </div>
207
+
208
+ {/* Step 3: Model Access */}
209
+ <div className="bedrock-wizard-step">
210
+ <h4>Step 3: Model Access</h4>
211
+ <p className="admin-hint">
212
+ Bedrock requires you to request access for each model family.
213
+ </p>
214
+ <div className="bedrock-model-access-hint">
215
+ <a href={`https://console.aws.amazon.com/bedrock/home?region=${region}#/modelaccess`} target="_blank" rel="noopener noreferrer" className="admin-mini-btn">
216
+ 📖 Open Model Access in AWS Console
217
+ </a>
218
+ </div>
219
+ <div className="bedrock-family-grid">
220
+ {MODEL_FAMILIES.map((family) => (<label key={family.name} className={`bedrock-family-card ${selectedFamilies.includes(family.name) ? 'selected' : ''}`}>
221
+ <input type="checkbox" checked={selectedFamilies.includes(family.name)} onChange={(e) => {
222
+ if (e.target.checked) {
223
+ setSelectedFamilies((prev) => [...prev, family.name]);
224
+ }
225
+ else {
226
+ setSelectedFamilies((prev) => prev.filter((f) => f !== family.name));
227
+ }
228
+ }}/>
229
+ <div>
230
+ <strong>{family.name}</strong>
231
+ <span>{family.models.length} model(s)</span>
232
+ </div>
233
+ </label>))}
234
+ </div>
235
+ <p className="admin-hint" style={{ marginTop: 8 }}>
236
+ In the AWS Console, select the families above and submit. Approval is usually instant for Anthropic and Meta models.
237
+ </p>
238
+ </div>
239
+
240
+ {/* Save Button */}
241
+ <div className="bedrock-wizard-actions">
242
+ <button type="button" className="admin-refresh-btn" onClick={() => void saveSetup()} disabled={saving || (authMethod === 'bearer' && !apiKey) || (authMethod === 'iam' && (!accessKeyId || !secretAccessKey))}>
243
+ {saving ? '⏳ Saving…' : '💾 Save & Test'}
244
+ </button>
245
+ <button type="button" className="admin-mini-btn" onClick={() => setStep('overview')}>
246
+ Cancel
247
+ </button>
248
+ </div>
249
+ </div>)}
250
+
251
+ {/* ── Probe Results ──────────────────────────────────────────────── */}
252
+ {step === 'test' && probeResults && (<div className="bedrock-probe-results">
253
+ <h3 className="section-subtitle">🔍 Model Probe Results ({status.region})</h3>
254
+ <div className="bedrock-probe-grid">
255
+ {probeResults.map((r) => (<div key={r.modelId} className={`bedrock-probe-card bedrock-probe-${r.status}`}>
256
+ <span className={`bedrock-probe-icon`}>
257
+ {r.status === 'accessible' ? '✅' : r.status === 'permission-denied' ? '🔒' : r.status === 'not-found' ? '⚫' : '❌'}
258
+ </span>
259
+ <span className="bedrock-probe-id">{r.modelId}</span>
260
+ <span className="bedrock-probe-status">
261
+ {r.status === 'accessible' ? 'Ready' :
262
+ r.status === 'permission-denied' ? `Need access (HTTP ${r.httpStatus})` :
263
+ r.status === 'not-found' ? 'Not in this region' : 'Error'}
264
+ </span>
265
+ </div>))}
266
+ </div>
267
+ {probeResults.some((r) => r.status === 'permission-denied') && (<div className="bedrock-probe-action">
268
+ <p>Some models exist in {status.region} but access is not approved.</p>
269
+ <a href={`https://console.aws.amazon.com/bedrock/home?region=${status.region}#/modelaccess`} target="_blank" rel="noopener noreferrer" className="admin-mini-btn">
270
+ 🔓 Request Model Access in AWS Console →
271
+ </a>
272
+ </div>)}
273
+ <button type="button" className="admin-mini-btn" onClick={() => setStep('overview')} style={{ marginTop: 12 }}>
274
+ ← Back
275
+ </button>
276
+ </div>)}
277
+
278
+ {/* ── Getting Started Guide (when not configured) ──────────────── */}
279
+ {!status.configured && step === 'overview' && (<div className="bedrock-getting-started">
280
+ <h3 className="section-subtitle">📋 Getting Started with Bedrock</h3>
281
+ <div className="bedrock-steps">
282
+ <div className="bedrock-step">
283
+ <span className="bedrock-step-num">1</span>
284
+ <div>
285
+ <strong>Create an AWS account</strong> (or use existing)
286
+ <span>New to AWS? Sign up at <a href="https://aws.amazon.com/" target="_blank" rel="noopener noreferrer">aws.amazon.com</a></span>
287
+ </div>
288
+ </div>
289
+ <div className="bedrock-step">
290
+ <span className="bedrock-step-num">2</span>
291
+ <div>
292
+ <strong>Get Bedrock API key</strong>
293
+ <span>Bedrock → Settings → API keys → Create key</span>
294
+ </div>
295
+ </div>
296
+ <div className="bedrock-step">
297
+ <span className="bedrock-step-num">3</span>
298
+ <div>
299
+ <strong>Request model access</strong>
300
+ <span>Bedrock → Model access → Select Claude, Llama, etc. → Submit</span>
301
+ </div>
302
+ </div>
303
+ <div className="bedrock-step">
304
+ <span className="bedrock-step-num">4</span>
305
+ <div>
306
+ <strong>Configure in this wizard</strong>
307
+ <span>Click "Setup Wizard" above to enter your credentials</span>
308
+ </div>
309
+ </div>
310
+ </div>
311
+ </div>)}
312
+
313
+ {/* ── Quick Status (when configured) ──────────────────────────── */}
314
+ {status.configured && step === 'overview' && !probeResults && (<div className="bedrock-quick-status">
315
+ <p className="admin-hint">
316
+ Bedrock is configured. Click <strong>🔍 Test Models</strong> to verify connectivity and discover which models are accessible in {status.region}.
317
+ </p>
318
+ </div>)}
319
+ </div>);
320
+ }
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = BenchmarkCharts;
4
+ const recharts_1 = require("recharts");
5
+ function formatCost(usd) {
6
+ if (usd === undefined || usd === null)
7
+ return '$0.00';
8
+ return '$' + usd.toFixed(6);
9
+ }
10
+ function formatPercent(value) {
11
+ if (value === undefined || value === null)
12
+ return '0%';
13
+ return (value * 100).toFixed(1) + '%';
14
+ }
15
+ function BenchmarkCharts({ data }) {
16
+ if (!data) {
17
+ return <div className="loading-state"><p>Loading benchmark data...</p></div>;
18
+ }
19
+ const { benchmarks, evals } = data;
20
+ const latest = benchmarks.latest;
21
+ const runs = benchmarks.runs || [];
22
+ // ── Evaluation framework data (end-to-end agent tasks) ────────────────
23
+ const evalRuns = evals?.runs || [];
24
+ const latestEval = evals?.latest || null;
25
+ const evalChartData = evalRuns.map((run) => ({
26
+ name: run.model.length > 12 ? run.model.slice(0, 10) + '..' : run.model,
27
+ score: Math.round(run.summary.avgCompositeScore * 100),
28
+ completion: Math.round(run.summary.completionRate * 100),
29
+ tests: Math.round(run.summary.testPassRate * 100),
30
+ recovery: Math.round(run.summary.recoveryRate * 100),
31
+ efficiency: Math.round(run.summary.avgTokenEfficiency * 100),
32
+ fullModel: run.model,
33
+ provider: run.provider,
34
+ })).reverse();
35
+ // Build chart data from historical runs
36
+ const passRateData = runs.map((run) => ({
37
+ name: run.model.length > 12 ? run.model.slice(0, 10) + '..' : run.model,
38
+ passRate: run.summary.totalTasks > 0 ? Math.round((run.summary.tasksPassed / run.summary.totalTasks) * 100) : 0,
39
+ quality: Math.round(run.summary.avgQualityScore * 100),
40
+ latency: run.summary.medianLatencyMs,
41
+ cost: run.summary.totalCostUsd,
42
+ fullModel: run.model,
43
+ provider: run.provider,
44
+ })).reverse();
45
+ return (<>
46
+ <h2 className="section-title">📈 Benchmark Results</h2>
47
+
48
+ {/* Latest Run */}
49
+ <div className="benchmark-latest">
50
+ {latest ? (<>
51
+ <div className="benchmark-header">
52
+ <strong>Latest Run:</strong> {latest.provider}/{latest.model}
53
+ </div>
54
+ <div className="benchmark-stats">
55
+ <div className="benchmark-stat pass">
56
+ <div className="benchmark-stat-value">{latest.summary.tasksPassed}/{latest.summary.totalTasks}</div>
57
+ <div className="benchmark-stat-label">Passed</div>
58
+ </div>
59
+ <div className="benchmark-stat quality">
60
+ <div className="benchmark-stat-value">{formatPercent(latest.summary.avgQualityScore)}</div>
61
+ <div className="benchmark-stat-label">Quality</div>
62
+ </div>
63
+ <div className="benchmark-stat latency">
64
+ <div className="benchmark-stat-value">{latest.summary.medianLatencyMs}ms</div>
65
+ <div className="benchmark-stat-label">Latency</div>
66
+ </div>
67
+ <div className="benchmark-stat fail">
68
+ <div className="benchmark-stat-value">{formatCost(latest.summary.totalCostUsd)}</div>
69
+ <div className="benchmark-stat-label">Cost</div>
70
+ </div>
71
+ </div>
72
+ </>) : (<div className="empty-state">No benchmark runs yet. Run <code>buff benchmark</code> to start.</div>)}
73
+ </div>
74
+
75
+ {/* Pass Rate Chart */}
76
+ {passRateData.length > 1 && (<>
77
+ <h3 className="section-subtitle">Pass Rate by Model</h3>
78
+ <div className="chart-container">
79
+ <recharts_1.ResponsiveContainer width="100%" height={260}>
80
+ <recharts_1.BarChart data={passRateData} margin={{ top: 20, right: 20, left: 10, bottom: 40 }}>
81
+ <recharts_1.CartesianGrid strokeDasharray="3 3" stroke="#21262d"/>
82
+ <recharts_1.XAxis dataKey="name" tick={{ fill: '#8b949e', fontSize: 11 }} axisLine={{ stroke: '#30363d' }}/>
83
+ <recharts_1.YAxis domain={[0, 100]} tick={{ fill: '#8b949e', fontSize: 11 }} axisLine={{ stroke: '#30363d' }} tickFormatter={(v) => v + '%'}/>
84
+ <recharts_1.Tooltip contentStyle={{ background: '#161b22', border: '1px solid #30363d', borderRadius: 8 }} labelStyle={{ color: '#e6edf3' }} formatter={(value) => [value + '%', 'Pass Rate']}/>
85
+ <recharts_1.Bar dataKey="passRate" radius={[4, 4, 0, 0]}>
86
+ {passRateData.map((entry, i) => (<recharts_1.Cell key={i} fill={entry.passRate >= 80 ? '#3fb950' : entry.passRate >= 50 ? '#d29922' : '#f85149'} fillOpacity={0.8}/>))}
87
+ </recharts_1.Bar>
88
+ </recharts_1.BarChart>
89
+ </recharts_1.ResponsiveContainer>
90
+ </div>
91
+
92
+ {/* Latency Chart */}
93
+ <h3 className="section-subtitle">Latency by Model</h3>
94
+ <div className="chart-container">
95
+ <recharts_1.ResponsiveContainer width="100%" height={260}>
96
+ <recharts_1.BarChart data={passRateData} margin={{ top: 20, right: 20, left: 10, bottom: 40 }}>
97
+ <recharts_1.CartesianGrid strokeDasharray="3 3" stroke="#21262d"/>
98
+ <recharts_1.XAxis dataKey="name" tick={{ fill: '#8b949e', fontSize: 11 }} axisLine={{ stroke: '#30363d' }}/>
99
+ <recharts_1.YAxis tick={{ fill: '#8b949e', fontSize: 11 }} axisLine={{ stroke: '#30363d' }} tickFormatter={(v) => v + 'ms'}/>
100
+ <recharts_1.Tooltip contentStyle={{ background: '#161b22', border: '1px solid #30363d', borderRadius: 8 }} labelStyle={{ color: '#e6edf3' }} formatter={(value) => [value + 'ms', 'Latency']}/>
101
+ <recharts_1.Bar dataKey="latency" fill="#d29922" radius={[4, 4, 0, 0]} fillOpacity={0.8}/>
102
+ </recharts_1.BarChart>
103
+ </recharts_1.ResponsiveContainer>
104
+ </div>
105
+
106
+ {/* Cost Chart */}
107
+ <h3 className="section-subtitle">Cost by Model</h3>
108
+ <div className="chart-container">
109
+ <recharts_1.ResponsiveContainer width="100%" height={260}>
110
+ <recharts_1.BarChart data={passRateData} margin={{ top: 20, right: 20, left: 10, bottom: 40 }}>
111
+ <recharts_1.CartesianGrid strokeDasharray="3 3" stroke="#21262d"/>
112
+ <recharts_1.XAxis dataKey="name" tick={{ fill: '#8b949e', fontSize: 11 }} axisLine={{ stroke: '#30363d' }}/>
113
+ <recharts_1.YAxis tick={{ fill: '#8b949e', fontSize: 11 }} axisLine={{ stroke: '#30363d' }} tickFormatter={(v) => '$' + v.toFixed(6)}/>
114
+ <recharts_1.Tooltip contentStyle={{ background: '#161b22', border: '1px solid #30363d', borderRadius: 8 }} labelStyle={{ color: '#e6edf3' }} formatter={(value) => ['$' + value.toFixed(6), 'Cost']}/>
115
+ <recharts_1.Bar dataKey="cost" fill="#bc8cff" radius={[4, 4, 0, 0]} fillOpacity={0.8}/>
116
+ </recharts_1.BarChart>
117
+ </recharts_1.ResponsiveContainer>
118
+ </div>
119
+ </>)}
120
+
121
+ {/* ═══ Evaluation Framework Section ═══ */}
122
+ <h2 className="section-title" style={{ marginTop: 32 }}>🎯 Agent Evaluation</h2>
123
+ <p className="section-hint" style={{ color: '#8b949e', fontSize: 12, marginBottom: 16 }}>
124
+ End-to-end coding tasks run through the full agent pipeline — measures if the agent is actually improving.
125
+ </p>
126
+
127
+ {/* Latest Eval Run */}
128
+ <div className="benchmark-latest">
129
+ {latestEval ? (<>
130
+ <div className="benchmark-header">
131
+ <strong>Latest Eval Run:</strong> {latestEval.provider}/{latestEval.model}
132
+ </div>
133
+ <div className="benchmark-stats">
134
+ <div className="benchmark-stat pass">
135
+ <div className="benchmark-stat-value">{latestEval.summary.tasksPassed}/{latestEval.summary.totalTasks}</div>
136
+ <div className="benchmark-stat-label">Tests Passed</div>
137
+ </div>
138
+ <div className="benchmark-stat quality">
139
+ <div className="benchmark-stat-value">{formatPercent(latestEval.summary.avgCompositeScore)}</div>
140
+ <div className="benchmark-stat-label">Composite Score</div>
141
+ </div>
142
+ <div className="benchmark-stat latency">
143
+ <div className="benchmark-stat-value">{formatPercent(latestEval.summary.recoveryRate)}</div>
144
+ <div className="benchmark-stat-label">Recovery Rate</div>
145
+ </div>
146
+ <div className="benchmark-stat fail">
147
+ <div className="benchmark-stat-value">{latestEval.summary.totalRollbacks}</div>
148
+ <div className="benchmark-stat-label">Rollbacks</div>
149
+ </div>
150
+ <div className="benchmark-stat deps">
151
+ <div className="benchmark-stat-value">{formatPercent(latestEval.summary.dependencyInstallRate)}</div>
152
+ <div className="benchmark-stat-label">Deps Installed</div>
153
+ </div>
154
+ </div>
155
+ </>) : (<div className="empty-state">No eval runs yet. Run <code>buff eval run</code> to measure the agent end-to-end.</div>)}
156
+ </div>
157
+
158
+ {/* Eval Composite Score Chart */}
159
+ {evalChartData.length > 1 && (<>
160
+ <h3 className="section-subtitle">Composite Score by Model</h3>
161
+ <div className="chart-container">
162
+ <recharts_1.ResponsiveContainer width="100%" height={260}>
163
+ <recharts_1.BarChart data={evalChartData} margin={{ top: 20, right: 20, left: 10, bottom: 40 }}>
164
+ <recharts_1.CartesianGrid strokeDasharray="3 3" stroke="#21262d"/>
165
+ <recharts_1.XAxis dataKey="name" tick={{ fill: '#8b949e', fontSize: 11 }} axisLine={{ stroke: '#30363d' }}/>
166
+ <recharts_1.YAxis domain={[0, 100]} tick={{ fill: '#8b949e', fontSize: 11 }} axisLine={{ stroke: '#30363d' }} tickFormatter={(v) => v + '%'}/>
167
+ <recharts_1.Tooltip contentStyle={{ background: '#161b22', border: '1px solid #30363d', borderRadius: 8 }} labelStyle={{ color: '#e6edf3' }} formatter={(value) => [value + '%', 'Composite Score']}/>
168
+ <recharts_1.Bar dataKey="score" radius={[4, 4, 0, 0]}>
169
+ {evalChartData.map((entry, i) => (<recharts_1.Cell key={i} fill={entry.score >= 80 ? '#3fb950' : entry.score >= 50 ? '#d29922' : '#f85149'} fillOpacity={0.8}/>))}
170
+ </recharts_1.Bar>
171
+ </recharts_1.BarChart>
172
+ </recharts_1.ResponsiveContainer>
173
+ </div>
174
+
175
+ {/* Eval Metrics Breakdown Chart */}
176
+ <h3 className="section-subtitle">Metric Breakdown (completion / tests / recovery / token efficiency)</h3>
177
+ <div className="chart-container">
178
+ <recharts_1.ResponsiveContainer width="100%" height={260}>
179
+ <recharts_1.BarChart data={evalChartData} margin={{ top: 20, right: 20, left: 10, bottom: 40 }}>
180
+ <recharts_1.CartesianGrid strokeDasharray="3 3" stroke="#21262d"/>
181
+ <recharts_1.XAxis dataKey="name" tick={{ fill: '#8b949e', fontSize: 11 }} axisLine={{ stroke: '#30363d' }}/>
182
+ <recharts_1.YAxis domain={[0, 100]} tick={{ fill: '#8b949e', fontSize: 11 }} axisLine={{ stroke: '#30363d' }} tickFormatter={(v) => v + '%'}/>
183
+ <recharts_1.Tooltip contentStyle={{ background: '#161b22', border: '1px solid #30363d', borderRadius: 8 }} labelStyle={{ color: '#e6edf3' }}/>
184
+ <recharts_1.Legend wrapperStyle={{ color: '#8b949e' }}/>
185
+ <recharts_1.Bar dataKey="completion" name="Completion" fill="#3fb950" radius={[4, 4, 0, 0]} fillOpacity={0.8}/>
186
+ <recharts_1.Bar dataKey="tests" name="Tests" fill="#58a6ff" radius={[4, 4, 0, 0]} fillOpacity={0.8}/>
187
+ <recharts_1.Bar dataKey="recovery" name="Recovery" fill="#d29922" radius={[4, 4, 0, 0]} fillOpacity={0.8}/>
188
+ <recharts_1.Bar dataKey="efficiency" name="Token Eff." fill="#bc8cff" radius={[4, 4, 0, 0]} fillOpacity={0.8}/>
189
+ </recharts_1.BarChart>
190
+ </recharts_1.ResponsiveContainer>
191
+ </div>
192
+ </>)}
193
+
194
+ {/* Eval Run History */}
195
+ <h3 className="section-subtitle">Eval Run History</h3>
196
+ <div className="benchmark-list">
197
+ {evalRuns.length === 0 ? (<div className="empty-state">No eval runs yet. Run <code>buff eval run</code> to start.</div>) : (evalRuns.map((run) => {
198
+ const score = Math.round(run.summary.avgCompositeScore * 100);
199
+ const scoreClass = score >= 80 ? 'high' : score >= 50 ? 'medium' : 'low';
200
+ return (<div className="benchmark-item" key={run.id}>
201
+ <span className="benchmark-date">
202
+ {new Date(run.startedAt).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}
203
+ </span>
204
+ <span className="benchmark-model">{run.provider}/{run.model}</span>
205
+ <span className={`benchmark-score ${scoreClass}`}>{score}%</span>
206
+ </div>);
207
+ }))}
208
+ </div>
209
+
210
+ {/* Run History */}
211
+ <h3 className="section-subtitle">Run History</h3>
212
+ <div className="benchmark-list">
213
+ {runs.length === 0 ? (<div className="empty-state">No benchmark runs yet. Run <code>buff benchmark</code> to start.</div>) : (runs.map((run) => {
214
+ const passRate = run.summary.totalTasks > 0
215
+ ? Math.round((run.summary.tasksPassed / run.summary.totalTasks) * 100)
216
+ : 0;
217
+ const scoreClass = passRate >= 80 ? 'high' : passRate >= 50 ? 'medium' : 'low';
218
+ return (<div className="benchmark-item" key={run.id}>
219
+ <span className="benchmark-date">
220
+ {new Date(run.startedAt).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })}
221
+ </span>
222
+ <span className="benchmark-model">{run.provider}/{run.model}</span>
223
+ <span className={`benchmark-score ${scoreClass}`}>{passRate}%</span>
224
+ </div>);
225
+ }))}
226
+ </div>
227
+ </>);
228
+ }