langflower 0.1.1 → 0.1.3
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 +95 -105
- package/dist/{chunk-526FJL62.js → chunk-AO33IM2J.js} +1 -1
- package/dist/{chunk-WQZHA5FM.js → chunk-NIRPHJLO.js} +94 -33
- package/dist/index.js +298 -60
- package/docs/public/README.md +1 -0
- package/docs/public/getting-started.md +8 -1
- package/docs/public/launcher.md +110 -0
- package/package.json +1 -1
- package/ui-dist/apple-touch-icon.png +0 -0
- package/ui-dist/favicon-32x32.png +0 -0
- package/ui-dist/favicon.ico +0 -0
- package/ui-dist/index.html +4 -1
- package/ui-dist/main-JJURZFKA.js +318 -0
- package/vendor/node-sdk/dist/node-factory/define-tool-registrations/define-tool-registrations.d.ts +6 -6
- package/vendor/node-sdk/dist/node-factory/define-tool-registrations/define-tool-registrations.js +6 -6
- package/vendor/server/skeleton/skills/langflower-helper/SKILL.md +43 -10
- package/vendor/server/skeleton/skills/langflower-helper/architecture.md +9 -2
- package/vendor/server/skeleton/skills/langflower-helper/layout.md +12 -10
- package/vendor/server/skeleton/skills/langflower-node-writer/SKILL.md +69 -0
- package/vendor/server/skeleton/skills/langflower-workflow-writer/SKILL.md +15 -2
- package/vendor/server/skeleton/skills/spec-architect/SKILL.md +232 -0
- package/vendor/server/skeleton/workflows/advanced-coder.json +1 -0
- package/vendor/server/skeleton/workflows/simple-coder.json +1 -0
- package/ui-dist/main-X5M7PU3P.js +0 -317
package/README.md
CHANGED
|
@@ -3,125 +3,83 @@
|
|
|
3
3
|
> **Disclaimer:** Langflower is currently in internal testing. Anyone can
|
|
4
4
|
> download and try it, but some functions may not be stable.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
and emit on one output at any time, without waiting for the rest. The
|
|
12
|
-
runtime wires those nodes into a workflow.
|
|
13
|
-
|
|
14
|
-
That is enough for complex processing chains — including loops and
|
|
15
|
-
conditions.
|
|
16
|
-
|
|
17
|
-
The trick is the same rule applied to models. Because ports fire on their
|
|
18
|
-
own, an LLM agent is just another reactive node: prompt and tools in;
|
|
19
|
-
response out; streaming tool log, reasoning, and draft as extra outputs
|
|
20
|
-
that can update while the run continues. All LLM-specific logic stays as
|
|
21
|
-
that node's internal state. It does not leak through the rest of the app.
|
|
22
|
-
|
|
23
|
-
## Open possibilities
|
|
24
|
-
|
|
25
|
-
Because every unit of work is a node, Langflower is not pinned to one
|
|
26
|
-
product shape — coding harness, chat harness, or any other fixed loop.
|
|
27
|
-
Workflows stay flexible. With the right wiring they fit the job.
|
|
28
|
-
|
|
29
|
-
Need a chat? Wire user input, an agent, and HITL feedback. Agent-to-agent
|
|
30
|
-
dialogue is two agents connected together. Coding is the same graph plus
|
|
31
|
-
file-ops tools. Tired of “I’m done” while the code still does not compile?
|
|
32
|
-
Write a custom review-gate node. The agent never gets a path around it.
|
|
33
|
-
|
|
34
|
-
## Hard harness
|
|
35
|
-
|
|
36
|
-
The sequence is the workflow topology. That is how Langflower orchestrates
|
|
37
|
-
complex work: QA, review, and code checks sit on the graph, so agents
|
|
38
|
-
cannot skip them. A well-configured workflow forces high-quality output —
|
|
39
|
-
the model does not get to declare itself finished.
|
|
6
|
+
Langflower is a local visual workflow for a project folder: a node graph
|
|
7
|
+
that runs agents, tools, checks, and human gates on your machine. You
|
|
8
|
+
author the pipeline on a canvas in the browser you already have. The LLM
|
|
9
|
+
is a node in that graph, not the product — the topology you wire decides
|
|
10
|
+
what happens next. Data, custom nodes, and workflows stay in that folder.
|
|
40
11
|
|
|
41
12
|
**Not another chat harness. A local node graph.**
|
|
42
13
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
### Scoped to a folder
|
|
51
|
-
|
|
52
|
-
You start from a folder. Data, custom nodes, and workflows are scoped to
|
|
53
|
-
that workspace. Open the folder, and the graph, files, and run belong
|
|
54
|
-
together.
|
|
55
|
-
|
|
56
|
-
### Extensible even now
|
|
57
|
-
|
|
58
|
-
This is still an early version, but Langflower already supports custom
|
|
59
|
-
nodes and custom node packs. Share and reuse workflows and nodes the same
|
|
60
|
-
way you share the rest of the project.
|
|
14
|
+
The unit of work is a **reactive node**: typed inputs, typed outputs.
|
|
15
|
+
Each port fires on its own — a node can emit on one output without
|
|
16
|
+
waiting for the rest, so the node chooses the path. That is enough for
|
|
17
|
+
cycles and conditional branches, not only a straight chain. An LLM agent
|
|
18
|
+
is the same kind of node — prompt and tools in, response out. Coding,
|
|
19
|
+
chat, agent-to-agent dialogue, and custom gates are the same idea: pick
|
|
20
|
+
the graph, not a fixed loop.
|
|
61
21
|
|
|
62
22
|

