farmon 0.1.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/LICENSE +21 -0
- package/README.md +163 -0
- package/dist/bin/farmon.js +12 -0
- package/dist/bin/farmon.js.map +1 -0
- package/dist/execute/agents/index.js +19 -0
- package/dist/execute/agents/index.js.map +1 -0
- package/dist/execute/agents/instruction-classifier-agent.js +16 -0
- package/dist/execute/agents/instruction-classifier-agent.js.map +1 -0
- package/dist/execute/agents/mutation-agent.js +272 -0
- package/dist/execute/agents/mutation-agent.js.map +1 -0
- package/dist/execute/agents/query-agent.js +118 -0
- package/dist/execute/agents/query-agent.js.map +1 -0
- package/dist/execute/helpers/analyzers.js +8 -0
- package/dist/execute/helpers/analyzers.js.map +1 -0
- package/dist/execute/helpers/ensurers.js +1053 -0
- package/dist/execute/helpers/ensurers.js.map +1 -0
- package/dist/execute/helpers/finders.js +1454 -0
- package/dist/execute/helpers/finders.js.map +1 -0
- package/dist/execute/helpers/general.js +3736 -0
- package/dist/execute/helpers/general.js.map +1 -0
- package/dist/execute/helpers/import-helpers.js +183 -0
- package/dist/execute/helpers/import-helpers.js.map +1 -0
- package/dist/execute/helpers/parsers.js +840 -0
- package/dist/execute/helpers/parsers.js.map +1 -0
- package/dist/execute/helpers/prompt-maker.js +1163 -0
- package/dist/execute/helpers/prompt-maker.js.map +1 -0
- package/dist/execute/helpers/validators.js +40 -0
- package/dist/execute/helpers/validators.js.map +1 -0
- package/dist/execute/history/history-manager.js +1030 -0
- package/dist/execute/history/history-manager.js.map +1 -0
- package/dist/execute/history/rollback-handlers.js +2524 -0
- package/dist/execute/history/rollback-handlers.js.map +1 -0
- package/dist/execute/index.js +44 -0
- package/dist/execute/index.js.map +1 -0
- package/dist/execute/llm/call.js +103 -0
- package/dist/execute/llm/call.js.map +1 -0
- package/dist/execute/tasks/ast.js +3819 -0
- package/dist/execute/tasks/ast.js.map +1 -0
- package/dist/execute/tasks/generators.js +96 -0
- package/dist/execute/tasks/generators.js.map +1 -0
- package/dist/execute/tasks/index.js +7 -0
- package/dist/execute/tasks/index.js.map +1 -0
- package/dist/execute/tasks/mutations.js +8139 -0
- package/dist/execute/tasks/mutations.js.map +1 -0
- package/dist/execute/tasks/query.js +248 -0
- package/dist/execute/tasks/query.js.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/index.js +15 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama.js +40 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai-compatible.js +52 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/runtime/inject.js +250 -0
- package/dist/runtime/inject.js.map +1 -0
- package/dist/schemas/agent/action.schema.js +935 -0
- package/dist/schemas/agent/action.schema.js.map +1 -0
- package/dist/schemas/agent/index.js +4 -0
- package/dist/schemas/agent/index.js.map +1 -0
- package/dist/schemas/agent/llm.schema.js +16 -0
- package/dist/schemas/agent/llm.schema.js.map +1 -0
- package/dist/schemas/agent/planner.schema.js +17 -0
- package/dist/schemas/agent/planner.schema.js.map +1 -0
- package/dist/schemas/index.js +7 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/project/context.schema.js +2 -0
- package/dist/schemas/project/context.schema.js.map +1 -0
- package/dist/schemas/project/index.js +2 -0
- package/dist/schemas/project/index.js.map +1 -0
- package/dist/schemas/runtime/index.js +4 -0
- package/dist/schemas/runtime/index.js.map +1 -0
- package/dist/schemas/runtime/injector.schema.js +11 -0
- package/dist/schemas/runtime/injector.schema.js.map +1 -0
- package/dist/schemas/runtime/runtime.schema.js +73 -0
- package/dist/schemas/runtime/runtime.schema.js.map +1 -0
- package/dist/schemas/runtime/sse.schema.js +15 -0
- package/dist/schemas/runtime/sse.schema.js.map +1 -0
- package/dist/schemas/system/index.js +2 -0
- package/dist/schemas/system/index.js.map +1 -0
- package/dist/schemas/system/logger.schema.js +56 -0
- package/dist/schemas/system/logger.schema.js.map +1 -0
- package/dist/schemas/task/index.js +9 -0
- package/dist/schemas/task/index.js.map +1 -0
- package/dist/server/app-context.js +254 -0
- package/dist/server/app-context.js.map +1 -0
- package/dist/server/config.js +22 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/error.js +22 -0
- package/dist/server/error.js.map +1 -0
- package/dist/server/event-bus.js +60 -0
- package/dist/server/event-bus.js.map +1 -0
- package/dist/server/logger.js +57 -0
- package/dist/server/logger.js.map +1 -0
- package/dist/server/run.js +265 -0
- package/dist/server/run.js.map +1 -0
- package/dist/server/sse.js +143 -0
- package/dist/server/sse.js.map +1 -0
- package/dist/ui/assets/index-C4ydQSAw.css +2 -0
- package/dist/ui/assets/index-Dzo7S5xs.js +85 -0
- package/dist/ui/favicon.svg +1 -0
- package/dist/ui/icons.svg +24 -0
- package/dist/ui/index.html +14 -0
- package/dist/workers/prettier.js +11 -0
- package/dist/workers/prettier.js.map +1 -0
- package/package.json +114 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sarvpriy Arya
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Farmon
|
|
2
|
+
|
|
3
|
+
**Farmon** is an AI-powered coding assistant that understands and edits your React codebase through deterministic code transformations.
|
|
4
|
+
|
|
5
|
+
Unlike chat-based assistants that generate code snippets, Farmon analyzes your project, plans the required changes, and applies them directly to your source code while preserving project structure and formatting.
|
|
6
|
+
|
|
7
|
+
> **Status:** Early Preview 🚧
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Philosophy
|
|
12
|
+
|
|
13
|
+
Every week, a new LLM claims higher benchmark scores and better reasoning capabilities.
|
|
14
|
+
|
|
15
|
+
But there's a more practical question:
|
|
16
|
+
|
|
17
|
+
> **Can it reliably modify a real codebase over time?**
|
|
18
|
+
|
|
19
|
+
Software is deterministic. Large Language Models are probabilistic.
|
|
20
|
+
|
|
21
|
+
Farmon's goal is to bridge these two worlds by combining the reasoning ability of LLMs with deterministic software operations.
|
|
22
|
+
|
|
23
|
+
Today's AI coding tools often generate entire files or even complete projects in a single step. While this is impressive, the result can quickly become a black box—code that works, but is difficult to understand, review, debug, or evolve.
|
|
24
|
+
|
|
25
|
+
Farmon takes a different approach.
|
|
26
|
+
|
|
27
|
+
Instead of asking an LLM to generate an entire application, every request is decomposed into a sequence of small, deterministic mutation tasks. Each task performs one well-defined change to the existing codebase.
|
|
28
|
+
|
|
29
|
+
This keeps AI-generated software transparent rather than opaque. Every change can be inspected, reviewed, tested, undone, and reproduced.
|
|
30
|
+
|
|
31
|
+
The LLM decides **what** should change.
|
|
32
|
+
|
|
33
|
+
Farmon decides **how** that change is applied safely and consistently.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- 🤖 Natural language code editing
|
|
40
|
+
- ⚛️ React-aware component manipulation
|
|
41
|
+
- 🌳 AST-based code transformations
|
|
42
|
+
- 🎯 Deterministic mutation tasks
|
|
43
|
+
- ↩️ Built-in undo/redo architecture
|
|
44
|
+
- 🎨 Automatic code formatting
|
|
45
|
+
- 🔍 Project-aware code analysis
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Requirements
|
|
50
|
+
|
|
51
|
+
- Node.js 22+
|
|
52
|
+
- LLM API details (local or remote)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
Install Farmon:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npm install --save-dev farmon
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Create farmon.config.js
|
|
65
|
+
|
|
66
|
+
```jsx
|
|
67
|
+
/** @type {import("farmon").farmonConfig} */
|
|
68
|
+
export default {
|
|
69
|
+
llm: {
|
|
70
|
+
provider: "openai-compatible", // "openai-compatible" | "ollama"
|
|
71
|
+
baseUrl: "http://localhost:1234/v1", // "http://localhost:1234/v1"
|
|
72
|
+
model: "qwen3.5-9b", //"qwen3:8b",
|
|
73
|
+
},
|
|
74
|
+
appUrl: "http://localhost:5173", // user's app url
|
|
75
|
+
serverPort: 3001, // farmon server will run on this port
|
|
76
|
+
uiPort: 5174, // farmon iframe will run on this port
|
|
77
|
+
|
|
78
|
+
screenshot: {
|
|
79
|
+
enabled: true,
|
|
80
|
+
},
|
|
81
|
+
componentsDirectory: "src",
|
|
82
|
+
|
|
83
|
+
componentStructure: [".jsx", ".css", "index.ts"],
|
|
84
|
+
|
|
85
|
+
componentIdAttribute: "data-farmon-id", // this is for component selection system
|
|
86
|
+
selection: {
|
|
87
|
+
hoverColor: "#3b82f6",
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Start the Farmon server:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
farmon start
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Then import the runtime into your application:
|
|
99
|
+
|
|
100
|
+
```jsx
|
|
101
|
+
// inside main.jsx
|
|
102
|
+
|
|
103
|
+
import { init } from "farmon";
|
|
104
|
+
|
|
105
|
+
if (import.meta.env.DEV) {
|
|
106
|
+
init({
|
|
107
|
+
serverUrl: "http://localhost:3001", // the url where farmon server will run
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Example Commands
|
|
115
|
+
|
|
116
|
+
Farmon understands instructions such as:
|
|
117
|
+
|
|
118
|
+
- Remove the React starter code.
|
|
119
|
+
- Create a hero section.
|
|
120
|
+
- Add a navigation bar.
|
|
121
|
+
- Add a sticky header.
|
|
122
|
+
- Rename this component to `HeroSection`.
|
|
123
|
+
- Extract this JSX into a new component.
|
|
124
|
+
- Add a footer.
|
|
125
|
+
- Change the background color to gray.
|
|
126
|
+
- Make this button darker.
|
|
127
|
+
- Center this section.
|
|
128
|
+
- Rename this CSS class.
|
|
129
|
+
- Move this component into the `components/layout` directory.
|
|
130
|
+
|
|
131
|
+
## Roadmap
|
|
132
|
+
|
|
133
|
+
Current priorities include:
|
|
134
|
+
|
|
135
|
+
- Improved planning and reasoning
|
|
136
|
+
- Better project understanding
|
|
137
|
+
- Richer React support
|
|
138
|
+
- Enhanced undo/redo
|
|
139
|
+
- Expanded mutation library
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Roadmap
|
|
144
|
+
|
|
145
|
+
Current priorities include:
|
|
146
|
+
|
|
147
|
+
- Improved planning and reasoning
|
|
148
|
+
- Better project understanding
|
|
149
|
+
- Richer React support
|
|
150
|
+
- Enhanced undo/redo
|
|
151
|
+
- Expanded mutation library
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Contributing
|
|
156
|
+
|
|
157
|
+
Farmon is under active development. Contributions, ideas, bug reports, and feature requests are welcome.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const command = process.argv[2] ?? "start";
|
|
3
|
+
switch (command) {
|
|
4
|
+
case "start":
|
|
5
|
+
await import("../server/run.js");
|
|
6
|
+
break;
|
|
7
|
+
default:
|
|
8
|
+
console.error(`Unknown command: ${command}`);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=farmon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"farmon.js","sourceRoot":"","sources":["../../bin/farmon.ts"],"names":[],"mappings":";AAEA,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;AAE3C,QAAQ,OAAO,EAAE,CAAC;IAChB,KAAK,OAAO;QACV,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACjC,MAAM;IAER;QACE,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// export * from "./instruction-classifier-agent.js";
|
|
2
|
+
// export * from "./mutation-agent.js";
|
|
3
|
+
// export * from "./query-agent.js";
|
|
4
|
+
// agents/index.ts
|
|
5
|
+
import classifyInstruction from "./instruction-classifier-agent.js";
|
|
6
|
+
import mutationAgent from "./mutation-agent.js";
|
|
7
|
+
import queryAgent from "./query-agent.js";
|
|
8
|
+
// Bundle your agents into a structured object
|
|
9
|
+
const agents = {
|
|
10
|
+
classifyInstruction,
|
|
11
|
+
mutationAgent,
|
|
12
|
+
queryAgent,
|
|
13
|
+
// You can easily add more agents here later:
|
|
14
|
+
// coder: codeAgent,
|
|
15
|
+
// writer: writeAgent,
|
|
16
|
+
};
|
|
17
|
+
// Export the bundle as the default export
|
|
18
|
+
export default agents;
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../execute/agents/index.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,uCAAuC;AACvC,oCAAoC;AAEpC,kBAAkB;AAClB,OAAO,mBAAmB,MAAM,mCAAmC,CAAC;AACpE,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAE1C,8CAA8C;AAC9C,MAAM,MAAM,GAAG;IACb,mBAAmB;IACnB,aAAa;IACb,UAAU;IACV,6CAA6C;IAC7C,oBAAoB;IACpB,sBAAsB;CACvB,CAAC;AAEF,0CAA0C;AAC1C,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import promptMaker from "../../execute/helpers/prompt-maker.js";
|
|
2
|
+
import { callLLM } from "../../execute/llm/call.js";
|
|
3
|
+
import { instructionClassificationSchema } from "../../schemas/index.js";
|
|
4
|
+
import sse from "../../server/sse.js";
|
|
5
|
+
export default async function classifyInstruction(command, ctx) {
|
|
6
|
+
sse.emitInfo("Understanding your request...");
|
|
7
|
+
const prompt = promptMaker.buildInstructionClassifierPrompt(command);
|
|
8
|
+
sse.emitInfo(`Calling llm...`);
|
|
9
|
+
const response = await callLLM(prompt, {
|
|
10
|
+
...ctx,
|
|
11
|
+
caller: "instruction-classifier-agent",
|
|
12
|
+
});
|
|
13
|
+
const parsed = JSON.parse(response);
|
|
14
|
+
return instructionClassificationSchema.parse(parsed);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=instruction-classifier-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instruction-classifier-agent.js","sourceRoot":"","sources":["../../../execute/agents/instruction-classifier-agent.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,uCAAuC,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,GAAG,MAAM,qBAAqB,CAAC;AAEtC,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAe,EAAE,GAAG;IACpE,GAAG,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC;IAE9C,MAAM,MAAM,GAAG,WAAW,CAAC,gCAAgC,CAAC,OAAO,CAAC,CAAC;IAErE,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAE/B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE;QACrC,GAAG,GAAG;QACN,MAAM,EAAE,8BAA8B;KACvC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEpC,OAAO,+BAA+B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import history from "../../execute/history/history-manager.js";
|
|
2
|
+
import sse from "../../server/sse.js";
|
|
3
|
+
import generalHelpers from "../../execute/helpers/general.js";
|
|
4
|
+
import rollback from "../../execute/history/rollback-handlers.js";
|
|
5
|
+
import promptMaker from "../../execute/helpers/prompt-maker.js";
|
|
6
|
+
import { callLLM } from "../../execute/llm/call.js";
|
|
7
|
+
import { getComponentContext } from "../../server/app-context.js";
|
|
8
|
+
import { ERROR_CODES, } from "../../schemas/index.js";
|
|
9
|
+
import { mutations, generators, } from "../../execute/tasks/index.js";
|
|
10
|
+
import { EVENTS, TaskRegistry, } from "../../schemas/index.js";
|
|
11
|
+
import { LoomaError } from "../../server/error.js";
|
|
12
|
+
import parsers from "../helpers/parsers.js";
|
|
13
|
+
// import { buildInstructionClassifierPrompt } from "../../execute/helpers/prompt-maker.js";
|
|
14
|
+
// import invokeLLM, { callLLM, } from "../../execute/llm/llm.js";
|
|
15
|
+
import validator from "../../execute/helpers/validators.js";
|
|
16
|
+
const taskRegistry = {
|
|
17
|
+
// ...ast.default,
|
|
18
|
+
...mutations.default,
|
|
19
|
+
...generators.default,
|
|
20
|
+
};
|
|
21
|
+
export async function executeTask({ task, payload, taskOutputs, }, appContext) {
|
|
22
|
+
const resolvedPayload = generalHelpers.resolveTaskReferences({
|
|
23
|
+
value: payload,
|
|
24
|
+
taskOutputs,
|
|
25
|
+
});
|
|
26
|
+
console.log(`\n\nExecuting task: ${task} with resolvedPayload:`, resolvedPayload);
|
|
27
|
+
const schema = TaskRegistry[task];
|
|
28
|
+
const validatedPayload = schema.payload.parse(resolvedPayload);
|
|
29
|
+
const handler = taskRegistry[task];
|
|
30
|
+
if (!handler) {
|
|
31
|
+
throw new LoomaError(ERROR_CODES.TASK_NOT_FOUND, "Unknown task", {
|
|
32
|
+
task,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return await handler({
|
|
36
|
+
...validatedPayload,
|
|
37
|
+
}, appContext);
|
|
38
|
+
}
|
|
39
|
+
// -------------------------------------------------
|
|
40
|
+
// Execute action and append to history.
|
|
41
|
+
// -------------------------------------------------
|
|
42
|
+
async function executeAction({ actions, executionContext, }) {
|
|
43
|
+
sse.emitInfo("Executing action plan...");
|
|
44
|
+
const { componentContext, eventBus } = executionContext;
|
|
45
|
+
// ----------------------------------------------------------
|
|
46
|
+
// This object acts as shared memory between tasks.
|
|
47
|
+
//
|
|
48
|
+
// Each task output is stored using its taskId so that
|
|
49
|
+
// subsequent tasks can reference previous outputs.
|
|
50
|
+
// ----------------------------------------------------------
|
|
51
|
+
const taskOutputs = {
|
|
52
|
+
componentContext,
|
|
53
|
+
};
|
|
54
|
+
const mutationTasks = await generalHelpers.getExportedFunctionNames("mutation");
|
|
55
|
+
// ----------------------------------------------------------
|
|
56
|
+
// Collect mutation operations so that the entire action
|
|
57
|
+
// can be rolled back if any task fails.
|
|
58
|
+
// ----------------------------------------------------------
|
|
59
|
+
const operations = [];
|
|
60
|
+
const responseMessage = [];
|
|
61
|
+
try {
|
|
62
|
+
// ----------------------------------------------------------
|
|
63
|
+
// Execute tasks sequentially.
|
|
64
|
+
//
|
|
65
|
+
// Ordering matters because later tasks may depend on
|
|
66
|
+
// outputs produced by earlier tasks.
|
|
67
|
+
// ----------------------------------------------------------
|
|
68
|
+
for (const { taskId, task, payload } of actions) {
|
|
69
|
+
// logger.addStep("TASK_STARTED", { taskId, task, payload });
|
|
70
|
+
// sse.emitTaskStart({
|
|
71
|
+
// taskId,
|
|
72
|
+
// task,
|
|
73
|
+
// });
|
|
74
|
+
eventBus.emit(EVENTS.TASK_STARTED, { taskId, task, payload });
|
|
75
|
+
// ----------------------------------------------------------
|
|
76
|
+
// Execute the task.
|
|
77
|
+
// ----------------------------------------------------------
|
|
78
|
+
const taskOutput = await executeTask({
|
|
79
|
+
task: task,
|
|
80
|
+
payload,
|
|
81
|
+
taskOutputs,
|
|
82
|
+
}, executionContext.appContext);
|
|
83
|
+
eventBus.emit(EVENTS.TASK_COMPLETED, { taskId, task, payload });
|
|
84
|
+
// ----------------------------------------------------------
|
|
85
|
+
// Store task output for future tasks.
|
|
86
|
+
// ----------------------------------------------------------
|
|
87
|
+
taskOutputs[taskId] = taskOutput;
|
|
88
|
+
// ----------------------------------------------------------
|
|
89
|
+
// Mutation tasks produce operations that can later be
|
|
90
|
+
// undone or redone.
|
|
91
|
+
// ----------------------------------------------------------
|
|
92
|
+
if (mutationTasks.includes(task)) {
|
|
93
|
+
const operation = rollback.operationSerializers[task]({
|
|
94
|
+
payload,
|
|
95
|
+
result: taskOutput,
|
|
96
|
+
});
|
|
97
|
+
responseMessage.push(taskOutput.message);
|
|
98
|
+
operations.push({
|
|
99
|
+
taskId,
|
|
100
|
+
task,
|
|
101
|
+
payload,
|
|
102
|
+
taskOutput,
|
|
103
|
+
...operation,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// ----------------------------------------------------------
|
|
108
|
+
// Entire action executed successfully.
|
|
109
|
+
// ----------------------------------------------------------
|
|
110
|
+
return {
|
|
111
|
+
success: true,
|
|
112
|
+
operations,
|
|
113
|
+
responseMessage,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
const originalError = error instanceof Error ? error : new Error(String(error));
|
|
118
|
+
console.error(`Operation failed: ${originalError.message}. Rolling back...`);
|
|
119
|
+
const details = originalError instanceof LoomaError ? originalError.details : {};
|
|
120
|
+
eventBus.emit(EVENTS.TASK_FAILED, {
|
|
121
|
+
message: originalError.message,
|
|
122
|
+
...details,
|
|
123
|
+
});
|
|
124
|
+
try {
|
|
125
|
+
history.rollbackAction({ operations });
|
|
126
|
+
throw new LoomaError(ERROR_CODES.TASK_EXECUTION_FAILED, originalError.message, originalError);
|
|
127
|
+
}
|
|
128
|
+
catch (rollbackError) {
|
|
129
|
+
const rollback = rollbackError instanceof Error
|
|
130
|
+
? rollbackError
|
|
131
|
+
: new Error(String(rollbackError));
|
|
132
|
+
console.error("CRITICAL: Failed to rollback operations.", rollback);
|
|
133
|
+
throw new LoomaError(ERROR_CODES.ROLLBACK_FAILED, `Task execution failed and rollback was unsuccessful.`, {
|
|
134
|
+
originalError,
|
|
135
|
+
rollbackError: rollback,
|
|
136
|
+
operations,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export default async function mutationAgent(executionContext) {
|
|
142
|
+
const { command, request, logger, appContext, eventBus, } = executionContext;
|
|
143
|
+
const { componentId } = request;
|
|
144
|
+
const { componentRegistry } = appContext;
|
|
145
|
+
// ----------------------------------------------------------
|
|
146
|
+
// STEP 2:
|
|
147
|
+
// Resolve the selected component's context.
|
|
148
|
+
// This provides the LLM with information about the component
|
|
149
|
+
// the user is currently working on.
|
|
150
|
+
// ----------------------------------------------------------
|
|
151
|
+
const componentContext = getComponentContext({
|
|
152
|
+
componentId,
|
|
153
|
+
componentRegistry,
|
|
154
|
+
});
|
|
155
|
+
if (!componentContext) {
|
|
156
|
+
throw new LoomaError(ERROR_CODES.COMPONENT_NOT_FOUND, `Component context not found for componentId: ${componentId}`);
|
|
157
|
+
}
|
|
158
|
+
eventBus.emit(EVENTS.COMPONENT_CONTEXT, { componentContext });
|
|
159
|
+
executionContext.componentContext = componentContext;
|
|
160
|
+
// -------------------------------------------------
|
|
161
|
+
// Ask planner to create action plan.
|
|
162
|
+
// -------------------------------------------------
|
|
163
|
+
const plan = await gereratePlan(executionContext);
|
|
164
|
+
eventBus.emit(EVENTS.PLAN_GENERATED, { actions: plan.actions });
|
|
165
|
+
const actionExecutionResult = await executeAction({
|
|
166
|
+
actions: plan.actions,
|
|
167
|
+
executionContext,
|
|
168
|
+
});
|
|
169
|
+
generalHelpers.appendAction({
|
|
170
|
+
command,
|
|
171
|
+
operations: actionExecutionResult.operations,
|
|
172
|
+
undoPath: executionContext.appContext.project.undoPath,
|
|
173
|
+
});
|
|
174
|
+
// Prepare proper response
|
|
175
|
+
return "Done! " + actionExecutionResult.responseMessage.join(", ");
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
*
|
|
179
|
+
*
|
|
180
|
+
* You should provide:
|
|
181
|
+
* - user command
|
|
182
|
+
* - selected component context
|
|
183
|
+
* - available task definitions
|
|
184
|
+
* - architectural constraints
|
|
185
|
+
* - response schema
|
|
186
|
+
* - hard rules
|
|
187
|
+
|
|
188
|
+
* @param { command, componentCode} param0
|
|
189
|
+
* @returns actions [] having task and related prompt
|
|
190
|
+
*/
|
|
191
|
+
async function gereratePlan(executionContext) {
|
|
192
|
+
sse.emitInfo("Generating plan...");
|
|
193
|
+
const { command, logger, appContext, componentContext, eventBus, } = executionContext;
|
|
194
|
+
let basePrompt = await promptMaker.generatePlannerPrompt({
|
|
195
|
+
command,
|
|
196
|
+
componentContext,
|
|
197
|
+
projectDependencies: appContext.projectDependencies,
|
|
198
|
+
});
|
|
199
|
+
let previousError = null;
|
|
200
|
+
let actions;
|
|
201
|
+
// let caller: "planner" | "jsx" | "css" | "component";
|
|
202
|
+
const MAX_RETRIES = 3;
|
|
203
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
204
|
+
try {
|
|
205
|
+
// 1. Construct the prompt fresh for this specific attempt
|
|
206
|
+
let activePrompt = basePrompt;
|
|
207
|
+
if (previousError) {
|
|
208
|
+
activePrompt += `
|
|
209
|
+
Previous attempt produced invalid response.
|
|
210
|
+
|
|
211
|
+
Error:
|
|
212
|
+
${previousError}
|
|
213
|
+
|
|
214
|
+
Avoid repeating this error and regenerate the entire code.
|
|
215
|
+
`;
|
|
216
|
+
}
|
|
217
|
+
let response;
|
|
218
|
+
sse.emitInfo(`Calling llm...`);
|
|
219
|
+
eventBus.emit(EVENTS.PLANNER_PROMPT, { prompt: basePrompt });
|
|
220
|
+
response = await callLLM(activePrompt, {
|
|
221
|
+
...executionContext.appContext,
|
|
222
|
+
caller: "mutation-agent",
|
|
223
|
+
});
|
|
224
|
+
eventBus.emit(EVENTS.PLANNER_RESPONSE, { response });
|
|
225
|
+
const parsedResponse = parsers.parseLLMJsonResponse(response);
|
|
226
|
+
eventBus.emit(EVENTS.PLANNER_RESPONSE, { parsedResponse });
|
|
227
|
+
validator.validateResponse({
|
|
228
|
+
response: parsedResponse,
|
|
229
|
+
});
|
|
230
|
+
actions = parsedResponse;
|
|
231
|
+
// update it for caller
|
|
232
|
+
// if caller is jsx, css, componentCode
|
|
233
|
+
// then only format code
|
|
234
|
+
// otherwise check schema
|
|
235
|
+
// if (caller !== "planner") {
|
|
236
|
+
// return formatObjectCode(parsedResponse);
|
|
237
|
+
// }
|
|
238
|
+
return { actions };
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
console.error(`generatePlan [Attempt ${attempt}]:`, error.message); // Error: LLM returned very invalid JSON.
|
|
242
|
+
eventBus.emit(EVENTS.ERROR, { message: error.message });
|
|
243
|
+
previousError = error.message;
|
|
244
|
+
// 5. If we've exhausted all retries, throw the error so the UI knows it completely failed
|
|
245
|
+
if (attempt === MAX_RETRIES) {
|
|
246
|
+
throw new LoomaError(ERROR_CODES.LLM_INVALID_RESPONSE, `LLM generation failed after ${MAX_RETRIES} attempts. Last error: ${error.message}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/*
|
|
252
|
+
// === EXAMPLE USAGE ===
|
|
253
|
+
const messyLLMResponse = `
|
|
254
|
+
Sure! Here is the user data you requested:
|
|
255
|
+
\`\`\`json
|
|
256
|
+
{
|
|
257
|
+
"id": 101,
|
|
258
|
+
"name": "Alex Carter",
|
|
259
|
+
"roles": ["admin", "editor"],
|
|
260
|
+
}
|
|
261
|
+
\`\`\`
|
|
262
|
+
Let me know if you need anything else!`;
|
|
263
|
+
|
|
264
|
+
try {
|
|
265
|
+
const data = extractJSONFromLLM(messyLLMResponse);
|
|
266
|
+
console.log("Successfully extracted object:", data);
|
|
267
|
+
} catch (error) {
|
|
268
|
+
console.error("Extraction failed:", error.message);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
*/
|
|
272
|
+
//# sourceMappingURL=mutation-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation-agent.js","sourceRoot":"","sources":["../../../execute/agents/mutation-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import utils from "../../execute/helpers/general.js";
|
|
2
|
+
import promptMaker from "../../execute/helpers/prompt-maker.js";
|
|
3
|
+
import sse from "../../server/sse.js";
|
|
4
|
+
import { queryAgentResponseSchema, EVENTS, ERROR_CODES, } from "../../schemas/index.js";
|
|
5
|
+
import { query } from "../../execute/tasks/index.js";
|
|
6
|
+
import { callLLM } from "../../execute/llm/call.js";
|
|
7
|
+
import { LoomaError } from "../../server/error.js";
|
|
8
|
+
import parsers from "../helpers/parsers.js";
|
|
9
|
+
// type LLMResponse = Action[] | JSXResponse | CSSResponse | ComponentResponse;
|
|
10
|
+
const taskRegistry = {
|
|
11
|
+
...query.default,
|
|
12
|
+
};
|
|
13
|
+
export default async function queryAgent(executionContext) {
|
|
14
|
+
sse.emitInfo("Processing query...");
|
|
15
|
+
const { command, eventBus } = executionContext;
|
|
16
|
+
const { queryTasks } = await utils.generateTasksDocs();
|
|
17
|
+
const previousResults = [];
|
|
18
|
+
for (let step = 0; step < 10; step++) {
|
|
19
|
+
const prompt = promptMaker.createQueryAgentPrompt({
|
|
20
|
+
command,
|
|
21
|
+
taskDocs: queryTasks,
|
|
22
|
+
previousResults: JSON.stringify(previousResults, null, 2),
|
|
23
|
+
});
|
|
24
|
+
eventBus.emit(EVENTS.QUERY_AGENT_PROMPT, { prompt });
|
|
25
|
+
sse.emitInfo(`Calling llm...`);
|
|
26
|
+
const response = await callLLM(prompt, {
|
|
27
|
+
...executionContext.appContext,
|
|
28
|
+
caller: "query-agent",
|
|
29
|
+
});
|
|
30
|
+
eventBus.emit(EVENTS.QUERY_AGENT_RESPONSE, { response });
|
|
31
|
+
const decision = queryAgentResponseSchema.parse(parsers.parseLLMJsonResponse(response));
|
|
32
|
+
if (decision.status === "done") {
|
|
33
|
+
return decision.response;
|
|
34
|
+
}
|
|
35
|
+
eventBus.emit(EVENTS.TASK_STARTED, { decision });
|
|
36
|
+
const result = await executeQueryTask({
|
|
37
|
+
task: decision.task,
|
|
38
|
+
payload: decision.payload,
|
|
39
|
+
}, executionContext.appContext);
|
|
40
|
+
eventBus.emit(EVENTS.TASK_COMPLETED, {
|
|
41
|
+
task: decision.task,
|
|
42
|
+
result,
|
|
43
|
+
});
|
|
44
|
+
previousResults.push({
|
|
45
|
+
task: decision.task,
|
|
46
|
+
result,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
throw new LoomaError(ERROR_CODES.QUERY_AGENT_FAILED, `Query Agent exceeded maximum iterations.`);
|
|
50
|
+
}
|
|
51
|
+
export async function executeQueryTask({ task, payload }, appContext = {}) {
|
|
52
|
+
const handler = taskRegistry[task];
|
|
53
|
+
if (!handler) {
|
|
54
|
+
throw new LoomaError(ERROR_CODES.TASK_NOT_FOUND, `Unknown task: ${task}`);
|
|
55
|
+
}
|
|
56
|
+
return await handler({
|
|
57
|
+
...payload,
|
|
58
|
+
}, appContext);
|
|
59
|
+
}
|
|
60
|
+
// function parser.(response: string) {
|
|
61
|
+
// try {
|
|
62
|
+
// return JSON.parse(response);
|
|
63
|
+
// } catch {
|
|
64
|
+
// try {
|
|
65
|
+
// const extractedData = extractJSONFromLLM(response);
|
|
66
|
+
// // CRITICAL FIX: You must explicitly return the extracted data here
|
|
67
|
+
// return extractedData;
|
|
68
|
+
// } catch (error) {
|
|
69
|
+
// throw new LoomaError(
|
|
70
|
+
// ERROR_CODES.LLM_INVALID_RESPONSE,
|
|
71
|
+
// "LLM's response in invalid JSON",
|
|
72
|
+
// {
|
|
73
|
+
// response,
|
|
74
|
+
// originalError: error instanceof Error ? error.message : String(error),
|
|
75
|
+
// },
|
|
76
|
+
// );
|
|
77
|
+
// }
|
|
78
|
+
// }
|
|
79
|
+
// }
|
|
80
|
+
// function extractJSONFromLLM(llmResponse) {
|
|
81
|
+
// try {
|
|
82
|
+
// // 1. Clean markdown code blocks if present
|
|
83
|
+
// let cleanedText = llmResponse
|
|
84
|
+
// .replace(/```json/gi, "")
|
|
85
|
+
// .replace(/```/g, "")
|
|
86
|
+
// .trim();
|
|
87
|
+
// // 2. Use regex to find the first '{' or '[' and the last '}' or ']'
|
|
88
|
+
// const jsonMatch = cleanedText.match(/[\{\[]([\s\S]*?)[\}\]]/);
|
|
89
|
+
// if (!jsonMatch) {
|
|
90
|
+
// throw new Error("No JSON structure found in the response.");
|
|
91
|
+
// }
|
|
92
|
+
// // Extract the matched substring including the outer brackets
|
|
93
|
+
// const jsonString = jsonMatch[0];
|
|
94
|
+
// // 3. Attempt to parse the extracted string
|
|
95
|
+
// return JSON.parse(jsonString);
|
|
96
|
+
// } catch (firstError) {
|
|
97
|
+
// // 4. Fallback: Heavy cleaning for common LLM syntax errors
|
|
98
|
+
// try {
|
|
99
|
+
// const sanitized = repairLLMJsonString(llmResponse);
|
|
100
|
+
// return JSON.parse(sanitized);
|
|
101
|
+
// } catch (secondError) {
|
|
102
|
+
// throw new Error(
|
|
103
|
+
// `Failed to parse LLM JSON. Original error: ${firstError.message}`,
|
|
104
|
+
// );
|
|
105
|
+
// }
|
|
106
|
+
// }
|
|
107
|
+
// }
|
|
108
|
+
// function repairLLMJsonString(text) {
|
|
109
|
+
// // Isolate the text between first '{' and last '}'
|
|
110
|
+
// const start = text.indexOf("{");
|
|
111
|
+
// const end = text.lastIndexOf("}");
|
|
112
|
+
// if (start === -1 || end === -1) throw new Error("Brackets missing");
|
|
113
|
+
// let jsonStr = text.substring(start, end + 1);
|
|
114
|
+
// // Strip trailing commas before closing braces/brackets
|
|
115
|
+
// jsonStr = jsonStr.replace(/,\s*([\]\}])/g, "$1");
|
|
116
|
+
// return jsonStr;
|
|
117
|
+
// }
|
|
118
|
+
//# sourceMappingURL=query-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-agent.js","sourceRoot":"","sources":["../../../execute/agents/query-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzers.js","sourceRoot":"","sources":["../../../execute/helpers/analyzers.ts"],"names":[],"mappings":";AAAA,+CAA+C;AAC/C,mBAAmB;AACnB,sBAAsB;AACtB,eAAe;AACf,eAAe;AACf,iBAAiB"}
|