@fnet/cli 0.133.0 → 1.0.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/dist/fbin/index.js +14 -1
- package/dist/fnet/index.0jcm9pn5.js +1 -0
- package/dist/fnet/index.2084z2ed.js +2 -0
- package/dist/fnet/index.33f1ggpr.js +1 -0
- package/dist/fnet/index.3exge2js.js +1 -0
- package/dist/fnet/index.3kfx538h.js +1 -0
- package/dist/fnet/index.490y87nc.js +1 -0
- package/dist/fnet/index.4g9yezkq.js +1 -0
- package/dist/fnet/index.4jkat7r4.js +1 -0
- package/dist/fnet/index.7crx8ky1.js +1 -0
- package/dist/fnet/index.7vw06nrn.js +1 -0
- package/dist/fnet/index.9567fa9x.js +1 -0
- package/dist/fnet/index.gh75wt1m.js +1 -0
- package/dist/fnet/index.hzsfswvp.js +1 -0
- package/dist/fnet/index.jgpc3grc.js +1 -0
- package/dist/fnet/index.js +19 -1
- package/dist/fnet/index.p0zb7e1b.js +1 -0
- package/dist/fnet/index.r19p3bpa.js +2 -0
- package/dist/fnet/index.r82rtnmz.js +1 -0
- package/dist/fnet/index.s662t98v.js +1 -0
- package/dist/fnet/index.w74dpnpn.js +1 -0
- package/dist/fnet/index.xeaw5xa9.js +1 -0
- package/dist/fnet/index.zm4kesg6.js +1 -0
- package/dist/fnode/index.05n3mvs9.js +2 -0
- package/dist/fnode/index.2hc9tbyx.js +1 -0
- package/dist/fnode/index.2pnjg6dc.js +1 -0
- package/dist/fnode/index.9qgtmxq3.js +2 -0
- package/dist/fnode/index.b1q7y05p.js +1 -0
- package/dist/fnode/index.bhapgrs7.js +1 -0
- package/dist/fnode/index.cvxrf34y.js +2 -0
- package/dist/fnode/index.dp9wyahp.js +1 -0
- package/dist/fnode/index.eqxmcpdc.js +1 -0
- package/dist/fnode/index.f2tb0x3t.js +1 -0
- package/dist/fnode/index.fbzv6wwf.js +1 -0
- package/dist/fnode/index.gazd9raq.js +1 -0
- package/dist/fnode/index.hv4s25f0.js +3 -0
- package/dist/fnode/index.j5z7dtsx.js +1 -0
- package/dist/fnode/index.js +9 -1
- package/dist/fnode/index.kb4e4bxf.js +1 -0
- package/dist/fnode/index.qn0schqp.js +1 -0
- package/dist/fnode/index.rht29phd.js +1 -0
- package/dist/fnode/index.rzsfmek6.js +3 -0
- package/dist/fnode/index.s0nk6cv8.js +4 -0
- package/dist/fnode/index.s66v6wt4.js +1 -0
- package/dist/fnode/index.sv7v0y60.js +1 -0
- package/dist/fnode/index.tgkhgnrp.js +1 -0
- package/dist/fnode/index.vq706f75.js +1 -0
- package/dist/fnode/index.y8pvdcny.js +1 -0
- package/dist/fnode/index.z4vz93ww.js +1 -0
- package/dist/frun/index.js +1 -1
- package/dist/fservice/index.js +18 -1
- package/dist/fservice/index.q01yvaz0.js +2 -0
- package/package.json +21 -18
- package/readme.md +62 -15
- package/template/fnet/core/object.js +10 -10
- package/template/fnet/node/package.json.njk +6 -3
- package/template/fnet/node/src/cli/index.js.njk +5 -315
- package/template/fnet/node/src/cli/index.js.v1.njk +318 -0
- package/template/fnet/node/src/cli/v2/core/args-parser.njk +10 -0
- package/template/fnet/node/src/cli/v2/core/imports.njk +31 -0
- package/template/fnet/node/src/cli/v2/core/run-wrapper.njk +25 -0
- package/template/fnet/node/src/cli/v2/index.js.njk +184 -0
- package/template/fnet/node/src/cli/v2/modes/default/extend.njk +11 -0
- package/template/fnet/node/src/cli/v2/modes/default/standard.njk +20 -0
- package/template/fnet/node/src/cli/v2/modes/http/builtin.njk +66 -0
- package/template/fnet/node/src/cli/v2/modes/http/imports.njk +9 -0
- package/template/fnet/node/src/cli/v2/modes/http/index.njk +12 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/imports.njk +33 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/index.njk +30 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/server-setup.njk +15 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/tool-handlers.njk +46 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/transport-http.njk +222 -0
- package/template/fnet/node/src/cli/v2/modes/mcp/transport-stdio.njk +9 -0
- package/template/fnet/node/src/cli/v2/modes/pipeline/imports.njk +9 -0
- package/template/fnet/node/src/cli/v2/modes/pipeline/index.njk +113 -0
- package/template/fnet/node/src/cli/v2/modes/webhook/imports.njk +9 -0
- package/template/fnet/node/src/cli/v2/modes/webhook/index.njk +127 -0
- package/template/fnet/node/src/cli/v2/modes/websocket/imports.njk +15 -0
- package/template/fnet/node/src/cli/v2/modes/websocket/index.njk +104 -0
- package/template/fnet/node/src/default/blocks/assign.js.njk +10 -48
- package/template/fnet/node/src/default/blocks/call.js.njk +110 -156
- package/template/fnet/node/src/default/blocks/for.js.njk +58 -74
- package/template/fnet/node/src/default/blocks/form.js.njk +21 -59
- package/template/fnet/node/src/default/blocks/http.js.njk +135 -0
- package/template/fnet/node/src/default/blocks/modules.js.njk +10 -52
- package/template/fnet/node/src/default/blocks/new.js.njk +40 -85
- package/template/fnet/node/src/default/blocks/next.js.njk +10 -32
- package/template/fnet/node/src/default/blocks/output.js.njk +10 -48
- package/template/fnet/node/src/default/blocks/parallel.js.njk +64 -0
- package/template/fnet/node/src/default/blocks/pipeline.js.njk +109 -0
- package/template/fnet/node/src/default/blocks/raise.js.njk +9 -25
- package/template/fnet/node/src/default/blocks/retry.js.njk +70 -0
- package/template/fnet/node/src/default/blocks/return.js.njk +13 -25
- package/template/fnet/node/src/default/blocks/schedule.js.njk +66 -0
- package/template/fnet/node/src/default/blocks/signal.js.njk +10 -32
- package/template/fnet/node/src/default/blocks/steps.js.njk +32 -48
- package/template/fnet/node/src/default/blocks/switch.js.njk +37 -67
- package/template/fnet/node/src/default/blocks/tryexcept.js.njk +58 -52
- package/template/fnet/node/src/default/blocks/wait.js.njk +10 -30
- package/template/fnet/node/src/default/input.args.js.njk +5 -2
- package/template/fnet/node/src/default/macros/block-body-header.js.njk +1 -1
- package/template/fnet/node/src/default/macros/block-header.js.njk +0 -3
- package/template/fnet/node/src/default/macros/block-next.js.njk +1 -1
- package/template/fnet/node/src/default/macros/block-run-footer.js.njk +1 -1
- package/template/fnet/node/src/default/macros/block-run-header.js.njk +14 -2
- package/template/fnet/node/src/default/macros/page.js.njk +1 -1
- package/template/fnet/node/src/default/types/block.js.njk +133 -0
- package/template/fnet/node/src/default/workflow.js.njk +8 -6
- package/template/fnode/node/package.json.njk +5 -4
- package/template/fnode/node/src/cli/index.js.njk +3 -397
- package/template/fnode/node/src/cli/index.js.v1.njk +464 -0
- package/template/fnode/node/src/cli/v2/core/args-parser.njk +10 -0
- package/template/fnode/node/src/cli/v2/core/imports.njk +29 -0
- package/template/fnode/node/src/cli/v2/core/run-wrapper.njk +25 -0
- package/template/fnode/node/src/cli/v2/index.js.njk +184 -0
- package/template/fnode/node/src/cli/v2/modes/default/extend.njk +11 -0
- package/template/fnode/node/src/cli/v2/modes/default/standard.njk +19 -0
- package/template/fnode/node/src/cli/v2/modes/http/builtin.njk +61 -0
- package/template/fnode/node/src/cli/v2/modes/http/imports.njk +9 -0
- package/template/fnode/node/src/cli/v2/modes/http/index.njk +12 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/imports.njk +33 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/index.njk +30 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/server-setup.njk +15 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/tool-handlers.njk +41 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/transport-http.njk +212 -0
- package/template/fnode/node/src/cli/v2/modes/mcp/transport-stdio.njk +9 -0
- package/template/fnode/node/src/cli/v2/modes/pipeline/imports.njk +9 -0
- package/template/fnode/node/src/cli/v2/modes/pipeline/index.njk +103 -0
- package/template/fnode/node/src/cli/v2/modes/webhook/imports.njk +9 -0
- package/template/fnode/node/src/cli/v2/modes/webhook/index.njk +122 -0
- package/template/fnode/node/src/cli/v2/modes/websocket/imports.njk +15 -0
- package/template/fnode/node/src/cli/v2/modes/websocket/index.njk +99 -0
- package/template/fnode/node/src/default/input.args.js.njk +6 -2
- package/dist/fnet/index.-SGbq2cI.js +0 -1
- package/dist/fnet/index.B5XE4ChJ.js +0 -1
- package/dist/fnet/index.Bft2w7m3.js +0 -1
- package/dist/fnet/index.BuYxdKtK.js +0 -1
- package/dist/fnet/index.C0YpfQ5j.js +0 -1
- package/dist/fnet/index.C2S9JYhS.js +0 -1
- package/dist/fnet/index.C7saWH6d.js +0 -1
- package/dist/fnet/index.CDct_kkF.js +0 -1
- package/dist/fnet/index.CMC8mlye.js +0 -1
- package/dist/fnet/index.CmMM-Ek9.js +0 -1
- package/dist/fnet/index.CuMyez3E.js +0 -1
- package/dist/fnet/index.CzAV0S36.js +0 -1
- package/dist/fnet/index.D2N9YZmA.js +0 -1
- package/dist/fnet/index.D3p7pncT.js +0 -1
- package/dist/fnet/index.DG8TqL-1.js +0 -1
- package/dist/fnet/index.DI3yyTtl.js +0 -1
- package/dist/fnet/index.DOYkqsYT.js +0 -1
- package/dist/fnet/index.DWpw12No.js +0 -1
- package/dist/fnet/index.DrwlOzAe.js +0 -1
- package/dist/fnet/index.Q-CYRcna.js +0 -1
- package/dist/fnet/index.W6RYgypK.js +0 -1
- package/dist/fnet/index.xd8c7XMr.js +0 -1
- package/dist/fnode/index.-SGbq2cI.js +0 -1
- package/dist/fnode/index.B5XE4ChJ.js +0 -1
- package/dist/fnode/index.B8gal9up.js +0 -1
- package/dist/fnode/index.BU1440aO.js +0 -1
- package/dist/fnode/index.BcGYSPne.js +0 -1
- package/dist/fnode/index.Bft2w7m3.js +0 -1
- package/dist/fnode/index.BuYxdKtK.js +0 -1
- package/dist/fnode/index.C2S9JYhS.js +0 -1
- package/dist/fnode/index.C7saWH6d.js +0 -1
- package/dist/fnode/index.CDct_kkF.js +0 -1
- package/dist/fnode/index.CMC8mlye.js +0 -1
- package/dist/fnode/index.CmMM-Ek9.js +0 -1
- package/dist/fnode/index.CuMyez3E.js +0 -1
- package/dist/fnode/index.CzAV0S36.js +0 -1
- package/dist/fnode/index.D2N9YZmA.js +0 -1
- package/dist/fnode/index.D3p7pncT.js +0 -1
- package/dist/fnode/index.DG8TqL-1.js +0 -1
- package/dist/fnode/index.DI3yyTtl.js +0 -1
- package/dist/fnode/index.DWpw12No.js +0 -1
- package/dist/fnode/index.DrwlOzAe.js +0 -1
- package/dist/fnode/index.N_a5FdgA.js +0 -1
- package/dist/fnode/index.Q-CYRcna.js +0 -1
- package/dist/fnode/index.UNoFg95r.js +0 -1
- package/dist/fnode/index.W6RYgypK.js +0 -1
- package/dist/fnode/index.xd8c7XMr.js +0 -1
- package/template/fnet/core/print.js +0 -1
- package/template/fnet/node/src/default/macros/workflow-header.js.njk +0 -7
package/readme.md
CHANGED
|
@@ -16,12 +16,18 @@
|
|
|
16
16
|
|
|
17
17
|
## Overview
|
|
18
18
|
|
|
19
|
-
Flownet is a
|
|
19
|
+
Flownet is a low-level flow framework that separates **Core** (your business logic) from **Layers** (infrastructure, dev, build, runtime, and delivery). This separation allows developers to focus on functional code while Flownet automates the surrounding infrastructure. The `@fnet/cli` package provides command-line tools to create, build, and manage Flownet projects.
|
|
20
|
+
|
|
21
|
+
Flownet provides primitives for composing workflows similar to how React provides components for UI development. It emphasizes a **schema-first approach** with **deterministic core**, enabling **multi-runtime portability**.
|
|
20
22
|
|
|
21
23
|
### Key Features
|
|
22
24
|
|
|
25
|
+
- **Core vs Layers Architecture**: Separate your business logic (Core) from infrastructure (Layers) for cleaner, more maintainable code
|
|
26
|
+
- **Nodes & Flows**: Reusable functional units (Nodes) with explicit I/O schemas, orchestrated by Flows
|
|
27
|
+
- **I/O Contracts**: Schema-first contracts define clear input/output expectations for deterministic behavior
|
|
28
|
+
- **Automatic Dependency Detection**: Simplified dependency management across your project
|
|
29
|
+
- **Multi-Runtime Support**: Deploy to Node.js, Bun, Deno, or Python - choose the best runtime for each task
|
|
23
30
|
- **Language Agnostic**: Support for multiple programming languages (JavaScript, Python) in the same project
|
|
24
|
-
- **Runtime Flexibility**: Choose the best runtime for each task (Node.js, Python, Bun)
|
|
25
31
|
- **Unified Interface**: Consistent commands across different project types
|
|
26
32
|
- **Tag-Based Configuration**: Powerful conditional configuration with `--ftag` parameter
|
|
27
33
|
- **Isolated Workspace**: All build artifacts and dependencies are kept in `.workspace` directory
|
|
@@ -97,54 +103,95 @@ fbin list
|
|
|
97
103
|
fbin uninstall awesome-tool --yes
|
|
98
104
|
```
|
|
99
105
|
|
|
106
|
+
## Core Concepts
|
|
107
|
+
|
|
108
|
+
### Nodes & Flows
|
|
109
|
+
|
|
110
|
+
**Nodes** are reusable functional units that encapsulate business logic with explicit input/output schemas. Each Node:
|
|
111
|
+
|
|
112
|
+
- Has a deterministic, pure function at its core
|
|
113
|
+
- Defines clear I/O contracts (input and output schemas)
|
|
114
|
+
- Can be composed and reused across different Flows
|
|
115
|
+
- Supports automatic dependency detection
|
|
116
|
+
|
|
117
|
+
**Flows** orchestrate Nodes and sub-Flows to create complex workflows. Flows:
|
|
118
|
+
|
|
119
|
+
- Connect multiple Nodes with explicit data contracts
|
|
120
|
+
- Enable multi-runtime portability through schema-first design
|
|
121
|
+
- Support complex data transformations and conditional logic
|
|
122
|
+
- Maintain deterministic behavior across different runtimes
|
|
123
|
+
|
|
124
|
+
### I/O Contracts
|
|
125
|
+
|
|
126
|
+
Flownet uses schema-first contracts to define clear input and output expectations. This approach:
|
|
127
|
+
|
|
128
|
+
- Ensures deterministic behavior across different runtimes
|
|
129
|
+
- Enables automatic validation and type checking
|
|
130
|
+
- Facilitates multi-runtime portability
|
|
131
|
+
- Improves code clarity and maintainability
|
|
132
|
+
|
|
100
133
|
## Project Types
|
|
101
134
|
|
|
102
135
|
Flownet supports two main project types:
|
|
103
136
|
|
|
104
137
|
### fnode Project
|
|
105
138
|
|
|
106
|
-
An **fnode project** (Flow Node Project) is a classic/node-style project that focuses on creating reusable
|
|
139
|
+
An **fnode project** (Flow Node Project) is a classic/node-style project that focuses on creating reusable Nodes or standalone applications. These projects:
|
|
107
140
|
|
|
108
141
|
- Use `fnode.yaml` as their configuration file
|
|
109
142
|
- Typically contain a single code file in the `src` directory
|
|
110
143
|
- Can be built with different runtimes (Node.js, Python, Bun)
|
|
111
144
|
- Support multiple programming languages simultaneously
|
|
145
|
+
- Ideal for creating reusable components with explicit I/O contracts
|
|
112
146
|
|
|
113
147
|
### fnet Project
|
|
114
148
|
|
|
115
|
-
An **fnet project** (Flow Project) is a workflow-oriented project that focuses on orchestrating multiple
|
|
149
|
+
An **fnet project** (Flow Project) is a workflow-oriented project that focuses on orchestrating multiple Nodes and Flows. These projects:
|
|
116
150
|
|
|
117
151
|
- Use `fnet.yaml` as their configuration file
|
|
118
|
-
- Define workflows that connect multiple
|
|
152
|
+
- Define workflows that connect multiple Nodes and sub-Flows
|
|
119
153
|
- Support complex data flows and transformations
|
|
154
|
+
- Enable multi-runtime deployment strategies
|
|
155
|
+
- Ideal for building complex business logic orchestrations
|
|
120
156
|
|
|
121
157
|
## CLI Tools
|
|
122
158
|
|
|
123
|
-
Flownet provides
|
|
159
|
+
Flownet provides five main CLI tools:
|
|
124
160
|
|
|
125
|
-
- **`fnode`**: For Node/classic projects (uses `fnode.yaml`)
|
|
126
|
-
- **`fnet`**: For Workflow projects (uses `fnet.yaml`)
|
|
161
|
+
- **`fnode`**: For Node/classic projects (uses `fnode.yaml`) - create and manage reusable Nodes
|
|
162
|
+
- **`fnet`**: For Workflow projects (uses `fnet.yaml`) - create and manage Flows that orchestrate Nodes
|
|
127
163
|
- **`frun`**: Unified interface that works with both project types (auto-detects project file)
|
|
128
164
|
- **`fbin`**: Binary management system for installing, compiling, and managing CLI tools
|
|
165
|
+
- **`fservice`**: Service management for deploying and running Flownet applications
|
|
129
166
|
|
|
130
|
-
## Multi-Language Support
|
|
167
|
+
## Multi-Language & Multi-Runtime Support
|
|
131
168
|
|
|
132
|
-
Flownet supports multiple programming languages simultaneously within the same project:
|
|
169
|
+
Flownet supports multiple programming languages and runtimes simultaneously within the same project:
|
|
133
170
|
|
|
134
171
|
```text
|
|
135
172
|
my-project/
|
|
136
173
|
├── src/
|
|
137
|
-
│ ├── index.js # JavaScript implementation (used by
|
|
174
|
+
│ ├── index.js # JavaScript implementation (used by Node.js and Bun)
|
|
138
175
|
│ └── index.py # Python implementation
|
|
139
176
|
├── fnode.yaml # Project configuration file
|
|
140
177
|
└── .workspace/ # Build infrastructure (managed by CLI)
|
|
141
178
|
```
|
|
142
179
|
|
|
143
|
-
|
|
180
|
+
### Supported Runtimes
|
|
181
|
+
|
|
182
|
+
- **Node.js**: JavaScript/TypeScript execution with full npm ecosystem support
|
|
183
|
+
- **Bun**: Fast JavaScript runtime with improved performance
|
|
184
|
+
- **Deno**: Secure JavaScript/TypeScript runtime with built-in tooling
|
|
185
|
+
- **Python**: Python 3.x for data processing and scientific computing
|
|
186
|
+
|
|
187
|
+
### Multi-Runtime Portability
|
|
188
|
+
|
|
189
|
+
Thanks to Flownet's schema-first approach and deterministic core:
|
|
144
190
|
|
|
145
|
-
- Write your core logic once and
|
|
146
|
-
- Choose the best
|
|
147
|
-
-
|
|
191
|
+
- Write your core logic once and deploy to multiple runtimes
|
|
192
|
+
- Choose the best runtime for each specific use case
|
|
193
|
+
- Migrate between runtimes without changing your business logic
|
|
194
|
+
- Use JavaScript with Node.js for quick development, Python for data processing, and Bun for improved performance
|
|
148
195
|
|
|
149
196
|
## Tag-Based Configuration
|
|
150
197
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import getValue from "get-value";
|
|
2
|
-
import setValue from "set-value";
|
|
3
|
-
import
|
|
1
|
+
// import getValue from "get-value";
|
|
2
|
+
// import setValue from "set-value";
|
|
3
|
+
import { setProperty, getProperty } from "dot-prop";
|
|
4
4
|
|
|
5
5
|
export default class Object {
|
|
6
6
|
#property;
|
|
@@ -14,14 +14,14 @@ export default class Object {
|
|
|
14
14
|
this.#context = context;
|
|
15
15
|
|
|
16
16
|
this.get = (path, options) => {
|
|
17
|
-
return
|
|
17
|
+
return getProperty(this.#property, path, options);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
this.set = (path, value, options) => {
|
|
21
|
-
return
|
|
21
|
+
return setProperty(this.#property, path, value, options);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
this.print =
|
|
24
|
+
this.print = console.log;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
get module() {
|
|
@@ -29,19 +29,19 @@ export default class Object {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
getModule(path) {
|
|
32
|
-
return
|
|
32
|
+
return getProperty(this.#module, path);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
setModule(path, module) {
|
|
36
36
|
if (typeof module !== "function") throw new Error("Module must be a function");
|
|
37
|
-
return
|
|
37
|
+
return setProperty(this.#module, path, module);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
get getValue() {
|
|
41
|
-
return
|
|
41
|
+
return getProperty;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
get setValue() {
|
|
45
|
-
return
|
|
45
|
+
return setProperty;
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -72,14 +72,14 @@
|
|
|
72
72
|
{% if atom.doc.features.cli.enabled %}
|
|
73
73
|
{% if atom.doc.features.project.format ==='cjs' %}
|
|
74
74
|
,"cli": "bun {{atom.doc.features.cli.node_options}} {{atom.doc.features.cli.dir}}/index.cjs"
|
|
75
|
-
{% if atom.doc.features.cli.mcp.enabled===true %}
|
|
75
|
+
{% if atom.doc.features.cli.mcp.enabled === true %}
|
|
76
76
|
,"mcp": "bun {{atom.doc.features.cli.node_options}} {{atom.doc.features.cli.dir}}/index.cjs --cli-mode=mcp"
|
|
77
77
|
,"mcp-inspect": "bunx @modelcontextprotocol/inspector bun {{atom.doc.features.cli.node_options}} {{atom.doc.features.cli.dir}}/index.cjs --cli-mode=mcp"
|
|
78
78
|
{% endif %}
|
|
79
79
|
{% else %}
|
|
80
80
|
,"cli": "bun {{atom.doc.features.cli.node_options}} {{atom.doc.features.cli.output.file}}"
|
|
81
|
-
,"cli:dev": "bun {{atom.doc.features.cli.node_options}} {{atom.doc.features.cli.input.file}}"
|
|
82
|
-
{% if atom.doc.features.cli.mcp.enabled===true %}
|
|
81
|
+
,"cli:dev": "NODE_PRESERVE_SYMLINKS=1 bun {{atom.doc.features.cli.node_options}} {{atom.doc.features.cli.input.file}}"
|
|
82
|
+
{% if atom.doc.features.cli.mcp.enabled === true %}
|
|
83
83
|
,"cli:mcp": "bun {{atom.doc.features.cli.node_options}} {{atom.doc.features.cli.output.file}} --cli-mode=mcp"
|
|
84
84
|
,"cli:mcp:inspect": "bunx @modelcontextprotocol/inspector bun {{atom.doc.features.cli.node_options}} {{atom.doc.features.cli.output.file}} --cli-mode=mcp"
|
|
85
85
|
,"cli:mcp:dev": "bun {{atom.doc.features.cli.node_options}} {{atom.doc.features.cli.input.file}} --cli-mode=mcp"
|
|
@@ -89,6 +89,9 @@
|
|
|
89
89
|
,"cli:compile": "fbin compile {{atom.doc.features.cli.output.file}} -o .bin/{{atom.doc['npm::bin'] or atom.doc['name'] or atom['id']}} --yes"
|
|
90
90
|
,"cli:compile:dev": "fbin compile {{atom.doc.features.cli.input.file}} -o .bin/{{atom.doc['npm::bin'] or atom.doc['name'] or atom['id']}} --yes"
|
|
91
91
|
,"cli:install": "fbin install ./.bin/{{atom.doc['npm::bin'] or atom.doc['name'] or atom['id']}} --yes"
|
|
92
|
+
,"cli:install:symlink": "fbin install ./.bin/{{atom.doc['npm::bin'] or atom.doc['name'] or atom['id']}} --yes --symlink"
|
|
93
|
+
,"cli:uninstall": "fbin uninstall {{atom.doc['npm::bin'] or atom.doc['name'] or atom['id']}} --yes"
|
|
94
|
+
|
|
92
95
|
{% endif %}
|
|
93
96
|
|
|
94
97
|
{% if atom.doc.features.app.enabled %}
|
|
@@ -1,319 +1,9 @@
|
|
|
1
1
|
{% if atom.doc.features.cli.enabled===true %}
|
|
2
2
|
|
|
3
|
-
{
|
|
4
|
-
{%
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
9
|
-
import express from "express";
|
|
10
|
-
{% endmacro %}
|
|
3
|
+
{% if atom.doc.features.cli.template.version ==='v1' %}
|
|
4
|
+
{% include "./index.js.v1.njk" %}
|
|
5
|
+
{% else %}
|
|
6
|
+
{% include "./v2/index.js.njk" %}
|
|
7
|
+
{% endif %}
|
|
11
8
|
|
|
12
|
-
{% macro mcpModeCodeExtended(runFn) %}
|
|
13
|
-
if (cliMode === 'mcp') {
|
|
14
|
-
// MCP mode code
|
|
15
|
-
const server = new Server({
|
|
16
|
-
name: "{{atom.doc.features.cli.mcp.name or atom.doc.name}}",
|
|
17
|
-
version: "{{atom.doc.version or '0.0.1'}}"
|
|
18
|
-
}, {
|
|
19
|
-
capabilities: {
|
|
20
|
-
tools: {}
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// Define available tools
|
|
25
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
26
|
-
return {
|
|
27
|
-
tools: [{
|
|
28
|
-
name: "{{atom.doc.features.cli.mcp.tool.name or atom.doc.name}}",
|
|
29
|
-
description: "{{atom.doc.features.cli.mcp.tool.description or atom.doc.description}}",
|
|
30
|
-
inputSchema: inputSchema,
|
|
31
|
-
}]
|
|
32
|
-
};
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Handle tool execution
|
|
36
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
37
|
-
if (request.params.name === "{{atom.doc.features.cli.mcp.tool.name or atom.doc.name}}") {
|
|
38
|
-
try {
|
|
39
|
-
const result = await {{ runFn }}(request.params.arguments, { Engine });
|
|
40
|
-
return {
|
|
41
|
-
content: [{
|
|
42
|
-
type: "text",
|
|
43
|
-
text: JSON.stringify(result)
|
|
44
|
-
}]
|
|
45
|
-
};
|
|
46
|
-
} catch (error) {
|
|
47
|
-
return {
|
|
48
|
-
content: [{
|
|
49
|
-
type: "text",
|
|
50
|
-
text: `Error: ${error.message}`
|
|
51
|
-
}],
|
|
52
|
-
isError: true
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
throw new Error("Tool not found");
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Get transport type from arguments
|
|
60
|
-
const transportType = args['mcp-transport'] || args.mcp_transport || 'stdio';
|
|
61
|
-
let transport;
|
|
62
|
-
|
|
63
|
-
if (transportType === 'stdio') {
|
|
64
|
-
// Use stdio transport
|
|
65
|
-
transport = new StdioServerTransport();
|
|
66
|
-
} else if (transportType === 'sse') {
|
|
67
|
-
// Use SSE transport
|
|
68
|
-
const app = express();
|
|
69
|
-
app.use(express.json());
|
|
70
|
-
|
|
71
|
-
const port = args['cli-port'] || args.cli_port || 3000;
|
|
72
|
-
const server = app.listen(port, () => {
|
|
73
|
-
console.log(`MCP server started with SSE transport on port ${port}`);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
transport = new StreamableHTTPServerTransport({
|
|
77
|
-
sessionIdGenerator: () => Math.random().toString(36).substring(2, 15),
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
app.post('/sse', async (req, res) => {
|
|
81
|
-
await transport.handleRequest(req, res, req.body);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
app.get('/sse', async (req, res) => {
|
|
85
|
-
await transport.handleRequest(req, res);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
app.delete('/sse', async (req, res) => {
|
|
89
|
-
await transport.handleRequest(req, res);
|
|
90
|
-
});
|
|
91
|
-
} else {
|
|
92
|
-
console.error(`Unknown MCP transport type: ${transportType}`);
|
|
93
|
-
console.error(`Supported types: stdio, sse`);
|
|
94
|
-
process.exit(1);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
await server.connect(transport);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
{% endmacro %}
|
|
101
|
-
|
|
102
|
-
{% macro mcpModeCodeEngine(engineVar) %}
|
|
103
|
-
if (cliMode === 'mcp') {
|
|
104
|
-
// MCP mode code
|
|
105
|
-
const server = new Server({
|
|
106
|
-
name: "{{atom.doc.features.cli.mcp.name or atom.doc.name}}",
|
|
107
|
-
version: "{{atom.doc.version or '0.0.1'}}"
|
|
108
|
-
}, {
|
|
109
|
-
capabilities: {
|
|
110
|
-
tools: {}
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// Define available tools
|
|
115
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
116
|
-
return {
|
|
117
|
-
tools: [{
|
|
118
|
-
name: "{{atom.doc.features.cli.mcp.tool.name or atom.doc.name}}",
|
|
119
|
-
description: "{{atom.doc.features.cli.mcp.tool.description or atom.doc.description}}",
|
|
120
|
-
inputSchema: inputSchema,
|
|
121
|
-
}]
|
|
122
|
-
};
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
// Handle tool execution
|
|
126
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
127
|
-
if (request.params.name === "{{atom.doc.features.cli.mcp.tool.name or atom.doc.name}}") {
|
|
128
|
-
try {
|
|
129
|
-
const result = await {{ engineVar }}.run(request.params.arguments);
|
|
130
|
-
return {
|
|
131
|
-
content: [{
|
|
132
|
-
type: "text",
|
|
133
|
-
text: JSON.stringify(result)
|
|
134
|
-
}]
|
|
135
|
-
};
|
|
136
|
-
} catch (error) {
|
|
137
|
-
return {
|
|
138
|
-
content: [{
|
|
139
|
-
type: "text",
|
|
140
|
-
text: `Error: ${error.message}`
|
|
141
|
-
}],
|
|
142
|
-
isError: true
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
throw new Error("Tool not found");
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// Note: Direct access to workflow nodes is not implemented in this version
|
|
150
|
-
// In a future version, we could expose workflow nodes as separate MCP tools
|
|
151
|
-
|
|
152
|
-
// Get transport type from arguments
|
|
153
|
-
const transportType = args['mcp-transport'] || args.mcp_transport || 'stdio';
|
|
154
|
-
let transport;
|
|
155
|
-
|
|
156
|
-
if (transportType === 'stdio') {
|
|
157
|
-
// Use stdio transport
|
|
158
|
-
transport = new StdioServerTransport();
|
|
159
|
-
} else if (transportType === 'sse') {
|
|
160
|
-
// Use SSE transport
|
|
161
|
-
const app = express();
|
|
162
|
-
app.use(express.json());
|
|
163
|
-
|
|
164
|
-
const port = args['cli-port'] || args.cli_port || 3000;
|
|
165
|
-
const server = app.listen(port, () => {
|
|
166
|
-
console.log(`MCP server started with SSE transport on port ${port}`);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
transport = new StreamableHTTPServerTransport({
|
|
170
|
-
sessionIdGenerator: () => Math.random().toString(36).substring(2, 15),
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
app.post('/sse', async (req, res) => {
|
|
174
|
-
await transport.handleRequest(req, res, req.body);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
app.get('/sse', async (req, res) => {
|
|
178
|
-
await transport.handleRequest(req, res);
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
app.delete('/sse', async (req, res) => {
|
|
182
|
-
await transport.handleRequest(req, res);
|
|
183
|
-
});
|
|
184
|
-
} else {
|
|
185
|
-
console.error(`Unknown MCP transport type: ${transportType}`);
|
|
186
|
-
console.error(`Supported types: stdio, sse`);
|
|
187
|
-
process.exit(1);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
await server.connect(transport);
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
{% endmacro %}
|
|
194
|
-
|
|
195
|
-
{% macro httpModeCodeExpress(runFn, engineParam) %}
|
|
196
|
-
if (cliMode === 'http') {
|
|
197
|
-
// HTTP mode code using Express
|
|
198
|
-
const app = express();
|
|
199
|
-
app.use(express.json());
|
|
200
|
-
|
|
201
|
-
app.post('/{{atom.doc.features.cli.http.path or atom.doc.name}}', async (req, res) => {
|
|
202
|
-
try {
|
|
203
|
-
const result = await {{ runFn }}(req.body{{ engineParam }});
|
|
204
|
-
res.json(result);
|
|
205
|
-
} catch (error) {
|
|
206
|
-
res.status(500).json({ error: error.message });
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
const port = args['cli-port'] || args.cli_port || 3000;
|
|
211
|
-
app.listen(port, () => {
|
|
212
|
-
console.log(`HTTP server started on port ${port}`);
|
|
213
|
-
});
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
{% endmacro %}
|
|
217
|
-
|
|
218
|
-
{% macro defaultModeExtended() %}
|
|
219
|
-
if (cliMode === 'default') {
|
|
220
|
-
// Default mode code
|
|
221
|
-
return await runExtended(await argv(), { Engine });
|
|
222
|
-
}
|
|
223
|
-
{% endmacro %}
|
|
224
|
-
|
|
225
|
-
{% macro defaultModeEngine(engineVar) %}
|
|
226
|
-
if (cliMode === 'default') {
|
|
227
|
-
// Default mode code
|
|
228
|
-
const result = await {{ engineVar }}.run(await argv());
|
|
229
|
-
|
|
230
|
-
if (typeof result !== 'undefined') {
|
|
231
|
-
const stdout_format = args['stdout-format'] || args.stdout_format || null;
|
|
232
|
-
|
|
233
|
-
if (stdout_format === 'json') console.log(JSON.stringify(result, null, 2));
|
|
234
|
-
else console.log(result);
|
|
235
|
-
}
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
{% endmacro %}
|
|
239
|
-
|
|
240
|
-
{% macro runWithCatch() %}
|
|
241
|
-
run()
|
|
242
|
-
.catch((error) => {
|
|
243
|
-
console.error(error.message);
|
|
244
|
-
process.exit(1);
|
|
245
|
-
});
|
|
246
|
-
{% endmacro %}
|
|
247
|
-
|
|
248
|
-
{% macro runWithThenCatch() %}
|
|
249
|
-
run()
|
|
250
|
-
.then(() => {
|
|
251
|
-
{# process.exit(0); #}
|
|
252
|
-
})
|
|
253
|
-
.catch((error) => {
|
|
254
|
-
console.error(error.message);
|
|
255
|
-
process.exit(1);
|
|
256
|
-
});
|
|
257
|
-
{% endmacro %}
|
|
258
|
-
|
|
259
|
-
{# Main template starts here #}
|
|
260
|
-
import argv from '../default/input.args.js';
|
|
261
|
-
import { schema as inputSchema } from '../default/validate_input.js';
|
|
262
|
-
import { default as Engine } from '../default/{{atom.doc.features.cli_default_entry_file or atom.doc.features.main_default_entry_file}}';
|
|
263
|
-
|
|
264
|
-
{% if atom.doc.features.cli.mcp.enabled===true %}
|
|
265
|
-
{{ importMcpDependencies() }}
|
|
266
|
-
{% elif atom.doc.features.cli.http.enabled===true %}
|
|
267
|
-
// Using express for HTTP mode
|
|
268
|
-
import express from 'express';
|
|
269
|
-
{% endif %}
|
|
270
|
-
|
|
271
|
-
{% if atom.doc.features.cli.extend===true %}
|
|
272
|
-
{# TYPE 1 #}
|
|
273
|
-
import { default as runExtended } from '../../../cli/index.js';
|
|
274
|
-
import argsParser from 'yargs-parser';
|
|
275
|
-
|
|
276
|
-
const run = async () => {
|
|
277
|
-
const args = argsParser(process.argv.slice(2));
|
|
278
|
-
const cliMode = args['cli-mode'] || args.cli_mode || 'default';
|
|
279
|
-
|
|
280
|
-
{{ defaultModeExtended() }}
|
|
281
|
-
|
|
282
|
-
{% if atom.doc.features.cli.mcp.enabled===true %}
|
|
283
|
-
{{ mcpModeCodeExtended('runExtended') }}
|
|
284
|
-
{% endif %}
|
|
285
|
-
|
|
286
|
-
{% if atom.doc.features.cli.http.enabled===true %}
|
|
287
|
-
{{ httpModeCodeExpress('runExtended', ', { Engine }') }}
|
|
288
|
-
{% endif %}
|
|
289
|
-
|
|
290
|
-
console.error(`Unknown CLI mode: ${cliMode}`);
|
|
291
|
-
process.exit(1);
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
{{ runWithThenCatch() }}
|
|
295
|
-
{% else %}
|
|
296
|
-
{# TYPE 2 #}
|
|
297
|
-
import argsParser from 'yargs-parser';
|
|
298
|
-
const run = async () => {
|
|
299
|
-
const args =argsParser(process.argv.slice(2));
|
|
300
|
-
const cliMode = args['cli-mode'] || args.cli_mode || 'default';
|
|
301
|
-
const engine = new Engine();
|
|
302
|
-
|
|
303
|
-
{{ defaultModeEngine('engine') }}
|
|
304
|
-
|
|
305
|
-
{% if atom.doc.features.cli.mcp.enabled===true %}
|
|
306
|
-
{{ mcpModeCodeEngine('engine') }}
|
|
307
|
-
{% endif %}
|
|
308
|
-
|
|
309
|
-
{% if atom.doc.features.cli.http.enabled===true %}
|
|
310
|
-
{{ httpModeCodeExpress('engine.run', '') }}
|
|
311
|
-
{% endif %}
|
|
312
|
-
|
|
313
|
-
console.error(`Unknown CLI mode: ${cliMode}`);
|
|
314
|
-
process.exit(1);
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
{{ runWithCatch() }}
|
|
318
9
|
{% endif %}
|
|
319
|
-
{% endif %}
|