@plainconceptsplatform/agent-harness 2.2.1 → 2.4.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 +23 -12
- package/{src → cli}/commands/join.js +3 -4
- package/{src → cli}/commands/migrate.js +1 -1
- package/{src → cli}/commands/update.js +13 -1
- package/{src → cli}/commands/wizard.js +1 -1
- package/{src → cli}/index.js +1 -1
- package/{src → cli}/presets/agents-content.json +4 -4
- package/cli/presets/browser.json +10 -0
- package/{src → cli}/presets/clean.json +21 -21
- package/{src → cli}/presets/optimization.json +37 -37
- package/{src → cli}/presets/platforms.json +76 -76
- package/{src → cli}/presets/quota.json +16 -16
- package/{src → cli}/presets/source.json +23 -23
- package/cli/steps/browser/index.js +48 -0
- package/{src → cli}/steps/clean/index.js +120 -120
- package/{src → cli}/steps/copy/agents.js +119 -119
- package/{src → cli}/steps/copy/commands.js +95 -95
- package/{src → cli}/steps/copy/fullstack-engineer.js +5 -1
- package/{src → cli}/steps/copy/index.js +1 -1
- package/{src → cli}/steps/copy/opencode-json.js +50 -1
- package/{src → cli}/steps/copy/skills.js +2 -2
- package/{src → cli}/steps/metadata/index.js +4 -0
- package/{src → cli}/steps/models/format.js +88 -88
- package/{src → cli}/steps/models/index.js +64 -64
- package/{src → cli}/steps/openspec/index.js +136 -136
- package/{src → cli}/steps/optimization/codegraph.js +127 -127
- package/cli/steps/optimization/detect.js +66 -0
- package/{src → cli}/steps/optimization/humanizer.js +17 -17
- package/{src → cli}/steps/optimization/index.js +163 -163
- package/{src → cli}/steps/optimization/memory.js +88 -88
- package/{src → cli}/steps/optimization/patch-guardrails.js +109 -109
- package/{src → cli}/steps/optimization/quota.js +119 -119
- package/{src → cli}/steps/optimization/simple-english.js +17 -17
- package/{src → cli}/steps/optimization/skills-lock.js +30 -30
- package/{src → cli}/steps/platform/index.js +109 -109
- package/{src → cli}/steps/source/index.js +123 -123
- package/cli/utils/agent-color.js +111 -0
- package/{src → cli}/utils/exec-spinner.js +47 -47
- package/{src → cli}/utils/exec.js +134 -134
- package/{src → cli}/utils/models-pricing.js +42 -42
- package/{src → cli}/utils/paths.js +1 -1
- package/{src → cli}/utils/process.js +3 -3
- package/{src → cli}/utils/terminal.js +6 -6
- package/harness/.agents/skills/browser-automation/SKILL.md +72 -0
- package/{src/content → harness}/.agents/skills/pc-make-engineer/SKILL.md +1 -1
- package/{src/content → harness}/.agents/skills/pc-make-engineer/template.md +1 -2
- package/{src/content → harness}/.agents/skills/pc-plan-archive/SKILL.md +3 -0
- package/{src/content → harness}/.agents/skills/pc-plan-explore/SKILL.md +3 -0
- package/{src/content → harness}/.agents/skills/pc-plan-goal/SKILL.md +5 -16
- package/{src/content → harness}/.agents/skills/pc-plan-goal/branching.md +1 -1
- package/{src/content → harness}/.agents/skills/pc-plan-goal/output.md +5 -8
- package/{src/content → harness}/.agents/skills/pc-plan-story/SKILL.md +3 -0
- package/{src/content → harness}/.agents/skills/pc-userstory-browser/SKILL.md +136 -132
- package/{src/content → harness}/.opencode/package.json +9 -10
- package/{src/content → harness}/.opencode/plugins/pc-subagent-tiers.js +91 -4
- package/{src/content → harness}/ARCHITECTURE.md +16 -16
- package/{src/content → harness}/DESIGN.md +16 -16
- package/{src/content → harness}/opencode.jsonc +11 -3
- package/{src/content → harness}/openspec/config.yaml +20 -20
- package/{src/content → harness}/skills-lock.json +17 -17
- package/package.json +7 -7
- package/src/content/.agents/skills/browser-automation/SKILL.md +0 -66
- package/src/presets/browser.json +0 -22
- package/src/steps/browser/index.js +0 -91
- /package/{src → cli}/commands/shared.js +0 -0
- /package/{src → cli}/commands/single.js +0 -0
- /package/{src → cli}/fragments/archive/az.md +0 -0
- /package/{src → cli}/fragments/archive/gh.md +0 -0
- /package/{src → cli}/fragments/archive/gl.md +0 -0
- /package/{src → cli}/fragments/archive/none.md +0 -0
- /package/{src → cli}/fragments/guardrails/codegraph.md +0 -0
- /package/{src → cli}/fragments/guardrails/humanizer.md +0 -0
- /package/{src → cli}/fragments/guardrails/memory.md +0 -0
- /package/{src → cli}/fragments/guardrails/rtk.md +0 -0
- /package/{src → cli}/fragments/guardrails/simple-english.md +0 -0
- /package/{src → cli}/fragments/ops-backlog/az.md +0 -0
- /package/{src → cli}/fragments/ops-backlog/gh.md +0 -0
- /package/{src → cli}/fragments/ops-backlog/jira.md +0 -0
- /package/{src → cli}/fragments/ops-evidence/az.md +0 -0
- /package/{src → cli}/fragments/ops-evidence/gh.md +0 -0
- /package/{src → cli}/fragments/ops-evidence/jira.md +0 -0
- /package/{src → cli}/fragments/ops-review/az.md +0 -0
- /package/{src → cli}/fragments/ops-review/gh.md +0 -0
- /package/{src → cli}/fragments/ops-review/gl.md +0 -0
- /package/{src → cli}/fragments/ops-ship/az.md +0 -0
- /package/{src → cli}/fragments/ops-ship/gh.md +0 -0
- /package/{src → cli}/fragments/ops-ship/gl.md +0 -0
- /package/{src → cli}/presets/models.json +0 -0
- /package/{src → cli}/presets/openspec.json +0 -0
- /package/{src → cli}/steps/models/write.js +0 -0
- /package/{src → cli}/utils/copy.js +0 -0
- /package/{src → cli}/utils/legacy-check.js +0 -0
- /package/{src → cli}/utils/models-cache.js +0 -0
- /package/{src → cli}/utils/update-manifest.js +0 -0
- /package/{src/content → harness}/.agents/skills/pc-guardrails-generic/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-guardrails-project/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-architecture/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-architecture/structure-template.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-design/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-engineer/signal-mapping.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-evidence-scaffold/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-evidence-scaffold/evidence-contract.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-guardrails/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-guardrails/category-reference.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-merge-risk-assess/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-merge-risk-assess/category-reference.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-user-model/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-ops-evidence/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-ops-ship/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-apply/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-apply/simple-mode.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-goal/failure-policy.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-goal/output-mode.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-propose/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-propose/task-annotation.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-quick/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-repo-audit/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-repo-help/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-repo-initialize/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-repo-onboard/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-repo-verify/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-userstory-az/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-userstory-gh/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-userstory-jira/SKILL.md +0 -0
- /package/{src/content → harness}/.opencode/_gitignore +0 -0
- /package/{src/content → harness}/.opencode/commands/init.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-architecture.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-design.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-engineer.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-evidence-scaffold.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-guardrails.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-user-model.md +0 -0
- /package/{src/content → harness}/.opencode/commands/ops-backlog.md +0 -0
- /package/{src/content → harness}/.opencode/commands/ops-evidence.md +0 -0
- /package/{src/content → harness}/.opencode/commands/ops-review.md +0 -0
- /package/{src/content → harness}/.opencode/commands/ops-ship.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-apply.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-archive.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-explore.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-goal.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-propose.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-quick.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-story.md +0 -0
- /package/{src/content → harness}/.opencode/commands/repo-audit.md +0 -0
- /package/{src/content → harness}/.opencode/commands/repo-help.md +0 -0
- /package/{src/content → harness}/.opencode/commands/repo-initialize.md +0 -0
- /package/{src/content → harness}/.opencode/commands/repo-onboard.md +0 -0
- /package/{src/content → harness}/.opencode/commands/repo-verify.md +0 -0
- /package/{src/content → harness}/.opencode/plugins/pc-subagent-monitor.js +0 -0
- /package/{src/content → harness}/.opencode/plugins/pc-system-reminders.js +0 -0
- /package/{src/content → harness}/.opencode/tui/pc-subagents.tsx +0 -0
- /package/{src/content → harness}/.opencode/tui.json +0 -0
- /package/{src/content → harness}/AGENTS.md +0 -0
- /package/{src/content → harness}/openspec/changes/archive/.gitkeep +0 -0
- /package/{src/content → harness}/openspec/specs/.gitkeep +0 -0
package/README.md
CHANGED
|
@@ -92,6 +92,8 @@ Reach for individual steps when you want something narrower:
|
|
|
92
92
|
|
|
93
93
|
> **Upgrading from `opencode-onboard` v1?** v2 renamed the config files and the skill prefix (`ob-` became `pc-`), and it does not migrate v1 projects. The CLI detects one and refuses to run rather than half-patching it. Re-onboard on a clean branch: remove `.opencode/` and `.agents/skills/ob-*`, then run the wizard again.
|
|
94
94
|
|
|
95
|
+
> **Browser tooling changed in v2.4.** The `@different-ai/opencode-browser` plugin (and its Chrome extension) was replaced by [`agent-browser`](https://github.com/vercel-labs/agent-browser), wired in as an MCP server in `opencode.jsonc`. Running `update` strips the old plugin entry, adds the MCP block, and installs the new binary — no manual unloading of the extension is needed, though you can remove it from `chrome://extensions` yourself. Skills you wrote that call `browser_*` tools directly must switch to the `agent-browser` CLI or the `agent_browser_*` MCP tools. Backlog-browser users: agent-browser runs its own Chrome, so log in once per project using the `--session backlog --restore` flow described in `pc-userstory-browser`.
|
|
96
|
+
|
|
95
97
|
---
|
|
96
98
|
|
|
97
99
|
## Installing the harness
|
|
@@ -108,7 +110,7 @@ The first run is a 10-step wizard. It keeps the current step visible, plus the l
|
|
|
108
110
|
| **6. Initialize OpenSpec** | Runs `npx @fission-ai/openspec init` silently for structured change management |
|
|
109
111
|
| **7. Choose models** | Fetches live model list from [models.dev](https://models.dev), lets you pick plan, build, and fast models with cost indicators and canonical pricing |
|
|
110
112
|
| **8. Token optimization tools** | Optional and recommended. One checklist step for RTK check, opencode-quota setup, Simple English install, codegraph install, agentmemory install, humanizer install, and token-optimization rule injection into guardrails |
|
|
111
|
-
| **9. Install browser
|
|
113
|
+
| **9. Install browser tooling** | Installs `agent-browser` globally and downloads its Chrome for Testing binary |
|
|
112
114
|
| **10. Write onboarding metadata** | Writes `.opencode/harness.json` with selected setup details |
|
|
113
115
|
|
|
114
116
|
When it finishes, open OpenCode in your project and type:
|
|
@@ -203,7 +205,7 @@ Built-in skills (`pc-` prefix) shipped with agent-harness:
|
|
|
203
205
|
| `pc-userstory-az` | Parse an Azure DevOps work item URL |
|
|
204
206
|
| `pc-userstory-jira` | Parse a Jira issue URL via `acli` CLI |
|
|
205
207
|
| `pc-userstory-browser` | Parse work item from any URL via browser automation (Linear, Trello, and so on) |
|
|
206
|
-
| `browser-automation` | Browser control via
|
|
208
|
+
| `browser-automation` | Browser control via `agent-browser` (localhost and browser backlog exception) |
|
|
207
209
|
| `pc-plan-explore` | Read-only exploration procedure behind `/plan-explore`; autonomous mode used by `/plan-goal` |
|
|
208
210
|
| `pc-plan-propose` | Proposal + task-enrichment procedure behind `/plan-propose`; autonomous mode used by `/plan-goal` |
|
|
209
211
|
| `pc-plan-apply` | Wave-implementation procedure behind `/plan-apply`; autonomous mode used by `/plan-goal` |
|
|
@@ -307,7 +309,7 @@ your-project/
|
|
|
307
309
|
└── browser-automation/
|
|
308
310
|
```
|
|
309
311
|
|
|
310
|
-
Platform skills ship as suffixed variants (`pc-userstory-gh`, `pc-userstory-az`, `pc-userstory-jira`, `pc-userstory-browser`) and the installer copies only the matching one, renamed to its generic name. Platform operations (ship, review, backlog) are injected directly into the `/ops-*` command files from `
|
|
312
|
+
Platform skills ship as suffixed variants (`pc-userstory-gh`, `pc-userstory-az`, `pc-userstory-jira`, `pc-userstory-browser`) and the installer copies only the matching one, renamed to its generic name. Platform operations (ship, review, backlog) are injected directly into the `/ops-*` command files from `cli/fragments/ops-*/` during onboarding. Source-roots metadata lands in `.opencode/source-roots.json`. The always-shipped reminder plugin loads every agent ability, guardrails first, and repeats mandatory skill loads after compaction. Token-optimization guidance is injected into `pc-guardrails-generic` marker blocks during onboarding.
|
|
311
313
|
|
|
312
314
|
---
|
|
313
315
|
|
|
@@ -374,11 +376,22 @@ Long unattended agent sessions can consume significant tokens. Set these control
|
|
|
374
376
|
|
|
375
377
|
## Development
|
|
376
378
|
|
|
377
|
-
The
|
|
379
|
+
The repository splits along one line: **`harness/` is the product, `cli/` is the machinery that installs it.**
|
|
380
|
+
|
|
381
|
+
```
|
|
382
|
+
harness/ what lands in your repository, copied verbatim
|
|
383
|
+
cli/ the installer: commands, wizard steps, presets, fragments
|
|
384
|
+
skills/ skills about this CLI, for agents that operate it
|
|
385
|
+
docs/ the documentation site
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
Browse `harness/` to see what the Plain Concepts Platform Harness actually is, without reading a line of installer code.
|
|
389
|
+
|
|
390
|
+
Inside `cli/`, the layout follows the ten wizard steps: one directory per step under `cli/steps/`, each owning its prompts and its file writes, with `cli/commands/` holding the top-level entry points (`wizard`, `update`, `join`, `migrate`, `single`).
|
|
378
391
|
|
|
379
392
|
Data the CLI reads lives in two places, split by kind:
|
|
380
393
|
|
|
381
|
-
**`
|
|
394
|
+
**`cli/presets/`** holds JSON that shapes the wizard's questions and defaults:
|
|
382
395
|
|
|
383
396
|
- `source.json` controls source-scope prompt options
|
|
384
397
|
- `platforms.json` controls platform labels, CLI checks, and backlog-only flags
|
|
@@ -386,15 +399,13 @@ Data the CLI reads lives in two places, split by kind:
|
|
|
386
399
|
- `models.json` controls model role prompts and agent assignments
|
|
387
400
|
- `optimization.json` controls RTK, quota, Simple English, codegraph, agentmemory, and humanizer checklist defaults
|
|
388
401
|
- `quota.json` controls opencode-quota defaults
|
|
389
|
-
- `browser.json` controls
|
|
390
|
-
|
|
391
|
-
**`src/fragments/`** holds Markdown injected into the installed harness, one directory per marker family: `archive/`, `guardrails/`, `ops-backlog/`, `ops-evidence/`, `ops-review/`, `ops-ship/`. Each file is the platform-specific body that replaces a `<!-- PC-PLATFORM-*-START -->` block.
|
|
402
|
+
- `browser.json` controls the agent-browser installer (npm package + Chrome setup)
|
|
392
403
|
|
|
393
|
-
**`
|
|
404
|
+
**`cli/fragments/`** holds Markdown injected into the installed harness, one directory per marker family: `archive/`, `guardrails/`, `ops-backlog/`, `ops-evidence/`, `ops-review/`, `ops-ship/`. Each file is the platform-specific body that replaces a `<!-- PC-PLATFORM-*-START -->` block.
|
|
394
405
|
|
|
395
|
-
Every filename the harness writes into a project is declared once in `
|
|
406
|
+
Every filename the harness writes into a project is declared once in `cli/utils/paths.js`. Change it there, and remember the OpenCode plugins under `harness/.opencode/plugins/` read those same names at runtime.
|
|
396
407
|
|
|
397
|
-
`skills/` holds skills *about this CLI*, for agents that have to operate it. See [skills/README.md](./skills/README.md). They are not published to npm, and they are separate from the `pc-*` skills in `
|
|
408
|
+
`skills/` holds skills *about this CLI*, for agents that have to operate it. See [skills/README.md](./skills/README.md). They are not published to npm, and they are separate from the `pc-*` skills in `harness/` that get installed into your project.
|
|
398
409
|
|
|
399
410
|
```bash
|
|
400
411
|
git clone https://github.com/PlainConceptsPlatform/agent-harness.git
|
|
@@ -402,7 +413,7 @@ cd agent-harness
|
|
|
402
413
|
pnpm install
|
|
403
414
|
|
|
404
415
|
# Run the CLI locally
|
|
405
|
-
node
|
|
416
|
+
node cli/index.js
|
|
406
417
|
|
|
407
418
|
# Run tests
|
|
408
419
|
pnpm test
|
|
@@ -28,7 +28,6 @@ export async function runJoin() {
|
|
|
28
28
|
|
|
29
29
|
const backlogPlatform = saved?.platform?.backlog
|
|
30
30
|
const repoPlatform = saved?.platform?.repo
|
|
31
|
-
const installScope = 'local'
|
|
32
31
|
const teamModels = saved?.models ?? {}
|
|
33
32
|
|
|
34
33
|
const opencodeDir = path.join(process.cwd(), '.opencode')
|
|
@@ -177,9 +176,9 @@ export async function runJoin() {
|
|
|
177
176
|
header('Step 7, Checking rtk')
|
|
178
177
|
await checkRtk({ skipHeader: true, skipPrompt: true })
|
|
179
178
|
|
|
180
|
-
// Step 8: Browser
|
|
181
|
-
header('Step 8, Installing
|
|
182
|
-
await installBrowser(
|
|
179
|
+
// Step 8: Browser automation
|
|
180
|
+
header('Step 8, Installing agent-browser')
|
|
181
|
+
await installBrowser()
|
|
183
182
|
|
|
184
183
|
// Step 9: Model tier guidance
|
|
185
184
|
header('Step 9, Model tiers')
|
|
@@ -9,7 +9,7 @@ import { CONFIG_FILE, MANIFEST_FILE, OPENCODE_DIR, USER_CONFIG_FILE } from '../u
|
|
|
9
9
|
import { exit } from '../utils/process.js'
|
|
10
10
|
|
|
11
11
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
12
|
-
const CONTENT_SKILLS_DIR = path.resolve(__dirname, '
|
|
12
|
+
const CONTENT_SKILLS_DIR = path.resolve(__dirname, '../../harness/.agents/skills')
|
|
13
13
|
|
|
14
14
|
// State files, old name to new. The run-state file is deleted rather than moved:
|
|
15
15
|
// it is live wave state owned by the monitor plugin and is rebuilt on demand.
|
|
@@ -7,7 +7,9 @@ import { readHarnessConfig } from './shared.js'
|
|
|
7
7
|
import { copyContentStep } from '../steps/copy/index.js'
|
|
8
8
|
import { writeModelsToConfigs } from '../steps/models/write.js'
|
|
9
9
|
import { patchGuardrails } from '../steps/optimization/patch-guardrails.js'
|
|
10
|
+
import { reconcileTools } from '../steps/optimization/detect.js'
|
|
10
11
|
import { writeHarnessConfig } from '../steps/metadata/index.js'
|
|
12
|
+
import { info } from '../utils/exec.js'
|
|
11
13
|
import { exit } from '../utils/process.js'
|
|
12
14
|
|
|
13
15
|
const SIMPLE_ENGLISH_ENTRY = {
|
|
@@ -58,7 +60,17 @@ export async function runUpdate() {
|
|
|
58
60
|
await writeModelsToConfigs({ buildModel: saved.models.build })
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
// Reconcile against what is actually installed before patching guardrails.
|
|
64
|
+
// The saved flags drift: a project can be running the codegraph and
|
|
65
|
+
// agentmemory MCP servers with harness.json still recording them as false,
|
|
66
|
+
// and patchGuardrails would then empty those marker sections and strip the
|
|
67
|
+
// guidance for tools the project genuinely uses.
|
|
68
|
+
const tools = reconcileTools(saved.tools ?? {})
|
|
69
|
+
const gained = Object.keys(tools).filter(k => tools[k] && !saved.tools?.[k])
|
|
70
|
+
if (gained.length > 0) {
|
|
71
|
+
info(`Detected installed tools missing from harness.json: ${gained.join(', ')}`)
|
|
72
|
+
}
|
|
73
|
+
|
|
62
74
|
await migrateCavemanSkill(tools)
|
|
63
75
|
await patchGuardrails({
|
|
64
76
|
rtk: !!tools.rtk,
|
|
@@ -90,7 +90,7 @@ export async function runWizard(version) {
|
|
|
90
90
|
const tokenOpt = await tokenOptimizationStep({ ctx })
|
|
91
91
|
const { rtk, quota, simpleEnglish, codegraph, memory, humanizer } = tokenOpt
|
|
92
92
|
|
|
93
|
-
await installBrowser(
|
|
93
|
+
await installBrowser()
|
|
94
94
|
|
|
95
95
|
await writeHarnessConfig({
|
|
96
96
|
...ctx,
|
package/{src → cli}/index.js
RENAMED
|
@@ -26,7 +26,7 @@ function printHelp(version) {
|
|
|
26
26
|
console.log(' openspec Run OpenSpec initialization step')
|
|
27
27
|
console.log(' models Run models selection step')
|
|
28
28
|
console.log(' optimization Run token optimization tools step')
|
|
29
|
-
console.log(' browser Run
|
|
29
|
+
console.log(' browser Run agent-browser installer step')
|
|
30
30
|
console.log(' metadata Write onboarding metadata step')
|
|
31
31
|
console.log()
|
|
32
32
|
console.log('Options:')
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"skillsGuide": "### Repo Platform: GitLab\n- `pc-ops-ship` -> creates GitLab merge requests via `glab` CLI. Load when shipping a branch or processing MR feedback.\n\n### Backlog Platform\n- Work item skills are loaded based on `platform.backlog` (GitHub / Azure / Jira)."
|
|
44
44
|
},
|
|
45
45
|
"browser": {
|
|
46
|
-
"devopsSkills": "- Selected backlog platform: `browser` (from onboarding platform step).\n- No CLI integration for the backlog system. Work items are fetched via
|
|
47
|
-
"devopsMode": "This project uses browser automation for backlog/work items (no CLI) and a separate repo platform for code. Work items are read from web pages using
|
|
46
|
+
"devopsSkills": "- Selected backlog platform: `browser` (from onboarding platform step).\n- No CLI integration for the backlog system. Work items are fetched via agent-browser.\n- The `pc-userstory` skill opens work item URLs the user provides and reads page content.\n- PRs and code review use the repo platform (GitHub / Azure DevOps / GitLab) configured separately.",
|
|
47
|
+
"devopsMode": "This project uses browser automation for backlog/work items (no CLI) and a separate repo platform for code. Work items are read from web pages using agent-browser. Create PRs via the repo platform CLI. The browser navigation exception ONLY applies to work item URLs the user explicitly provides.",
|
|
48
48
|
"workflow": "When the user provides a work item URL from any backlog tool (Azure DevOps, Linear, Trello, etc.), **I own the full lifecycle**. I load `pc-userstory` skill to navigate to the URL via browser and read the page content.\n\nTrigger patterns, I recognize ALL of these, exact wording does not matter:\n- User pastes any URL to a work item/ticket/issue -> load `pc-userstory` skill -> navigate via browser -> read page text + snapshot -> parse work item -> load the `pc-plan-propose` skill -> confirm -> load the `pc-plan-apply` skill -> ship\n- `implement the plan` / `implement` / `start` / `go` -> load the `pc-plan-apply` skill -> ship\n- PR feedback -> use the repo platform CLI (gh, az, or glab) for PR operations\n\n**Any work item URL in the user's message is a trigger, regardless of the backlog tool it points to.**\n\nFor PR creation and code review, use the repo platform (configured as `platform.repo`). Browser is backlog-only: it has no PR capability.",
|
|
49
|
-
"pipeline": "```\nlead (main session)\n -> open work item URL in browser (
|
|
50
|
-
"skillsGuide": "### Backlog Platform: Others (Browser)\n- `pc-userstory` ->
|
|
49
|
+
"pipeline": "```\nlead (main session)\n -> open work item URL in browser (agent-browser --session backlog --restore open)\n -> wait for load (agent-browser wait --load networkidle)\n -> read page content (agent-browser snapshot + read)\n -> parse work item fields from snapshot\n -> pc-plan-propose (propose + enrich tasks)\n |\n [confirm when scope needs it]\n |\n*-engineer specialists (parallel via pc-plan-apply)\n -> implement assigned tasks (parallel waves)\n |\nlead verifies, creates PR via repo platform (gh / az / glab)\n```\n\n### Phase 1, Fetch & Plan\n\n```\n1. User provides a work item URL.\n2. Open the URL via agent-browser --session backlog --restore open.\n3. Wait for load via agent-browser wait --load networkidle.\n4. Take an accessibility snapshot via agent-browser snapshot.\n5. Parse title, description, acceptance criteria from the snapshot.\n6. Load the pc-plan-propose skill to create the OpenSpec change.\n7. Confirm with the user.\n```\n\n### Phase 2, Implement & Ship\n\n```\n1. Load the pc-plan-apply skill to implement via parallel subagent waves.\n2. Create PR via repo platform CLI (gh pr create, az repos pr create, or glab mr create).\n3. Archive change after PR is merged.\n```",
|
|
50
|
+
"skillsGuide": "### Backlog Platform: Others (Browser)\n- `pc-userstory` -> opens work item URLs via agent-browser, reads page content, creates OpenSpec changes. Load when a URL the user provides does not match GitHub/Azure/Jira CLI platforms.\n\n### Repo Platform\n- PR skills are loaded based on `platform.repo` (GitHub / Azure DevOps / GitLab)."
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
{
|
|
2
|
-
"preserve": ["DESIGN.md", "ARCHITECTURE.md", "openspec"],
|
|
3
|
-
"detectFiles": [
|
|
4
|
-
"AGENTS.md",
|
|
5
|
-
"CLAUDE.md",
|
|
6
|
-
"ARCHITECTURE.md",
|
|
7
|
-
"DESIGN.md",
|
|
8
|
-
".cursorrules",
|
|
9
|
-
".clinerules",
|
|
10
|
-
".windsurfrules",
|
|
11
|
-
".github/copilot-instructions.md",
|
|
12
|
-
"copilot-instructions.md",
|
|
13
|
-
".aider.conf.yml",
|
|
14
|
-
".aider",
|
|
15
|
-
".opencode",
|
|
16
|
-
".agents"
|
|
17
|
-
],
|
|
18
|
-
"directoryTargets": [".opencode", ".agents"],
|
|
19
|
-
"preserveSubfolders": ["skills"],
|
|
20
|
-
"selectionMessage": "Select AI config files to remove:"
|
|
21
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"preserve": ["DESIGN.md", "ARCHITECTURE.md", "openspec"],
|
|
3
|
+
"detectFiles": [
|
|
4
|
+
"AGENTS.md",
|
|
5
|
+
"CLAUDE.md",
|
|
6
|
+
"ARCHITECTURE.md",
|
|
7
|
+
"DESIGN.md",
|
|
8
|
+
".cursorrules",
|
|
9
|
+
".clinerules",
|
|
10
|
+
".windsurfrules",
|
|
11
|
+
".github/copilot-instructions.md",
|
|
12
|
+
"copilot-instructions.md",
|
|
13
|
+
".aider.conf.yml",
|
|
14
|
+
".aider",
|
|
15
|
+
".opencode",
|
|
16
|
+
".agents"
|
|
17
|
+
],
|
|
18
|
+
"directoryTargets": [".opencode", ".agents"],
|
|
19
|
+
"preserveSubfolders": ["skills"],
|
|
20
|
+
"selectionMessage": "Select AI config files to remove:"
|
|
21
|
+
}
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
{
|
|
2
|
-
"message": "Enable tools:",
|
|
3
|
-
"info": "Choose which optimization tools to enable (recommended: all).",
|
|
4
|
-
"timeoutMs": 30000,
|
|
5
|
-
"choices": [
|
|
6
|
-
{
|
|
7
|
-
"name": "RTK check (recommended)",
|
|
8
|
-
"value": "rtk",
|
|
9
|
-
"checked": true
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"name": "opencode-quota plugin (recommended)",
|
|
13
|
-
"value": "quota",
|
|
14
|
-
"checked": true
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"name": "Simple English concise mode (recommended)",
|
|
18
|
-
"value": "simpleEnglish",
|
|
19
|
-
"checked": true
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"name": "codegraph semantic index (recommended)",
|
|
23
|
-
"value": "codegraph",
|
|
24
|
-
"checked": true
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"name": "agentmemory local memory server",
|
|
28
|
-
"value": "memory",
|
|
29
|
-
"checked": true
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"name": "humanizer skill (removes AI writing patterns)",
|
|
33
|
-
"value": "humanizer",
|
|
34
|
-
"checked": true
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"message": "Enable tools:",
|
|
3
|
+
"info": "Choose which optimization tools to enable (recommended: all).",
|
|
4
|
+
"timeoutMs": 30000,
|
|
5
|
+
"choices": [
|
|
6
|
+
{
|
|
7
|
+
"name": "RTK check (recommended)",
|
|
8
|
+
"value": "rtk",
|
|
9
|
+
"checked": true
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "opencode-quota plugin (recommended)",
|
|
13
|
+
"value": "quota",
|
|
14
|
+
"checked": true
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "Simple English concise mode (recommended)",
|
|
18
|
+
"value": "simpleEnglish",
|
|
19
|
+
"checked": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": "codegraph semantic index (recommended)",
|
|
23
|
+
"value": "codegraph",
|
|
24
|
+
"checked": true
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "agentmemory local memory server",
|
|
28
|
+
"value": "memory",
|
|
29
|
+
"checked": true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "humanizer skill (removes AI writing patterns)",
|
|
33
|
+
"value": "humanizer",
|
|
34
|
+
"checked": true
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"value": "github",
|
|
4
|
-
"name": "GitHub",
|
|
5
|
-
"cli": {
|
|
6
|
-
"command": "gh",
|
|
7
|
-
"displayName": "GitHub CLI (gh)",
|
|
8
|
-
"installUrl": "https://cli.github.com",
|
|
9
|
-
"authCheck": {
|
|
10
|
-
"args": ["auth", "status"],
|
|
11
|
-
"notAuthenticatedMessage": "GitHub CLI not authenticated. Run:",
|
|
12
|
-
"commands": ["gh auth login"]
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"value": "azure",
|
|
18
|
-
"name": "Azure DevOps",
|
|
19
|
-
"cli": {
|
|
20
|
-
"command": "az",
|
|
21
|
-
"displayName": "Azure CLI (az)",
|
|
22
|
-
"installUrl": "https://learn.microsoft.com/en-us/cli/azure/install-azure-cli",
|
|
23
|
-
"extensionCheck": {
|
|
24
|
-
"args": ["extension", "list", "--query", "[?name=='azure-devops']", "-o", "tsv"],
|
|
25
|
-
"expectedOutput": "azure-devops",
|
|
26
|
-
"missingMessage": "azure-devops extension not found. Run:",
|
|
27
|
-
"errorMessage": "Could not check azure-devops extension. Run:",
|
|
28
|
-
"commands": [
|
|
29
|
-
"az extension add --name azure-devops",
|
|
30
|
-
"az config set extension.dynamic_install_allow_preview=true",
|
|
31
|
-
"az login",
|
|
32
|
-
"az devops login --organization https://dev.azure.com/<your-org>"
|
|
33
|
-
]
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"value": "jira",
|
|
39
|
-
"name": "Jira (Atlassian)",
|
|
40
|
-
"backlogOnly": true,
|
|
41
|
-
"cli": {
|
|
42
|
-
"command": "acli",
|
|
43
|
-
"displayName": "Atlassian CLI (acli)",
|
|
44
|
-
"installUrl": "https://developer.atlassian.com/cloud/acli/guides/install-acli/",
|
|
45
|
-
"authCheck": {
|
|
46
|
-
"args": ["jira", "auth", "status"],
|
|
47
|
-
"notAuthenticatedMessage": "Atlassian CLI not authenticated. Run:",
|
|
48
|
-
"commands": ["acli jira auth login --site <yoursite>.atlassian.net --email <email> --token"]
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"value": "gitlab",
|
|
54
|
-
"name": "GitLab",
|
|
55
|
-
"repoOnly": true,
|
|
56
|
-
"cli": {
|
|
57
|
-
"command": "glab",
|
|
58
|
-
"displayName": "GitLab CLI (glab)",
|
|
59
|
-
"installUrl": "https://gitlab.com/gitlab-org/cli/#installation",
|
|
60
|
-
"authCheck": {
|
|
61
|
-
"args": ["auth", "status"],
|
|
62
|
-
"notAuthenticatedMessage": "GitLab CLI not authenticated. Run:",
|
|
63
|
-
"commands": ["glab auth login"]
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
"value": "browser",
|
|
69
|
-
"name": "Others (Browser)",
|
|
70
|
-
"backlogOnly": true
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"value": "none",
|
|
74
|
-
"name": "None"
|
|
75
|
-
}
|
|
76
|
-
]
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"value": "github",
|
|
4
|
+
"name": "GitHub",
|
|
5
|
+
"cli": {
|
|
6
|
+
"command": "gh",
|
|
7
|
+
"displayName": "GitHub CLI (gh)",
|
|
8
|
+
"installUrl": "https://cli.github.com",
|
|
9
|
+
"authCheck": {
|
|
10
|
+
"args": ["auth", "status"],
|
|
11
|
+
"notAuthenticatedMessage": "GitHub CLI not authenticated. Run:",
|
|
12
|
+
"commands": ["gh auth login"]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"value": "azure",
|
|
18
|
+
"name": "Azure DevOps",
|
|
19
|
+
"cli": {
|
|
20
|
+
"command": "az",
|
|
21
|
+
"displayName": "Azure CLI (az)",
|
|
22
|
+
"installUrl": "https://learn.microsoft.com/en-us/cli/azure/install-azure-cli",
|
|
23
|
+
"extensionCheck": {
|
|
24
|
+
"args": ["extension", "list", "--query", "[?name=='azure-devops']", "-o", "tsv"],
|
|
25
|
+
"expectedOutput": "azure-devops",
|
|
26
|
+
"missingMessage": "azure-devops extension not found. Run:",
|
|
27
|
+
"errorMessage": "Could not check azure-devops extension. Run:",
|
|
28
|
+
"commands": [
|
|
29
|
+
"az extension add --name azure-devops",
|
|
30
|
+
"az config set extension.dynamic_install_allow_preview=true",
|
|
31
|
+
"az login",
|
|
32
|
+
"az devops login --organization https://dev.azure.com/<your-org>"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"value": "jira",
|
|
39
|
+
"name": "Jira (Atlassian)",
|
|
40
|
+
"backlogOnly": true,
|
|
41
|
+
"cli": {
|
|
42
|
+
"command": "acli",
|
|
43
|
+
"displayName": "Atlassian CLI (acli)",
|
|
44
|
+
"installUrl": "https://developer.atlassian.com/cloud/acli/guides/install-acli/",
|
|
45
|
+
"authCheck": {
|
|
46
|
+
"args": ["jira", "auth", "status"],
|
|
47
|
+
"notAuthenticatedMessage": "Atlassian CLI not authenticated. Run:",
|
|
48
|
+
"commands": ["acli jira auth login --site <yoursite>.atlassian.net --email <email> --token"]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"value": "gitlab",
|
|
54
|
+
"name": "GitLab",
|
|
55
|
+
"repoOnly": true,
|
|
56
|
+
"cli": {
|
|
57
|
+
"command": "glab",
|
|
58
|
+
"displayName": "GitLab CLI (glab)",
|
|
59
|
+
"installUrl": "https://gitlab.com/gitlab-org/cli/#installation",
|
|
60
|
+
"authCheck": {
|
|
61
|
+
"args": ["auth", "status"],
|
|
62
|
+
"notAuthenticatedMessage": "GitLab CLI not authenticated. Run:",
|
|
63
|
+
"commands": ["glab auth login"]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"value": "browser",
|
|
69
|
+
"name": "Others (Browser)",
|
|
70
|
+
"backlogOnly": true
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"value": "none",
|
|
74
|
+
"name": "None"
|
|
75
|
+
}
|
|
76
|
+
]
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
{
|
|
2
|
-
"plugin": "@slkiser/opencode-quota@4.2.0",
|
|
3
|
-
"prompt": {
|
|
4
|
-
"message": "Install opencode-quota with recommended defaults?",
|
|
5
|
-
"default": true,
|
|
6
|
-
"timeoutMs": 20000
|
|
7
|
-
},
|
|
8
|
-
"defaults": {
|
|
9
|
-
"enabledProviders": "auto",
|
|
10
|
-
"formatStyle": "singleWindow",
|
|
11
|
-
"percentDisplayMode": "used",
|
|
12
|
-
"showSessionTokens": true,
|
|
13
|
-
"enableToast": false,
|
|
14
|
-
"tuiCommandDisplay": "inline"
|
|
15
|
-
}
|
|
16
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"plugin": "@slkiser/opencode-quota@4.2.0",
|
|
3
|
+
"prompt": {
|
|
4
|
+
"message": "Install opencode-quota with recommended defaults?",
|
|
5
|
+
"default": true,
|
|
6
|
+
"timeoutMs": 20000
|
|
7
|
+
},
|
|
8
|
+
"defaults": {
|
|
9
|
+
"enabledProviders": "auto",
|
|
10
|
+
"formatStyle": "singleWindow",
|
|
11
|
+
"percentDisplayMode": "used",
|
|
12
|
+
"showSessionTokens": true,
|
|
13
|
+
"enableToast": false,
|
|
14
|
+
"tuiCommandDisplay": "inline"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
{
|
|
2
|
-
"message": "Source code location:",
|
|
3
|
-
"default": "current",
|
|
4
|
-
"choices": [
|
|
5
|
-
{
|
|
6
|
-
"name": "Current folder (default)",
|
|
7
|
-
"value": "current",
|
|
8
|
-
"description": "Use this repository only"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"name": "Select folders in parent (../)",
|
|
12
|
-
"value": "parent",
|
|
13
|
-
"description": "Use when this repo only contains agent config"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"name": "Select child folders (./*/)",
|
|
17
|
-
"value": "children",
|
|
18
|
-
"description": "Use when source code lives in subdirectories of this repo"
|
|
19
|
-
}
|
|
20
|
-
],
|
|
21
|
-
"parentSelectionMessage": "Select source folders from parent directory:",
|
|
22
|
-
"childrenSelectionMessage": "Select child folders to include as source:"
|
|
23
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"message": "Source code location:",
|
|
3
|
+
"default": "current",
|
|
4
|
+
"choices": [
|
|
5
|
+
{
|
|
6
|
+
"name": "Current folder (default)",
|
|
7
|
+
"value": "current",
|
|
8
|
+
"description": "Use this repository only"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "Select folders in parent (../)",
|
|
12
|
+
"value": "parent",
|
|
13
|
+
"description": "Use when this repo only contains agent config"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "Select child folders (./*/)",
|
|
17
|
+
"value": "children",
|
|
18
|
+
"description": "Use when source code lives in subdirectories of this repo"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"parentSelectionMessage": "Select source folders from parent directory:",
|
|
22
|
+
"childrenSelectionMessage": "Select child folders to include as source:"
|
|
23
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { execa } from 'execa'
|
|
2
|
+
import fse from 'fs-extra'
|
|
3
|
+
import { header, info, success, warn, error } from '../../utils/exec.js'
|
|
4
|
+
import os from 'os'
|
|
5
|
+
import path from 'path'
|
|
6
|
+
import { fileURLToPath } from 'url'
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const BROWSER_PRESET_PATH = path.resolve(__dirname, '../../presets/browser.json')
|
|
10
|
+
const browserPreset = await fse.readJson(BROWSER_PRESET_PATH)
|
|
11
|
+
|
|
12
|
+
export async function installBrowser() {
|
|
13
|
+
header('Step 9, Installing agent-browser')
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const install = await execa(browserPreset.installer.command, browserPreset.installer.args, {
|
|
17
|
+
cwd: os.homedir(),
|
|
18
|
+
reject: false,
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
if (install.exitCode !== 0) {
|
|
22
|
+
warn('agent-browser npm install exited with non-zero code')
|
|
23
|
+
if (install.stderr) info(install.stderr)
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
success('agent-browser installed')
|
|
27
|
+
} catch (err) {
|
|
28
|
+
error(`Failed to install agent-browser: ${err.message}`)
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const chrome = await execa(browserPreset.chromeSetup.command, browserPreset.chromeSetup.args, {
|
|
34
|
+
cwd: os.homedir(),
|
|
35
|
+
reject: false,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
if (chrome.exitCode === 0) {
|
|
39
|
+
success('agent-browser Chrome ready')
|
|
40
|
+
if (chrome.stdout) info(chrome.stdout.trim())
|
|
41
|
+
} else {
|
|
42
|
+
warn('agent-browser install (Chrome setup) exited with non-zero code')
|
|
43
|
+
if (chrome.stderr) info(chrome.stderr)
|
|
44
|
+
}
|
|
45
|
+
} catch (err) {
|
|
46
|
+
error(`Failed to set up Chrome for agent-browser: ${err.message}`)
|
|
47
|
+
}
|
|
48
|
+
}
|