@swarmclawai/swarmclaw 1.5.70 → 1.6.0

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 CHANGED
@@ -399,6 +399,24 @@ Operational docs: https://swarmclaw.ai/docs/observability
399
399
 
400
400
  ## Releases
401
401
 
402
+ ### v1.6.0 Highlights
403
+
404
+ Operator Quality Center release for builders running autonomous agents in production-like workflows.
405
+
406
+ - **New Quality workspace.** `/quality` brings run health, failed/running counts, pending approvals, latest eval scores, and attention shortcuts into one operator surface.
407
+ - **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.
408
+ - **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.
409
+ - **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.
410
+ - **Home launchpad quality actions.** First-run users can jump straight to evals, approvals, failed runs, and release QA missions from the operational launchpad.
411
+
412
+ ### v1.5.71 Highlights
413
+
414
+ Fast-follow release for [#60](https://github.com/swarmclawai/swarmclaw/pull/60) by [@borislavnnikolov](https://github.com/borislavnnikolov). Thanks Borislav!
415
+
416
+ - **Browser MCP works from standalone builds again.** The Next standalone output now includes the Playwright MCP runtime packages required by packaged SwarmClaw builds.
417
+ - **Host browser launches use cached Chromium.** Local Playwright MCP startup now selects Chromium explicitly instead of depending on a system Chrome install.
418
+ - **Standalone repair is more robust.** The build repair step now fills partially traced Playwright MCP package directories, and the packaging and browser startup paths are covered by regression tests.
419
+
402
420
  ### v1.5.70 Highlights
403
421
 
404
422
  Fast-follow release for [#56](https://github.com/swarmclawai/swarmclaw/pull/56) by [@latentwill](https://github.com/latentwill). Thanks latentwill!
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swarmclawai/swarmclaw",
3
- "version": "1.5.70",
3
+ "version": "1.6.0",
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,7 +87,7 @@
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/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
92
  "test:e2e": "tsx .workbench/browser-e2e/run.ts",
93
93
  "test:mcp:conformance": "node --import tsx ./scripts/mcp-conformance-check.ts",
@@ -35,6 +35,11 @@ export const REQUIRED_NEXT_METADATA_FILES = [
35
35
  'get-metadata-route.js',
36
36
  'is-metadata-route.js',
37
37
  ]
38
+ export const REQUIRED_STANDALONE_BROWSER_PACKAGES = [
39
+ '@playwright/mcp',
40
+ 'playwright',
41
+ 'playwright-core',
42
+ ]
38
43
 
39
44
  function parsePositiveInteger(value) {
40
45
  const parsed = Number.parseInt(String(value ?? '').trim(), 10)
@@ -187,6 +192,27 @@ export function repairStandaloneCssTreeData(cwd = process.cwd()) {
187
192
  return repaired
188
193
  }
189
194
 
195
+ export function repairStandaloneBrowserMcpRuntime(cwd = process.cwd()) {
196
+ const standaloneDir = path.join(cwd, '.next', 'standalone')
197
+ if (!fs.existsSync(standaloneDir)) return false
198
+
199
+ let repaired = false
200
+ const standaloneNodeModules = path.join(standaloneDir, 'node_modules')
201
+ for (const packageName of REQUIRED_STANDALONE_BROWSER_PACKAGES) {
202
+ const sourceDir = path.join(cwd, 'node_modules', ...packageName.split('/'))
203
+ const targetDir = path.join(standaloneNodeModules, ...packageName.split('/'))
204
+ if (!fs.existsSync(sourceDir)) {
205
+ throw new Error(`Missing required browser MCP runtime package under ${sourceDir}.`)
206
+ }
207
+
208
+ fs.mkdirSync(path.dirname(targetDir), { recursive: true })
209
+ fs.cpSync(sourceDir, targetDir, { recursive: true, force: true })
210
+ repaired = true
211
+ }
212
+
213
+ return repaired
214
+ }
215
+
190
216
  export function repairStandaloneNextMetadata(cwd = process.cwd()) {
191
217
  const standaloneDir = path.join(cwd, '.next', 'standalone')
192
218
  if (!fs.existsSync(standaloneDir)) return false
@@ -248,6 +274,9 @@ function main() {
248
274
  if (result.status === 0 && repairStandaloneCssTreeData(process.cwd())) {
249
275
  console.error('Copied css-tree/data/ into standalone build output.')
250
276
  }
277
+ if (result.status === 0 && repairStandaloneBrowserMcpRuntime(process.cwd())) {
278
+ console.error('Copied Playwright MCP runtime packages into standalone build output.')
279
+ }
251
280
  process.exit(result.status)
252
281
  }
253
282
  if (result.signal) {
@@ -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
- setLaunchpadFlag(hasFlag)
121
- if (hasFlag) safeStorageRemove(HOME_LAUNCHPAD_AFTER_SETUP_KEY)
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>
@@ -0,0 +1,7 @@
1
+ 'use client'
2
+
3
+ import { QualityWorkspace } from '@/components/quality/quality-workspace'
4
+
5
+ export default function QualityPage() {
6
+ return <QualityWorkspace />
7
+ }
@@ -27,6 +27,10 @@ type Props = {
27
27
  onOpenBuilder: () => void
28
28
  onOpenConnectors: () => void
29
29
  onOpenUsage: () => void
30
+ onRunEvalSuite: () => void
31
+ onReviewApprovals: () => void
32
+ onInspectFailedRuns: () => void
33
+ onStartReleaseQaMission: () => void
30
34
  }
31
35
 
32
36
  export function HomeLaunchpad({
@@ -42,6 +46,10 @@ export function HomeLaunchpad({
42
46
  onOpenBuilder,
43
47
  onOpenConnectors,
44
48
  onOpenUsage,
49
+ onRunEvalSuite,
50
+ onReviewApprovals,
51
+ onInspectFailedRuns,
52
+ onStartReleaseQaMission,
45
53
  }: Props) {
46
54
  return (
47
55
  <div className="max-w-[980px] mx-auto px-6 py-10">
@@ -120,6 +128,30 @@ export function HomeLaunchpad({
120
128
  actionLabel="Open Usage"
121
129
  onClick={onOpenUsage}
122
130
  />
131
+ <LaunchActionCard
132
+ title="Run Eval Suite"
133
+ description="Open the Quality Center and run scenario or suite checks against an agent before shipping."
134
+ actionLabel="Open Eval Lab"
135
+ onClick={onRunEvalSuite}
136
+ />
137
+ <LaunchActionCard
138
+ title="Review Approvals"
139
+ description="Clear pending human-loop, tool, connector, skill, agent, and budget requests from one desk."
140
+ actionLabel="Open Approvals"
141
+ onClick={onReviewApprovals}
142
+ />
143
+ <LaunchActionCard
144
+ title="Inspect Failed Runs"
145
+ description="Filter recent run failures and open replay evidence without leaving the operator workflow."
146
+ actionLabel="Open Run Review"
147
+ onClick={onInspectFailedRuns}
148
+ />
149
+ <LaunchActionCard
150
+ title="Start Release QA Mission"
151
+ description="Use a budgeted mission template to collect release readiness evidence and quality notes."
152
+ actionLabel="Open Missions"
153
+ onClick={onStartReleaseQaMission}
154
+ />
123
155
  </div>
124
156
 
125
157
  <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'}`}>