@swarmclawai/swarmclaw 1.5.36 → 1.5.38
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 +22 -80
- package/package.json +6 -1
- package/public/provider-logos/droid-cli.svg +7 -0
- package/src/app/api/setup/check-provider/route.ts +4 -2
- package/src/app/api/setup/doctor/route.ts +1 -0
- package/src/components/agents/agent-sheet.tsx +3 -1
- package/src/components/agents/inspector-panel.tsx +1 -0
- package/src/components/chat/activity-moment.tsx +1 -0
- package/src/components/chat/chat-header.tsx +2 -1
- package/src/components/chat/tool-call-bubble.tsx +5 -0
- package/src/components/tasks/task-card.tsx +11 -3
- package/src/components/tasks/task-sheet.tsx +19 -8
- package/src/lib/orchestrator-config.ts +1 -0
- package/src/lib/provider-sets.ts +3 -3
- package/src/lib/providers/cli-utils.test.ts +2 -0
- package/src/lib/providers/cli-utils.ts +28 -1
- package/src/lib/providers/droid-cli.ts +220 -0
- package/src/lib/providers/index.ts +11 -1
- package/src/lib/server/agents/agent-availability.test.ts +1 -1
- package/src/lib/server/agents/agent-thread-session.ts +1 -0
- package/src/lib/server/agents/task-session.ts +2 -0
- package/src/lib/server/autonomy/supervisor-reflection.ts +12 -0
- package/src/lib/server/build-llm.test.ts +12 -0
- package/src/lib/server/build-llm.ts +2 -0
- package/src/lib/server/capability-router.ts +3 -1
- package/src/lib/server/chat-execution/chat-execution-utils.ts +11 -0
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +2 -0
- package/src/lib/server/chat-execution/chat-turn-preparation.ts +12 -1
- package/src/lib/server/chat-execution/chat-turn-state.test.ts +39 -0
- package/src/lib/server/chat-execution/chat-turn-state.ts +4 -0
- package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +1 -0
- package/src/lib/server/chat-execution/continuation-evaluator.ts +10 -0
- package/src/lib/server/chat-execution/prompt-sections.ts +2 -0
- package/src/lib/server/chat-execution/tool-event-tracker.test.ts +67 -0
- package/src/lib/server/chat-execution/tool-event-tracker.ts +38 -0
- package/src/lib/server/chat-execution/tool-summary-progress.test.ts +42 -0
- package/src/lib/server/chat-execution/tool-summary-progress.ts +13 -0
- package/src/lib/server/chatrooms/chatroom-helpers.ts +3 -0
- package/src/lib/server/chats/chat-session-service.ts +4 -0
- package/src/lib/server/connectors/session.ts +2 -0
- package/src/lib/server/context-manager.ts +1 -0
- package/src/lib/server/openclaw/gateway.ts +27 -7
- package/src/lib/server/provider-health.ts +4 -2
- package/src/lib/server/provider-model-discovery.test.ts +1 -1
- package/src/lib/server/provider-model-discovery.ts +1 -1
- package/src/lib/server/runtime/daemon-state/core.ts +2 -2
- package/src/lib/server/runtime/queue/core.ts +6 -0
- package/src/lib/server/runtime/queue-recovery.test.ts +115 -0
- package/src/lib/server/session-reset-policy.ts +2 -0
- package/src/lib/server/session-tools/context.ts +2 -2
- package/src/lib/server/session-tools/delegate-droid.test.ts +24 -0
- package/src/lib/server/session-tools/delegate.ts +105 -12
- package/src/lib/server/session-tools/index.ts +3 -2
- package/src/lib/server/session-tools/session-info.ts +1 -0
- package/src/lib/server/storage-normalization.ts +3 -0
- package/src/lib/server/tasks/task-checkout.ts +7 -1
- package/src/lib/server/tool-aliases.ts +1 -1
- package/src/lib/server/tool-capability-policy.ts +2 -1
- package/src/lib/setup-defaults.ts +21 -0
- package/src/types/misc.ts +1 -1
- package/src/types/provider.ts +1 -1
- package/src/types/session.ts +3 -0
package/README.md
CHANGED
|
@@ -40,6 +40,7 @@ Extension tutorial: https://swarmclaw.ai/docs/extension-tutorial
|
|
|
40
40
|
<td align="center"><img src="doc/assets/logos/gemini-cli.svg" width="32" alt="Gemini CLI"><br><sub>Gemini CLI</sub></td>
|
|
41
41
|
<td align="center"><img src="doc/assets/logos/opencode.svg" width="32" alt="OpenCode"><br><sub>OpenCode</sub></td>
|
|
42
42
|
<td align="center"><img src="doc/assets/logos/copilot-cli.svg" width="32" alt="Copilot CLI"><br><sub>Copilot</sub></td>
|
|
43
|
+
<td align="center"><img src="public/provider-logos/droid-cli.svg" width="32" alt="Factory Droid CLI"><br><sub>Droid</sub></td>
|
|
43
44
|
<td align="center"><img src="doc/assets/logos/cursor-cli.svg" width="32" alt="Cursor Agent CLI"><br><sub>Cursor</sub></td>
|
|
44
45
|
<td align="center"><img src="doc/assets/logos/qwen-code-cli.svg" width="32" alt="Qwen Code CLI"><br><sub>Qwen Code</sub></td>
|
|
45
46
|
<td align="center"><img src="doc/assets/logos/goose.svg" width="32" alt="Goose"><br><sub>Goose</sub></td>
|
|
@@ -65,7 +66,7 @@ Extension tutorial: https://swarmclaw.ai/docs/extension-tutorial
|
|
|
65
66
|
- Node.js 22.6+ (`nvm use` will pick up the repo's `.nvmrc`, which matches CI)
|
|
66
67
|
- npm 10+ or another supported package manager
|
|
67
68
|
- Docker Desktop is recommended for sandbox browser execution
|
|
68
|
-
- Optional provider CLIs if you want delegated CLI backends such as Claude Code, Codex, OpenCode, Gemini, Copilot, Cursor Agent, Qwen Code, or Goose
|
|
69
|
+
- Optional provider CLIs if you want delegated CLI backends such as Claude Code, Codex, OpenCode, Gemini, Copilot, Factory Droid, Cursor Agent, Qwen Code, or Goose
|
|
69
70
|
|
|
70
71
|
## Quick Start
|
|
71
72
|
|
|
@@ -388,6 +389,25 @@ Operational docs: https://swarmclaw.ai/docs/observability
|
|
|
388
389
|
|
|
389
390
|
## Releases
|
|
390
391
|
|
|
392
|
+
### v1.5.38 Highlights
|
|
393
|
+
|
|
394
|
+
- **Task queue: reclaim stale checkouts**: `checkoutTask()` now reclaims a lingering `checkoutRunId` on a `queued` task instead of refusing it forever. An ungraceful server exit mid-turn (crash, SIGKILL, HMR reload) previously left tasks uncheckoutable, producing a dispatch → orphan-recovery → failed-checkout spin that logged "Recovering orphaned queued task" tens of thousands of times per session. `scheduleRetryOrDeadLetter()` also clears the prior checkout when scheduling a retry or dead-lettering.
|
|
395
|
+
- **Chat: suppress duplicate parallel tool calls**: some OSS models on Ollama (notably `devstral`) emit the same tool call twice in a single turn. The LangGraph tool-event tracker now dedupes by `name + input` signature, swallowing the duplicate start and its result while allowing a genuinely later identical call once the first completes. Hardened against replayed-start events (HMR, graph retries) that previously could leak a `run_id` into both the accepted and suppressed sets and leave `pendingCount` stuck above zero.
|
|
396
|
+
- **Chat: disable `parallel_tool_calls` for Ollama**: local Ollama sessions now pass `parallel_tool_calls: false` to prevent the upstream duplicate-call behavior at the source for models that honor it.
|
|
397
|
+
- **Chat: no-progress guard for tool summary retries**: if the model produces essentially no new text on a `tool_summary` continuation, the loop stops retrying instead of streaming the same short sentence two or three times. The guard is snapshot-aware: a transient-error rollback no longer leaves a stale progress counter that silently skips a legitimate retry (`lastToolSummaryTextLen` is now round-tripped through `ChatTurnState.snapshot`/`restore`).
|
|
398
|
+
- **Task UI: distinguish retry-pending from failure**: a retrying task now renders in amber with a "Retry Pending" label in the task card and sheet, instead of the same red treatment used for dead-lettered failures.
|
|
399
|
+
- **Autonomy: dedupe reflection memories across kinds**: the supervisor reflection writer now drops notes whose normalized text has already been stored this run, eliminating near-identical memory rows classified under multiple kinds.
|
|
400
|
+
- **OpenClaw gateway: fast-fail on dangling credentials**: when an agent's OpenClaw route references a deleted or missing credential, the gateway now refuses to dial the WebSocket up front instead of attempting an unauthenticated handshake and waiting the full 120 s for the agent-side timeout. The credential-missing log line is promoted from warn to error so it surfaces in routine monitoring.
|
|
401
|
+
- **Prompt size profiler**: setting `SWARMCLAW_PROFILE_PROMPT=1` now logs a per-section size breakdown of the assembled system prompt (block index, first-line label, char count) on every turn, making it practical to diagnose why a specific agent is eating context budget. Off by default so production turns stay quiet.
|
|
402
|
+
|
|
403
|
+
### v1.5.37 Highlights
|
|
404
|
+
|
|
405
|
+
- **Factory Droid CLI as a provider and delegation backend**: adds [`droid`](https://docs.factory.ai/cli/droid-exec/overview) as a first-class chat provider and `delegate` backend with streaming JSON output, session resume, and a conservative `--auto low` autonomy pin on the delegate path. Install `droid` and sign in via browser (or set `FACTORY_API_KEY`), then pick **Factory Droid CLI** in the setup wizard. Resolves #38.
|
|
406
|
+
- **Desktop Release CI hardening**: v1.5.36's Electron build workflow failed on all three platforms. This release:
|
|
407
|
+
- Adds a proper `author` with email to `package.json` and a `linux.maintainer` entry in `electron-builder.yml` so the Linux `.deb` target stops rejecting the build.
|
|
408
|
+
- Pins `outputFileTracingRoot` in `next.config.ts` to the project root so the Next.js build no longer walks `C:\Users\<user>\Application Data` (a legacy NTFS junction that throws EPERM on Windows runners).
|
|
409
|
+
- Pins Python 3.11 in the desktop-release workflow so `node-gyp` rebuilds of native modules (`node-liblzma`, etc.) succeed on Python 3.12+ runners where `distutils` was removed from the stdlib.
|
|
410
|
+
|
|
391
411
|
### v1.5.36 Highlights
|
|
392
412
|
|
|
393
413
|
- **Desktop app (Electron)**: SwarmClaw now ships as a native desktop app for macOS (Apple Silicon + Intel), Windows, and Linux (AppImage + .deb). Download from [swarmclaw.ai/downloads](https://swarmclaw.ai/downloads). The app wraps the existing standalone server inside an Electron shell, stores data in the OS app-data directory, and auto-updates via GitHub Releases (notify-only on unsigned macOS builds).
|
|
@@ -408,85 +428,7 @@ Operational docs: https://swarmclaw.ai/docs/observability
|
|
|
408
428
|
- **Chat execution context hardening**: tool invocation now resolves names case-insensitively, oversized tool results are truncated before they are fed back into the model, and proactive grounding/heartbeat prompts stay smaller under pressure to reduce avoidable context blowouts.
|
|
409
429
|
- **API compatibility fixes**: OpenAI-compatible streaming now captures reasoning deltas from providers that emit them outside `delta.content`, and A2A endpoints are exempt from the main proxy access-key gate so they can rely on their own auth scheme.
|
|
410
430
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
- **CLI global flag compatibility**: legacy-routed commands now honor the documented `--access-key` and `--base-url` aliases even when they appear after the subcommand, so authenticated CLI automation works the same across binary entry points.
|
|
414
|
-
- **Docker build memory hardening**: production Next.js builds now size `--max-old-space-size` from the detected container/cgroup memory limit, with `SWARMCLAW_BUILD_MAX_OLD_SPACE_SIZE_MB` available as an explicit override for constrained Docker Desktop and CI environments.
|
|
415
|
-
|
|
416
|
-
### v1.5.31 Highlights
|
|
417
|
-
|
|
418
|
-
- **Fix Docker first-run crash**: resolved `EISDIR: illegal operation on a directory, read` error when running `docker compose up` without a pre-existing `.env.local` file. Docker was creating a directory mount instead of a file, which crashed Next.js on startup. Replaced the file bind mount with `env_file` directive using `required: false`.
|
|
419
|
-
|
|
420
|
-
### v1.5.4 Highlights
|
|
421
|
-
|
|
422
|
-
- **Cursor Agent CLI built-in provider**: Cursor Agent CLI is now a first-class worker provider with session continuity, headless execution, and delegation support.
|
|
423
|
-
- **Qwen Code CLI built-in provider**: Qwen Code CLI is now available as a built-in worker provider and delegation backend with structured headless execution support.
|
|
424
|
-
- **Goose built-in provider**: Goose is now supported as a runtime-managed worker provider, using its own local auth and provider configuration while preserving SwarmClaw session continuity.
|
|
425
|
-
- **CLI setup and health parity**: setup flows, provider checks, setup doctor, and provider-facing UI now recognize Cursor, Qwen Code, and Goose alongside the existing CLI-backed providers.
|
|
426
|
-
|
|
427
|
-
### v1.5.3 Highlights
|
|
428
|
-
|
|
429
|
-
- **Copilot CLI v1.x compatibility**: the `copilot-cli` provider now handles the current event format (`assistant.message_delta`, `assistant.message`, updated `result` payload) while keeping backward compatibility with the legacy format. Also fixes `--resume` flag syntax. (Community contribution by [@borislavnnikolov](https://github.com/borislavnnikolov) -- PR #36)
|
|
430
|
-
|
|
431
|
-
### v1.5.2 Highlights
|
|
432
|
-
|
|
433
|
-
- **Hosted deploy path for SwarmClaw itself**: added root-level `render.yaml`, `fly.toml`, and `railway.json` so the published `ghcr.io/swarmclawai/swarmclaw:latest` image is easier to run on always-on platforms.
|
|
434
|
-
- **Public health endpoint for hosted platforms**: added `/api/healthz` and exempted it from access-key auth so Render, Fly.io, and Railway can perform liveness checks without weakening the rest of the API surface.
|
|
435
|
-
- **OTLP/OpenTelemetry foundation**: SwarmClaw can now export traces for chat turns, direct model streams, protocol runs, and tool execution to any OTLP-compatible backend using environment variables only.
|
|
436
|
-
- **Docs and landing-page deploy refresh**: `swarmclaw.ai` now exposes the hosted deploy path and a dedicated observability guide instead of burying those operator workflows in general setup docs.
|
|
437
|
-
|
|
438
|
-
### v1.5.1 Highlights
|
|
439
|
-
|
|
440
|
-
- **Standalone connector lifecycle**: connector start, stop, status, and repair now work correctly in standalone production builds (`npm start` / pm2) where the daemon runs in-process. Previously these operations silently failed because the controller assumed a daemon subprocess was always present. (Community contribution by [@borislavnnikolov](https://github.com/borislavnnikolov) -- PR #35)
|
|
441
|
-
|
|
442
|
-
### v1.5.0 Highlights
|
|
443
|
-
|
|
444
|
-
- **First-run activation refresh**: setup now includes a dedicated start-path step, broad starter shapes instead of niche presets, and draft agents generated directly from the chosen setup shape.
|
|
445
|
-
- **Guided post-setup launchpad**: finishing setup now routes through action-oriented next steps such as opening the first agent chat, launching a structured session, connecting platforms, or reviewing usage.
|
|
446
|
-
- **State-aware home and protocols**: fresh workspaces now open on a launchpad instead of a sparse ops dashboard, and the Protocols page now surfaces the visual builder and template gallery directly.
|
|
447
|
-
|
|
448
|
-
### v1.4.9 Highlights
|
|
449
|
-
|
|
450
|
-
- **Standalone build reliability**: `public/`, `.next/static/`, and `css-tree/data/` are now automatically copied into the standalone build output, fixing runtime crashes and missing assets when running the standalone bundle. (Community contribution by [@borislavnnikolov](https://github.com/borislavnnikolov) — PR #34)
|
|
451
|
-
|
|
452
|
-
### v1.4.8 Highlights
|
|
453
|
-
|
|
454
|
-
- **Agent-scoped SwarmFeed dashboard**: the in-app feed now has an explicit acting-agent model so humans can direct social actions without ever posting as a separate user identity.
|
|
455
|
-
- **Expanded feed surface**: added Bookmarks and Notifications tabs, SwarmFeed search, suggested follows, thread detail sheets, profile sheets, and a restored visible composer.
|
|
456
|
-
- **Broader SwarmFeed tool/API support**: the built-in `swarmfeed` tool and internal API now support follow/unfollow, bookmark/unbookmark, quote reposts, notifications, profile lookup, thread reads, and search.
|
|
457
|
-
- **Social heartbeat enforcement**: task-completion posting, daily/manual-only guardrails, and heartbeat dependency warnings now match the agent-first SwarmFeed model instead of leaving social automation loosely implied.
|
|
458
|
-
|
|
459
|
-
### v1.4.7 Highlights
|
|
460
|
-
|
|
461
|
-
- **Hermes Agent built-in provider**: Added first-class Hermes support through the Hermes API server, including optional auth, local or remote `/v1` endpoints, and runtime-managed agent handling.
|
|
462
|
-
- **OpenRouter built-in provider**: OpenRouter is now a built-in provider instead of living only behind the generic custom-provider path.
|
|
463
|
-
- **Runtime-managed provider handling**: Hermes now skips SwarmClaw's local extension/tool injection path so its own runtime stays in control, while setup and model discovery still work through the normal provider flow.
|
|
464
|
-
- **Provider docs refresh**: README and docs now reflect the new provider list, remote Hermes API-server support, and logo assets for OpenRouter and Hermes Agent.
|
|
465
|
-
|
|
466
|
-
### v1.4.6 Highlights
|
|
467
|
-
|
|
468
|
-
- **SwarmDock startup sync**: Existing SwarmDock agents now authenticate and reconcile their live marketplace profile on connector start, updating stale description, skills, framework/model metadata, and payout wallet fields
|
|
469
|
-
- **Agent wallet fallback**: SwarmDock connectors now fall back to the agent's selected marketplace wallet when no connector-level wallet address is configured
|
|
470
|
-
- **Task filter fix**: The built-in `swarmdock` tool now uses the correct `skills=` task filter when browsing marketplace tasks from chat
|
|
471
|
-
- **SwarmDock SDK bump**: Updated `@swarmdock/sdk` from `0.5.2` to `0.5.3`, aligning the connector with the published metadata-sync fixes
|
|
472
|
-
|
|
473
|
-
### v1.4.5 Highlights
|
|
474
|
-
|
|
475
|
-
- **OpenClaw 2026.4.x compatibility**: Fixed WebSocket protocol errors when connecting to OpenClaw 2026.4.2+ gateways (`profileId` was incorrectly included in RPC params)
|
|
476
|
-
- **OpenClaw dependency bump**: Updated minimum OpenClaw from `2026.2.26` to `2026.4.2`
|
|
477
|
-
|
|
478
|
-
### v1.4.4 Highlights
|
|
479
|
-
|
|
480
|
-
- **SwarmDock SDK bump**: Updated `@swarmdock/sdk` from `0.4.1` to `0.5.2`, picking up new error types, skill templates, and agent primitives
|
|
481
|
-
|
|
482
|
-
### v1.4.3 Highlights
|
|
483
|
-
|
|
484
|
-
- **SwarmDock agent opt-in**: Agents can now opt into the SwarmDock marketplace directly from their settings sheet with description, skills, wallet, and auto-bid configuration
|
|
485
|
-
- **SwarmFeed & SwarmDock tools**: Agents get `swarmfeed` and `swarmdock` tools auto-enabled when opted in, allowing autonomous posting, replying, liking, browsing tasks, and checking status from chat
|
|
486
|
-
- **Auto-registration**: Enabling SwarmFeed on an agent automatically registers it on the SwarmFeed network (no manual connector setup required)
|
|
487
|
-
- **Marketplace page**: New `/marketplace` sidebar page showing live SwarmDock tasks and agents
|
|
488
|
-
- **Following tab fix**: SwarmFeed Following tab gracefully handles unregistered agents instead of showing a 401 error
|
|
489
|
-
- **Compose removal**: Removed manual compose UI from Feed page — agents post autonomously through their tools
|
|
431
|
+
Older releases: https://swarmclaw.ai/docs/release-notes
|
|
490
432
|
|
|
491
433
|
- GitHub releases: https://github.com/swarmclawai/swarmclaw/releases
|
|
492
434
|
- npm package: https://www.npmjs.com/package/@swarmclawai/swarmclaw
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swarmclawai/swarmclaw",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.38",
|
|
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",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "SwarmClaw",
|
|
9
|
+
"email": "noreply@swarmclaw.ai",
|
|
10
|
+
"url": "https://swarmclaw.ai"
|
|
11
|
+
},
|
|
7
12
|
"publishConfig": {
|
|
8
13
|
"access": "public",
|
|
9
14
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="Factory Droid CLI">
|
|
2
|
+
<rect x="2" y="2" width="60" height="60" rx="14" fill="#0f172a"/>
|
|
3
|
+
<rect x="2" y="2" width="60" height="60" rx="14" fill="none" stroke="#38bdf8" stroke-width="2"/>
|
|
4
|
+
<path d="M20 22 h24 v6 h-9 v16 h-6 v-16 h-9 z" fill="#e2e8f0"/>
|
|
5
|
+
<circle cx="16" cy="48" r="2.5" fill="#38bdf8"/>
|
|
6
|
+
<circle cx="48" cy="48" r="2.5" fill="#38bdf8"/>
|
|
7
|
+
</svg>
|
|
@@ -12,6 +12,7 @@ type SetupProvider =
|
|
|
12
12
|
| 'opencode-cli'
|
|
13
13
|
| 'gemini-cli'
|
|
14
14
|
| 'copilot-cli'
|
|
15
|
+
| 'droid-cli'
|
|
15
16
|
| 'cursor-cli'
|
|
16
17
|
| 'qwen-code-cli'
|
|
17
18
|
| 'goose'
|
|
@@ -31,7 +32,7 @@ type SetupProvider =
|
|
|
31
32
|
| 'openclaw'
|
|
32
33
|
| 'hermes'
|
|
33
34
|
|
|
34
|
-
type CliSetupProvider = 'claude-cli' | 'codex-cli' | 'opencode-cli' | 'gemini-cli' | 'copilot-cli' | 'cursor-cli' | 'qwen-code-cli' | 'goose'
|
|
35
|
+
type CliSetupProvider = 'claude-cli' | 'codex-cli' | 'opencode-cli' | 'gemini-cli' | 'copilot-cli' | 'droid-cli' | 'cursor-cli' | 'qwen-code-cli' | 'goose'
|
|
35
36
|
|
|
36
37
|
interface SetupCheckBody {
|
|
37
38
|
provider?: string
|
|
@@ -285,6 +286,7 @@ function checkCliProvider(provider: CliSetupProvider): { ok: boolean; message: s
|
|
|
285
286
|
'opencode-cli': { binary: 'opencode', backend: 'opencode' as const, label: 'OpenCode CLI' },
|
|
286
287
|
'gemini-cli': { binary: 'gemini', backend: 'gemini' as const, label: 'Gemini CLI' },
|
|
287
288
|
'copilot-cli': { binary: 'copilot', backend: 'copilot' as const, label: 'GitHub Copilot CLI' },
|
|
289
|
+
'droid-cli': { binary: 'droid', backend: 'droid' as const, label: 'Factory Droid CLI' },
|
|
288
290
|
'cursor-cli': { binary: 'cursor-agent', backend: 'cursor' as const, label: 'Cursor Agent CLI' },
|
|
289
291
|
'qwen-code-cli': { binary: 'qwen', backend: 'qwen' as const, label: 'Qwen Code CLI' },
|
|
290
292
|
goose: { binary: 'goose', backend: 'goose' as const, label: 'Goose CLI' },
|
|
@@ -312,7 +314,7 @@ export async function POST(req: Request) {
|
|
|
312
314
|
const credentialId = clean(body.credentialId)
|
|
313
315
|
const endpoint = clean(body.endpoint)
|
|
314
316
|
const model = clean(body.model)
|
|
315
|
-
const CLI_PROVIDERS = new Set<CliSetupProvider>(['claude-cli', 'codex-cli', 'opencode-cli', 'gemini-cli', 'copilot-cli', 'cursor-cli', 'qwen-code-cli', 'goose'])
|
|
317
|
+
const CLI_PROVIDERS = new Set<CliSetupProvider>(['claude-cli', 'codex-cli', 'opencode-cli', 'gemini-cli', 'copilot-cli', 'droid-cli', 'cursor-cli', 'qwen-code-cli', 'goose'])
|
|
316
318
|
|
|
317
319
|
// Resolve credentialId to an API key if no raw key was provided
|
|
318
320
|
if (!apiKey && credentialId) {
|
|
@@ -203,6 +203,7 @@ export async function GET(req: Request) {
|
|
|
203
203
|
{ id: 'opencode-cli', label: 'OpenCode CLI', command: 'opencode' },
|
|
204
204
|
{ id: 'gemini-cli', label: 'Gemini CLI', command: 'gemini' },
|
|
205
205
|
{ id: 'copilot-cli', label: 'GitHub Copilot CLI', command: 'copilot' },
|
|
206
|
+
{ id: 'droid-cli', label: 'Factory Droid CLI', command: 'droid' },
|
|
206
207
|
{ id: 'cursor-cli', label: 'Cursor Agent CLI', command: 'cursor-agent' },
|
|
207
208
|
{ id: 'qwen-code-cli', label: 'Qwen Code CLI', command: 'qwen' },
|
|
208
209
|
{ id: 'goose', label: 'Goose CLI', command: 'goose' },
|
|
@@ -2513,7 +2513,9 @@ export function AgentSheet() {
|
|
|
2513
2513
|
? 'Gemini CLI uses its own built-in tools and runtime — SwarmClaw does not inject local platform tools for it.'
|
|
2514
2514
|
: provider === 'copilot-cli'
|
|
2515
2515
|
? 'GitHub Copilot CLI uses its own built-in tools and runtime — SwarmClaw does not inject local platform tools for it.'
|
|
2516
|
-
: provider === '
|
|
2516
|
+
: provider === 'droid-cli'
|
|
2517
|
+
? 'Factory Droid CLI uses its own built-in tools and autonomy controls — SwarmClaw does not inject local platform tools for it.'
|
|
2518
|
+
: provider === 'cursor-cli'
|
|
2517
2519
|
? 'Cursor Agent CLI runs with its own native tool/runtime layer — SwarmClaw sends prompts directly without injecting local platform tools.'
|
|
2518
2520
|
: provider === 'qwen-code-cli'
|
|
2519
2521
|
? 'Qwen Code CLI uses its own native tools and runtime — SwarmClaw does not inject local platform tools for it.'
|
|
@@ -53,6 +53,7 @@ const PROVIDER_LABELS: Record<string, string> = {
|
|
|
53
53
|
'opencode-cli': 'OpenCode CLI',
|
|
54
54
|
'gemini-cli': 'Gemini CLI',
|
|
55
55
|
'copilot-cli': 'Copilot CLI',
|
|
56
|
+
'droid-cli': 'Droid CLI',
|
|
56
57
|
'cursor-cli': 'Cursor CLI',
|
|
57
58
|
'qwen-code-cli': 'Qwen Code CLI',
|
|
58
59
|
goose: 'Goose',
|
|
@@ -14,6 +14,7 @@ const NOTABLE_TOOLS: Record<string, { label: string; color: string; icon: 'brain
|
|
|
14
14
|
delegate_to_opencode_cli: { label: 'Delegated to OpenCode', color: '#38BDF8', icon: 'delegate' },
|
|
15
15
|
delegate_to_gemini_cli: { label: 'Delegated to Gemini CLI', color: '#38BDF8', icon: 'delegate' },
|
|
16
16
|
delegate_to_cursor_cli: { label: 'Delegated to Cursor CLI', color: '#38BDF8', icon: 'delegate' },
|
|
17
|
+
delegate_to_droid_cli: { label: 'Delegated to Factory Droid', color: '#38BDF8', icon: 'delegate' },
|
|
17
18
|
delegate_to_qwen_code_cli: { label: 'Delegated to Qwen Code', color: '#38BDF8', icon: 'delegate' },
|
|
18
19
|
delegate_to_agent: { label: 'Delegating task', color: '#6366F1', icon: 'delegate' },
|
|
19
20
|
check_delegation_status: { label: 'Checking delegation', color: '#6366F1', icon: 'delegate' },
|
|
@@ -220,10 +220,11 @@ export function ChatHeader({ session, streaming, onStop, onMenuToggle, onBack, m
|
|
|
220
220
|
opencodeSessionId: null,
|
|
221
221
|
geminiSessionId: null,
|
|
222
222
|
copilotSessionId: null,
|
|
223
|
+
droidSessionId: null,
|
|
223
224
|
cursorSessionId: null,
|
|
224
225
|
qwenSessionId: null,
|
|
225
226
|
acpSessionId: null,
|
|
226
|
-
delegateResumeIds: { claudeCode: null, codex: null, opencode: null, gemini: null, copilot: null, cursor: null, qwen: null },
|
|
227
|
+
delegateResumeIds: { claudeCode: null, codex: null, opencode: null, gemini: null, copilot: null, droid: null, cursor: null, qwen: null },
|
|
227
228
|
})
|
|
228
229
|
await refreshSession(session.id)
|
|
229
230
|
} catch { /* best-effort */ }
|
|
@@ -28,6 +28,7 @@ const TOOL_COLORS: Record<string, string> = {
|
|
|
28
28
|
delegate_to_opencode_cli: '#14B8A6',
|
|
29
29
|
delegate_to_gemini_cli: '#2563EB',
|
|
30
30
|
delegate_to_copilot_cli: '#6366F1',
|
|
31
|
+
delegate_to_droid_cli: '#A855F7',
|
|
31
32
|
delegate_to_cursor_cli: '#F97316',
|
|
32
33
|
delegate_to_qwen_code_cli: '#22C55E',
|
|
33
34
|
whoami_tool: '#8B5CF6',
|
|
@@ -81,6 +82,7 @@ export const TOOL_LABELS: Record<string, string> = {
|
|
|
81
82
|
opencode_cli: 'OpenCode CLI',
|
|
82
83
|
gemini_cli: 'Gemini CLI',
|
|
83
84
|
copilot_cli: 'Copilot CLI',
|
|
85
|
+
droid_cli: 'Factory Droid',
|
|
84
86
|
cursor_cli: 'Cursor CLI',
|
|
85
87
|
qwen_code_cli: 'Qwen Code CLI',
|
|
86
88
|
spawn_subagent: 'Subagent',
|
|
@@ -91,6 +93,7 @@ export const TOOL_LABELS: Record<string, string> = {
|
|
|
91
93
|
delegate_to_opencode_cli: 'OpenCode CLI',
|
|
92
94
|
delegate_to_gemini_cli: 'Gemini CLI',
|
|
93
95
|
delegate_to_copilot_cli: 'Copilot CLI',
|
|
96
|
+
delegate_to_droid_cli: 'Factory Droid',
|
|
94
97
|
delegate_to_cursor_cli: 'Cursor CLI',
|
|
95
98
|
delegate_to_qwen_code_cli: 'Qwen Code CLI',
|
|
96
99
|
whoami_tool: 'Who Am I',
|
|
@@ -129,6 +132,7 @@ export const TOOL_DESCRIPTIONS: Record<string, string> = {
|
|
|
129
132
|
opencode_cli: 'Enable delegation to OpenCode CLI',
|
|
130
133
|
gemini_cli: 'Enable delegation to Gemini CLI',
|
|
131
134
|
copilot_cli: 'Enable delegation to GitHub Copilot CLI',
|
|
135
|
+
droid_cli: 'Enable delegation to Factory Droid CLI',
|
|
132
136
|
cursor_cli: 'Enable delegation to Cursor Agent CLI',
|
|
133
137
|
qwen_code_cli: 'Enable delegation to Qwen Code CLI',
|
|
134
138
|
spawn_subagent: 'Spawn native subagents with lineage tracking and batch support',
|
|
@@ -139,6 +143,7 @@ export const TOOL_DESCRIPTIONS: Record<string, string> = {
|
|
|
139
143
|
delegate_to_opencode_cli: 'Delegate complex coding tasks to OpenCode CLI',
|
|
140
144
|
delegate_to_gemini_cli: 'Delegate complex coding tasks to Gemini CLI',
|
|
141
145
|
delegate_to_copilot_cli: 'Delegate complex coding tasks to GitHub Copilot CLI',
|
|
146
|
+
delegate_to_droid_cli: 'Delegate complex coding tasks to Factory Droid CLI',
|
|
142
147
|
delegate_to_cursor_cli: 'Delegate complex coding tasks to Cursor Agent CLI',
|
|
143
148
|
delegate_to_qwen_code_cli: 'Delegate complex coding tasks to Qwen Code CLI',
|
|
144
149
|
whoami_tool: 'Reveal the current agent and chat context',
|
|
@@ -343,9 +343,17 @@ export function TaskCard({
|
|
|
343
343
|
)}
|
|
344
344
|
</div>
|
|
345
345
|
|
|
346
|
-
{task.error && (
|
|
347
|
-
|
|
348
|
-
|
|
346
|
+
{task.error && (() => {
|
|
347
|
+
const retryPending =
|
|
348
|
+
task.status !== 'failed' &&
|
|
349
|
+
!task.deadLetteredAt &&
|
|
350
|
+
(task.retryScheduledAt != null || /^Retry scheduled after failure/i.test(task.error))
|
|
351
|
+
return (
|
|
352
|
+
<p className={`mt-2 text-[11px] line-clamp-2 ${retryPending ? 'text-amber-400/80' : 'text-red-400/80'}`}>
|
|
353
|
+
{task.error}
|
|
354
|
+
</p>
|
|
355
|
+
)
|
|
356
|
+
})()}
|
|
349
357
|
|
|
350
358
|
{/* Inline comments — show latest 2 */}
|
|
351
359
|
{task.comments && task.comments.length > 0 && (
|
|
@@ -549,15 +549,26 @@ export function TaskSheet() {
|
|
|
549
549
|
</div>
|
|
550
550
|
)}
|
|
551
551
|
|
|
552
|
-
{/* Error */}
|
|
553
|
-
{editing.error && (
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
552
|
+
{/* Error / Retry notice */}
|
|
553
|
+
{editing.error && (() => {
|
|
554
|
+
const retryPending =
|
|
555
|
+
editing.status !== 'failed' &&
|
|
556
|
+
!editing.deadLetteredAt &&
|
|
557
|
+
(editing.retryScheduledAt != null || /^Retry scheduled after failure/i.test(editing.error))
|
|
558
|
+
const label = retryPending ? 'Retry Pending' : 'Error'
|
|
559
|
+
const tone = retryPending
|
|
560
|
+
? 'border-amber-500/15 bg-amber-500/[0.04] text-amber-300/80'
|
|
561
|
+
: 'border-red-500/10 bg-red-500/[0.03] text-red-400/80'
|
|
562
|
+
const labelTone = retryPending ? 'text-amber-400' : 'text-red-400'
|
|
563
|
+
return (
|
|
564
|
+
<div className="mb-8">
|
|
565
|
+
<label className={`block font-display text-[12px] font-600 uppercase tracking-[0.08em] mb-3 ${labelTone}`}>{label}</label>
|
|
566
|
+
<div className={`p-4 rounded-[14px] border text-[13px] whitespace-pre-wrap ${tone}`}>
|
|
567
|
+
{editing.error}
|
|
568
|
+
</div>
|
|
558
569
|
</div>
|
|
559
|
-
|
|
560
|
-
)}
|
|
570
|
+
)
|
|
571
|
+
})()}
|
|
561
572
|
|
|
562
573
|
{/* Comments (with input — adding comments from view mode is useful) */}
|
|
563
574
|
<div className="mb-8">
|
package/src/lib/provider-sets.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/** CLI providers that use their own tool execution outside the shared tool-runtime path. */
|
|
2
|
-
export const NON_LANGGRAPH_PROVIDER_IDS = new Set(['claude-cli', 'codex-cli', 'opencode-cli', 'gemini-cli', 'copilot-cli', 'cursor-cli', 'qwen-code-cli'])
|
|
2
|
+
export const NON_LANGGRAPH_PROVIDER_IDS = new Set(['claude-cli', 'codex-cli', 'opencode-cli', 'gemini-cli', 'copilot-cli', 'droid-cli', 'cursor-cli', 'qwen-code-cli'])
|
|
3
3
|
|
|
4
4
|
/** Providers that manage their own runtime/tool loop even when reached over an API endpoint. */
|
|
5
5
|
export const RUNTIME_MANAGED_PROVIDER_IDS = new Set(['hermes', 'goose'])
|
|
6
6
|
|
|
7
7
|
/** Providers with native tool/capability support (CLI providers + OpenClaw + Hermes). */
|
|
8
|
-
export const NATIVE_CAPABILITY_PROVIDER_IDS = new Set(['claude-cli', 'codex-cli', 'opencode-cli', 'gemini-cli', 'copilot-cli', 'cursor-cli', 'qwen-code-cli', 'goose', 'openclaw', 'hermes'])
|
|
8
|
+
export const NATIVE_CAPABILITY_PROVIDER_IDS = new Set(['claude-cli', 'codex-cli', 'opencode-cli', 'gemini-cli', 'copilot-cli', 'droid-cli', 'cursor-cli', 'qwen-code-cli', 'goose', 'openclaw', 'hermes'])
|
|
9
9
|
|
|
10
10
|
/** Providers that can only act as workers — no coordinator role, no heartbeat, no advanced settings. */
|
|
11
|
-
export const WORKER_ONLY_PROVIDER_IDS = new Set(['claude-cli', 'codex-cli', 'opencode-cli', 'gemini-cli', 'copilot-cli', 'cursor-cli', 'qwen-code-cli', 'goose', 'openclaw', 'hermes'])
|
|
11
|
+
export const WORKER_ONLY_PROVIDER_IDS = new Set(['claude-cli', 'codex-cli', 'opencode-cli', 'gemini-cli', 'copilot-cli', 'droid-cli', 'cursor-cli', 'qwen-code-cli', 'goose', 'openclaw', 'hermes'])
|
|
@@ -94,6 +94,7 @@ describe('isCliProvider', () => {
|
|
|
94
94
|
assert.equal(isCliProvider('opencode-cli'), true)
|
|
95
95
|
assert.equal(isCliProvider('gemini-cli'), true)
|
|
96
96
|
assert.equal(isCliProvider('copilot-cli'), true)
|
|
97
|
+
assert.equal(isCliProvider('droid-cli'), true)
|
|
97
98
|
assert.equal(isCliProvider('cursor-cli'), true)
|
|
98
99
|
assert.equal(isCliProvider('qwen-code-cli'), true)
|
|
99
100
|
assert.equal(isCliProvider('goose'), true)
|
|
@@ -118,6 +119,7 @@ describe('CLI_PROVIDER_CAPABILITIES', () => {
|
|
|
118
119
|
assert.ok('opencode-cli' in CLI_PROVIDER_CAPABILITIES)
|
|
119
120
|
assert.ok('gemini-cli' in CLI_PROVIDER_CAPABILITIES)
|
|
120
121
|
assert.ok('copilot-cli' in CLI_PROVIDER_CAPABILITIES)
|
|
122
|
+
assert.ok('droid-cli' in CLI_PROVIDER_CAPABILITIES)
|
|
121
123
|
assert.ok('cursor-cli' in CLI_PROVIDER_CAPABILITIES)
|
|
122
124
|
assert.ok('qwen-code-cli' in CLI_PROVIDER_CAPABILITIES)
|
|
123
125
|
assert.ok('goose' in CLI_PROVIDER_CAPABILITIES)
|
|
@@ -45,6 +45,13 @@ const KNOWN_BINARY_PATHS: Record<string, string[]> = {
|
|
|
45
45
|
'/opt/homebrew/bin/copilot',
|
|
46
46
|
path.join(os.homedir(), '.npm-global/bin/copilot'),
|
|
47
47
|
],
|
|
48
|
+
droid: [
|
|
49
|
+
path.join(os.homedir(), '.local/bin/droid'),
|
|
50
|
+
'/usr/local/bin/droid',
|
|
51
|
+
'/opt/homebrew/bin/droid',
|
|
52
|
+
path.join(os.homedir(), '.npm-global/bin/droid'),
|
|
53
|
+
path.join(os.homedir(), '.factory/bin/droid'),
|
|
54
|
+
],
|
|
48
55
|
'cursor-agent': [
|
|
49
56
|
path.join(os.homedir(), '.local/bin/cursor-agent'),
|
|
50
57
|
'/usr/local/bin/cursor-agent',
|
|
@@ -166,7 +173,7 @@ export interface AuthProbeResult {
|
|
|
166
173
|
*/
|
|
167
174
|
export function probeCliAuth(
|
|
168
175
|
binary: string,
|
|
169
|
-
backend: 'claude' | 'codex' | 'opencode' | 'gemini' | 'copilot' | 'cursor' | 'qwen' | 'goose',
|
|
176
|
+
backend: 'claude' | 'codex' | 'opencode' | 'gemini' | 'copilot' | 'droid' | 'cursor' | 'qwen' | 'goose',
|
|
170
177
|
env: NodeJS.ProcessEnv,
|
|
171
178
|
cwd?: string,
|
|
172
179
|
): AuthProbeResult {
|
|
@@ -277,6 +284,25 @@ export function probeCliAuth(
|
|
|
277
284
|
return { authenticated: true }
|
|
278
285
|
}
|
|
279
286
|
|
|
287
|
+
if (backend === 'droid') {
|
|
288
|
+
if (process.env.FACTORY_API_KEY || env.FACTORY_API_KEY) {
|
|
289
|
+
return { authenticated: true }
|
|
290
|
+
}
|
|
291
|
+
const configPaths = [
|
|
292
|
+
path.join(os.homedir(), '.factory', 'config.json'),
|
|
293
|
+
path.join(os.homedir(), '.config', 'factory', 'config.json'),
|
|
294
|
+
path.join(os.homedir(), '.factory', 'auth.json'),
|
|
295
|
+
]
|
|
296
|
+
const hasConfig = configPaths.some((p) => fs.existsSync(p))
|
|
297
|
+
if (!hasConfig) {
|
|
298
|
+
return {
|
|
299
|
+
authenticated: false,
|
|
300
|
+
errorMessage: 'Factory Droid CLI is not authenticated. Run `droid` once to sign in via browser, or set FACTORY_API_KEY and try again.',
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return { authenticated: true }
|
|
304
|
+
}
|
|
305
|
+
|
|
280
306
|
if (backend === 'cursor') {
|
|
281
307
|
try {
|
|
282
308
|
const probe = spawnSync(binary, ['status'], {
|
|
@@ -427,6 +453,7 @@ export const CLI_PROVIDER_CAPABILITIES: Record<string, string> = {
|
|
|
427
453
|
'opencode-cli': 'code analysis, generation across multiple LLM backends',
|
|
428
454
|
'gemini-cli': 'code generation, analysis with Gemini models',
|
|
429
455
|
'copilot-cli': 'code generation, analysis, multi-model support via GitHub Copilot',
|
|
456
|
+
'droid-cli': 'code generation, refactoring, and automation via Factory Droid with configurable autonomy',
|
|
430
457
|
'cursor-cli': 'full-agent coding workflows, multi-file edits, project-aware code changes',
|
|
431
458
|
'qwen-code-cli': 'terminal-native coding workflows, code generation, review, and automation',
|
|
432
459
|
goose: 'agentic coding workflows with extensions, tools, and runtime-managed execution',
|