@swarmclawai/swarmclaw 1.5.71 → 1.6.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/README.md +21 -0
- package/package.json +3 -3
- package/src/app/.well-known/agent-card.json/route.ts +15 -0
- package/src/app/api/.well-known/agent-card/route.ts +6 -37
- package/src/app/home/page.tsx +11 -3
- package/src/app/quality/page.tsx +7 -0
- package/src/components/home/home-launchpad.tsx +109 -5
- package/src/components/layout/sidebar-rail.tsx +6 -0
- package/src/components/quality/quality-workspace.tsx +632 -0
- package/src/components/runs/run-list.tsx +53 -2
- package/src/components/shared/command-palette.tsx +1 -0
- package/src/lib/a2a/agent-card.test.ts +94 -0
- package/src/lib/a2a/agent-card.ts +41 -1
- package/src/lib/app/navigation.ts +1 -0
- package/src/lib/app/view-constants.test.ts +8 -1
- package/src/lib/app/view-constants.ts +9 -1
- package/src/lib/providers/opencode-cli.test.ts +9 -0
- package/src/lib/providers/opencode-cli.ts +5 -1
- package/src/lib/quality/quality-summary.test.ts +122 -0
- package/src/lib/quality/quality-summary.ts +150 -0
- package/src/lib/server/missions/mission-templates.test.ts +39 -0
- package/src/lib/server/missions/mission-templates.ts +185 -0
- package/src/lib/server/protocols/protocol-service.test.ts +25 -0
- package/src/lib/server/protocols/protocol-templates.ts +48 -0
- package/src/lib/strip-internal-metadata.test.ts +23 -0
- package/src/lib/strip-internal-metadata.ts +136 -7
- package/src/types/session.ts +1 -1
package/README.md
CHANGED
|
@@ -399,6 +399,27 @@ Operational docs: https://swarmclaw.ai/docs/observability
|
|
|
399
399
|
|
|
400
400
|
## Releases
|
|
401
401
|
|
|
402
|
+
### v1.6.1 Highlights
|
|
403
|
+
|
|
404
|
+
Follow-up release for v1.6 with workflow starts, safer metadata handling, A2A discovery polish, and [#61](https://github.com/swarmclawai/swarmclaw/pull/61) by [@latentwill](https://github.com/latentwill). Thanks latentwill!
|
|
405
|
+
|
|
406
|
+
- **Mission and protocol templates for real work.** New starter paths cover codebase review sprints, research bureau scans, content studio cycles, release readiness panels, synthesis panels, and builder review loops.
|
|
407
|
+
- **Home launchpad paths.** First-run users can choose a self-hosted assistant, visual workflow, or autonomous mission path, with quality actions still one click away.
|
|
408
|
+
- **A2A discovery is easier to integrate.** The canonical `/.well-known/agent-card.json` endpoint now works alongside the legacy API route and hides disabled or trashed agents from public discovery.
|
|
409
|
+
- **Internal metadata stripping is safer.** Side-channel JSON is removed with balanced-object parsing and zod validation so nested payloads are scrubbed without deleting ordinary user JSON.
|
|
410
|
+
- **Browser smoke gate restored.** `npm run test:e2e` now runs a Playwright smoke against health, A2A discovery, `/home`, and `/quality`, either against a live URL or a temporary local dev server.
|
|
411
|
+
- **OpenCode CLI hang fixed.** OpenCode CLI delegation no longer keeps an inherited stdin pipe open, preventing hangs in non-interactive runs.
|
|
412
|
+
|
|
413
|
+
### v1.6.0 Highlights
|
|
414
|
+
|
|
415
|
+
Operator Quality Center release for builders running autonomous agents in production-like workflows.
|
|
416
|
+
|
|
417
|
+
- **New Quality workspace.** `/quality` brings run health, failed/running counts, pending approvals, latest eval scores, and attention shortcuts into one operator surface.
|
|
418
|
+
- **Eval Lab and Approval Desk.** Existing eval and approval APIs are now exposed through a practical UI for running scenarios/suites, reviewing score evidence, and approving or denying human-loop/tool/connector/skill requests.
|
|
419
|
+
- **Run Review upgrades.** The run history now has source filtering and search across run id, source, errors, results, and ownership fields while keeping the existing replay/evidence sheet.
|
|
420
|
+
- **Release-ready mission templates.** New templates cover Release Candidate QA, Agent Cost Audit, Connector Smoke Test, Failed Run Triage, and Weekly Agent Quality Report using the existing mission budget/report model.
|
|
421
|
+
- **Home launchpad quality actions.** First-run users can jump straight to evals, approvals, failed runs, and release QA missions from the operational launchpad.
|
|
422
|
+
|
|
402
423
|
### v1.5.71 Highlights
|
|
403
424
|
|
|
404
425
|
Fast-follow release for [#60](https://github.com/swarmclawai/swarmclaw/pull/60) by [@borislavnnikolov](https://github.com/borislavnnikolov). Thanks Borislav!
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swarmclawai/swarmclaw",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "Build and run autonomous AI agents with OpenClaw, Hermes, multiple model providers, orchestration, delegation, memory, skills, schedules, and chat connectors.",
|
|
5
5
|
"main": "electron-dist/main.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -87,9 +87,9 @@
|
|
|
87
87
|
"test:cli": "node --test src/cli/*.test.js bin/*.test.js scripts/postinstall.test.mjs scripts/run-next-build.test.mjs scripts/run-next-typegen.test.mjs",
|
|
88
88
|
"test:setup": "tsx --test src/app/api/setup/check-provider/route.test.ts src/lib/server/provider-model-discovery.test.ts src/components/auth/setup-wizard/utils.test.ts src/components/auth/setup-wizard/types.test.ts src/hooks/setup-done-detection.test.ts src/lib/setup-defaults.test.ts src/lib/server/storage-auth.test.ts src/lib/server/storage-auth-docker.test.ts",
|
|
89
89
|
"test:openclaw": "tsx --test src/lib/openclaw/openclaw-agent-id.test.ts src/lib/openclaw/openclaw-endpoint.test.ts src/lib/server/agents/agent-runtime-config.test.ts src/lib/server/build-llm.test.ts src/lib/server/connectors/connector-routing.test.ts src/lib/server/connectors/openclaw.test.ts src/lib/server/connectors/swarmdock.test.ts src/lib/server/gateway/protocol.test.ts src/lib/server/llm-response-cache.test.ts src/lib/server/mcp-conformance.test.ts src/lib/server/openclaw/agent-resolver.test.ts src/lib/server/openclaw/deploy.test.ts src/lib/server/openclaw/skills-normalize.test.ts src/lib/server/session-tools/openclaw-nodes.test.ts src/lib/server/session-tools/swarmdock.test.ts src/lib/server/tasks/task-quality-gate.test.ts src/lib/server/tasks/task-validation.test.ts src/lib/server/tool-capability-policy.test.ts src/lib/providers/openai.test.ts src/lib/providers/openclaw-exports.test.ts src/app/api/openclaw/dashboard-url/route.test.ts",
|
|
90
|
-
"test:runtime": "tsx --test src/lib/server/mcp-gateway-runtime.test.ts src/lib/server/mcp-connection-pool.test.ts src/lib/server/knowledge-sources.test.ts src/lib/server/chat-execution/chat-execution-grounding.test.ts src/lib/server/chat-execution/chat-turn-preparation.test.ts src/lib/server/chat-execution/iteration-timers.test.ts src/lib/server/chat-execution/post-stream-finalization.test.ts src/lib/server/chats/clear-undo-snapshots.test.ts src/lib/server/connectors/email.test.ts src/lib/server/protocols/protocol-service.test.ts src/lib/server/runtime/run-ledger.test.ts src/lib/server/observability/otel-config.test.ts src/lib/server/safe-parse-body.test.ts src/lib/app/view-constants.test.ts src/app/api/approvals/route.test.ts src/app/api/agents/agents-route.test.ts src/app/api/tasks/tasks-route.test.ts src/app/api/chats/chat-route.test.ts src/app/api/chats/clear-route.test.ts src/app/api/chats/compact-route.test.ts src/app/api/chats/context-status-route.test.ts src/app/api/connectors/connector-doctor-route.test.ts src/app/api/healthz/route.test.ts src/app/api/logs/route.test.ts src/app/api/providers/[id]/route.test.ts src/app/api/tts/route.test.ts",
|
|
90
|
+
"test:runtime": "tsx --test src/lib/a2a/agent-card.test.ts src/lib/strip-internal-metadata.test.ts src/lib/providers/opencode-cli.test.ts src/lib/server/mcp-gateway-runtime.test.ts src/lib/server/mcp-connection-pool.test.ts src/lib/server/knowledge-sources.test.ts src/lib/server/chat-execution/chat-execution-grounding.test.ts src/lib/server/chat-execution/chat-turn-preparation.test.ts src/lib/server/chat-execution/iteration-timers.test.ts src/lib/server/chat-execution/post-stream-finalization.test.ts src/lib/server/chats/clear-undo-snapshots.test.ts src/lib/server/connectors/email.test.ts src/lib/server/protocols/protocol-service.test.ts src/lib/server/runtime/run-ledger.test.ts src/lib/server/observability/otel-config.test.ts src/lib/server/safe-parse-body.test.ts src/lib/server/missions/mission-templates.test.ts src/lib/app/view-constants.test.ts src/lib/quality/quality-summary.test.ts src/app/api/approvals/route.test.ts src/app/api/agents/agents-route.test.ts src/app/api/tasks/tasks-route.test.ts src/app/api/chats/chat-route.test.ts src/app/api/chats/clear-route.test.ts src/app/api/chats/compact-route.test.ts src/app/api/chats/context-status-route.test.ts src/app/api/connectors/connector-doctor-route.test.ts src/app/api/healthz/route.test.ts src/app/api/logs/route.test.ts src/app/api/providers/[id]/route.test.ts src/app/api/tts/route.test.ts",
|
|
91
91
|
"test:builder": "tsx --test src/features/protocols/builder/utils/nodes-to-template.test.ts src/features/protocols/builder/utils/template-to-nodes.test.ts src/features/protocols/builder/validators/dag-validator.test.ts",
|
|
92
|
-
"test:e2e": "tsx
|
|
92
|
+
"test:e2e": "node --import tsx scripts/browser-e2e-smoke.ts",
|
|
93
93
|
"test:mcp:conformance": "node --import tsx ./scripts/mcp-conformance-check.ts",
|
|
94
94
|
"electron:compile": "tsc -p electron/tsconfig.json",
|
|
95
95
|
"electron:dev": "npm run electron:compile && electron electron-dist/main.js",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { buildAgentCardDiscoveryPayload } from '@/lib/a2a/agent-card'
|
|
3
|
+
|
|
4
|
+
export const dynamic = 'force-dynamic'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* GET /.well-known/agent-card.json?agentId=xxx
|
|
8
|
+
*
|
|
9
|
+
* Canonical public A2A Agent Card discovery endpoint. If agentId is omitted,
|
|
10
|
+
* returns a directory of discoverable local SwarmClaw agents.
|
|
11
|
+
*/
|
|
12
|
+
export async function GET(req: Request) {
|
|
13
|
+
const { body, status } = buildAgentCardDiscoveryPayload(req)
|
|
14
|
+
return NextResponse.json(body, { status })
|
|
15
|
+
}
|
|
@@ -1,46 +1,15 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
-
import {
|
|
3
|
-
import { generateAgentCard } from '@/lib/a2a/agent-card'
|
|
2
|
+
import { buildAgentCardDiscoveryPayload } from '@/lib/a2a/agent-card'
|
|
4
3
|
|
|
5
4
|
export const dynamic = 'force-dynamic'
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
|
-
* GET /.well-known/agent-card
|
|
7
|
+
* GET /api/.well-known/agent-card?agentId=xxx
|
|
9
8
|
*
|
|
10
|
-
* A2A Agent Card discovery endpoint.
|
|
11
|
-
*
|
|
12
|
-
* Otherwise, returns a directory of all non-disabled agents.
|
|
13
|
-
*
|
|
14
|
-
* Publicly accessible per A2A spec — no auth required for discovery.
|
|
9
|
+
* Back-compatible A2A Agent Card discovery endpoint. The canonical public
|
|
10
|
+
* well-known URL is implemented at /.well-known/agent-card.json.
|
|
15
11
|
*/
|
|
16
12
|
export async function GET(req: Request) {
|
|
17
|
-
const {
|
|
18
|
-
|
|
19
|
-
const baseUrl = `${new URL(req.url).origin}`
|
|
20
|
-
|
|
21
|
-
if (agentId) {
|
|
22
|
-
const agent = getAgent(agentId)
|
|
23
|
-
if (!agent) {
|
|
24
|
-
return NextResponse.json({ error: 'Agent not found' }, { status: 404 })
|
|
25
|
-
}
|
|
26
|
-
if (agent.disabled) {
|
|
27
|
-
return NextResponse.json({ error: 'Agent is disabled' }, { status: 404 })
|
|
28
|
-
}
|
|
29
|
-
const card = generateAgentCard(agent, baseUrl)
|
|
30
|
-
return NextResponse.json(card)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Return directory of all active agents
|
|
34
|
-
const agents = listAgents()
|
|
35
|
-
const directory = Object.values(agents)
|
|
36
|
-
.filter(a => !a.disabled)
|
|
37
|
-
.map(a => ({
|
|
38
|
-
name: a.name,
|
|
39
|
-
description: a.description || `SwarmClaw agent: ${a.name}`,
|
|
40
|
-
agentId: a.id,
|
|
41
|
-
apiEndpoint: `${baseUrl}/api/a2a`,
|
|
42
|
-
cardUrl: `${baseUrl}/api/.well-known/agent-card?agentId=${a.id}`,
|
|
43
|
-
}))
|
|
44
|
-
|
|
45
|
-
return NextResponse.json({ agents: directory, protocolVersion: '0.3.0' })
|
|
13
|
+
const { body, status } = buildAgentCardDiscoveryPayload(req)
|
|
14
|
+
return NextResponse.json(body, { status })
|
|
46
15
|
}
|
package/src/app/home/page.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import { useEffect, useMemo, useState } from 'react'
|
|
3
|
+
import { useEffect, useMemo, useRef, useState } from 'react'
|
|
4
4
|
import { useRouter } from 'next/navigation'
|
|
5
5
|
import { AreaChart, Area, ResponsiveContainer, Tooltip } from 'recharts'
|
|
6
6
|
import { useAppStore } from '@/stores/use-app-store'
|
|
@@ -109,6 +109,7 @@ export default function HomePage() {
|
|
|
109
109
|
const [localhostBrowser, setLocalhostBrowser] = useState(false)
|
|
110
110
|
const [pageReady, setPageReady] = useState(false)
|
|
111
111
|
const [launchpadFlag, setLaunchpadFlag] = useState(false)
|
|
112
|
+
const launchpadFlagConsumedRef = useRef(false)
|
|
112
113
|
const mountedRef = useMountedRef()
|
|
113
114
|
|
|
114
115
|
useEffect(() => {
|
|
@@ -116,9 +117,12 @@ export default function HomePage() {
|
|
|
116
117
|
}, [])
|
|
117
118
|
|
|
118
119
|
useEffect(() => {
|
|
120
|
+
if (launchpadFlagConsumedRef.current) return
|
|
119
121
|
const hasFlag = safeStorageGet(HOME_LAUNCHPAD_AFTER_SETUP_KEY) === '1'
|
|
120
|
-
|
|
121
|
-
|
|
122
|
+
if (!hasFlag) return
|
|
123
|
+
launchpadFlagConsumedRef.current = true
|
|
124
|
+
setLaunchpadFlag(true)
|
|
125
|
+
safeStorageRemove(HOME_LAUNCHPAD_AFTER_SETUP_KEY)
|
|
122
126
|
}, [])
|
|
123
127
|
|
|
124
128
|
const allAgents = Object.values(agents).filter((a) => !a.trashedAt)
|
|
@@ -279,6 +283,10 @@ export default function HomePage() {
|
|
|
279
283
|
onOpenBuilder={openBuilder}
|
|
280
284
|
onOpenConnectors={() => navigateTo('connectors')}
|
|
281
285
|
onOpenUsage={() => navigateTo('usage')}
|
|
286
|
+
onRunEvalSuite={() => navigateTo('quality')}
|
|
287
|
+
onReviewApprovals={() => navigateTo('quality')}
|
|
288
|
+
onInspectFailedRuns={() => navigateTo('quality')}
|
|
289
|
+
onStartReleaseQaMission={() => navigateTo('missions')}
|
|
282
290
|
/>
|
|
283
291
|
</div>
|
|
284
292
|
</MainContent>
|
|
@@ -14,6 +14,48 @@ function SnapshotItem({ label, value, hint }: { label: string; value: string; hi
|
|
|
14
14
|
)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
function PathCard({
|
|
18
|
+
kicker,
|
|
19
|
+
title,
|
|
20
|
+
description,
|
|
21
|
+
primaryLabel,
|
|
22
|
+
secondaryLabel,
|
|
23
|
+
onPrimary,
|
|
24
|
+
onSecondary,
|
|
25
|
+
}: {
|
|
26
|
+
kicker: string
|
|
27
|
+
title: string
|
|
28
|
+
description: string
|
|
29
|
+
primaryLabel: string
|
|
30
|
+
secondaryLabel: string
|
|
31
|
+
onPrimary: () => void
|
|
32
|
+
onSecondary: () => void
|
|
33
|
+
}) {
|
|
34
|
+
return (
|
|
35
|
+
<div className="flex min-h-[220px] flex-col rounded-[18px] border border-white/[0.07] bg-white/[0.03] p-5">
|
|
36
|
+
<div className="text-[11px] font-700 uppercase tracking-[0.12em] text-text-3/55">{kicker}</div>
|
|
37
|
+
<div className="mt-3 text-[18px] font-display font-700 tracking-normal text-text">{title}</div>
|
|
38
|
+
<p className="mt-2 flex-1 text-[13px] leading-relaxed text-text-3/72">{description}</p>
|
|
39
|
+
<div className="mt-5 flex flex-wrap gap-2">
|
|
40
|
+
<button
|
|
41
|
+
type="button"
|
|
42
|
+
onClick={onPrimary}
|
|
43
|
+
className="rounded-[10px] bg-accent-bright px-3.5 py-2 text-[12px] font-display font-700 text-black transition-opacity hover:opacity-90"
|
|
44
|
+
>
|
|
45
|
+
{primaryLabel}
|
|
46
|
+
</button>
|
|
47
|
+
<button
|
|
48
|
+
type="button"
|
|
49
|
+
onClick={onSecondary}
|
|
50
|
+
className="rounded-[10px] border border-white/[0.08] bg-white/[0.04] px-3.5 py-2 text-[12px] font-display font-700 text-text-2 transition-colors hover:bg-white/[0.08]"
|
|
51
|
+
>
|
|
52
|
+
{secondaryLabel}
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
17
59
|
type Props = {
|
|
18
60
|
firstAgent: Agent | null
|
|
19
61
|
agentCount: number
|
|
@@ -27,6 +69,10 @@ type Props = {
|
|
|
27
69
|
onOpenBuilder: () => void
|
|
28
70
|
onOpenConnectors: () => void
|
|
29
71
|
onOpenUsage: () => void
|
|
72
|
+
onRunEvalSuite: () => void
|
|
73
|
+
onReviewApprovals: () => void
|
|
74
|
+
onInspectFailedRuns: () => void
|
|
75
|
+
onStartReleaseQaMission: () => void
|
|
30
76
|
}
|
|
31
77
|
|
|
32
78
|
export function HomeLaunchpad({
|
|
@@ -42,20 +88,24 @@ export function HomeLaunchpad({
|
|
|
42
88
|
onOpenBuilder,
|
|
43
89
|
onOpenConnectors,
|
|
44
90
|
onOpenUsage,
|
|
91
|
+
onRunEvalSuite,
|
|
92
|
+
onReviewApprovals,
|
|
93
|
+
onInspectFailedRuns,
|
|
94
|
+
onStartReleaseQaMission,
|
|
45
95
|
}: Props) {
|
|
46
96
|
return (
|
|
47
97
|
<div className="max-w-[980px] mx-auto px-6 py-10">
|
|
48
|
-
<div className="rounded-[
|
|
98
|
+
<div className="rounded-[20px] border border-white/[0.06] bg-white/[0.025] p-6">
|
|
49
99
|
<div className="inline-flex rounded-full border border-white/[0.08] bg-white/[0.03] px-3 py-1 text-[11px] font-700 uppercase tracking-[0.16em] text-text-3/70">
|
|
50
|
-
Launchpad
|
|
100
|
+
v1.6 Launchpad
|
|
51
101
|
</div>
|
|
52
102
|
<div className="mt-4 flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
|
|
53
103
|
<div className="max-w-[620px]">
|
|
54
|
-
<h1 className="font-display text-[34px] font-700 tracking-
|
|
55
|
-
|
|
104
|
+
<h1 className="font-display text-[34px] font-700 tracking-normal text-text">
|
|
105
|
+
Pick a path and watch the workspace move.
|
|
56
106
|
</h1>
|
|
57
107
|
<p className="mt-3 text-[15px] leading-relaxed text-text-3/72">
|
|
58
|
-
|
|
108
|
+
Start with a local assistant, a reusable workflow, or a budgeted autonomous mission. The rest of the control plane stays one click away.
|
|
59
109
|
</p>
|
|
60
110
|
</div>
|
|
61
111
|
<div className="rounded-[18px] border border-white/[0.06] bg-white/[0.03] p-4 min-w-[240px]">
|
|
@@ -86,6 +136,36 @@ export function HomeLaunchpad({
|
|
|
86
136
|
</div>
|
|
87
137
|
</div>
|
|
88
138
|
|
|
139
|
+
<div className="mt-6 grid gap-3 lg:grid-cols-3">
|
|
140
|
+
<PathCard
|
|
141
|
+
kicker="Self-hosted assistant"
|
|
142
|
+
title={firstAgent ? `Work with ${firstAgent.name}` : 'Create the first agent'}
|
|
143
|
+
description="Open a live agent chat, then add memory, local tools, provider routing, or connector access as the work demands."
|
|
144
|
+
primaryLabel={firstAgent ? 'Open Chat' : 'Open Agents'}
|
|
145
|
+
secondaryLabel="Connect Platform"
|
|
146
|
+
onPrimary={onOpenFirstAgent}
|
|
147
|
+
onSecondary={onOpenConnectors}
|
|
148
|
+
/>
|
|
149
|
+
<PathCard
|
|
150
|
+
kicker="Visual workflow"
|
|
151
|
+
title="Shape a reusable run"
|
|
152
|
+
description="Use protocol templates and the builder to turn review, research, planning, or release checks into durable workflows."
|
|
153
|
+
primaryLabel="Open Builder"
|
|
154
|
+
secondaryLabel="Use Templates"
|
|
155
|
+
onPrimary={onOpenBuilder}
|
|
156
|
+
onSecondary={onOpenProtocols}
|
|
157
|
+
/>
|
|
158
|
+
<PathCard
|
|
159
|
+
kicker="Autonomous mission"
|
|
160
|
+
title="Run with budgets"
|
|
161
|
+
description="Start a mission template for release QA, research, support triage, cost audit, or failed-run review with reports and caps."
|
|
162
|
+
primaryLabel="Open Missions"
|
|
163
|
+
secondaryLabel="Quality Center"
|
|
164
|
+
onPrimary={onStartReleaseQaMission}
|
|
165
|
+
onSecondary={onRunEvalSuite}
|
|
166
|
+
/>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
89
169
|
<div className="mt-6 grid gap-3 md:grid-cols-2 xl:grid-cols-3">
|
|
90
170
|
<LaunchActionCard
|
|
91
171
|
title={firstAgent ? 'Open First Agent Chat' : 'Open Agents'}
|
|
@@ -120,6 +200,30 @@ export function HomeLaunchpad({
|
|
|
120
200
|
actionLabel="Open Usage"
|
|
121
201
|
onClick={onOpenUsage}
|
|
122
202
|
/>
|
|
203
|
+
<LaunchActionCard
|
|
204
|
+
title="Run Eval Suite"
|
|
205
|
+
description="Open the Quality Center and run scenario or suite checks against an agent before shipping."
|
|
206
|
+
actionLabel="Open Eval Lab"
|
|
207
|
+
onClick={onRunEvalSuite}
|
|
208
|
+
/>
|
|
209
|
+
<LaunchActionCard
|
|
210
|
+
title="Review Approvals"
|
|
211
|
+
description="Clear pending human-loop, tool, connector, skill, agent, and budget requests from one desk."
|
|
212
|
+
actionLabel="Open Approvals"
|
|
213
|
+
onClick={onReviewApprovals}
|
|
214
|
+
/>
|
|
215
|
+
<LaunchActionCard
|
|
216
|
+
title="Inspect Failed Runs"
|
|
217
|
+
description="Filter recent run failures and open replay evidence without leaving the operator workflow."
|
|
218
|
+
actionLabel="Open Run Review"
|
|
219
|
+
onClick={onInspectFailedRuns}
|
|
220
|
+
/>
|
|
221
|
+
<LaunchActionCard
|
|
222
|
+
title="Start Release QA Mission"
|
|
223
|
+
description="Use a budgeted mission template to collect release readiness evidence and quality notes."
|
|
224
|
+
actionLabel="Open Missions"
|
|
225
|
+
onClick={onStartReleaseQaMission}
|
|
226
|
+
/>
|
|
123
227
|
</div>
|
|
124
228
|
|
|
125
229
|
<div className="mt-8 grid gap-3 md:grid-cols-2 xl:grid-cols-3">
|
|
@@ -305,6 +305,12 @@ export function SidebarRail({
|
|
|
305
305
|
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />
|
|
306
306
|
</svg>
|
|
307
307
|
</NavItem>
|
|
308
|
+
<NavItem view="quality" label="Quality" expanded={railExpanded} isActive={isNavActive('quality')} onClick={() => handleNavClick('quality')}>
|
|
309
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
310
|
+
<path d="M9 12l2 2 4-4" />
|
|
311
|
+
<path d="M12 3l7 4v5c0 4.4-2.9 8.5-7 9-4.1-.5-7-4.6-7-9V7l7-4z" />
|
|
312
|
+
</svg>
|
|
313
|
+
</NavItem>
|
|
308
314
|
</div>
|
|
309
315
|
|
|
310
316
|
<div className={`flex flex-col gap-0.5 ${railExpanded ? '' : 'items-center'}`}>
|