cowork-os 0.3.71 → 0.3.73
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/CHANGELOG.md +34 -1
- package/README.md +62 -2
- package/dist/daemon/daemon/control-plane-methods.js +8 -8
- package/dist/daemon/electron/agent/browser/browser-service.js +43 -1
- package/dist/daemon/electron/agent/custom-skill-loader.js +78 -5
- package/dist/daemon/electron/agent/daemon.js +52 -2
- package/dist/daemon/electron/agent/executor.js +891 -126
- package/dist/daemon/electron/agent/llm/pricing.js +4 -0
- package/dist/daemon/electron/agent/llm/types.js +4 -4
- package/dist/daemon/electron/agent/search/provider-factory.js +65 -35
- package/dist/daemon/electron/agent/skills/organizer.js +1 -0
- package/dist/daemon/electron/agent/tools/browser-tools.js +6 -4
- package/dist/daemon/electron/agent/tools/cron-tools.js +1 -1
- package/dist/daemon/electron/agent/tools/file-tools.js +35 -8
- package/dist/daemon/electron/agent/tools/glob-tools.js +45 -7
- package/dist/daemon/electron/agent/tools/grep-tools.js +1 -1
- package/dist/daemon/electron/agent/tools/registry.js +77 -6
- package/dist/daemon/electron/agent/tools/search-tools.js +14 -3
- package/dist/daemon/electron/agent/tools/x-browser-scripts.js +426 -0
- package/dist/daemon/electron/agent/tools/x-tools.js +995 -15
- package/dist/daemon/electron/agents/agent-dispatch.js +8 -34
- package/dist/daemon/electron/agents/role-persona.js +221 -0
- package/dist/daemon/electron/control-plane/llm-configure.js +198 -0
- package/dist/daemon/electron/control-plane/protocol.js +1 -0
- package/dist/daemon/electron/control-plane/web-ui.js +174 -3
- package/dist/daemon/electron/database/repositories.js +4 -2
- package/dist/daemon/electron/database/schema.js +8 -7
- package/dist/daemon/electron/gateway/index.js +3 -0
- package/dist/daemon/electron/gateway/router.js +119 -71
- package/dist/daemon/electron/utils/pdf-parser.js +51 -0
- package/dist/daemon/electron/utils/pptx-extractor.js +461 -0
- package/dist/daemon/electron/utils/temp-workspace.js +211 -0
- package/dist/daemon/shared/types.js +9 -1
- package/dist/electron/electron/agent/browser/browser-service.js +43 -1
- package/dist/electron/electron/agent/custom-skill-loader.js +78 -5
- package/dist/electron/electron/agent/daemon.js +52 -2
- package/dist/electron/electron/agent/executor.js +891 -126
- package/dist/electron/electron/agent/llm/pricing.js +4 -0
- package/dist/electron/electron/agent/llm/types.js +4 -4
- package/dist/electron/electron/agent/search/provider-factory.js +65 -35
- package/dist/electron/electron/agent/skills/organizer.js +1 -0
- package/dist/electron/electron/agent/tools/browser-tools.js +6 -4
- package/dist/electron/electron/agent/tools/cron-tools.js +1 -1
- package/dist/electron/electron/agent/tools/file-tools.js +35 -8
- package/dist/electron/electron/agent/tools/glob-tools.js +45 -7
- package/dist/electron/electron/agent/tools/grep-tools.js +1 -1
- package/dist/electron/electron/agent/tools/registry.js +77 -6
- package/dist/electron/electron/agent/tools/search-tools.js +14 -3
- package/dist/electron/electron/agent/tools/x-browser-scripts.js +426 -0
- package/dist/electron/electron/agent/tools/x-tools.js +995 -15
- package/dist/electron/electron/agents/HeartbeatService.js +285 -19
- package/dist/electron/electron/agents/agent-dispatch.js +8 -34
- package/dist/electron/electron/agents/role-persona.js +221 -0
- package/dist/electron/electron/control-plane/handlers.js +18 -12
- package/dist/electron/electron/control-plane/llm-configure.js +198 -0
- package/dist/electron/electron/control-plane/protocol.js +1 -0
- package/dist/electron/electron/control-plane/web-ui.js +174 -3
- package/dist/electron/electron/database/repositories.js +4 -2
- package/dist/electron/electron/database/schema.js +8 -7
- package/dist/electron/electron/gateway/index.js +3 -0
- package/dist/electron/electron/gateway/router.js +119 -71
- package/dist/electron/electron/ipc/handlers.js +198 -75
- package/dist/electron/electron/ipc/image-viewer-ocr.js +93 -0
- package/dist/electron/electron/main.js +81 -18
- package/dist/electron/electron/preload.js +2 -2
- package/dist/electron/electron/tray/TrayManager.js +62 -47
- package/dist/electron/electron/utils/pdf-parser.js +51 -0
- package/dist/electron/electron/utils/pptx-extractor.js +461 -0
- package/dist/electron/electron/utils/temp-workspace.js +211 -0
- package/dist/electron/electron/utils/validation.js +32 -17
- package/dist/electron/shared/types.js +9 -1
- package/dist/renderer/assets/{index-Xvm2AXZV.js → index-DGA4L_Zx.js} +88 -75
- package/dist/renderer/index.html +1 -1
- package/docs/ARCHITECTURE.md +3 -1
- package/docs/node-daemon.md +1 -1
- package/docs/self-hosting.md +1 -1
- package/docs/vps-linux.md +30 -1
- package/node_modules/libsignal/.eslintrc.json +31 -0
- package/node_modules/libsignal/.npmignore +3 -0
- package/node_modules/libsignal/generate-proto.sh +1 -0
- package/node_modules/libsignal/protos/WhisperTextProtocol.proto +28 -0
- package/package.json +6 -5
- package/resources/skills/1password.json +10 -2
- package/resources/skills/add-documentation.json +13 -2
- package/resources/skills/agentic-image-loop.json +9 -1
- package/resources/skills/analyze-csv.json +9 -1
- package/resources/skills/apple-notes.json +10 -2
- package/resources/skills/apple-reminders.json +10 -2
- package/resources/skills/auto-commenter.json +9 -1
- package/resources/skills/bear-notes.json +10 -2
- package/resources/skills/bird.json +23 -5
- package/resources/skills/blogwatcher.json +10 -2
- package/resources/skills/blucli.json +10 -2
- package/resources/skills/bluebubbles.json +10 -2
- package/resources/skills/camsnap.json +10 -2
- package/resources/skills/clean-imports.json +9 -1
- package/resources/skills/code-review.json +13 -2
- package/resources/skills/code-reviewer.json +6 -0
- package/resources/skills/coding-agent.json +10 -2
- package/resources/skills/compare-files.json +9 -1
- package/resources/skills/convert-code.json +9 -1
- package/resources/skills/create-changelog.json +9 -1
- package/resources/skills/debug-error.json +13 -2
- package/resources/skills/dependency-check.json +9 -1
- package/resources/skills/developer-growth-analysis.json +7 -1
- package/resources/skills/discord.json +10 -2
- package/resources/skills/eightctl.json +10 -2
- package/resources/skills/explain-code.json +9 -1
- package/resources/skills/extract-todos.json +9 -1
- package/resources/skills/food-order.json +10 -2
- package/resources/skills/frontend-design.json +7 -1
- package/resources/skills/gemini.json +10 -2
- package/resources/skills/generate-readme.json +13 -2
- package/resources/skills/gifgrep.json +10 -2
- package/resources/skills/git-commit.json +9 -1
- package/resources/skills/github.json +10 -2
- package/resources/skills/gog.json +11 -1
- package/resources/skills/goplaces.json +10 -2
- package/resources/skills/himalaya.json +11 -1
- package/resources/skills/imsg.json +10 -2
- package/resources/skills/karpathy-guidelines.json +9 -1
- package/resources/skills/last30days.json +19 -2
- package/resources/skills/local-places.json +10 -2
- package/resources/skills/local-websearch.json +7 -1
- package/resources/skills/mcporter.json +10 -2
- package/resources/skills/memory-kit.json +9 -1
- package/resources/skills/model-usage.json +10 -2
- package/resources/skills/multi-pr-review.json +7 -1
- package/resources/skills/nano-pdf.json +10 -2
- package/resources/skills/notion.json +10 -2
- package/resources/skills/obsidian.json +10 -2
- package/resources/skills/openai-image-gen.json +11 -3
- package/resources/skills/openai-whisper-api.json +10 -2
- package/resources/skills/openai-whisper.json +10 -2
- package/resources/skills/openhue.json +10 -2
- package/resources/skills/oracle.json +10 -2
- package/resources/skills/ordercli.json +10 -2
- package/resources/skills/peekaboo.json +10 -2
- package/resources/skills/prd.json +7 -1
- package/resources/skills/project-structure.json +9 -1
- package/resources/skills/proofread.json +9 -1
- package/resources/skills/react-native-skills.json +7 -1
- package/resources/skills/refactor-code.json +9 -1
- package/resources/skills/rename-symbol.json +9 -1
- package/resources/skills/sag.json +10 -2
- package/resources/skills/security-audit.json +9 -1
- package/resources/skills/session-logs.json +9 -1
- package/resources/skills/sherpa-onnx-tts.json +10 -2
- package/resources/skills/skill-creator.json +12 -2
- package/resources/skills/skill-hub.json +22 -4
- package/resources/skills/slack.json +10 -2
- package/resources/skills/songsee.json +10 -2
- package/resources/skills/sonoscli.json +10 -2
- package/resources/skills/spotify-player.json +10 -2
- package/resources/skills/startup-cfo.json +9 -1
- package/resources/skills/summarize-folder.json +13 -2
- package/resources/skills/summarize.json +18 -2
- package/resources/skills/supabase-sdk-patterns.json +7 -1
- package/resources/skills/things-mac.json +10 -2
- package/resources/skills/tmux.json +10 -2
- package/resources/skills/translate.json +13 -2
- package/resources/skills/trello.json +10 -2
- package/resources/skills/usecase-booking-options.json +9 -1
- package/resources/skills/usecase-draft-reply.json +21 -3
- package/resources/skills/usecase-family-digest.json +19 -3
- package/resources/skills/usecase-household-capture.json +9 -1
- package/resources/skills/usecase-newsletter-digest.json +17 -3
- package/resources/skills/usecase-transaction-scan.json +14 -2
- package/resources/skills/video-frames.json +10 -2
- package/resources/skills/voice-call.json +9 -1
- package/resources/skills/wacli.json +10 -2
- package/resources/skills/weather.json +10 -2
- package/resources/skills/write-tests.json +13 -2
- package/scripts/qa/validate-skills-routing.mjs +128 -0
- package/src/daemon/control-plane-methods.ts +9 -8
- package/src/electron/agent/__tests__/auto-commenter-skill.test.ts +1 -0
- package/src/electron/agent/__tests__/custom-skill-loader.test.ts +38 -0
- package/src/electron/agent/__tests__/executor-completion-contract.test.ts +201 -0
- package/src/electron/agent/__tests__/executor-step-failures.test.ts +355 -2
- package/src/electron/agent/__tests__/executor-workspace-classification.test.ts +42 -0
- package/src/electron/agent/__tests__/executor-workspace-preflight-ack.test.ts +95 -14
- package/src/electron/agent/__tests__/memory-kit-skill.test.ts +1 -0
- package/src/electron/agent/browser/browser-service.ts +56 -2
- package/src/electron/agent/custom-skill-loader.ts +97 -5
- package/src/electron/agent/daemon.ts +58 -3
- package/src/electron/agent/executor.ts +1022 -133
- package/src/electron/agent/llm/pricing.ts +4 -0
- package/src/electron/agent/llm/types.ts +4 -4
- package/src/electron/agent/search/__tests__/provider-factory.test.ts +150 -0
- package/src/electron/agent/search/provider-factory.ts +79 -38
- package/src/electron/agent/search/types.ts +4 -0
- package/src/electron/agent/skills/organizer.ts +1 -0
- package/src/electron/agent/tools/__tests__/search-tools.test.ts +5 -0
- package/src/electron/agent/tools/__tests__/use-skill.test.ts +19 -0
- package/src/electron/agent/tools/browser-tools.ts +8 -5
- package/src/electron/agent/tools/cron-tools.ts +2 -2
- package/src/electron/agent/tools/file-tools.ts +37 -12
- package/src/electron/agent/tools/glob-tools.ts +63 -9
- package/src/electron/agent/tools/grep-tools.ts +1 -1
- package/src/electron/agent/tools/registry.ts +84 -6
- package/src/electron/agent/tools/search-tools.ts +14 -3
- package/src/electron/agent/tools/x-browser-scripts.ts +445 -0
- package/src/electron/agent/tools/x-tools.ts +1120 -16
- package/src/electron/agents/HeartbeatService.ts +364 -19
- package/src/electron/agents/__tests__/HeartbeatService.test.ts +102 -1
- package/src/electron/agents/__tests__/agent-dispatch.test.ts +48 -0
- package/src/electron/agents/__tests__/role-persona.test.ts +137 -0
- package/src/electron/agents/agent-dispatch.ts +13 -29
- package/src/electron/agents/role-persona.ts +225 -0
- package/src/electron/control-plane/__tests__/protocol-new-methods.test.ts +1 -0
- package/src/electron/control-plane/handlers.ts +21 -13
- package/src/electron/control-plane/llm-configure.ts +234 -0
- package/src/electron/control-plane/protocol.ts +1 -0
- package/src/electron/control-plane/web-ui.ts +174 -3
- package/src/electron/database/repositories.ts +4 -2
- package/src/electron/database/schema.ts +8 -7
- package/src/electron/gateway/index.ts +3 -0
- package/src/electron/gateway/router.ts +132 -80
- package/src/electron/ipc/handlers.ts +284 -96
- package/src/electron/ipc/image-viewer-ocr.ts +113 -0
- package/src/electron/main.ts +83 -19
- package/src/electron/preload.ts +30 -5
- package/src/electron/tray/TrayManager.ts +73 -55
- package/src/electron/utils/__tests__/temp-workspace.test.ts +334 -0
- package/src/electron/utils/__tests__/validation.test.ts +9 -0
- package/src/electron/utils/pdf-parser.ts +88 -0
- package/src/electron/utils/pptx-extractor.ts +486 -0
- package/src/electron/utils/temp-workspace.ts +248 -0
- package/src/electron/utils/validation.ts +37 -17
- package/src/renderer/App.tsx +82 -19
- package/src/renderer/components/ActivityFeed.tsx +2 -2
- package/src/renderer/components/MainContent.tsx +173 -113
- package/src/renderer/components/MissionControlPanel.tsx +16 -13
- package/src/renderer/components/NotificationPanel.tsx +1 -8
- package/src/renderer/components/RightPanel.tsx +2 -2
- package/src/renderer/components/Sidebar.tsx +7 -1
- package/src/renderer/components/TaskTimeline.tsx +12 -6
- package/src/renderer/components/TaskView.tsx +15 -13
- package/src/renderer/components/XSettings.tsx +2 -0
- package/src/renderer/components/utils/attachment-content.ts +97 -0
- package/src/renderer/hooks/useOnboardingFlow.ts +0 -1
- package/src/renderer/utils/agentMessages.ts +1 -1
- package/src/shared/types.ts +36 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.73] - 2026-02-14
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Release pipeline fix**: included daemon TypeScript sources in shared ESLint targets so `npm run lint` runs instead of failing with parse errors before build/publish steps.
|
|
14
|
+
- **Workspace/task validation fix**: enforced `PersonalityId` validation for task agent configs to prevent runtime/inference mismatches during task creation.
|
|
15
|
+
- **CLI and release install tests alignment**: updated control-plane and skill validation tests to match current runtime behaviors and skill metadata output.
|
|
16
|
+
- **Workspace preflight reliability**: stabilized ambiguous temp-task auto-switch behavior when project-signals are present and tests now validate that behavior.
|
|
17
|
+
|
|
18
|
+
## [0.3.72] - 2026-02-14
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **Session workspace isolation and cleanup**: temp tasks now get session-scoped workspace IDs, dedicated temp directories, and automatic pruning by age + usage caps.
|
|
22
|
+
- **Autonomous task mode** in execution flow and control-plane/web-UI paths, with optional bypass of interactive approval prompts where explicitly enabled.
|
|
23
|
+
- **Companion-mode handling for short conversational prompts** to return concise check-in responses without running task pipeline when appropriate.
|
|
24
|
+
- **Search execution ordering** now prefers Brave when available and can safely fallback through configured providers automatically.
|
|
25
|
+
- **PDF parsing compatibility wrapper** with runtime-safe handling for both legacy and v2 parser module shapes.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- **Task completion validation tightened** with final-response contracts (required direct answers, artifact checks, verification evidence).
|
|
29
|
+
- **Stricter tool failure handling** for hard/unavailable/disallowed outcomes to prevent false completion without real progress.
|
|
30
|
+
- **Temporary workspace handling** now uses explicit session-aware IDs and filters temp workspaces from user-visible lists consistently.
|
|
31
|
+
- **Search and file tools** now enforce more bounded scanning behavior and clearer fallback behavior under high-load conditions.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
- **Watch/skip recommendation tasks** now block artifact tools and require direct recommendation output.
|
|
35
|
+
- **Intermittent approval/partial-task updates** reduced by normalizing auto-approved events in UI and task-stream handling.
|
|
36
|
+
- **Temp workspace lifecycle reliability** improved through scheduled pruning and safer restore/create paths.
|
|
37
|
+
|
|
10
38
|
## [0.3.69] - 2026-02-11
|
|
11
39
|
|
|
12
40
|
### Fixed
|
|
@@ -481,6 +509,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
481
509
|
|
|
482
510
|
| Version | Date | Highlights |
|
|
483
511
|
|---------|------|------------|
|
|
512
|
+
| 0.3.73 | 2026-02-14 | Release automation hardening and task/workspace validation fixes |
|
|
513
|
+
| 0.3.72 | 2026-02-14 | Session-based temp workspaces, autonomous execution mode, safer completion validation |
|
|
484
514
|
| 0.3.29 | 2025-02-08 | Multi-provider image generation, visual annotation, local embeddings, verification UX |
|
|
485
515
|
| 0.3.25 | 2025-02-05 | Google Workspace integration, gateway enhancements, agent retry logic |
|
|
486
516
|
| 0.1.6 | 2025-01-25 | Discord bot integration with slash commands |
|
|
@@ -490,7 +520,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
490
520
|
| 0.1.0 | 2025-01-24 | First public release with core features |
|
|
491
521
|
| 0.0.1 | 2025-01-20 | Initial development setup |
|
|
492
522
|
|
|
493
|
-
[Unreleased]: https://github.com/CoWork-OS/CoWork-OS/compare/v0.3.
|
|
523
|
+
[Unreleased]: https://github.com/CoWork-OS/CoWork-OS/compare/v0.3.73...HEAD
|
|
524
|
+
[0.3.73]: https://github.com/CoWork-OS/CoWork-OS/releases/tag/v0.3.73
|
|
525
|
+
[0.3.72]: https://github.com/CoWork-OS/CoWork-OS/releases/tag/v0.3.72
|
|
526
|
+
[0.3.71]: https://github.com/CoWork-OS/CoWork-OS/releases/tag/v0.3.71
|
|
494
527
|
[0.3.29]: https://github.com/CoWork-OS/CoWork-OS/releases/tag/v0.3.29
|
|
495
528
|
[0.3.25]: https://github.com/CoWork-OS/CoWork-OS/releases/tag/v0.3.25
|
|
496
529
|
[0.1.6]: https://github.com/CoWork-OS/CoWork-OS/releases/tag/v0.1.6
|
package/README.md
CHANGED
|
@@ -36,6 +36,13 @@ Your AI needs a secure home. CoWork OS provides the runtime, security layers, an
|
|
|
36
36
|
| **Security-First** | 2800+ unit tests, configurable guardrails, approval workflows, gateway hardening |
|
|
37
37
|
| **Local-First** | Your data stays on your machine. BYOK (Bring Your Own Key) |
|
|
38
38
|
|
|
39
|
+
### What’s new in 0.3.73
|
|
40
|
+
|
|
41
|
+
- **Release and install reliability**: fixed publish-blocking type/lint regressions so npm desktop/client releases can be published reliably.
|
|
42
|
+
- **Task config validation**: stricter `personalityId` validation for task `agentConfig` avoids malformed IDs reaching task execution.
|
|
43
|
+
- **Control-plane/LLM error handling alignment**: tests and runtime error codes now match shared validation shapes for predictable client behavior.
|
|
44
|
+
- **Workspace auto-switch confidence**: improved ambiguous temp-task preflight handling when preferred workspace signals are available.
|
|
45
|
+
|
|
39
46
|
> **Status**: macOS desktop app + headless/server mode (Linux/VPS). Cross-platform desktop support planned.
|
|
40
47
|
|
|
41
48
|
---
|
|
@@ -70,6 +77,16 @@ pkill -f '/cowork-os' || true
|
|
|
70
77
|
npx cowork-os
|
|
71
78
|
```
|
|
72
79
|
|
|
80
|
+
#### Install reliability notes (macOS / low-memory environments)
|
|
81
|
+
|
|
82
|
+
- If install fails with `SIGKILL` during `node_modules/electron/install.js`, use a two-step install:
|
|
83
|
+
- `npm install --ignore-scripts cowork-os@latest --no-audit --no-fund`
|
|
84
|
+
- `npm run setup` (from the install directory) before launching the CLI
|
|
85
|
+
- For local package testing, use the same `--ignore-scripts` flow with the tarball:
|
|
86
|
+
- `npm init -y`
|
|
87
|
+
- `npm install --ignore-scripts /path/to/cowork-os-<version>.tgz`
|
|
88
|
+
- If you already have a global install, verify with `coworkd-node --version` and avoid launching without dependency setup on first run.
|
|
89
|
+
|
|
73
90
|
You can also install globally and launch directly:
|
|
74
91
|
|
|
75
92
|
```bash
|
|
@@ -193,6 +210,7 @@ ssh -N -L 28789:127.0.0.1:18789 user@your-vps
|
|
|
193
210
|
|
|
194
211
|
- `http://127.0.0.1:18789/` (or `http://127.0.0.1:28789/` if you used 28789)
|
|
195
212
|
- Paste the token from step 1
|
|
213
|
+
- If you skipped `OPENAI_API_KEY`/`ANTHROPIC_API_KEY`, use the **LLM Setup** panel in this UI to configure provider credentials.
|
|
196
214
|
|
|
197
215
|
For production/persistent setup and Docker/systemd options, use:
|
|
198
216
|
|
|
@@ -407,7 +425,6 @@ Configure in **Settings** > **Appearance**.
|
|
|
407
425
|
### Agent Capabilities
|
|
408
426
|
|
|
409
427
|
- **Task-Based Workflow**: Multi-step execution with plan-execute-observe loops
|
|
410
|
-
- **Goal Mode**: Define success criteria and auto-retry until verification passes
|
|
411
428
|
- **Dynamic Re-Planning**: Agent can revise its plan mid-execution
|
|
412
429
|
- **85+ Built-in Skills**: GitHub, Slack, Notion, Spotify, Apple Notes, and more
|
|
413
430
|
- **Document Creation**: Excel, Word, PDF, PowerPoint with professional formatting
|
|
@@ -417,10 +434,13 @@ Configure in **Settings** > **Appearance**.
|
|
|
417
434
|
- **Performance Reviews**: Score and review agent-role outcomes, with autonomy-level recommendations
|
|
418
435
|
- **Voice Calls**: Outbound phone calls via ElevenLabs Agents (list agents, list numbers, initiate calls)
|
|
419
436
|
- **Vision**: Analyze workspace images (screenshots, photos, diagrams) via `analyze_image` tool (OpenAI, Anthropic, or Gemini)
|
|
437
|
+
- **X Browser Fallback**: `x_action` automatically falls back to browser-mode read/write flows when Bird CLI is blocked (rate limits, auth challenges, access issues)
|
|
438
|
+
- **Attachment OCR (Optional)**: Extract image text in local file previews with Tesseract (`tesseract` binary must be installed and on `PATH`)
|
|
420
439
|
- **Image Generation**: Create images via `generate_image` with multi-provider support (Gemini, OpenAI gpt-image-1/1.5/DALL-E, Azure OpenAI) and automatic provider selection
|
|
421
440
|
- **Visual Annotation**: Iterative image refinement with the Visual Annotator — generate, annotate, refine, repeat until approved
|
|
422
441
|
- **Email IMAP Access**: Direct IMAP mailbox access via `email_imap_unread` — check unread emails without needing Google Workspace
|
|
423
442
|
- **Workspace Recency**: Workspaces ordered by last used time for quick access
|
|
443
|
+
- **Hook-Triggered Heartbeat Wakeups**: Agents can act on hook-based wake events as explicit check-in prompts
|
|
424
444
|
|
|
425
445
|
### Voice Mode
|
|
426
446
|
|
|
@@ -489,6 +509,40 @@ Notes:
|
|
|
489
509
|
|
|
490
510
|
Configure in **Settings** > **Memory Hub**.
|
|
491
511
|
|
|
512
|
+
### Role Profile Files (`.cowork/agents/`)
|
|
513
|
+
|
|
514
|
+
You can define per-role personality and operating guidelines directly in workspace files.
|
|
515
|
+
When a role runs, CoWork loads these first; if missing, it falls back to legacy role metadata.
|
|
516
|
+
|
|
517
|
+
Expected structure:
|
|
518
|
+
|
|
519
|
+
| File | Purpose |
|
|
520
|
+
|---|---|
|
|
521
|
+
| `.cowork/agents/<role-id>/SOUL.md` | Role personality, behavior style, and execution philosophy |
|
|
522
|
+
| `.cowork/agents/<role-id>/IDENTITY.md` | Role-specific identity and constraints |
|
|
523
|
+
| `.cowork/agents/<role-id>/RULES.md` | Operational rules, safety boundaries, communication defaults |
|
|
524
|
+
|
|
525
|
+
Role resolution checks these folder candidates in order:
|
|
526
|
+
|
|
527
|
+
- `<normalized role.name>` (keeps folder-safe letters, numbers, `_`, `-`, `.`)
|
|
528
|
+
- slugified variant of role name (ASCII-safe fallback)
|
|
529
|
+
- `<normalized role.displayName>` (same normalization)
|
|
530
|
+
- slugified variant of displayName
|
|
531
|
+
- `<normalized role.id>`
|
|
532
|
+
- slugified variant of id
|
|
533
|
+
- `default`
|
|
534
|
+
|
|
535
|
+
Only non-empty `.cowork/agents/...` files are used. If no files are found, CoWork uses existing DB role `soul` notes.
|
|
536
|
+
|
|
537
|
+
Tips:
|
|
538
|
+
|
|
539
|
+
- Start by cloning a profile from an existing role: copy one `*.md` file to a new role folder.
|
|
540
|
+
- Keep templates simple; the first 4k chars per file are injected into prompts.
|
|
541
|
+
- Keep sensitive values out of these files; `.cowork` content is sanitized before use.
|
|
542
|
+
- Quick scaffold:
|
|
543
|
+
- `mkdir -p .cowork/agents/<role-id> && printf '%s\n' "# SOUL.md" "..." > .cowork/agents/<role-id>/SOUL.md`
|
|
544
|
+
- If you are unsure about the folder name, place a `default` profile at `.cowork/agents/default/` and copy it to `.../<role-id>/`.
|
|
545
|
+
|
|
492
546
|
### Agent Teams
|
|
493
547
|
|
|
494
548
|
Coordinate multiple agents working together on complex tasks with shared state.
|
|
@@ -547,6 +601,10 @@ Full Playwright integration:
|
|
|
547
601
|
- Click, fill forms, type text, press keys
|
|
548
602
|
- Extract page content, links, and form data
|
|
549
603
|
- Scroll pages, wait for elements, execute JavaScript
|
|
604
|
+
- Browser automation supports `browser_channel`:
|
|
605
|
+
- `chromium` (default bundled Chromium)
|
|
606
|
+
- `chrome` (system Google Chrome)
|
|
607
|
+
- `brave` (system Brave or a path set in `BRAVE_PATH`)
|
|
550
608
|
|
|
551
609
|
### System Tools
|
|
552
610
|
|
|
@@ -1680,7 +1738,7 @@ Claude Code-style tools for developers.
|
|
|
1680
1738
|
→ grep pattern="TODO:" glob="*.ts"
|
|
1681
1739
|
```
|
|
1682
1740
|
|
|
1683
|
-
**Smart Document Detection**: Automatically detects document-heavy workspaces (PDF/DOCX) and provides helpful guidance to use `read_file` instead, since grep only searches text files.
|
|
1741
|
+
**Smart Document Detection**: Automatically detects document-heavy workspaces (PDF/DOCX/PPTX) and provides helpful guidance to use `read_file` instead, since grep only searches text files.
|
|
1684
1742
|
|
|
1685
1743
|
### edit_file - Surgical Editing
|
|
1686
1744
|
|
|
@@ -2207,6 +2265,7 @@ Users must comply with their model provider's terms:
|
|
|
2207
2265
|
- [x] Chat commands: `/schedule`, `/digest`, `/followups`, `/brief` across all gateway channels
|
|
2208
2266
|
- [x] Inbound attachment persistence (channel messages save files to `.cowork/inbox/attachments/`)
|
|
2209
2267
|
- [x] Cron template variables (`{{today}}`, `{{chat_messages}}`, etc.) and conditional delivery
|
|
2268
|
+
- [x] Brave browser channel support via `browser_navigate` (`browser_channel: "chrome" | "chromium" | "brave"`)
|
|
2210
2269
|
- [x] Image generation via `generate_image` with multi-provider support (Gemini, OpenAI, Azure OpenAI)
|
|
2211
2270
|
- [x] Visual annotation tools and Agentic Image Loop skill for iterative image refinement
|
|
2212
2271
|
- [x] Inline image preview in task event timeline
|
|
@@ -2219,6 +2278,7 @@ Users must comply with their model provider's terms:
|
|
|
2219
2278
|
- [x] Control plane web dashboard, approval API, and channel management API
|
|
2220
2279
|
- [x] Docker and VPS deployment support (Dockerfiles, docker-compose, systemd units)
|
|
2221
2280
|
- [x] Dedicated workspaces for scheduled cron jobs (auto-created from temp workspace)
|
|
2281
|
+
- [x] Hook wake requests for heartbeat processing, including queueing, coalescing, and immediate scheduling
|
|
2222
2282
|
|
|
2223
2283
|
### Planned
|
|
2224
2284
|
|
|
@@ -46,8 +46,8 @@ const protocol_1 = require("../electron/control-plane/protocol");
|
|
|
46
46
|
const settings_1 = require("../electron/control-plane/settings");
|
|
47
47
|
const types_1 = require("../shared/types");
|
|
48
48
|
const repositories_1 = require("../electron/database/repositories");
|
|
49
|
-
const llm_1 = require("../electron/agent/llm");
|
|
50
49
|
const search_1 = require("../electron/agent/search");
|
|
50
|
+
const llm_configure_1 = require("../electron/control-plane/llm-configure");
|
|
51
51
|
const runtime_mode_1 = require("../electron/utils/runtime-mode");
|
|
52
52
|
const user_data_dir_1 = require("../electron/utils/user-data-dir");
|
|
53
53
|
function requireScope(client, scope) {
|
|
@@ -844,6 +844,11 @@ function registerControlPlaneMethods(server, deps) {
|
|
|
844
844
|
await channelGateway.removeChannel(channelId);
|
|
845
845
|
return { ok: true };
|
|
846
846
|
});
|
|
847
|
+
// LLM setup (headless-friendly credential/provider configuration).
|
|
848
|
+
server.registerMethod(protocol_1.Methods.LLM_CONFIGURE, async (client, params) => {
|
|
849
|
+
requireScope(client, 'admin');
|
|
850
|
+
return (0, llm_configure_1.configureLlmFromControlPlaneParams)(params);
|
|
851
|
+
});
|
|
847
852
|
// Config/health (sanitized; no secrets).
|
|
848
853
|
server.registerMethod(protocol_1.Methods.CONFIG_GET, async (client) => {
|
|
849
854
|
requireScope(client, 'read');
|
|
@@ -863,12 +868,7 @@ function registerControlPlaneMethods(server, deps) {
|
|
|
863
868
|
tasksByStatus[status] = safeCount;
|
|
864
869
|
taskTotal += safeCount;
|
|
865
870
|
}
|
|
866
|
-
const
|
|
867
|
-
const llm = {
|
|
868
|
-
currentProvider: llmStatus.currentProvider,
|
|
869
|
-
currentModel: llmStatus.currentModel,
|
|
870
|
-
providers: llmStatus.providers,
|
|
871
|
-
};
|
|
871
|
+
const llm = (0, llm_configure_1.getControlPlaneLlmStatus)();
|
|
872
872
|
const anyLlmConfigured = llm.providers.some((p) => p.configured);
|
|
873
873
|
const currentProviderConfigured = llm.providers.find((p) => p.type === llm.currentProvider)?.configured || false;
|
|
874
874
|
const searchStatus = search_1.SearchProviderFactory.getConfigStatus();
|
|
@@ -896,7 +896,7 @@ function registerControlPlaneMethods(server, deps) {
|
|
|
896
896
|
warnings.push('No workspaces configured. Set COWORK_BOOTSTRAP_WORKSPACE_PATH on startup or create one via workspace.create.');
|
|
897
897
|
}
|
|
898
898
|
if (!anyLlmConfigured) {
|
|
899
|
-
warnings.push('No LLM provider credentials configured.
|
|
899
|
+
warnings.push('No LLM provider credentials configured. Configure one via Control Plane (LLM Setup / llm.configure), or use COWORK_IMPORT_ENV_SETTINGS=1 with provider env vars and restart.');
|
|
900
900
|
}
|
|
901
901
|
else if (!currentProviderConfigured) {
|
|
902
902
|
warnings.push(`Selected LLM provider "${llm.currentProvider}" is not configured. Either switch provider or configure its credentials.`);
|
|
@@ -50,9 +50,42 @@ class BrowserService {
|
|
|
50
50
|
this.options = {
|
|
51
51
|
headless: options.headless ?? true,
|
|
52
52
|
timeout: options.timeout ?? 30000,
|
|
53
|
-
viewport: options.viewport ?? { width: 1280, height: 720 }
|
|
53
|
+
viewport: options.viewport ?? { width: 1280, height: 720 },
|
|
54
|
+
userDataDir: options.userDataDir,
|
|
55
|
+
channel: options.channel,
|
|
54
56
|
};
|
|
55
57
|
}
|
|
58
|
+
async resolveBraveExecutablePath() {
|
|
59
|
+
const envPath = process.env.BRAVE_PATH?.trim();
|
|
60
|
+
const candidates = [
|
|
61
|
+
envPath,
|
|
62
|
+
process.platform === 'darwin'
|
|
63
|
+
? '/Applications/Brave Browser.app/Contents/MacOS/Brave Browser'
|
|
64
|
+
: undefined,
|
|
65
|
+
process.platform === 'linux' ? '/usr/bin/brave-browser' : undefined,
|
|
66
|
+
process.platform === 'linux' ? '/usr/bin/brave-browser-stable' : undefined,
|
|
67
|
+
process.platform === 'linux' ? '/snap/bin/brave' : undefined,
|
|
68
|
+
process.platform === 'win32' && process.env.LOCALAPPDATA
|
|
69
|
+
? path.join(process.env.LOCALAPPDATA, 'BraveSoftware', 'Brave-Browser', 'Application', 'brave.exe')
|
|
70
|
+
: undefined,
|
|
71
|
+
process.platform === 'win32'
|
|
72
|
+
? 'C:\\Program Files\\BraveSoftware\\Brave-Browser\\Application\\brave.exe'
|
|
73
|
+
: undefined,
|
|
74
|
+
process.platform === 'win32'
|
|
75
|
+
? 'C:\\Program Files (x86)\\BraveSoftware\\Brave-Browser\\Application\\brave.exe'
|
|
76
|
+
: undefined,
|
|
77
|
+
].filter((value) => Boolean(value));
|
|
78
|
+
for (const candidate of candidates) {
|
|
79
|
+
try {
|
|
80
|
+
await fs.access(candidate);
|
|
81
|
+
return candidate;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Keep scanning candidates.
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
56
89
|
/**
|
|
57
90
|
* Initialize the browser
|
|
58
91
|
* Uses try-finally to ensure cleanup on errors
|
|
@@ -64,11 +97,19 @@ class BrowserService {
|
|
|
64
97
|
let context = null;
|
|
65
98
|
try {
|
|
66
99
|
const channel = this.options.channel === 'chrome' ? 'chrome' : undefined;
|
|
100
|
+
const executablePath = this.options.channel === 'brave'
|
|
101
|
+
? await this.resolveBraveExecutablePath()
|
|
102
|
+
: undefined;
|
|
103
|
+
if (this.options.channel === 'brave' && !executablePath) {
|
|
104
|
+
throw new Error('Brave browser was requested but no Brave executable was found. ' +
|
|
105
|
+
'Install Brave or set BRAVE_PATH to the Brave binary path.');
|
|
106
|
+
}
|
|
67
107
|
if (this.options.userDataDir) {
|
|
68
108
|
await fs.mkdir(this.options.userDataDir, { recursive: true });
|
|
69
109
|
context = await playwright_1.chromium.launchPersistentContext(this.options.userDataDir, {
|
|
70
110
|
headless: this.options.headless,
|
|
71
111
|
...(channel ? { channel } : {}),
|
|
112
|
+
...(executablePath ? { executablePath } : {}),
|
|
72
113
|
viewport: this.options.viewport,
|
|
73
114
|
});
|
|
74
115
|
browser = context.browser();
|
|
@@ -77,6 +118,7 @@ class BrowserService {
|
|
|
77
118
|
browser = await playwright_1.chromium.launch({
|
|
78
119
|
headless: this.options.headless,
|
|
79
120
|
...(channel ? { channel } : {}),
|
|
121
|
+
...(executablePath ? { executablePath } : {}),
|
|
80
122
|
});
|
|
81
123
|
context = await browser.newContext({
|
|
82
124
|
viewport: this.options.viewport,
|
|
@@ -304,7 +304,8 @@ class CustomSkillLoader {
|
|
|
304
304
|
* List skills that can be automatically invoked by the model
|
|
305
305
|
* Excludes guidelines and skills with disableModelInvocation set
|
|
306
306
|
*/
|
|
307
|
-
listModelInvocableSkills() {
|
|
307
|
+
listModelInvocableSkills(options = {}) {
|
|
308
|
+
const availableToolNames = options.availableToolNames;
|
|
308
309
|
return this.listSkills().filter((skill) => {
|
|
309
310
|
// Exclude guideline skills
|
|
310
311
|
if (skill.type === 'guideline')
|
|
@@ -315,6 +316,22 @@ class CustomSkillLoader {
|
|
|
315
316
|
// Exclude skills that explicitly disable model invocation
|
|
316
317
|
if (skill.invocation?.disableModelInvocation === true)
|
|
317
318
|
return false;
|
|
319
|
+
// If tool availability is provided, filter out skills that cannot run in this context.
|
|
320
|
+
if (availableToolNames) {
|
|
321
|
+
const skillRequires = (skill.requires || {});
|
|
322
|
+
const requiredTools = Array.isArray(skillRequires.tools)
|
|
323
|
+
? skillRequires.tools.filter((tool) => typeof tool === 'string' && tool.trim().length > 0)
|
|
324
|
+
: [];
|
|
325
|
+
if (requiredTools.some((tool) => !availableToolNames.has(tool))) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
// Skills requiring external binaries generally need run_command access.
|
|
329
|
+
const hasBinaryRequirements = (Array.isArray(skill.requires?.bins) && skill.requires.bins.length > 0) ||
|
|
330
|
+
(Array.isArray(skill.requires?.anyBins) && skill.requires.anyBins.length > 0);
|
|
331
|
+
if (hasBinaryRequirements && !availableToolNames.has('run_command')) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
318
335
|
return true;
|
|
319
336
|
});
|
|
320
337
|
}
|
|
@@ -322,8 +339,8 @@ class CustomSkillLoader {
|
|
|
322
339
|
* Get formatted skill descriptions for the model's system prompt
|
|
323
340
|
* Groups skills by category and includes parameter info
|
|
324
341
|
*/
|
|
325
|
-
getSkillDescriptionsForModel() {
|
|
326
|
-
const skills = this.listModelInvocableSkills();
|
|
342
|
+
getSkillDescriptionsForModel(options = {}) {
|
|
343
|
+
const skills = this.listModelInvocableSkills(options);
|
|
327
344
|
if (skills.length === 0) {
|
|
328
345
|
return '';
|
|
329
346
|
}
|
|
@@ -345,10 +362,47 @@ class CustomSkillLoader {
|
|
|
345
362
|
? ` (params: ${skill.parameters.map(p => p.name + (p.required ? '*' : '')).join(', ')})`
|
|
346
363
|
: '';
|
|
347
364
|
lines.push(`- ${skill.id}: ${skill.description}${paramInfo}`);
|
|
365
|
+
const routingHints = this.getSkillRoutingHints(skill);
|
|
366
|
+
for (const hint of routingHints) {
|
|
367
|
+
lines.push(` ${hint}`);
|
|
368
|
+
}
|
|
348
369
|
}
|
|
349
370
|
}
|
|
350
371
|
return lines.join('\n');
|
|
351
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Build compact routing and success hints for model prompt listing.
|
|
375
|
+
* These are intentionally short and should act like decision boundaries.
|
|
376
|
+
*/
|
|
377
|
+
getSkillRoutingHints(skill) {
|
|
378
|
+
const routing = skill.metadata?.routing;
|
|
379
|
+
if (!routing) {
|
|
380
|
+
return [];
|
|
381
|
+
}
|
|
382
|
+
const hints = [];
|
|
383
|
+
if (routing.useWhen) {
|
|
384
|
+
hints.push(`Use when: ${routing.useWhen}`);
|
|
385
|
+
}
|
|
386
|
+
if (routing.dontUseWhen && !this.isLowSignalRoutingHint('dontUseWhen', routing.dontUseWhen)) {
|
|
387
|
+
hints.push(`Don't use when: ${routing.dontUseWhen}`);
|
|
388
|
+
}
|
|
389
|
+
if (routing.outputs && !this.isLowSignalRoutingHint('outputs', routing.outputs)) {
|
|
390
|
+
hints.push(`Outputs: ${routing.outputs}`);
|
|
391
|
+
}
|
|
392
|
+
if (routing.successCriteria && !this.isLowSignalRoutingHint('successCriteria', routing.successCriteria)) {
|
|
393
|
+
hints.push(`Success criteria: ${routing.successCriteria}`);
|
|
394
|
+
}
|
|
395
|
+
if (routing.expectedArtifacts?.length) {
|
|
396
|
+
hints.push(`Artifacts: ${routing.expectedArtifacts.join(', ')}`);
|
|
397
|
+
}
|
|
398
|
+
return hints;
|
|
399
|
+
}
|
|
400
|
+
isLowSignalRoutingHint(kind, value) {
|
|
401
|
+
const normalized = value.trim();
|
|
402
|
+
if (!normalized)
|
|
403
|
+
return true;
|
|
404
|
+
return CustomSkillLoader.LOW_SIGNAL_ROUTING_HINT_PATTERNS[kind].some((pattern) => pattern.test(normalized));
|
|
405
|
+
}
|
|
352
406
|
/**
|
|
353
407
|
* Get a specific skill by ID
|
|
354
408
|
*/
|
|
@@ -358,8 +412,8 @@ class CustomSkillLoader {
|
|
|
358
412
|
/**
|
|
359
413
|
* Expand a skill's prompt template with parameter values
|
|
360
414
|
*/
|
|
361
|
-
expandPrompt(skill, parameterValues) {
|
|
362
|
-
let prompt = this.
|
|
415
|
+
expandPrompt(skill, parameterValues, context = {}) {
|
|
416
|
+
let prompt = this.expandSkillPromptPlaceholders(skill.prompt, skill, context);
|
|
363
417
|
// Replace {{param}} placeholders with values
|
|
364
418
|
if (skill.parameters) {
|
|
365
419
|
for (const param of skill.parameters) {
|
|
@@ -382,6 +436,13 @@ class CustomSkillLoader {
|
|
|
382
436
|
const baseDir = this.resolveBaseDir(skill);
|
|
383
437
|
return prompt.replace(/\{baseDir\}/g, baseDir);
|
|
384
438
|
}
|
|
439
|
+
expandSkillPromptPlaceholders(prompt, skill, context) {
|
|
440
|
+
let output = this.expandBaseDir(prompt, skill);
|
|
441
|
+
if (context.artifactDir) {
|
|
442
|
+
output = output.replace(/\{artifactDir\}/g, context.artifactDir);
|
|
443
|
+
}
|
|
444
|
+
return output;
|
|
445
|
+
}
|
|
385
446
|
resolveBaseDir(skill) {
|
|
386
447
|
const fileDir = skill.filePath ? path.dirname(skill.filePath) : this.bundledSkillsDir;
|
|
387
448
|
const candidates = [
|
|
@@ -580,6 +641,18 @@ class CustomSkillLoader {
|
|
|
580
641
|
}
|
|
581
642
|
}
|
|
582
643
|
exports.CustomSkillLoader = CustomSkillLoader;
|
|
644
|
+
CustomSkillLoader.LOW_SIGNAL_ROUTING_HINT_PATTERNS = {
|
|
645
|
+
dontUseWhen: [
|
|
646
|
+
/planning documents,\s*high-level strategy,\s*or non-executable discussion/i,
|
|
647
|
+
],
|
|
648
|
+
outputs: [
|
|
649
|
+
/^Outcome from .*task-specific result plus concrete action notes\.?$/i,
|
|
650
|
+
],
|
|
651
|
+
successCriteria: [
|
|
652
|
+
/returns concrete actions and decisions matching the requested task/i,
|
|
653
|
+
/no fabricated tool-side behavior/i,
|
|
654
|
+
],
|
|
655
|
+
};
|
|
583
656
|
// Singleton instance
|
|
584
657
|
let instance = null;
|
|
585
658
|
function getCustomSkillLoader(config) {
|
|
@@ -381,6 +381,11 @@ class AgentDaemon extends events_1.EventEmitter {
|
|
|
381
381
|
const parent = this.taskRepo.findById(params.parentTaskId);
|
|
382
382
|
const parentGatewayContext = parent?.agentConfig?.gatewayContext;
|
|
383
383
|
const childGatewayContext = params.agentConfig?.gatewayContext;
|
|
384
|
+
const parentAutonomousMode = parent?.agentConfig?.autonomousMode === true;
|
|
385
|
+
const mergedAutonomousMode = parentAutonomousMode || params.agentConfig?.autonomousMode === true;
|
|
386
|
+
const mergedAllowUserInput = mergedAutonomousMode
|
|
387
|
+
? false
|
|
388
|
+
: params.agentConfig?.allowUserInput ?? parent?.agentConfig?.allowUserInput;
|
|
384
389
|
// Prevent privilege escalation: a child task may not become "more private" than its parent.
|
|
385
390
|
const mergedGatewayContext = (() => {
|
|
386
391
|
const rank = {
|
|
@@ -418,6 +423,12 @@ class AgentDaemon extends events_1.EventEmitter {
|
|
|
418
423
|
if (mergedToolRestrictions) {
|
|
419
424
|
next.toolRestrictions = mergedToolRestrictions;
|
|
420
425
|
}
|
|
426
|
+
if (mergedAutonomousMode !== undefined) {
|
|
427
|
+
next.autonomousMode = mergedAutonomousMode;
|
|
428
|
+
}
|
|
429
|
+
if (mergedAllowUserInput !== undefined) {
|
|
430
|
+
next.allowUserInput = mergedAllowUserInput;
|
|
431
|
+
}
|
|
421
432
|
return Object.keys(next).length > 0 ? next : undefined;
|
|
422
433
|
})();
|
|
423
434
|
const task = this.taskRepo.create({
|
|
@@ -520,7 +531,15 @@ class AgentDaemon extends events_1.EventEmitter {
|
|
|
520
531
|
return;
|
|
521
532
|
const planSummary = this.buildPlanSummary(plan);
|
|
522
533
|
for (const role of rolesToDispatch) {
|
|
523
|
-
const
|
|
534
|
+
const workspacePath = task.workspaceId
|
|
535
|
+
? this.workspaceRepo.findById(task.workspaceId)?.path
|
|
536
|
+
: undefined;
|
|
537
|
+
const childPrompt = (0, agent_dispatch_1.buildAgentDispatchPrompt)(role, { title: task.title, prompt: task.prompt }, {
|
|
538
|
+
...(planSummary ? { planSummary } : {}),
|
|
539
|
+
includeRoleDetails: false,
|
|
540
|
+
includeRoleProfile: true,
|
|
541
|
+
workspacePath,
|
|
542
|
+
});
|
|
524
543
|
const childTask = await this.createChildTask({
|
|
525
544
|
title: `@${role.displayName}: ${task.title}`,
|
|
526
545
|
prompt: childPrompt,
|
|
@@ -714,6 +733,27 @@ class AgentDaemon extends events_1.EventEmitter {
|
|
|
714
733
|
* Request approval from user for an action
|
|
715
734
|
*/
|
|
716
735
|
async requestApproval(taskId, type, description, details) {
|
|
736
|
+
const task = this.taskRepo.findById(taskId);
|
|
737
|
+
if (task?.agentConfig?.autonomousMode) {
|
|
738
|
+
const approval = this.approvalRepo.create({
|
|
739
|
+
taskId,
|
|
740
|
+
type: type,
|
|
741
|
+
description,
|
|
742
|
+
details,
|
|
743
|
+
status: 'approved',
|
|
744
|
+
requestedAt: Date.now(),
|
|
745
|
+
});
|
|
746
|
+
this.approvalRepo.update(approval.id, 'approved');
|
|
747
|
+
this.logEvent(taskId, 'approval_requested', {
|
|
748
|
+
approval,
|
|
749
|
+
autoApproved: true,
|
|
750
|
+
});
|
|
751
|
+
this.logEvent(taskId, 'approval_granted', {
|
|
752
|
+
approvalId: approval.id,
|
|
753
|
+
autoApproved: true,
|
|
754
|
+
});
|
|
755
|
+
return true;
|
|
756
|
+
}
|
|
717
757
|
const approval = this.approvalRepo.create({
|
|
718
758
|
taskId,
|
|
719
759
|
type: type,
|
|
@@ -1643,6 +1683,16 @@ class AgentDaemon extends events_1.EventEmitter {
|
|
|
1643
1683
|
getWorkspaceByPath(path) {
|
|
1644
1684
|
return this.workspaceRepo.findByPath(path);
|
|
1645
1685
|
}
|
|
1686
|
+
/**
|
|
1687
|
+
* Get the most recently used non-temporary workspace, if any.
|
|
1688
|
+
*/
|
|
1689
|
+
getMostRecentNonTempWorkspace() {
|
|
1690
|
+
const workspaces = this.workspaceRepo.findAll();
|
|
1691
|
+
return workspaces.find((workspace) => !(0, types_1.isTempWorkspaceId)(workspace.id) &&
|
|
1692
|
+
!workspace.isTemp &&
|
|
1693
|
+
typeof workspace.path === 'string' &&
|
|
1694
|
+
workspace.path.trim().length > 0);
|
|
1695
|
+
}
|
|
1646
1696
|
/**
|
|
1647
1697
|
* Create a new workspace with default permissions
|
|
1648
1698
|
*/
|
|
@@ -1657,7 +1707,7 @@ class AgentDaemon extends events_1.EventEmitter {
|
|
|
1657
1707
|
return this.workspaceRepo.create(name, path, defaultPermissions);
|
|
1658
1708
|
}
|
|
1659
1709
|
/**
|
|
1660
|
-
* Update task fields (for
|
|
1710
|
+
* Update task fields (for retry/verification attempt tracking, etc.)
|
|
1661
1711
|
*/
|
|
1662
1712
|
updateTask(taskId, updates) {
|
|
1663
1713
|
const existing = this.taskRepo.findById(taskId);
|