@mrpatronz/nexusflow 1.7.0 → 1.9.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 +57 -23
- package/dist/agent/AntigravityCliAdapter.d.ts +7 -0
- package/dist/agent/AntigravityCliAdapter.d.ts.map +1 -0
- package/dist/agent/AntigravityCliAdapter.js +13 -0
- package/dist/agent/AntigravityCliAdapter.js.map +1 -0
- package/dist/agent/ClaudeCliAdapter.d.ts +16 -0
- package/dist/agent/ClaudeCliAdapter.d.ts.map +1 -0
- package/dist/agent/ClaudeCliAdapter.js +34 -0
- package/dist/agent/ClaudeCliAdapter.js.map +1 -0
- package/dist/agent/CliAdapterBase.d.ts +48 -0
- package/dist/agent/CliAdapterBase.d.ts.map +1 -0
- package/dist/agent/CliAdapterBase.js +120 -0
- package/dist/agent/CliAdapterBase.js.map +1 -0
- package/dist/agent/NativeAgent.d.ts +13 -0
- package/dist/agent/NativeAgent.d.ts.map +1 -0
- package/dist/agent/NativeAgent.js +97 -0
- package/dist/agent/NativeAgent.js.map +1 -0
- package/dist/agent/NativeAgentBase.d.ts +27 -0
- package/dist/agent/NativeAgentBase.d.ts.map +1 -0
- package/dist/agent/NativeAgentBase.js +58 -0
- package/dist/agent/NativeAgentBase.js.map +1 -0
- package/dist/agent/NativeClaudeAgent.d.ts +13 -0
- package/dist/agent/NativeClaudeAgent.d.ts.map +1 -0
- package/dist/agent/NativeClaudeAgent.js +115 -0
- package/dist/agent/NativeClaudeAgent.js.map +1 -0
- package/dist/agent/NativeGoogleAgent.d.ts +13 -0
- package/dist/agent/NativeGoogleAgent.d.ts.map +1 -0
- package/dist/agent/NativeGoogleAgent.js +90 -0
- package/dist/agent/NativeGoogleAgent.js.map +1 -0
- package/dist/agent/ProviderRegistry.d.ts +31 -0
- package/dist/agent/ProviderRegistry.d.ts.map +1 -0
- package/dist/agent/ProviderRegistry.js +20 -0
- package/dist/agent/ProviderRegistry.js.map +1 -0
- package/dist/agent/ProviderRegistry.test.d.ts +2 -0
- package/dist/agent/ProviderRegistry.test.d.ts.map +1 -0
- package/dist/agent/ProviderRegistry.test.js +57 -0
- package/dist/agent/ProviderRegistry.test.js.map +1 -0
- package/dist/agent/adapters.d.ts +3 -0
- package/dist/agent/adapters.d.ts.map +1 -0
- package/dist/agent/adapters.js +48 -0
- package/dist/agent/adapters.js.map +1 -0
- package/dist/agent/nativeAgent.test.d.ts +2 -0
- package/dist/agent/nativeAgent.test.d.ts.map +1 -0
- package/dist/agent/nativeAgent.test.js +35 -0
- package/dist/agent/nativeAgent.test.js.map +1 -0
- package/dist/agent/nativeTools.d.ts +26 -0
- package/dist/agent/nativeTools.d.ts.map +1 -0
- package/dist/agent/nativeTools.js +62 -0
- package/dist/agent/nativeTools.js.map +1 -0
- package/dist/agent/nativeTools.test.d.ts +2 -0
- package/dist/agent/nativeTools.test.d.ts.map +1 -0
- package/dist/agent/nativeTools.test.js +67 -0
- package/dist/agent/nativeTools.test.js.map +1 -0
- package/dist/agent/session.d.ts +25 -0
- package/dist/agent/session.d.ts.map +1 -0
- package/dist/agent/session.js +31 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/agent/session.test.d.ts +2 -0
- package/dist/agent/session.test.d.ts.map +1 -0
- package/dist/agent/session.test.js +44 -0
- package/dist/agent/session.test.js.map +1 -0
- package/dist/commands/create.d.ts +8 -7
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +134 -65
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/desktop.d.ts +4 -5
- package/dist/commands/desktop.d.ts.map +1 -1
- package/dist/commands/desktop.js +35 -89
- package/dist/commands/desktop.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +0 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -72
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +2 -1
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/project.d.ts +30 -0
- package/dist/commands/project.d.ts.map +1 -0
- package/dist/commands/project.js +125 -0
- package/dist/commands/project.js.map +1 -0
- package/dist/commands/refresh.js +1 -1
- package/dist/commands/refresh.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +18 -2
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/stop.d.ts +1 -1
- package/dist/commands/stop.d.ts.map +1 -1
- package/dist/commands/stop.js +19 -2
- package/dist/commands/stop.js.map +1 -1
- package/dist/commands/tui.js +0 -1
- package/dist/commands/tui.js.map +1 -1
- package/dist/commands/ui.d.ts +7 -3
- package/dist/commands/ui.d.ts.map +1 -1
- package/dist/commands/ui.js +12 -6
- package/dist/commands/ui.js.map +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +0 -9
- package/dist/core/config.js.map +1 -1
- package/dist/core/config.test.js +0 -9
- package/dist/core/config.test.js.map +1 -1
- package/dist/core/doctor.d.ts +1 -3
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +18 -69
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/finish.d.ts.map +1 -1
- package/dist/core/finish.js +5 -0
- package/dist/core/finish.js.map +1 -1
- package/dist/core/graph.d.ts.map +1 -1
- package/dist/core/graph.js +2 -1
- package/dist/core/graph.js.map +1 -1
- package/dist/core/projects.d.ts +58 -0
- package/dist/core/projects.d.ts.map +1 -0
- package/dist/core/projects.js +190 -0
- package/dist/core/projects.js.map +1 -0
- package/dist/core/projects.test.d.ts +2 -0
- package/dist/core/projects.test.d.ts.map +1 -0
- package/dist/core/projects.test.js +165 -0
- package/dist/core/projects.test.js.map +1 -0
- package/dist/core/sync.d.ts.map +1 -1
- package/dist/core/sync.js +21 -0
- package/dist/core/sync.js.map +1 -1
- package/dist/core/sync.test.js +15 -0
- package/dist/core/sync.test.js.map +1 -1
- package/dist/core/workspace.create.test.js +68 -1
- package/dist/core/workspace.create.test.js.map +1 -1
- package/dist/core/workspace.d.ts +4 -3
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +138 -64
- package/dist/core/workspace.js.map +1 -1
- package/dist/desktop-server.d.ts +13 -0
- package/dist/desktop-server.d.ts.map +1 -0
- package/dist/desktop-server.js +23 -0
- package/dist/desktop-server.js.map +1 -0
- package/dist/generators/antigravity.js +1 -1
- package/dist/generators/antigravity.js.map +1 -1
- package/dist/generators/base.d.ts +1 -8
- package/dist/generators/base.d.ts.map +1 -1
- package/dist/generators/base.js +107 -58
- package/dist/generators/base.js.map +1 -1
- package/dist/generators/base.test.d.ts +2 -0
- package/dist/generators/base.test.d.ts.map +1 -0
- package/dist/generators/base.test.js +80 -0
- package/dist/generators/base.test.js.map +1 -0
- package/dist/generators/claude.js +1 -1
- package/dist/generators/claude.js.map +1 -1
- package/dist/generators/codex.js +1 -1
- package/dist/generators/codex.js.map +1 -1
- package/dist/generators/copilot.js +1 -1
- package/dist/generators/copilot.js.map +1 -1
- package/dist/generators/cursor.js +1 -1
- package/dist/generators/cursor.js.map +1 -1
- package/dist/generators/diff-context.d.ts.map +1 -1
- package/dist/generators/diff-context.js +3 -1
- package/dist/generators/diff-context.js.map +1 -1
- package/dist/generators/index.js +1 -1
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/map-generator.d.ts.map +1 -1
- package/dist/generators/map-generator.js +3 -1
- package/dist/generators/map-generator.js.map +1 -1
- package/dist/gui/assets/DashboardPage-C3NH97y2.js +1 -0
- package/dist/gui/assets/GettingStartedPage-og-Kv7Sm.js +1 -0
- package/dist/gui/assets/ProjectsPage-COqqadEr.js +1 -0
- package/dist/gui/assets/ScaffoldRepoInline-DRipQsos.js +1 -0
- package/dist/gui/assets/Separator-Chx6O62Y.js +1 -0
- package/dist/gui/assets/SettingsPage-CpU3V9oU.js +1 -0
- package/dist/gui/assets/StartWorkPage-DIND0hJy.js +1 -0
- package/dist/gui/assets/StrategiesPage-6LWOnKdk.js +3 -0
- package/dist/gui/assets/WorkspacesPage-BUqgOhuy.js +6 -0
- package/dist/gui/assets/badge-BnkhqVEF.js +1 -0
- package/dist/gui/assets/button-cPldH5S4.js +1 -0
- package/dist/gui/assets/card-82INhRRE.js +1 -0
- package/dist/gui/assets/circle-plus-C0PNc7h4.js +1 -0
- package/dist/gui/assets/cpu-CPUNnHRM.js +1 -0
- package/dist/gui/assets/empty-DWyDwDYB.js +1 -0
- package/dist/gui/assets/external-link-BtYhMxno.js +1 -0
- package/dist/gui/assets/git-branch-Dw55pQWa.js +1 -0
- package/dist/gui/assets/index-CsA2SueF.css +2 -0
- package/dist/gui/assets/index-CyYbQwRf.js +52 -0
- package/dist/gui/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/gui/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/gui/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/gui/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/gui/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/gui/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/gui/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-100-normal-DlYB2XW3.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-100-normal-DzH8uRxw.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-200-normal-CHn02WOn.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-200-normal-DvzYDkvL.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-300-normal-BYcAiAh2.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-300-normal-DuMDZskh.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-600-normal-BfsvjouI.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-800-normal-D2mQHRMK.woff2 +0 -0
- package/dist/gui/assets/jetbrains-mono-latin-800-normal-Dj9qwObk.woff +0 -0
- package/dist/gui/assets/label-JFgMNsTn.js +1 -0
- package/dist/gui/assets/search-ChVovkOL.js +1 -0
- package/dist/gui/assets/skeleton-CCPbfn1L.js +1 -0
- package/dist/gui/assets/spinner-DXt6mnJk.js +1 -0
- package/dist/gui/assets/textarea-BLU5HXmZ.js +1 -0
- package/dist/gui/assets/trash-2-Da8F2gKd.js +1 -0
- package/dist/gui/assets/useAriaLabelledBy-CjNlctb9.js +1 -0
- package/dist/gui/assets/useCompositeListItem-DWGFLKqA.js +1 -0
- package/dist/gui/index.html +16 -6
- package/dist/index.js +56 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +4 -63
- package/dist/mcp/tools.js.map +1 -1
- package/dist/orchestration/detect.d.ts.map +1 -1
- package/dist/orchestration/detect.js +72 -26
- package/dist/orchestration/detect.js.map +1 -1
- package/dist/orchestration/index.d.ts +3 -1
- package/dist/orchestration/index.d.ts.map +1 -1
- package/dist/orchestration/index.js +3 -1
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/log-tail.d.ts +27 -0
- package/dist/orchestration/log-tail.d.ts.map +1 -0
- package/dist/orchestration/log-tail.js +93 -0
- package/dist/orchestration/log-tail.js.map +1 -0
- package/dist/orchestration/log-tail.test.d.ts +2 -0
- package/dist/orchestration/log-tail.test.d.ts.map +1 -0
- package/dist/orchestration/log-tail.test.js +72 -0
- package/dist/orchestration/log-tail.test.js.map +1 -0
- package/dist/orchestration/orchestrator.d.ts +26 -0
- package/dist/orchestration/orchestrator.d.ts.map +1 -0
- package/dist/orchestration/orchestrator.js +102 -0
- package/dist/orchestration/orchestrator.js.map +1 -0
- package/dist/orchestration/orchestrator.test.d.ts +2 -0
- package/dist/orchestration/orchestrator.test.d.ts.map +1 -0
- package/dist/orchestration/orchestrator.test.js +85 -0
- package/dist/orchestration/orchestrator.test.js.map +1 -0
- package/dist/orchestration/runner.d.ts +62 -3
- package/dist/orchestration/runner.d.ts.map +1 -1
- package/dist/orchestration/runner.js +198 -103
- package/dist/orchestration/runner.js.map +1 -1
- package/dist/orchestration/runner.test.js +125 -1
- package/dist/orchestration/runner.test.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +395 -126
- package/dist/server.js.map +1 -1
- package/dist/server.test.js +111 -123
- package/dist/server.test.js.map +1 -1
- package/dist/types.d.ts +79 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/feature.d.ts +42 -0
- package/dist/utils/feature.d.ts.map +1 -0
- package/dist/utils/feature.js +52 -0
- package/dist/utils/feature.js.map +1 -0
- package/dist/utils/multi-git.d.ts.map +1 -1
- package/dist/utils/multi-git.js +30 -7
- package/dist/utils/multi-git.js.map +1 -1
- package/dist/utils/session-finder.d.ts +21 -1
- package/dist/utils/session-finder.d.ts.map +1 -1
- package/dist/utils/session-finder.js +220 -143
- package/dist/utils/session-finder.js.map +1 -1
- package/dist/utils/session-finder.test.d.ts +2 -0
- package/dist/utils/session-finder.test.d.ts.map +1 -0
- package/dist/utils/session-finder.test.js +65 -0
- package/dist/utils/session-finder.test.js.map +1 -0
- package/dist/utils/slug.d.ts +12 -0
- package/dist/utils/slug.d.ts.map +1 -0
- package/dist/utils/slug.js +18 -0
- package/dist/utils/slug.js.map +1 -0
- package/dist/utils/test-command.d.ts +12 -0
- package/dist/utils/test-command.d.ts.map +1 -0
- package/dist/utils/test-command.js +22 -0
- package/dist/utils/test-command.js.map +1 -0
- package/dist/utils/update-check.d.ts +8 -0
- package/dist/utils/update-check.d.ts.map +1 -1
- package/dist/utils/update-check.js +13 -7
- package/dist/utils/update-check.js.map +1 -1
- package/dist/utils/update-check.test.d.ts +2 -0
- package/dist/utils/update-check.test.d.ts.map +1 -0
- package/dist/utils/update-check.test.js +25 -0
- package/dist/utils/update-check.test.js.map +1 -0
- package/dist/utils/workflow-advisor.d.ts +2 -2
- package/dist/utils/workflow-advisor.d.ts.map +1 -1
- package/dist/utils/workflow-advisor.js +50 -92
- package/dist/utils/workflow-advisor.js.map +1 -1
- package/dist/utils/workflows.d.ts.map +1 -1
- package/dist/utils/workflows.js +2 -4
- package/dist/utils/workflows.js.map +1 -1
- package/package.json +10 -1
- package/dist/gui/assets/index-CB-Ekvrs.css +0 -1
- package/dist/gui/assets/index-CixLsYSa.js +0 -26
- package/dist/utils/local-ai.d.ts +0 -27
- package/dist/utils/local-ai.d.ts.map +0 -1
- package/dist/utils/local-ai.js +0 -100
- package/dist/utils/local-ai.js.map +0 -1
- package/dist/utils/local-ai.test.d.ts +0 -2
- package/dist/utils/local-ai.test.d.ts.map +0 -1
- package/dist/utils/local-ai.test.js +0 -108
- package/dist/utils/local-ai.test.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,13 +10,14 @@
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
NexusFlow combines multiple Git repositories into a single feature workspace and generates the context files that your AI coding assistant needs to understand all of them at once. It
|
|
13
|
+
NexusFlow combines multiple Git repositories into a single feature workspace and generates the context files that your AI coding assistant needs to understand all of them at once. It can create isolated **git worktrees** on clean feature branches, or work in-place directly in your source repositories when you want to manage branches yourself.
|
|
14
14
|
|
|
15
15
|
> **New to NexusFlow?** Jump to the [Getting Started Guide](GETTING_STARTED.md) for a hands-on walkthrough.
|
|
16
16
|
|
|
17
17
|
## ✨ Features
|
|
18
18
|
|
|
19
|
-
- **Multi-repo workspaces** — group any set of local Git repos
|
|
19
|
+
- **Multi-repo workspaces** — group any set of local Git repos in isolated worktrees or in-place source repositories
|
|
20
|
+
- **Project registry** — save named, persistent repo groups in `~/.nexusflow/projects.json` and reuse them from the CLI or API
|
|
20
21
|
- **The full feature loop** — `create` opens a workspace, `finish` closes it: commit + push every repo, open PRs (or print compare links), promote learnings, and optionally clean up
|
|
21
22
|
- **Knowledge that accumulates** — capture decisions and gotchas as you work with `nexusflow knowledge add`, then `promote` the reusable ones into per-repo memory that survives across features
|
|
22
23
|
- **AI context generation** — automatically writes `CLAUDE.md`, `AGENTS.md`, `.github/copilot-instructions.md`, and `.cursor/rules/nexusflow.mdc`
|
|
@@ -76,20 +77,49 @@ nexusflow init
|
|
|
76
77
|
# 2 — Create a feature workspace
|
|
77
78
|
nexusflow create
|
|
78
79
|
|
|
79
|
-
# 3 — Or
|
|
80
|
-
nexusflow
|
|
80
|
+
# 3 — Or use the GUI: desktop app (see desktop/) or browser dashboard
|
|
81
|
+
nexusflow dashboard
|
|
81
82
|
```
|
|
82
83
|
|
|
83
84
|
The `create` wizard walks you through:
|
|
84
85
|
|
|
85
|
-
1. **
|
|
86
|
-
2. **
|
|
87
|
-
3. **
|
|
88
|
-
4. **
|
|
89
|
-
5. **
|
|
86
|
+
1. **Choose a repo source** — start from a registered project or scan/pick ad-hoc repos
|
|
87
|
+
2. **Choose a work mode** — isolated worktrees or in-place source repositories
|
|
88
|
+
3. **Name the branch or workspace** — branch name for worktrees, workspace name for in-place
|
|
89
|
+
4. **Describe what you're building** — plain text or a path to a `.md` file
|
|
90
|
+
5. **Choose AI assistant(s)** — auto-detects what's installed
|
|
91
|
+
6. **Done!** — workspace created with AI context files, plus git worktrees in isolated mode
|
|
92
|
+
|
|
93
|
+
## 📚 Projects
|
|
94
|
+
|
|
95
|
+
A project is a named, persistent group of source repositories stored centrally in `~/.nexusflow/projects.json`. Project ids are slugified from the name, so `Hogia Billing` becomes `hogia-billing`. Use either the `project` command group or its `proj` alias:
|
|
96
|
+
|
|
97
|
+
| Command | Description |
|
|
98
|
+
|:---|:---|
|
|
99
|
+
| `nexusflow project add -n, --name <name> -r, --repos <paths...> [-d, --description <text>]` | Register a project; omit `--repos` to use the interactive repo picker |
|
|
100
|
+
| `nexusflow project list` | List registered projects (alias: `ls`) |
|
|
101
|
+
| `nexusflow project show [id]` | Show a registered project |
|
|
102
|
+
| `nexusflow project remove [id] [-y, --yes]` | Remove a project from the registry (alias: `rm`) |
|
|
103
|
+
|
|
104
|
+
Removing a project only edits the registry — it never deletes repositories or workspaces on disk. The HTTP API exposes the same registry through `GET /api/projects`, `POST /api/projects`, `PUT /api/projects/:id`, and `DELETE /api/projects/:id`.
|
|
105
|
+
|
|
106
|
+
## 🧭 Work Modes
|
|
107
|
+
|
|
108
|
+
`nexusflow create` offers registered projects first (ad-hoc repo scanning is still available), then asks how the workspace should work:
|
|
109
|
+
|
|
110
|
+
| Mode | What it does |
|
|
111
|
+
|:---|:---|
|
|
112
|
+
| **Isolated worktrees** | The classic flow: NexusFlow creates a feature branch and git worktree per repo inside the workspace directory. |
|
|
113
|
+
| **In-place** | NexusFlow works directly in the source repositories. No branches or worktrees are created; you provide a workspace name, and the workspace directory only holds `nexusflow.json` plus generated AI context files. |
|
|
114
|
+
|
|
115
|
+
In in-place workspaces, `nexusflow sync` is a deliberate no-op because you manage branches yourself. `nexusflow finish` commits and pushes each repo's current branch, and only offers PR/compare links when that branch differs from the default branch. Deleting an in-place workspace never touches the source repositories, `nexusflow list` tags it with `[in-place]`, and agent sessions for single-repo in-place workspaces run in the repo root.
|
|
116
|
+
|
|
117
|
+
For API callers, `POST /api/workspace` accepts optional `mode` (`worktree` default, or `in-place`), `name` (required for in-place), and `projectId`. Existing workspace manifests without a `mode` field are treated as `worktree` mode.
|
|
90
118
|
|
|
91
119
|
## 📂 What Gets Generated
|
|
92
120
|
|
|
121
|
+
In isolated worktree mode:
|
|
122
|
+
|
|
93
123
|
```
|
|
94
124
|
~/dev/workspaces/feature/user-auth/
|
|
95
125
|
├── CLAUDE.md # Context for Claude / Antigravity
|
|
@@ -104,29 +134,33 @@ The `create` wizard walks you through:
|
|
|
104
134
|
└── my-frontend/ # ← Git worktree on feature branch
|
|
105
135
|
```
|
|
106
136
|
|
|
137
|
+
In-place workspaces keep the manifest and generated AI context files in the workspace directory while the code stays in the source repositories.
|
|
138
|
+
|
|
107
139
|
Open this folder in your editor → your AI assistant picks up the context → it understands *all* your repos.
|
|
108
140
|
|
|
109
141
|
## 🖥️ Commands
|
|
110
142
|
|
|
111
143
|
| Command | Description |
|
|
112
144
|
|:---|:---|
|
|
113
|
-
| `nexusflow create` | Interactive wizard to create a new
|
|
114
|
-
| `nexusflow list` | List all existing workspaces (alias: `ls`) |
|
|
145
|
+
| `nexusflow create` | Interactive wizard to create a new worktree or in-place workspace |
|
|
146
|
+
| `nexusflow list` | List all existing workspaces, tagging in-place ones with `[in-place]` (alias: `ls`) |
|
|
115
147
|
| `nexusflow open` | Re-open a workspace in your editor |
|
|
116
148
|
| `nexusflow init` | Configure NexusFlow settings |
|
|
149
|
+
| `nexusflow project` | Manage registered repo groups: `add`, `list`/`ls`, `show`, `remove`/`rm` (alias: `proj`) |
|
|
117
150
|
| `nexusflow add-repo` | Add a repository to an existing workspace (alias: `add`) |
|
|
118
|
-
| `nexusflow remove` | Delete a workspace and prune its git worktrees (alias: `rm`) |
|
|
151
|
+
| `nexusflow remove` | Delete a workspace and prune its git worktrees when present (alias: `rm`) |
|
|
119
152
|
| `nexusflow start` | Start all services in a workspace (auto-detected) |
|
|
120
153
|
| `nexusflow stop` | Stop all running services |
|
|
121
154
|
| `nexusflow status` | Show running/stopped status and PIDs |
|
|
122
155
|
| `nexusflow logs` | Tail aggregated logs from all services |
|
|
123
|
-
| `nexusflow ui` |
|
|
124
|
-
| `nexusflow dashboard` |
|
|
156
|
+
| `nexusflow ui` | Start the dashboard server — the backend the desktop app embeds (`--port`, `--open`, `--strict-port`) |
|
|
157
|
+
| `nexusflow dashboard` | Open the dashboard in your browser (alias: `dash`) |
|
|
125
158
|
| `nexusflow tui` | Open the interactive terminal (TUI) dashboard |
|
|
126
159
|
| `nexusflow diff` | View changes across all sub-repositories, including unpushed commits (`--repo` to filter) |
|
|
127
160
|
| `nexusflow commit` | Commit and push changes across all modified repositories (`--repo`, `--no-push`, `--dry-run`) |
|
|
128
|
-
| `nexusflow sync` | Rebase
|
|
161
|
+
| `nexusflow sync` | Rebase worktree-mode repositories with default base branches; deliberate no-op for in-place workspaces |
|
|
129
162
|
| `nexusflow finish` | Close out a feature: commit & push all repos, open PRs / print compare links, promote learnings, optionally remove the workspace (`-m`, `--no-pr`, `--no-knowledge`, `--cleanup`, `--dry-run`) |
|
|
163
|
+
| `nexusflow review` | Start an iterative reviewer-implementer agent loop with automated verification harnesses |
|
|
130
164
|
| `nexusflow knowledge` | Capture & manage workspace learnings: `add` (decision/gotcha/progress/…), `show`, `promote` into per-repo base knowledge |
|
|
131
165
|
| `nexusflow refresh`| Regenerate maps, plan, and AI context files — only re-analyzes changed repos (`--force` for a full pass) |
|
|
132
166
|
| `nexusflow handoff` | Generate a compact handoff bundle (`nexusflow-handoff.md`) for session resumption |
|
|
@@ -135,7 +169,7 @@ Open this folder in your editor → your AI assistant picks up the context → i
|
|
|
135
169
|
| `nexusflow config` | View and update configuration: `show`, `get <key>`, `set <key> <value>` |
|
|
136
170
|
| `nexusflow adapter` | Manage storage adapters: `list`, `use`, `info`, `init` |
|
|
137
171
|
| `nexusflow mcp` | Manage the MCP server for AI assistants: `run`, `setup` |
|
|
138
|
-
| `nexusflow desktop` | Launch the
|
|
172
|
+
| `nexusflow desktop` | Launch the Electron desktop app from the workspace `desktop/` project (requires a built CLI and `desktop/` deps installed) |
|
|
139
173
|
|
|
140
174
|
## 🤖 Supported AI Assistants
|
|
141
175
|
|
|
@@ -152,7 +186,7 @@ NexusFlow auto-detects which assistants are available on your machine and genera
|
|
|
152
186
|
|
|
153
187
|
NexusFlow is built around a single loop:
|
|
154
188
|
|
|
155
|
-
1. **`nexusflow create`** — open a
|
|
189
|
+
1. **`nexusflow create`** — open a worktree or in-place workspace with AI context files generated. Along the way you can **scaffold a brand-new project** (a fresh local git repo in your dev directory) and, per repo, **check out an existing branch** — local or remote — instead of creating the feature branch.
|
|
156
190
|
2. **Work** — your AI assistant edits code across repos. As it goes, it records learnings:
|
|
157
191
|
```bash
|
|
158
192
|
nexusflow knowledge add -t decision -m "Chose worktrees over submodules for isolation"
|
|
@@ -162,10 +196,10 @@ NexusFlow is built around a single loop:
|
|
|
162
196
|
Entries land under the right heading in `nexusflow-knowledge.md` (routed through your storage adapter — local or central vault — so the GUI and the generators all see the same file). No hand-editing, no accidental overwrites.
|
|
163
197
|
3. **`nexusflow finish`** — close it out:
|
|
164
198
|
- Shows a preflight status table (branch, dirty files, unpushed commits) per repo.
|
|
165
|
-
- Commits any remaining changes
|
|
199
|
+
- Commits any remaining changes and pushes every branch; worktree-mode repos on the wrong branch or in a detached HEAD are skipped, while in-place workspaces use each repo's current branch.
|
|
166
200
|
- Opens a PR per repo with the GitHub CLI when it's installed and authenticated; otherwise prints a ready-to-click **compare URL** for GitHub, GitLab, Azure DevOps, or Bitbucket.
|
|
167
201
|
- Offers to **promote** reusable learnings into each repo's persistent base knowledge (so they survive into the next feature).
|
|
168
|
-
- With `--cleanup`, removes the workspace once everything is confirmed pushed (never while you're `cd`'d inside it).
|
|
202
|
+
- With `--cleanup`, removes the workspace once everything is confirmed pushed (never while you're `cd`'d inside it, and never touching source repositories for in-place workspaces).
|
|
169
203
|
|
|
170
204
|
```bash
|
|
171
205
|
nexusflow finish --dry-run # preview what would happen
|
|
@@ -189,7 +223,7 @@ NexusFlow is built around a single loop:
|
|
|
189
223
|
| `promote_knowledge` | Copy a learning into a repo's persistent base knowledge |
|
|
190
224
|
| `finish_workspace` | Commit, push, and return PR/compare links (never deletes anything) |
|
|
191
225
|
| `get_service_logs` | Tail a running service's logs |
|
|
192
|
-
|
|
226
|
+
|
|
193
227
|
|
|
194
228
|
Read-only tools are annotated as such; `finish_workspace` deliberately cannot delete worktrees (cleanup stays a human-confirmed CLI action). Pass `--debug` (or set `NEXUSFLOW_DEBUG=1`) on any CLI command to surface diagnostic logging on stderr.
|
|
195
229
|
|
|
@@ -260,7 +294,7 @@ nexusflow schedule disable <id>
|
|
|
260
294
|
nexusflow schedule run <id>
|
|
261
295
|
```
|
|
262
296
|
|
|
263
|
-
Jobs are stored in `~/.nexusflow/schedules.json` and executed while a NexusFlow server is running — start one with `nexusflow ui` (use `--daemon
|
|
297
|
+
Jobs are stored in `~/.nexusflow/schedules.json` and executed while a NexusFlow server is running — start one with `nexusflow ui` (use `--daemon` for a background host). A job whose interval elapsed while no server was running simply runs on the next scheduler tick.
|
|
264
298
|
|
|
265
299
|
Scheduled runs are **token-efficient by design**: they use the same analysis cache as `nexusflow refresh`, so only repos whose content changed are re-analyzed, and unchanged context files are left byte-identical (no git churn, no invalidated AI prompt caches). The dashboard API exposes the same functionality under `/api/schedules`.
|
|
266
300
|
|
|
@@ -283,9 +317,9 @@ The dashboard integrates an **AI Strategy Analysis** inspector:
|
|
|
283
317
|
2. (Optional) Provide a comment or specific evaluation focus (e.g. *"Ensure subagent roles are distinct"*).
|
|
284
318
|
3. Click **Inspect Strategy** to have the AI analyze the strategy rules, identify ambiguities/contradictions, rate its orchestration effectiveness, and generate an optimized rewritten guideline.
|
|
285
319
|
|
|
286
|
-
##
|
|
320
|
+
## 🖥️ Dashboard (Desktop App & Browser)
|
|
287
321
|
|
|
288
|
-
|
|
322
|
+
The primary GUI is the Electron desktop app in `desktop/` (`npm install && npm start` there). It embeds the same dashboard the browser sees. For browser access, run `nexusflow dashboard`; `nexusflow ui` starts the underlying server without opening anything (add `--open` to launch a browser). For the platform rationale (Electron vs Tauri and friends), see [docs/desktop-platform.md](docs/desktop-platform.md). The dashboard is a full-featured dark-themed GUI:
|
|
289
323
|
|
|
290
324
|
- **Workspaces tab** — create, browse, and manage feature workspaces
|
|
291
325
|
- **Sessions tab** — view past AI conversation transcripts and resume sessions
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CliAdapterBase } from './CliAdapterBase.js';
|
|
2
|
+
export declare class AntigravityCliAdapter extends CliAdapterBase {
|
|
3
|
+
protected readonly binary = "agy";
|
|
4
|
+
protected readonly label = "agy CLI";
|
|
5
|
+
protected buildArgs(isFirstTurn: boolean, prompt: string): string[];
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=AntigravityCliAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AntigravityCliAdapter.d.ts","sourceRoot":"","sources":["../../src/agent/AntigravityCliAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,qBAAa,qBAAsB,SAAQ,cAAc;IACvD,SAAS,CAAC,QAAQ,CAAC,MAAM,SAAS;IAClC,SAAS,CAAC,QAAQ,CAAC,KAAK,aAAa;IAMrC,SAAS,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;CAGpE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CliAdapterBase } from './CliAdapterBase.js';
|
|
2
|
+
export class AntigravityCliAdapter extends CliAdapterBase {
|
|
3
|
+
binary = 'agy';
|
|
4
|
+
label = 'agy CLI';
|
|
5
|
+
// agy is a native binary: reads the prompt from argv and needs no shell
|
|
6
|
+
// (argv is passed literally, so multi-word prompts are safe without quoting).
|
|
7
|
+
// -p runs a single prompt; -c continues the conversation for later turns.
|
|
8
|
+
// agy has no resume-by-id, so no fallback.
|
|
9
|
+
buildArgs(isFirstTurn, prompt) {
|
|
10
|
+
return isFirstTurn ? ['-p', prompt] : ['-c', '-p', prompt];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=AntigravityCliAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AntigravityCliAdapter.js","sourceRoot":"","sources":["../../src/agent/AntigravityCliAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IACpC,MAAM,GAAG,KAAK,CAAC;IACf,KAAK,GAAG,SAAS,CAAC;IACrC,wEAAwE;IACxE,8EAA8E;IAE9E,0EAA0E;IAC1E,2CAA2C;IACjC,SAAS,CAAC,WAAoB,EAAE,MAAc;QACtD,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7D,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CliAdapterBase } from './CliAdapterBase.js';
|
|
2
|
+
import { type AgentSession } from './session.js';
|
|
3
|
+
export declare class ClaudeCliAdapter extends CliAdapterBase {
|
|
4
|
+
protected readonly binary = "claude";
|
|
5
|
+
protected readonly label = "claude CLI";
|
|
6
|
+
protected readonly useShell = true;
|
|
7
|
+
protected readonly promptViaStdin = true;
|
|
8
|
+
protected fallbackMessage: string;
|
|
9
|
+
private session;
|
|
10
|
+
private sessionEstablished;
|
|
11
|
+
start(cwd: string, session?: AgentSession): Promise<void>;
|
|
12
|
+
protected buildArgs(isFirstTurn: boolean): string[];
|
|
13
|
+
protected fallbackArgs(): string[] | null;
|
|
14
|
+
protected onTurnComplete(succeeded: boolean): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=ClaudeCliAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeCliAdapter.d.ts","sourceRoot":"","sources":["../../src/agent/ClaudeCliAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEtE,qBAAa,gBAAiB,SAAQ,cAAc;IAClD,SAAS,CAAC,QAAQ,CAAC,MAAM,YAAY;IACrC,SAAS,CAAC,QAAQ,CAAC,KAAK,gBAAgB;IAGxC,SAAS,CAAC,QAAQ,CAAC,QAAQ,QAAQ;IACnC,SAAS,CAAC,QAAQ,CAAC,cAAc,QAAQ;IACzC,SAAS,CAAC,eAAe,SAAiE;IAE1F,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,kBAAkB,CAAkB;IAE/B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;IAMtD,SAAS,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,GAAG,MAAM,EAAE;IAMnD,SAAS,CAAC,YAAY,IAAI,MAAM,EAAE,GAAG,IAAI;IAOzC,SAAS,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;CAGnD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CliAdapterBase } from './CliAdapterBase.js';
|
|
2
|
+
import { buildClaudeTurnArgs } from './session.js';
|
|
3
|
+
export class ClaudeCliAdapter extends CliAdapterBase {
|
|
4
|
+
binary = 'claude';
|
|
5
|
+
label = 'claude CLI';
|
|
6
|
+
// claude is an npm .cmd shim: needs a shell on Windows, and under a shell an
|
|
7
|
+
// argv prompt would split on spaces, so the prompt goes over stdin.
|
|
8
|
+
useShell = true;
|
|
9
|
+
promptViaStdin = true;
|
|
10
|
+
fallbackMessage = 'Could not resume the previous session — starting a new one.';
|
|
11
|
+
session;
|
|
12
|
+
sessionEstablished = false;
|
|
13
|
+
async start(cwd, session) {
|
|
14
|
+
await super.start(cwd);
|
|
15
|
+
this.session = session;
|
|
16
|
+
this.sessionEstablished = false;
|
|
17
|
+
}
|
|
18
|
+
buildArgs(isFirstTurn) {
|
|
19
|
+
return buildClaudeTurnArgs(isFirstTurn, this.session);
|
|
20
|
+
}
|
|
21
|
+
// A --resume of a purged session fails on the very first turn; the id is
|
|
22
|
+
// then free, so one retry with --session-id recreates it under the same id.
|
|
23
|
+
fallbackArgs() {
|
|
24
|
+
if (this.session?.resume === true && !this.sessionEstablished) {
|
|
25
|
+
return ['-p', '--session-id', this.session.id];
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
onTurnComplete(succeeded) {
|
|
30
|
+
if (succeeded)
|
|
31
|
+
this.sessionEstablished = true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=ClaudeCliAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeCliAdapter.js","sourceRoot":"","sources":["../../src/agent/ClaudeCliAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAqB,MAAM,cAAc,CAAC;AAEtE,MAAM,OAAO,gBAAiB,SAAQ,cAAc;IAC/B,MAAM,GAAG,QAAQ,CAAC;IAClB,KAAK,GAAG,YAAY,CAAC;IACxC,6EAA6E;IAC7E,oEAAoE;IACjD,QAAQ,GAAG,IAAI,CAAC;IAChB,cAAc,GAAG,IAAI,CAAC;IAC/B,eAAe,GAAG,6DAA6D,CAAC;IAElF,OAAO,CAA2B;IAClC,kBAAkB,GAAY,KAAK,CAAC;IAErC,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,OAAsB;QACpD,MAAM,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;IAClC,CAAC;IAES,SAAS,CAAC,WAAoB;QACtC,OAAO,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;IAED,yEAAyE;IACzE,4EAA4E;IAClE,YAAY;QACpB,IAAI,IAAI,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC9D,OAAO,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAES,cAAc,CAAC,SAAkB;QACzC,IAAI,SAAS;YAAE,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAChD,CAAC;CACF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { type ChildProcess } from 'node:child_process';
|
|
3
|
+
/**
|
|
4
|
+
* Shared lifecycle for CLI-backed agents (claude, agy). Each turn spawns the
|
|
5
|
+
* binary once in print mode, streams stdout as `data`, and emits `idle` when
|
|
6
|
+
* the turn ends. Subclasses supply the binary, the per-turn args, how the
|
|
7
|
+
* prompt is delivered, and (optionally) a one-shot fallback used when the
|
|
8
|
+
* first attempt of a turn fails with no output.
|
|
9
|
+
*
|
|
10
|
+
* Prompt delivery differs per CLI: `claude` is an npm `.cmd` shim that needs
|
|
11
|
+
* `shell: true` on Windows, and under a shell an argv prompt would be split on
|
|
12
|
+
* spaces, so its prompt goes over stdin. `agy` is a native binary that reads
|
|
13
|
+
* the prompt from argv and needs no shell (argv is passed literally, so no
|
|
14
|
+
* quoting hazard).
|
|
15
|
+
*/
|
|
16
|
+
export declare abstract class CliAdapterBase extends EventEmitter {
|
|
17
|
+
protected cwd: string;
|
|
18
|
+
protected isFirstTurn: boolean;
|
|
19
|
+
private isProcessing;
|
|
20
|
+
private stopped;
|
|
21
|
+
private child;
|
|
22
|
+
/** Executable name, e.g. 'claude' or 'agy'. */
|
|
23
|
+
protected abstract readonly binary: string;
|
|
24
|
+
/** Short label for stderr/error diagnostics. */
|
|
25
|
+
protected abstract readonly label: string;
|
|
26
|
+
/** Spawn through a shell (needed to resolve a `.cmd` shim on Windows). */
|
|
27
|
+
protected readonly useShell: boolean;
|
|
28
|
+
/** Pipe the prompt to stdin (true) vs. include it in argv via buildArgs (false). */
|
|
29
|
+
protected readonly promptViaStdin: boolean;
|
|
30
|
+
/** Args for one print-mode turn. Receives the prompt so argv-mode CLIs can
|
|
31
|
+
* include it; stdin-mode CLIs ignore it. */
|
|
32
|
+
protected abstract buildArgs(isFirstTurn: boolean, prompt: string): string[];
|
|
33
|
+
/**
|
|
34
|
+
* Args to retry with when the first attempt of a turn exits non-zero with no
|
|
35
|
+
* output (e.g. resuming a purged session). Return null for no fallback.
|
|
36
|
+
*/
|
|
37
|
+
protected fallbackArgs(): string[] | null;
|
|
38
|
+
/** Message emitted as a `system` event when the fallback kicks in. */
|
|
39
|
+
protected fallbackMessage: string;
|
|
40
|
+
/** Called once per turn after it settles; `succeeded` if it produced output or exited 0. */
|
|
41
|
+
protected onTurnComplete(_succeeded: boolean): void;
|
|
42
|
+
start(cwd: string): Promise<void>;
|
|
43
|
+
send(data: string): Promise<void>;
|
|
44
|
+
private runTurn;
|
|
45
|
+
stop(): void;
|
|
46
|
+
}
|
|
47
|
+
export declare function killTree(child: ChildProcess | null): void;
|
|
48
|
+
//# sourceMappingURL=CliAdapterBase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CliAdapterBase.d.ts","sourceRoot":"","sources":["../../src/agent/CliAdapterBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE9D;;;;;;;;;;;;GAYG;AACH,8BAAsB,cAAe,SAAQ,YAAY;IACvD,SAAS,CAAC,GAAG,EAAE,MAAM,CAAM;IAC3B,SAAS,CAAC,WAAW,EAAE,OAAO,CAAQ;IACtC,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,KAAK,CAA6B;IAE1C,+CAA+C;IAC/C,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAC3C,gDAAgD;IAChD,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAC1C,0EAA0E;IAC1E,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAS;IAC7C,oFAAoF;IACpF,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAS;IAEnD;iDAC6C;IAC7C,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAE5E;;;OAGG;IACH,SAAS,CAAC,YAAY,IAAI,MAAM,EAAE,GAAG,IAAI;IAIzC,sEAAsE;IACtE,SAAS,CAAC,eAAe,EAAE,MAAM,CAAe;IAEhD,4FAA4F;IAC5F,SAAS,CAAC,cAAc,CAAC,UAAU,EAAE,OAAO,GAAG,IAAI;IAEtC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9C,OAAO,CAAC,OAAO;IA0DR,IAAI,IAAI,IAAI;CAOpB;AAID,wBAAgB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,QAOlD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
/**
|
|
4
|
+
* Shared lifecycle for CLI-backed agents (claude, agy). Each turn spawns the
|
|
5
|
+
* binary once in print mode, streams stdout as `data`, and emits `idle` when
|
|
6
|
+
* the turn ends. Subclasses supply the binary, the per-turn args, how the
|
|
7
|
+
* prompt is delivered, and (optionally) a one-shot fallback used when the
|
|
8
|
+
* first attempt of a turn fails with no output.
|
|
9
|
+
*
|
|
10
|
+
* Prompt delivery differs per CLI: `claude` is an npm `.cmd` shim that needs
|
|
11
|
+
* `shell: true` on Windows, and under a shell an argv prompt would be split on
|
|
12
|
+
* spaces, so its prompt goes over stdin. `agy` is a native binary that reads
|
|
13
|
+
* the prompt from argv and needs no shell (argv is passed literally, so no
|
|
14
|
+
* quoting hazard).
|
|
15
|
+
*/
|
|
16
|
+
export class CliAdapterBase extends EventEmitter {
|
|
17
|
+
cwd = '';
|
|
18
|
+
isFirstTurn = true;
|
|
19
|
+
isProcessing = false;
|
|
20
|
+
stopped = false;
|
|
21
|
+
child = null;
|
|
22
|
+
/** Spawn through a shell (needed to resolve a `.cmd` shim on Windows). */
|
|
23
|
+
useShell = false;
|
|
24
|
+
/** Pipe the prompt to stdin (true) vs. include it in argv via buildArgs (false). */
|
|
25
|
+
promptViaStdin = false;
|
|
26
|
+
/**
|
|
27
|
+
* Args to retry with when the first attempt of a turn exits non-zero with no
|
|
28
|
+
* output (e.g. resuming a purged session). Return null for no fallback.
|
|
29
|
+
*/
|
|
30
|
+
fallbackArgs() {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
/** Message emitted as a `system` event when the fallback kicks in. */
|
|
34
|
+
fallbackMessage = 'Retrying…';
|
|
35
|
+
/** Called once per turn after it settles; `succeeded` if it produced output or exited 0. */
|
|
36
|
+
onTurnComplete(_succeeded) { }
|
|
37
|
+
async start(cwd) {
|
|
38
|
+
this.cwd = cwd;
|
|
39
|
+
this.isFirstTurn = true;
|
|
40
|
+
}
|
|
41
|
+
async send(data) {
|
|
42
|
+
if (this.isProcessing)
|
|
43
|
+
return;
|
|
44
|
+
this.isProcessing = true;
|
|
45
|
+
this.stopped = false;
|
|
46
|
+
const args = this.buildArgs(this.isFirstTurn, data);
|
|
47
|
+
this.isFirstTurn = false;
|
|
48
|
+
this.runTurn(args, data, true);
|
|
49
|
+
}
|
|
50
|
+
runTurn(args, data, allowFallback) {
|
|
51
|
+
const cliProcess = spawn(this.binary, args, {
|
|
52
|
+
cwd: this.cwd,
|
|
53
|
+
shell: this.useShell,
|
|
54
|
+
env: { ...process.env, FORCE_COLOR: '0' } // Strip colors for easier parsing
|
|
55
|
+
});
|
|
56
|
+
this.child = cliProcess;
|
|
57
|
+
if (this.promptViaStdin) {
|
|
58
|
+
cliProcess.stdin?.write(data);
|
|
59
|
+
cliProcess.stdin?.end();
|
|
60
|
+
}
|
|
61
|
+
let producedOutput = false;
|
|
62
|
+
let stderrTail = '';
|
|
63
|
+
cliProcess.stdout?.on('data', (chunk) => {
|
|
64
|
+
producedOutput = true;
|
|
65
|
+
this.emit('data', chunk.toString());
|
|
66
|
+
});
|
|
67
|
+
// CLIs print warnings and progress on stderr; only keep it for diagnostics.
|
|
68
|
+
cliProcess.stderr?.on('data', (chunk) => {
|
|
69
|
+
const text = chunk.toString();
|
|
70
|
+
stderrTail = (stderrTail + text).slice(-2000);
|
|
71
|
+
console.warn(`[${this.label} stderr]`, text.trimEnd());
|
|
72
|
+
});
|
|
73
|
+
cliProcess.on('error', (err) => {
|
|
74
|
+
this.isProcessing = false;
|
|
75
|
+
this.child = null;
|
|
76
|
+
this.emit('error', new Error(`Failed to start ${this.label}: ${err.message}`));
|
|
77
|
+
this.emit('idle');
|
|
78
|
+
});
|
|
79
|
+
cliProcess.on('close', (code) => {
|
|
80
|
+
this.child = null;
|
|
81
|
+
if (!this.stopped && code !== 0 && !producedOutput && allowFallback) {
|
|
82
|
+
const fb = this.fallbackArgs();
|
|
83
|
+
if (fb) {
|
|
84
|
+
this.emit('system', this.fallbackMessage);
|
|
85
|
+
this.runTurn(fb, data, false);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
this.isProcessing = false;
|
|
90
|
+
this.onTurnComplete(code === 0 || producedOutput);
|
|
91
|
+
// A non-zero exit after an intentional stop is expected, not an error.
|
|
92
|
+
if (!this.stopped && code !== 0 && !producedOutput) {
|
|
93
|
+
this.emit('error', new Error(`${this.label} exited with code ${code}${stderrTail ? `: ${stderrTail.trim()}` : ''}`));
|
|
94
|
+
}
|
|
95
|
+
// Turn separation is the GUI's concern — do not inject stray output here,
|
|
96
|
+
// or a failed turn would spawn an empty bubble on the client.
|
|
97
|
+
this.emit('idle');
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
stop() {
|
|
101
|
+
this.stopped = true;
|
|
102
|
+
killTree(this.child);
|
|
103
|
+
this.child = null;
|
|
104
|
+
this.isProcessing = false;
|
|
105
|
+
this.emit('close', 0);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// With shell:true on Windows, child.kill() only kills the shell wrapper,
|
|
109
|
+
// so take the whole tree down via taskkill.
|
|
110
|
+
export function killTree(child) {
|
|
111
|
+
if (!child || child.killed || child.exitCode !== null || !child.pid)
|
|
112
|
+
return;
|
|
113
|
+
if (process.platform === 'win32') {
|
|
114
|
+
spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], { stdio: 'ignore' });
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
child.kill('SIGTERM');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=CliAdapterBase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CliAdapterBase.js","sourceRoot":"","sources":["../../src/agent/CliAdapterBase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { NativeAgentBase } from './NativeAgentBase.js';
|
|
2
|
+
export declare class NativeAgent extends NativeAgentBase {
|
|
3
|
+
protected readonly label = "NativeAgent";
|
|
4
|
+
private openai;
|
|
5
|
+
private messages;
|
|
6
|
+
private modelName;
|
|
7
|
+
constructor();
|
|
8
|
+
private client;
|
|
9
|
+
protected configError(): string | null;
|
|
10
|
+
protected resetHistory(): void;
|
|
11
|
+
protected runLoop(userInput: string, signal: AbortSignal): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=NativeAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeAgent.d.ts","sourceRoot":"","sources":["../../src/agent/NativeAgent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AASvD,qBAAa,WAAY,SAAQ,eAAe;IAC9C,SAAS,CAAC,QAAQ,CAAC,KAAK,iBAAiB;IACzC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,SAAS,CAAS;;IAS1B,OAAO,CAAC,MAAM;IAId,SAAS,CAAC,WAAW,IAAI,MAAM,GAAG,IAAI;IAItC,SAAS,CAAC,YAAY;cAIN,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;CAiF/D"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import { NativeAgentBase } from './NativeAgentBase.js';
|
|
3
|
+
import { NATIVE_TOOLS, NATIVE_STEP_LIMIT, STEP_LIMIT_NOTICE, buildSystemPrompt, executeNativeTool, } from './nativeTools.js';
|
|
4
|
+
export class NativeAgent extends NativeAgentBase {
|
|
5
|
+
label = 'NativeAgent';
|
|
6
|
+
openai = null;
|
|
7
|
+
messages = [];
|
|
8
|
+
modelName;
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
this.modelName = process.env.OPENAI_MODEL || 'gpt-4o';
|
|
12
|
+
}
|
|
13
|
+
// The OpenAI SDK throws on an empty key, so build the client lazily — after
|
|
14
|
+
// configError() has gated on the key being present.
|
|
15
|
+
client() {
|
|
16
|
+
return (this.openai ??= new OpenAI({ apiKey: process.env.OPENAI_API_KEY || '' }));
|
|
17
|
+
}
|
|
18
|
+
configError() {
|
|
19
|
+
return process.env.OPENAI_API_KEY ? null : 'OpenAI API key is not configured (set OPENAI_API_KEY).';
|
|
20
|
+
}
|
|
21
|
+
resetHistory() {
|
|
22
|
+
this.messages = [{ role: 'system', content: buildSystemPrompt(this.cwd) }];
|
|
23
|
+
}
|
|
24
|
+
async runLoop(userInput, signal) {
|
|
25
|
+
this.messages.push({ role: 'user', content: userInput });
|
|
26
|
+
const tools = NATIVE_TOOLS.map((t) => ({
|
|
27
|
+
type: 'function',
|
|
28
|
+
function: {
|
|
29
|
+
name: t.name,
|
|
30
|
+
description: t.description,
|
|
31
|
+
parameters: {
|
|
32
|
+
type: 'object',
|
|
33
|
+
properties: { [t.argName]: { type: 'string', description: t.argDescription } },
|
|
34
|
+
required: [t.argName],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
}));
|
|
38
|
+
let completed = false;
|
|
39
|
+
for (let step = 0; step < NATIVE_STEP_LIMIT; step++) {
|
|
40
|
+
if (signal.aborted)
|
|
41
|
+
break;
|
|
42
|
+
const stream = await this.client().chat.completions.create({
|
|
43
|
+
model: this.modelName,
|
|
44
|
+
messages: this.messages,
|
|
45
|
+
tools: tools,
|
|
46
|
+
stream: true,
|
|
47
|
+
}, { signal });
|
|
48
|
+
let content = '';
|
|
49
|
+
const toolCalls = [];
|
|
50
|
+
for await (const chunk of stream) {
|
|
51
|
+
const delta = chunk.choices[0]?.delta;
|
|
52
|
+
if (!delta)
|
|
53
|
+
continue;
|
|
54
|
+
if (delta.content) {
|
|
55
|
+
content += delta.content;
|
|
56
|
+
this.emit('data', delta.content);
|
|
57
|
+
}
|
|
58
|
+
if (delta.tool_calls) {
|
|
59
|
+
for (const toolCall of delta.tool_calls) {
|
|
60
|
+
const index = toolCall.index;
|
|
61
|
+
if (!toolCalls[index]) {
|
|
62
|
+
toolCalls[index] = {
|
|
63
|
+
id: toolCall.id,
|
|
64
|
+
type: 'function',
|
|
65
|
+
function: { name: toolCall.function?.name, arguments: '' },
|
|
66
|
+
};
|
|
67
|
+
this.emit('data', `\n\n*Running tool: ${toolCall.function?.name}*\n`);
|
|
68
|
+
}
|
|
69
|
+
if (toolCall.function?.arguments) {
|
|
70
|
+
toolCalls[index].function.arguments += toolCall.function.arguments;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
this.messages.push({ role: 'assistant', content, tool_calls: toolCalls.length > 0 ? toolCalls : undefined });
|
|
76
|
+
if (toolCalls.length === 0) {
|
|
77
|
+
completed = true;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
for (const tc of toolCalls) {
|
|
81
|
+
let result;
|
|
82
|
+
try {
|
|
83
|
+
const args = JSON.parse(tc.function.arguments || '{}');
|
|
84
|
+
result = await executeNativeTool(this.cwd, tc.function.name, args);
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
result = `Error: ${err.message}`;
|
|
88
|
+
}
|
|
89
|
+
this.messages.push({ role: 'tool', tool_call_id: tc.id, name: tc.function.name, content: result });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (!completed && !signal.aborted) {
|
|
93
|
+
this.emit('data', STEP_LIMIT_NOTICE);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=NativeAgent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeAgent.js","sourceRoot":"","sources":["../../src/agent/NativeAgent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
/**
|
|
3
|
+
* Shared lifecycle for the SDK-backed native agents. Owns the processing guard,
|
|
4
|
+
* the abort controller, and the idle/error signalling so each provider only
|
|
5
|
+
* implements its SDK-specific streaming loop.
|
|
6
|
+
*/
|
|
7
|
+
export declare abstract class NativeAgentBase extends EventEmitter {
|
|
8
|
+
protected cwd: string;
|
|
9
|
+
protected isProcessing: boolean;
|
|
10
|
+
protected abortController: AbortController | null;
|
|
11
|
+
/** Human label used in server-side error logs. */
|
|
12
|
+
protected abstract readonly label: string;
|
|
13
|
+
/** Clear provider-specific conversation history for a new session. */
|
|
14
|
+
protected abstract resetHistory(): void;
|
|
15
|
+
/** Run one user turn's agent loop, honoring `signal` for cancellation. */
|
|
16
|
+
protected abstract runLoop(userInput: string, signal: AbortSignal): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Returns a user-facing message when the provider isn't usable (e.g. missing
|
|
19
|
+
* API key), or null when it is. Checked before each turn so a misconfigured
|
|
20
|
+
* provider gives a clear error instead of a raw SDK auth exception.
|
|
21
|
+
*/
|
|
22
|
+
protected configError(): string | null;
|
|
23
|
+
start(cwd: string): Promise<void>;
|
|
24
|
+
send(data: string): Promise<void>;
|
|
25
|
+
stop(): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=NativeAgentBase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeAgentBase.d.ts","sourceRoot":"","sources":["../../src/agent/NativeAgentBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;GAIG;AACH,8BAAsB,eAAgB,SAAQ,YAAY;IACxD,SAAS,CAAC,GAAG,EAAE,MAAM,CAAM;IAC3B,SAAS,CAAC,YAAY,EAAE,OAAO,CAAS;IACxC,SAAS,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI,CAAQ;IAEzD,kDAAkD;IAClD,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAE1C,sEAAsE;IACtE,SAAS,CAAC,QAAQ,CAAC,YAAY,IAAI,IAAI;IAEvC,0EAA0E;IAC1E,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAEjF;;;;OAIG;IACH,SAAS,CAAC,WAAW,IAAI,MAAM,GAAG,IAAI;IAIzB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BvC,IAAI,IAAI,IAAI;CAKpB"}
|