Skip to content

Commit 7fa88ae

Browse files
committed
Merge branch 'ai-node'
2 parents b8d1f30 + fb11df2 commit 7fa88ae

202 files changed

Lines changed: 30661 additions & 641 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.claude
22
.ai
3+
conductor
34
.direnv
45
.env.*.local
56
.env.keys
@@ -35,7 +36,3 @@ coverage.out
3536
packages/server/server
3637
tools/collect_go_failures.py
3738
/server
38-
# Conductor
39-
40-
# Conductor
41-
conductor/
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
desktop: minor
3+
cli: minor
4+
---
5+
6+
Add AI node support with multi-provider LLM integration (OpenAI, Anthropic, Gemini), credential vault encryption, and variable introspection system

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*.har
44
AGENTS.md
55
CHANGELOG.md
6+
conductor/
67
dist
78
flake.lock
89
GEMINI.md

GEMINI.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,34 @@ DevTools is a local-first, open-source API testing platform (Postman alternative
5555
- **Fix:** `task fix` (runs Prettier and Syncpack).
5656
- **Go Benchmarks:** Use `task benchmark:run` to run, `task benchmark:baseline` to save baseline, and `task benchmark:compare` to compare.
5757

58+
### Nx Version Plans
59+
Version plans are file-based versioning for independent releases. They allow contributors to declare version bumps alongside their changes without modifying `package.json` directly.
60+
61+
**How it works:**
62+
1. When making a change that warrants a release, create a version plan file
63+
2. The file is stored in `.nx/version-plans/` as a markdown file
64+
3. During release, Nx reads all pending version plans and applies the bumps
65+
66+
**Creating a version plan:**
67+
```bash
68+
task version-plan project=desktop # Interactive prompt for bump type + message
69+
```
70+
71+
**Version plan file format:**
72+
```markdown
73+
---
74+
desktop: patch # or minor, major
75+
---
76+
77+
Description of the change (used in changelog)
78+
```
79+
80+
**Available projects:** `desktop`, `cli`, `api-recorder-extension`
81+
82+
**Configuration:** Defined in `nx.json` under `release.versionPlans`. Projects use independent versioning (`projectsRelationship: independent`).
83+
84+
**Reference:** [Nx Version Plans Documentation](https://nx.dev/recipes/nx-release/file-based-versioning-version-plans)
85+
5886
## Implementation Guidelines
5987

6088
### CLI (Go)
@@ -78,6 +106,24 @@ DevTools is a local-first, open-source API testing platform (Postman alternative
78106
- **Seeding:** Use `BaseTestServices.CreateTempCollection` to quickly seed workspace/user/collection state.
79107
- **Parallelism:** Safe to use `t.Parallel()` *only* if each subtest creates its own independent DB.
80108

109+
### Go Integration Testing Pattern
110+
Use this pattern for tests that require external services (APIs, Cloud), cost money, or are too slow for standard CI.
111+
112+
- **Naming Convention:** Start files with `integration_` (e.g., `integration_providers_test.go`).
113+
- **Build Tags:** Use specific tags to exclude from default `go test`.
114+
- Example: `//go:build ai_integration`
115+
- **Safety Guard:** Always check an explicit environment variable at the start of the test to prevent accidental execution.
116+
- Example: `if os.Getenv("RUN_XX_INTEGRATION") != "true" { t.Skip() }`
117+
- **Example Implementation (AI Node):**
118+
- **Location:** `packages/server/pkg/flow/node/nai/integration_*.go`
119+
- **Tag:** `ai_integration`
120+
- **Guard:** `RUN_AI_INTEGRATION_TESTS=true`
121+
- **Env Vars:**
122+
- `OPENAI_API_KEY`, `OPENAI_BASE_URL`, `OPENAI_MODEL`
123+
- `ANTHROPIC_API_KEY`, `ANTHROPIC_BASE_URL`, `ANTHROPIC_MODEL`
124+
- `GEMINI_API_KEY`
125+
- **Command:** `RUN_AI_INTEGRATION_TESTS=true OPENAI_API_KEY=sk-... go test -tags ai_integration -v ./packages/server/pkg/flow/node/nai`
126+
81127
### TypeScript/React (Client/Desktop)
82128
- **State/Effects:** Effect-TS and TanStack Query.
83129
- **Styling:** Tailwind CSS v4. Co-located with components.

apps/cli/cmd/flow.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/the-dev-tools/dev-tools/packages/server/pkg/idwrap"
1717
"github.com/the-dev-tools/dev-tools/packages/server/pkg/ioworkspace"
1818
"github.com/the-dev-tools/dev-tools/packages/server/pkg/model/mflow"
19+
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/scredential"
1920
yamlflowsimplev2 "github.com/the-dev-tools/dev-tools/packages/server/pkg/translate/yamlflowsimplev2"
2021
"github.com/the-dev-tools/dev-tools/packages/spec/dist/buf/go/api/node_js_executor/v1/node_js_executorv1connect"
2122

@@ -144,18 +145,25 @@ var yamlflowRunCmd = &cobra.Command{
144145
services.HTTPAssert,
145146
)
146147

148+
// Create LLM provider factory for AI nodes
149+
llmFactory := scredential.NewLLMProviderFactory(&services.Credential)
150+
147151
builder := flowbuilder.New(
148152
&services.Node,
149153
&services.NodeRequest,
150154
&services.NodeFor,
151155
&services.NodeForEach,
152156
&services.NodeIf,
153157
&services.NodeJS,
158+
&services.NodeAI,
159+
&services.NodeAiProvider,
160+
&services.NodeMemory,
154161
&services.Workspace,
155162
&services.Variable,
156163
&services.FlowVariable,
157164
resolver,
158165
services.Logger,
166+
llmFactory,
159167
)
160168

161169
if !quietMode {

apps/cli/go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4
55
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
66
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
77
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
8-
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
9-
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
9+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1010
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
1111
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
1212
github.com/expr-lang/expr v1.17.7 h1:Q0xY/e/2aCIp8g9s/LGvMDCC5PxYlvHgDZRQ4y16JX8=
@@ -18,6 +18,7 @@ github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8
1818
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
1919
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
2020
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
21+
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
2122
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
2223
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
2324
github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a h1://KbezygeMJZCSHH+HgUZiTeSoiuFspbMg1ge+eFj18=
@@ -45,8 +46,8 @@ github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNs
4546
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
4647
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
4748
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
48-
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
49-
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
49+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
50+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5051
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
5152
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
5253
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
@@ -90,9 +91,8 @@ golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
9091
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
9192
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
9293
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
94+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
9395
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
94-
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
95-
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
9696
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
9797
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
9898
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=

apps/cli/internal/common/services.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"log/slog"
88

99
"github.com/the-dev-tools/dev-tools/packages/db/pkg/sqlc/gen"
10+
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/scredential"
1011
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/senv"
1112
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/sflow"
1213
"github.com/the-dev-tools/dev-tools/packages/server/pkg/service/shttp"
@@ -36,6 +37,12 @@ type Services struct {
3637
NodeForEach sflow.NodeForEachService
3738
NodeIf sflow.NodeIfService
3839
NodeJS sflow.NodeJsService
40+
NodeAI sflow.NodeAIService
41+
NodeAiProvider sflow.NodeAiProviderService
42+
NodeMemory sflow.NodeMemoryService
43+
44+
// Credentials
45+
Credential scredential.CredentialService
3946

4047
// HTTP (V2)
4148
HTTP shttp.HTTPService
@@ -77,6 +84,12 @@ func CreateServices(ctx context.Context, db *sql.DB, logger *slog.Logger) (*Serv
7784
NodeForEach: sflow.NewNodeForEachService(queries),
7885
NodeIf: *sflow.NewNodeIfService(queries),
7986
NodeJS: sflow.NewNodeJsService(queries),
87+
NodeAI: sflow.NewNodeAIService(queries),
88+
NodeAiProvider: sflow.NewNodeAiProviderService(queries),
89+
NodeMemory: sflow.NewNodeMemoryService(queries),
90+
91+
// Credentials
92+
Credential: scredential.NewCredentialService(queries),
8093

8194
// HTTP (V2)
8295
HTTP: shttp.New(queries, logger),

apps/cli/internal/runner/runner_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,15 @@ func newFlowTestFixture(t *testing.T) *flowTestFixture {
110110
&nodeForEachService,
111111
nodeIfService,
112112
&nodeJSService,
113+
nil, // NodeAIService - not needed for CLI tests
114+
nil, // NodeAiProviderService - not needed for CLI tests
115+
nil, // NodeMemoryService - not needed for CLI tests
113116
&workspaceService,
114117
&varService,
115118
&flowVariableService,
116119
res,
117120
logger,
121+
nil, // LLMProviderFactory - not needed for CLI tests
118122
)
119123

120124
_ = logconsole.NewLogChanMap() // unused but kept for parity if needed

0 commit comments

Comments
 (0)