|
|
63
23
|
|
|
64
|
-
|
|
24
|
+
The default **starter** workflow: an onboarding helper plus a Writer
|
|
25
|
+
sub-agent for workflows and custom nodes.
|
|
65
26
|
|
|
66
|
-
|
|
67
|
-
2. Open a workflow on the canvas, or create one for the task.
|
|
68
|
-
3. Run it and watch agents, tools, checks, and file changes move through
|
|
69
|
-
visible stages.
|
|
70
|
-
4. Approve, reject, or add feedback when the workflow asks for a human
|
|
71
|
-
decision.
|
|
72
|
-
5. Find the resulting files and data in the same workspace.
|
|
73
|
-
|
|
74
|
-
## Under the hood
|
|
75
|
-
|
|
76
|
-
The core is a reactive runtime that wires nodes together. The **node SDK**
|
|
77
|
-
is the public contract: any node that follows it can run on that runtime.
|
|
78
|
-
**Common nodes** is the built-in catalog. It uses the same SDK as custom
|
|
79
|
-
node packs.
|
|
27
|
+

|
|
80
28
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
For a short builder-oriented picture, see
|
|
88
|
-
[How it works](https://github.com/earthdmitriy/langflower/blob/master/docs/public/how-it-works.md).
|
|
29
|
+
**Langflower dev** — the workflow used to develop Langflower itself.
|
|
30
|
+
Memory tools, ts-scan (MCP), and custom **LF Dev Tools** merge in a tool
|
|
31
|
+
collection and fan out to the agents. The prompt passes **lf-review-gate**
|
|
32
|
+
first (format, typecheck, tests) so Plan starts from a green tree. A
|
|
33
|
+
human review gate accepts the plan, then Coder works; the result must
|
|
34
|
+
pass lf-review-gate again, then a human review gate.
|
|
89
35
|
|
|
90
36
|
## Why Langflower
|
|
91
37
|
|
|
92
|
-
- **
|
|
93
|
-
|
|
94
|
-
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
the
|
|
38
|
+
- **The graph is the harness.** QA, review, build, and tests sit on the
|
|
39
|
+
topology, so the agent cannot skip them or declare itself finished. A
|
|
40
|
+
review-gate has no path around it.
|
|
41
|
+
- **Safe tools, not a general shell.** Wrap format, build, and unit tests
|
|
42
|
+
as custom nodes that expose a **ToolHandle**. You do not need a general
|
|
43
|
+
bash tool that could accidentally wipe all data from your disk. If a
|
|
44
|
+
command must stay open-ended, the workflow can still ask for approval
|
|
45
|
+
first.
|
|
46
|
+
- **Your browser, not a bundled one.** Close the tab and free those
|
|
47
|
+
resources; the server keeps the run. Reopen it, and the UI catches up.
|
|
48
|
+
|
|
49
|
+
Versus chat-style harnesses (OpenCode-like): order comes from the graph,
|
|
50
|
+
not from the model deciding it is done. Versus cloud graph tools
|
|
51
|
+
(Langflow, n8n): the same idea of wiring nodes, aimed at a folder on
|
|
52
|
+
your machine — home or a closed network with internal providers — not at
|
|
53
|
+
hosting a service.
|
|
54
|
+
|
|
55
|
+
**MCP** and **skills** work as usual. Custom nodes sit on top of the same
|
|
56
|
+
**ToolHandle** contract as built-ins.
|
|
102
57
|
|
|
103
|
-
##
|
|
58
|
+
## Quick start
|
|
104
59
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
60
|
+
If you do not want to bother with a terminal, use the **desktop
|
|
61
|
+
launcher**. Pick a project folder, click **Start**, and the editor opens
|
|
62
|
+
in the browser you already have. Several folders can run at once, each
|
|
63
|
+
on its own port. The launcher takes care of missing Node.js and
|
|
64
|
+
Langflower, and checks for Langflower updates for you. It does not
|
|
65
|
+
update itself — download a newer zip when you want a new window.
|
|
109
66
|
|
|
110
|
-
|
|
111
|
-
folder on your machine — home or a closed network with internal
|
|
112
|
-
providers — not at hosting a service or cloning ETL in the cloud.
|
|
67
|
+

|
|
113
68
|
|
|
114
|
-
|
|
69
|
+
Download a Windows or macOS zip from
|
|
70
|
+
[GitHub Releases](https://github.com/earthdmitriy/langflower/releases).
|
|
71
|
+
Unpack and run `langflower-launcher.exe` or `langflower-launcher`. It is
|
|
72
|
+
a portable app: no installation. The binary is unsigned, so Windows
|
|
73
|
+
Defender and macOS Gatekeeper might warn. On macOS: right-click the
|
|
74
|
+
file → **Open**. No Linux zip yet. Manual:
|
|
75
|
+
[Desktop launcher](https://github.com/earthdmitriy/langflower/blob/master/docs/public/launcher.md).
|
|
115
76
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
the editor and git tools you already have.
|
|
77
|
+
Langflower does not host a model. Live agent runs need you to **bring
|
|
78
|
+
your own key** (BYOK): add an OpenAI-compatible provider in Settings (gear icon)
|
|
79
|
+
and paste the API key there. Pointing at an environment variable is
|
|
80
|
+
optional. Simple nodes and the Fake LLM work without a key.
|
|
121
81
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
Requires **Node.js ≥ 22**.
|
|
82
|
+
From a terminal:
|
|
125
83
|
|
|
126
84
|
One-shot OS installers (Node LTS if needed + global `langflower`):
|
|
127
85
|
[install/](install/) (`windows.ps1`, `linux.sh`, `macos.sh`).
|
|
@@ -140,12 +98,43 @@ npm run install-local
|
|
|
140
98
|
npx langflower
|
|
141
99
|
```
|
|
142
100
|
|
|
143
|
-
|
|
144
|
-
in `.langflower/config.json`) for the selected folder. Use `-p` to
|
|
145
|
-
instances from different folders at once.
|
|
101
|
+
The CLI opens a local UI at `http://127.0.0.1:4010` (or `--port` / the
|
|
102
|
+
port in `.langflower/config.json`) for the selected folder. Use `-p` to
|
|
103
|
+
run several instances from different folders at once.
|
|
146
104
|
|
|
147
105
|
Full walkthrough: [Getting started](https://github.com/earthdmitriy/langflower/blob/master/docs/public/getting-started.md).
|
|
148
106
|
|
|
107
|
+
## How it works
|
|
108
|
+
|
|
109
|
+
1. Start Langflower with a project folder.
|
|
110
|
+
2. Open a workflow on the canvas, or create one for the task.
|
|
111
|
+
3. Run it and watch agents, tools, checks, and file changes move through
|
|
112
|
+
visible stages.
|
|
113
|
+
4. Approve, reject, or add feedback when the workflow asks for a human
|
|
114
|
+
decision.
|
|
115
|
+
5. Find the resulting files and data in the same workspace.
|
|
116
|
+
|
|
117
|
+
## What it lacks
|
|
118
|
+
|
|
119
|
+
- **Chat sessions.** You cannot save a chat and reopen it tomorrow.
|
|
120
|
+
Agent state lives inside the node for now. Maybe later.
|
|
121
|
+
- **Image and video.** No asset management for multimodal models. Not yet.
|
|
122
|
+
- **No built-in IDE or git UI.** We are not reinventing those wheels. Use
|
|
123
|
+
the editor and git tools you already have.
|
|
124
|
+
|
|
125
|
+
## Under the hood
|
|
126
|
+
|
|
127
|
+
The core is a reactive runtime. The **node SDK** is the public contract:
|
|
128
|
+
any node that follows it can run on that runtime. **Common nodes** is the
|
|
129
|
+
built-in catalog. It uses the same SDK as custom node packs.
|
|
130
|
+
|
|
131
|
+
The **server** compiles user-defined nodes and owns the live run. The
|
|
132
|
+
**UI** is a thin browser client over WebSocket; it does not own the
|
|
133
|
+
workflow.
|
|
134
|
+
|
|
135
|
+
For a short builder-oriented picture, see
|
|
136
|
+
[How it works](https://github.com/earthdmitriy/langflower/blob/master/docs/public/how-it-works.md).
|
|
137
|
+
|
|
149
138
|
Maintainers (monorepo only): [docs/RELEASE.md](https://github.com/earthdmitriy/langflower/blob/master/docs/RELEASE.md),
|
|
150
139
|
[packages/cli/README.md](https://github.com/earthdmitriy/langflower/blob/master/packages/cli/README.md).
|
|
151
140
|
|
|
@@ -155,6 +144,7 @@ Shipped with the npm package under [`docs/public/`](https://github.com/earthdmit
|
|
|
155
144
|
|
|
156
145
|
| Want to… | Start here |
|
|
157
146
|
| -------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
147
|
+
| Start without a terminal | [Desktop launcher](https://github.com/earthdmitriy/langflower/blob/master/docs/public/launcher.md) |
|
|
158
148
|
| Install and first run | [Getting started](https://github.com/earthdmitriy/langflower/blob/master/docs/public/getting-started.md) |
|
|
159
149
|
| Understand the product | [Product overview](https://github.com/earthdmitriy/langflower/blob/master/docs/public/product.md) |
|
|
160
150
|
| Use the canvas and runs | [Using the editor](https://github.com/earthdmitriy/langflower/blob/master/docs/public/using-the-editor.md) |
|
|
@@ -2,6 +2,75 @@ import { createRequire as __lfCreateRequire } from 'node:module';
|
|
|
2
2
|
const require = __lfCreateRequire(import.meta.url);
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
// packages/tools/dist/builtins/args.js
|
|
6
|
+
var asString = (args, key) => {
|
|
7
|
+
const value = args[key];
|
|
8
|
+
return typeof value === "string" ? value : void 0;
|
|
9
|
+
};
|
|
10
|
+
var asNumber = (args, key) => {
|
|
11
|
+
const value = args[key];
|
|
12
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
13
|
+
};
|
|
14
|
+
var asBoolean = (args, key, defaultValue) => {
|
|
15
|
+
const value = args[key];
|
|
16
|
+
return typeof value === "boolean" ? value : defaultValue;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// packages/tools/dist/builtins/ask_user/tool.js
|
|
20
|
+
var ASK_USER_ABORTED = "ask_user aborted.";
|
|
21
|
+
var invokeWithAbort = (work, signal) => {
|
|
22
|
+
if (signal === void 0) {
|
|
23
|
+
return work;
|
|
24
|
+
}
|
|
25
|
+
if (signal.aborted) {
|
|
26
|
+
return Promise.reject(new Error(ASK_USER_ABORTED));
|
|
27
|
+
}
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const onAbort = () => {
|
|
30
|
+
signal.removeEventListener("abort", onAbort);
|
|
31
|
+
reject(new Error(ASK_USER_ABORTED));
|
|
32
|
+
};
|
|
33
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
34
|
+
void work.then((text) => {
|
|
35
|
+
signal.removeEventListener("abort", onAbort);
|
|
36
|
+
resolve(text);
|
|
37
|
+
}, (error) => {
|
|
38
|
+
signal.removeEventListener("abort", onAbort);
|
|
39
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
var invoke = async (ctx, args) => {
|
|
44
|
+
const question = asString(args, "question");
|
|
45
|
+
if (question === void 0 || question.trim().length === 0) {
|
|
46
|
+
throw new Error("ask_user requires string argument \xABquestion\xBB.");
|
|
47
|
+
}
|
|
48
|
+
if (ctx.askUser === void 0) {
|
|
49
|
+
throw new Error("ask_user requires a live HITL host. No askUser hook is bound on this harness.");
|
|
50
|
+
}
|
|
51
|
+
return invokeWithAbort(ctx.askUser({ question: question.trim() }), ctx.signal);
|
|
52
|
+
};
|
|
53
|
+
var askUserTool = {
|
|
54
|
+
id: "ask_user",
|
|
55
|
+
registration: {
|
|
56
|
+
toolId: "ask_user",
|
|
57
|
+
name: "ask_user",
|
|
58
|
+
description: "Do not guess. If you are not sure, ask the user. Pauses the run so the operator can provide additional information.",
|
|
59
|
+
inputSchema: {
|
|
60
|
+
type: "object",
|
|
61
|
+
properties: {
|
|
62
|
+
question: {
|
|
63
|
+
type: "string",
|
|
64
|
+
description: "The question to show the operator. Be specific about what you need."
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
required: ["question"],
|
|
68
|
+
additionalProperties: false
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
invoke
|
|
72
|
+
};
|
|
73
|
+
|
|
5
74
|
// packages/tools/dist/builtins/bash/tool.js
|
|
6
75
|
import { spawn } from "node:child_process";
|
|
7
76
|
|
|
@@ -80,20 +149,6 @@ var formatNotFound = async (absolutePath, userPath) => {
|
|
|
80
149
|
return `File not found: \xAB${userPath}\xBB.${hint}`;
|
|
81
150
|
};
|
|
82
151
|
|
|
83
|
-
// packages/tools/dist/builtins/args.js
|
|
84
|
-
var asString = (args, key) => {
|
|
85
|
-
const value = args[key];
|
|
86
|
-
return typeof value === "string" ? value : void 0;
|
|
87
|
-
};
|
|
88
|
-
var asNumber = (args, key) => {
|
|
89
|
-
const value = args[key];
|
|
90
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
91
|
-
};
|
|
92
|
-
var asBoolean = (args, key, defaultValue) => {
|
|
93
|
-
const value = args[key];
|
|
94
|
-
return typeof value === "boolean" ? value : defaultValue;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
152
|
// packages/tools/dist/builtins/fence.js
|
|
98
153
|
var fenceOptions = (ctx) => ({
|
|
99
154
|
denyPaths: ctx.denyPaths,
|
|
@@ -103,7 +158,7 @@ var displayPath = (ctx, absolute) => toHarnessDisplayPath(ctx.projectRoot, absol
|
|
|
103
158
|
|
|
104
159
|
// packages/tools/dist/builtins/bash/tool.js
|
|
105
160
|
var MAX_BASH_OUTPUT = 1e5;
|
|
106
|
-
var
|
|
161
|
+
var invoke2 = async (ctx, args) => {
|
|
107
162
|
if (!ctx.bashEnabled) {
|
|
108
163
|
throw new Error("bash is disabled (default-deny). Enable bash on the project harness to run shell commands.");
|
|
109
164
|
}
|
|
@@ -170,13 +225,13 @@ var bashTool = {
|
|
|
170
225
|
additionalProperties: false
|
|
171
226
|
}
|
|
172
227
|
},
|
|
173
|
-
invoke
|
|
228
|
+
invoke: invoke2
|
|
174
229
|
};
|
|
175
230
|
|
|
176
231
|
// packages/tools/dist/builtins/create/tool.js
|
|
177
232
|
import fs2 from "node:fs/promises";
|
|
178
233
|
import path2 from "node:path";
|
|
179
|
-
var
|
|
234
|
+
var invoke3 = async (ctx, args) => {
|
|
180
235
|
const userPath = asString(args, "path");
|
|
181
236
|
const content = asString(args, "content");
|
|
182
237
|
if (userPath === void 0 || content === void 0) {
|
|
@@ -221,12 +276,12 @@ var createTool = {
|
|
|
221
276
|
additionalProperties: false
|
|
222
277
|
}
|
|
223
278
|
},
|
|
224
|
-
invoke:
|
|
279
|
+
invoke: invoke3
|
|
225
280
|
};
|
|
226
281
|
|
|
227
282
|
// packages/tools/dist/builtins/delete/tool.js
|
|
228
283
|
import fs3 from "node:fs/promises";
|
|
229
|
-
var
|
|
284
|
+
var invoke4 = async (ctx, args) => {
|
|
230
285
|
const userPath = asString(args, "path");
|
|
231
286
|
if (userPath === void 0) {
|
|
232
287
|
throw new Error("delete requires string argument \xABpath\xBB.");
|
|
@@ -261,12 +316,12 @@ var deleteTool = {
|
|
|
261
316
|
additionalProperties: false
|
|
262
317
|
}
|
|
263
318
|
},
|
|
264
|
-
invoke:
|
|
319
|
+
invoke: invoke4
|
|
265
320
|
};
|
|
266
321
|
|
|
267
322
|
// packages/tools/dist/builtins/edit/tool.js
|
|
268
323
|
import fs4 from "node:fs/promises";
|
|
269
|
-
var
|
|
324
|
+
var invoke5 = async (ctx, args) => {
|
|
270
325
|
const userPath = asString(args, "path");
|
|
271
326
|
const oldString = asString(args, "oldString");
|
|
272
327
|
const newString = asString(args, "newString");
|
|
@@ -323,7 +378,7 @@ var editTool = {
|
|
|
323
378
|
additionalProperties: false
|
|
324
379
|
}
|
|
325
380
|
},
|
|
326
|
-
invoke:
|
|
381
|
+
invoke: invoke5
|
|
327
382
|
};
|
|
328
383
|
|
|
329
384
|
// packages/tools/dist/builtins/glob/tool.js
|
|
@@ -546,7 +601,7 @@ var walkFiles = async (root, dir, options = true) => {
|
|
|
546
601
|
|
|
547
602
|
// packages/tools/dist/builtins/glob/tool.js
|
|
548
603
|
var MAX_GLOB_MATCHES = 200;
|
|
549
|
-
var
|
|
604
|
+
var invoke6 = async (ctx, args) => {
|
|
550
605
|
const pattern = asString(args, "pattern");
|
|
551
606
|
if (pattern === void 0) {
|
|
552
607
|
throw new Error("glob requires string argument \xABpattern\xBB.");
|
|
@@ -599,7 +654,7 @@ var globTool = {
|
|
|
599
654
|
additionalProperties: false
|
|
600
655
|
}
|
|
601
656
|
},
|
|
602
|
-
invoke:
|
|
657
|
+
invoke: invoke6
|
|
603
658
|
};
|
|
604
659
|
|
|
605
660
|
// packages/tools/dist/builtins/grep/tool.js
|
|
@@ -958,7 +1013,7 @@ var runGrepCascade = async (input, deps = {}) => {
|
|
|
958
1013
|
};
|
|
959
1014
|
|
|
960
1015
|
// packages/tools/dist/builtins/grep/tool.js
|
|
961
|
-
var
|
|
1016
|
+
var invoke7 = async (ctx, args) => {
|
|
962
1017
|
const pattern = asString(args, "pattern");
|
|
963
1018
|
if (pattern === void 0) {
|
|
964
1019
|
throw new Error("grep requires string argument \xABpattern\xBB.");
|
|
@@ -1014,7 +1069,7 @@ var grepTool = {
|
|
|
1014
1069
|
additionalProperties: false
|
|
1015
1070
|
}
|
|
1016
1071
|
},
|
|
1017
|
-
invoke:
|
|
1072
|
+
invoke: invoke7
|
|
1018
1073
|
};
|
|
1019
1074
|
|
|
1020
1075
|
// packages/tools/dist/builtins/read/tool.js
|
|
@@ -1048,7 +1103,7 @@ var sliceLines = (content, args) => {
|
|
|
1048
1103
|
}
|
|
1049
1104
|
return truncated;
|
|
1050
1105
|
};
|
|
1051
|
-
var
|
|
1106
|
+
var invoke8 = async (ctx, args) => {
|
|
1052
1107
|
const userPath = asString(args, "path");
|
|
1053
1108
|
if (userPath === void 0) {
|
|
1054
1109
|
throw new Error("read requires string argument \xABpath\xBB.");
|
|
@@ -1104,13 +1159,13 @@ var readTool = {
|
|
|
1104
1159
|
additionalProperties: false
|
|
1105
1160
|
}
|
|
1106
1161
|
},
|
|
1107
|
-
invoke:
|
|
1162
|
+
invoke: invoke8
|
|
1108
1163
|
};
|
|
1109
1164
|
|
|
1110
1165
|
// packages/tools/dist/builtins/write/tool.js
|
|
1111
1166
|
import fs10 from "node:fs/promises";
|
|
1112
1167
|
import path8 from "node:path";
|
|
1113
|
-
var
|
|
1168
|
+
var invoke9 = async (ctx, args) => {
|
|
1114
1169
|
const userPath = asString(args, "path");
|
|
1115
1170
|
const content = asString(args, "content");
|
|
1116
1171
|
if (userPath === void 0 || content === void 0) {
|
|
@@ -1143,7 +1198,7 @@ var writeTool = {
|
|
|
1143
1198
|
additionalProperties: false
|
|
1144
1199
|
}
|
|
1145
1200
|
},
|
|
1146
|
-
invoke:
|
|
1201
|
+
invoke: invoke9
|
|
1147
1202
|
};
|
|
1148
1203
|
|
|
1149
1204
|
// packages/tools/dist/builtins/catalog.js
|
|
@@ -1155,7 +1210,8 @@ var BUILTIN_TOOLS = [
|
|
|
1155
1210
|
writeTool,
|
|
1156
1211
|
createTool,
|
|
1157
1212
|
deleteTool,
|
|
1158
|
-
bashTool
|
|
1213
|
+
bashTool,
|
|
1214
|
+
askUserTool
|
|
1159
1215
|
];
|
|
1160
1216
|
var BUILTIN_TOOL_IDS = BUILTIN_TOOLS.map((tool) => tool.id);
|
|
1161
1217
|
var BUILTIN_REGISTRATIONS = BUILTIN_TOOLS.map((tool) => tool.registration);
|
|
@@ -1172,7 +1228,8 @@ var DEFAULT_PERMISSION_CONFIG = {
|
|
|
1172
1228
|
write: { "*": "allow" },
|
|
1173
1229
|
create: { "*": "allow" },
|
|
1174
1230
|
delete: { "*": "allow" },
|
|
1175
|
-
bash: { "*": "allow" }
|
|
1231
|
+
bash: { "*": "allow" },
|
|
1232
|
+
ask_user: { "*": "allow" }
|
|
1176
1233
|
};
|
|
1177
1234
|
var DECISION_RANK = {
|
|
1178
1235
|
deny: 3,
|
|
@@ -1261,6 +1318,9 @@ var permissionDetailForCall = (toolId, args) => {
|
|
|
1261
1318
|
if (toolId === "bash") {
|
|
1262
1319
|
return typeof args.command === "string" ? args.command : "";
|
|
1263
1320
|
}
|
|
1321
|
+
if (toolId === "ask_user") {
|
|
1322
|
+
return typeof args.question === "string" ? args.question : "";
|
|
1323
|
+
}
|
|
1264
1324
|
if (typeof args.path === "string" && args.path.length > 0) {
|
|
1265
1325
|
return args.path.replace(/\\/g, "/");
|
|
1266
1326
|
}
|
|
@@ -1385,7 +1445,8 @@ var createProjectHarness = (options) => {
|
|
|
1385
1445
|
projectRoot: options.projectRoot,
|
|
1386
1446
|
denyPaths: options.denyPaths ?? [],
|
|
1387
1447
|
allowedRoots: options.allowedRoots ?? [],
|
|
1388
|
-
bashEnabled: options.bashEnabled === true
|
|
1448
|
+
bashEnabled: options.bashEnabled === true,
|
|
1449
|
+
...options.askUser !== void 0 ? { askUser: options.askUser } : {}
|
|
1389
1450
|
};
|
|
1390
1451
|
const permission = {
|
|
1391
1452
|
...DEFAULT_PERMISSION_CONFIG,
|