@swarmclawai/swarmclaw 1.5.70 → 1.5.71

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,14 @@ Operational docs: https://swarmclaw.ai/docs/observability
399
399
 
400
400
  ## Releases
401
401
 
402
+ ### v1.5.71 Highlights
403
+
404
+ Fast-follow release for [#60](https://github.com/swarmclawai/swarmclaw/pull/60) by [@borislavnnikolov](https://github.com/borislavnnikolov). Thanks Borislav!
405
+
406
+ - **Browser MCP works from standalone builds again.** The Next standalone output now includes the Playwright MCP runtime packages required by packaged SwarmClaw builds.
407
+ - **Host browser launches use cached Chromium.** Local Playwright MCP startup now selects Chromium explicitly instead of depending on a system Chrome install.
408
+ - **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.
409
+
402
410
  ### v1.5.70 Highlights
403
411
 
404
412
  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.5.71",
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",
@@ -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) {
@@ -18,9 +18,12 @@ describe('browser tool connection config', () => {
18
18
  const params = buildBrowserStdioServerParams('/tmp/swarmclaw-browser-profile')
19
19
 
20
20
  assert.equal(params.command, process.execPath)
21
+ assert.equal(params.args.includes('--browser'), true)
22
+ assert.equal(params.args[params.args.indexOf('--browser') + 1], 'chromium')
21
23
  assert.equal(params.args.includes('--headless'), true)
22
24
  assert.equal(params.args.includes('--shared-browser-context'), false)
23
25
  assert.equal(params.args.includes('/tmp/swarmclaw-browser-profile'), true)
26
+ assert.equal((params.env as Record<string, string | undefined>).PLAYWRIGHT_MCP_BROWSER, 'chromium')
24
27
  assert.equal((params.env as Record<string, string | undefined>).PLAYWRIGHT_MCP_USER_DATA_DIR, '/tmp/swarmclaw-browser-profile')
25
28
  assert.equal(params.env.PLAYWRIGHT_MCP_OUTPUT_MODE, 'file')
26
29
  assert.equal(params.env.PLAYWRIGHT_MCP_TIMEOUT_ACTION, '60000')
@@ -39,10 +42,12 @@ describe('browser tool connection config', () => {
39
42
  assert.equal(params.args.includes('--cdp-header'), true)
40
43
  assert.equal(params.args.includes('Authorization: Bearer token-123'), true)
41
44
  assert.equal(params.args.includes('--allow-unrestricted-file-access'), true)
45
+ assert.equal(params.args.includes('--browser'), false)
42
46
  assert.equal(params.args.includes('--user-data-dir'), false)
43
47
  const env = params.env as Record<string, string | undefined>
44
48
  assert.equal(env.PLAYWRIGHT_MCP_CDP_ENDPOINT, 'http://127.0.0.1:44001')
45
49
  assert.equal(params.env.PLAYWRIGHT_MCP_ALLOW_UNRESTRICTED_FILE_ACCESS, '1')
50
+ assert.equal(env.PLAYWRIGHT_MCP_BROWSER, undefined)
46
51
  assert.equal(env.PLAYWRIGHT_MCP_USER_DATA_DIR, undefined)
47
52
  })
48
53
 
@@ -102,6 +102,7 @@ export function buildBrowserStdioServerParams(
102
102
  allowUnrestrictedFileAccess?: boolean
103
103
  },
104
104
  ) {
105
+ const browserName = 'chromium'
105
106
  const cliCandidates = [
106
107
  path.join(process.cwd(), 'node_modules', '@playwright', 'mcp', 'cli.js'),
107
108
  path.join(process.cwd(), '[project]', 'node_modules', '@playwright', 'mcp', 'cli.js'),
@@ -134,6 +135,7 @@ export function buildBrowserStdioServerParams(
134
135
  }
135
136
  } else {
136
137
  args.push(
138
+ '--browser', browserName,
137
139
  '--headless',
138
140
  '--user-data-dir', profileDir,
139
141
  )
@@ -145,6 +147,7 @@ export function buildBrowserStdioServerParams(
145
147
  env: {
146
148
  ...env,
147
149
  ...(cdpEndpoint ? { PLAYWRIGHT_MCP_CDP_ENDPOINT: cdpEndpoint } : {
150
+ PLAYWRIGHT_MCP_BROWSER: browserName,
148
151
  PLAYWRIGHT_MCP_USER_DATA_DIR: profileDir,
149
152
  PLAYWRIGHT_MCP_HEADLESS: '1',
150
153
  }),