@polka-codes/core 0.10.13 → 0.10.17
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/Agent/backoff.d.ts +7 -0
- package/dist/Agent/backoff.js +21 -0
- package/dist/Agent/backoff.js.map +1 -0
- package/dist/Agent/index.d.ts +2 -0
- package/dist/Agent/index.js +3 -0
- package/dist/Agent/index.js.map +1 -0
- package/dist/Agent/parseJsonFromMarkdown.d.ts +8 -0
- package/dist/Agent/parseJsonFromMarkdown.js +34 -0
- package/dist/Agent/parseJsonFromMarkdown.js.map +1 -0
- package/dist/Agent/parseJsonFromMarkdown.test.d.ts +1 -0
- package/dist/Agent/parseJsonFromMarkdown.test.js +70 -0
- package/dist/Agent/parseJsonFromMarkdown.test.js.map +1 -0
- package/dist/Agent/prompts.d.ts +9 -0
- package/dist/Agent/prompts.js +107 -0
- package/dist/Agent/prompts.js.map +1 -0
- package/dist/UsageMeter.d.ts +101 -0
- package/dist/UsageMeter.js +299 -0
- package/dist/UsageMeter.js.map +1 -0
- package/dist/UsageMeter.test.d.ts +4 -0
- package/dist/UsageMeter.test.js +556 -0
- package/dist/UsageMeter.test.js.map +1 -0
- package/dist/config/base.d.ts +68 -0
- package/dist/config/base.js +56 -0
- package/dist/config/base.js.map +1 -0
- package/dist/config/memory.d.ts +24 -0
- package/dist/config/memory.js +36 -0
- package/dist/config/memory.js.map +1 -0
- package/dist/config.d.ts +236 -0
- package/dist/config.js +184 -0
- package/dist/config.js.map +1 -0
- package/dist/errors/base.d.ts +31 -0
- package/dist/errors/base.js +60 -0
- package/dist/errors/base.js.map +1 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +3 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/fs/index.d.ts +2 -0
- package/dist/fs/index.js +3 -0
- package/dist/fs/index.js.map +1 -0
- package/dist/fs/node-provider.d.ts +16 -0
- package/dist/fs/node-provider.js +47 -0
- package/dist/fs/node-provider.js.map +1 -0
- package/dist/fs/provider.d.ts +61 -0
- package/dist/fs/provider.js +3 -0
- package/dist/fs/provider.js.map +1 -0
- package/dist/index.d.ts +20 -191
- package/dist/index.js +21 -4123
- package/dist/index.js.map +1 -0
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.js +2 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/types.d.ts +136 -0
- package/dist/memory/types.js +2 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/path.d.ts +9 -0
- package/dist/path.js +68 -0
- package/dist/path.js.map +1 -0
- package/dist/path.test.d.ts +1 -0
- package/dist/path.test.js +82 -0
- package/dist/path.test.js.map +1 -0
- package/dist/pricing/converter.d.ts +6 -0
- package/dist/pricing/converter.js +13 -0
- package/dist/pricing/converter.js.map +1 -0
- package/dist/pricing/converter.test.d.ts +1 -0
- package/dist/pricing/converter.test.js +54 -0
- package/dist/pricing/converter.test.js.map +1 -0
- package/dist/pricing/index.d.ts +2 -0
- package/dist/pricing/index.js +2 -0
- package/dist/pricing/index.js.map +1 -0
- package/dist/pricing/portkey-client.d.ts +2 -0
- package/dist/pricing/portkey-client.js +57 -0
- package/dist/pricing/portkey-client.js.map +1 -0
- package/dist/pricing/pricing-service.d.ts +6 -0
- package/dist/pricing/pricing-service.js +125 -0
- package/dist/pricing/pricing-service.js.map +1 -0
- package/dist/pricing/pricing-service.test.d.ts +1 -0
- package/dist/pricing/pricing-service.test.js +141 -0
- package/dist/pricing/pricing-service.test.js.map +1 -0
- package/dist/pricing/types.d.ts +24 -0
- package/dist/pricing/types.js +2 -0
- package/dist/pricing/types.js.map +1 -0
- package/dist/skills/__tests__/discovery.test.d.ts +1 -0
- package/dist/skills/__tests__/discovery.test.js +254 -0
- package/dist/skills/__tests__/discovery.test.js.map +1 -0
- package/dist/skills/__tests__/validation.test.d.ts +1 -0
- package/dist/skills/__tests__/validation.test.js +221 -0
- package/dist/skills/__tests__/validation.test.js.map +1 -0
- package/dist/skills/constants.d.ts +32 -0
- package/dist/skills/constants.js +50 -0
- package/dist/skills/constants.js.map +1 -0
- package/dist/skills/discovery.d.ts +56 -0
- package/dist/skills/discovery.js +392 -0
- package/dist/skills/discovery.js.map +1 -0
- package/dist/skills/index.d.ts +4 -0
- package/dist/skills/index.js +6 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/tools/index.d.ts +3 -0
- package/dist/skills/tools/index.js +5 -0
- package/dist/skills/tools/index.js.map +1 -0
- package/dist/skills/tools/listSkills.d.ts +54 -0
- package/dist/skills/tools/listSkills.js +52 -0
- package/dist/skills/tools/listSkills.js.map +1 -0
- package/dist/skills/tools/loadSkill.d.ts +52 -0
- package/dist/skills/tools/loadSkill.js +86 -0
- package/dist/skills/tools/loadSkill.js.map +1 -0
- package/dist/skills/tools/readSkillFile.d.ts +43 -0
- package/dist/skills/tools/readSkillFile.js +68 -0
- package/dist/skills/tools/readSkillFile.js.map +1 -0
- package/dist/skills/types.d.ts +83 -0
- package/dist/skills/types.js +42 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/skills/validation.d.ts +30 -0
- package/dist/skills/validation.js +133 -0
- package/dist/skills/validation.js.map +1 -0
- package/dist/tool.d.ts +51 -0
- package/dist/tool.js +2 -0
- package/dist/tool.js.map +1 -0
- package/dist/tools/askFollowupQuestion.d.ts +35 -0
- package/dist/tools/askFollowupQuestion.js +105 -0
- package/dist/tools/askFollowupQuestion.js.map +1 -0
- package/dist/tools/askFollowupQuestion.test.d.ts +1 -0
- package/dist/tools/askFollowupQuestion.test.js +80 -0
- package/dist/tools/askFollowupQuestion.test.js.map +1 -0
- package/dist/tools/executeCommand.d.ts +29 -0
- package/dist/tools/executeCommand.js +82 -0
- package/dist/tools/executeCommand.js.map +1 -0
- package/dist/tools/executeCommand.test.d.ts +1 -0
- package/dist/tools/executeCommand.test.js +60 -0
- package/dist/tools/executeCommand.test.js.map +1 -0
- package/dist/tools/fetchUrl.d.ts +26 -0
- package/dist/tools/fetchUrl.js +85 -0
- package/dist/tools/fetchUrl.js.map +1 -0
- package/dist/tools/index.d.ts +15 -0
- package/dist/tools/index.js +17 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/listFiles.d.ts +35 -0
- package/dist/tools/listFiles.js +61 -0
- package/dist/tools/listFiles.js.map +1 -0
- package/dist/tools/listFiles.test.d.ts +1 -0
- package/dist/tools/listFiles.test.js +59 -0
- package/dist/tools/listFiles.test.js.map +1 -0
- package/dist/tools/provider.d.ts +76 -0
- package/dist/tools/provider.js +60 -0
- package/dist/tools/provider.js.map +1 -0
- package/dist/tools/readBinaryFile.d.ts +26 -0
- package/dist/tools/readBinaryFile.js +52 -0
- package/dist/tools/readBinaryFile.js.map +1 -0
- package/dist/tools/readFile.d.ts +35 -0
- package/dist/tools/readFile.js +128 -0
- package/dist/tools/readFile.js.map +1 -0
- package/dist/tools/readFile.test.d.ts +1 -0
- package/dist/tools/readFile.test.js +37 -0
- package/dist/tools/readFile.test.js.map +1 -0
- package/dist/tools/removeFile.d.ts +26 -0
- package/dist/tools/removeFile.js +49 -0
- package/dist/tools/removeFile.js.map +1 -0
- package/dist/tools/removeFile.test.d.ts +1 -0
- package/dist/tools/removeFile.test.js +32 -0
- package/dist/tools/removeFile.test.js.map +1 -0
- package/dist/tools/renameFile.d.ts +29 -0
- package/dist/tools/renameFile.js +48 -0
- package/dist/tools/renameFile.js.map +1 -0
- package/dist/tools/renameFile.test.d.ts +1 -0
- package/dist/tools/renameFile.test.js +53 -0
- package/dist/tools/renameFile.test.js.map +1 -0
- package/dist/tools/replaceInFile.d.ts +29 -0
- package/dist/tools/replaceInFile.js +233 -0
- package/dist/tools/replaceInFile.js.map +1 -0
- package/dist/tools/replaceInFile.test.d.ts +1 -0
- package/dist/tools/replaceInFile.test.js +79 -0
- package/dist/tools/replaceInFile.test.js.map +1 -0
- package/dist/tools/response-builders.d.ts +64 -0
- package/dist/tools/response-builders.js +88 -0
- package/dist/tools/response-builders.js.map +1 -0
- package/dist/tools/search.d.ts +26 -0
- package/dist/tools/search.js +56 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/search.test.d.ts +1 -0
- package/dist/tools/search.test.js +22 -0
- package/dist/tools/search.test.js.map +1 -0
- package/dist/tools/searchFiles.d.ts +32 -0
- package/dist/tools/searchFiles.js +86 -0
- package/dist/tools/searchFiles.js.map +1 -0
- package/dist/tools/todo.d.ts +37 -0
- package/dist/tools/todo.js +41 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/tools/utils/index.d.ts +1 -0
- package/dist/tools/utils/index.js +2 -0
- package/dist/tools/utils/index.js.map +1 -0
- package/dist/tools/utils/replaceInFile.d.ts +7 -0
- package/dist/tools/utils/replaceInFile.js +133 -0
- package/dist/tools/utils/replaceInFile.js.map +1 -0
- package/dist/tools/utils/replaceInFile.test.d.ts +1 -0
- package/dist/tools/utils/replaceInFile.test.js +308 -0
- package/dist/tools/utils/replaceInFile.test.js.map +1 -0
- package/dist/tools/utils.d.ts +10 -0
- package/dist/tools/utils.js +27 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/tools/writeToFile.d.ts +29 -0
- package/dist/tools/writeToFile.js +85 -0
- package/dist/tools/writeToFile.js.map +1 -0
- package/dist/tools/writeToFile.test.d.ts +1 -0
- package/dist/tools/writeToFile.test.js +46 -0
- package/dist/tools/writeToFile.test.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/merge.d.ts +26 -0
- package/dist/utils/merge.js +45 -0
- package/dist/utils/merge.js.map +1 -0
- package/dist/workflow/agent.workflow.d.ts +39 -0
- package/dist/workflow/agent.workflow.js +166 -0
- package/dist/workflow/agent.workflow.js.map +1 -0
- package/dist/workflow/agent.workflow.test.d.ts +1 -0
- package/dist/workflow/agent.workflow.test.js +175 -0
- package/dist/workflow/agent.workflow.test.js.map +1 -0
- package/dist/workflow/control-flow.test.d.ts +1 -0
- package/dist/workflow/control-flow.test.js +323 -0
- package/dist/workflow/control-flow.test.js.map +1 -0
- package/dist/workflow/dynamic-edge-cases.test.d.ts +1 -0
- package/dist/workflow/dynamic-edge-cases.test.js +486 -0
- package/dist/workflow/dynamic-edge-cases.test.js.map +1 -0
- package/dist/workflow/dynamic-types.d.ts +124 -0
- package/dist/workflow/dynamic-types.js +105 -0
- package/dist/workflow/dynamic-types.js.map +1 -0
- package/dist/workflow/dynamic.d.ts +118 -0
- package/dist/workflow/dynamic.js +999 -0
- package/dist/workflow/dynamic.js.map +1 -0
- package/dist/workflow/index.d.ts +6 -0
- package/dist/workflow/index.js +8 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/json-ai-types.d.ts +122 -0
- package/dist/workflow/json-ai-types.js +144 -0
- package/dist/workflow/json-ai-types.js.map +1 -0
- package/dist/workflow/json-schema-conversion.test.d.ts +1 -0
- package/dist/workflow/json-schema-conversion.test.js +371 -0
- package/dist/workflow/json-schema-conversion.test.js.map +1 -0
- package/dist/workflow/try-catch.test.d.ts +1 -0
- package/dist/workflow/try-catch.test.js +443 -0
- package/dist/workflow/try-catch.test.js.map +1 -0
- package/dist/workflow/types.d.ts +103 -0
- package/dist/workflow/types.js +17 -0
- package/dist/workflow/types.js.map +1 -0
- package/dist/workflow/workflow.d.ts +29 -0
- package/dist/workflow/workflow.js +57 -0
- package/dist/workflow/workflow.js.map +1 -0
- package/dist/workflow/workflow.test.d.ts +1 -0
- package/dist/workflow/workflow.test.js +189 -0
- package/dist/workflow/workflow.test.js.map +1 -0
- package/package.json +9 -1
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import { replaceInFile } from './replaceInFile';
|
|
3
|
+
describe('replaceInFile', () => {
|
|
4
|
+
it('should perform basic single replacement', async () => {
|
|
5
|
+
const content = `line1
|
|
6
|
+
line2
|
|
7
|
+
line3`;
|
|
8
|
+
const diff = `<<<<<<< SEARCH
|
|
9
|
+
line2
|
|
10
|
+
=======
|
|
11
|
+
new line2
|
|
12
|
+
>>>>>>> REPLACE`;
|
|
13
|
+
const result = replaceInFile(content, diff);
|
|
14
|
+
expect(result).toEqual({
|
|
15
|
+
content: `line1
|
|
16
|
+
new line2
|
|
17
|
+
line3`,
|
|
18
|
+
status: 'all_diff_applied',
|
|
19
|
+
appliedCount: 1,
|
|
20
|
+
totalCount: 1,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
it('should handle multiple replacements', async () => {
|
|
24
|
+
const content = `line1
|
|
25
|
+
line2
|
|
26
|
+
line3
|
|
27
|
+
line2`;
|
|
28
|
+
const diff = `<<<<<<< SEARCH
|
|
29
|
+
line2
|
|
30
|
+
=======
|
|
31
|
+
new line2
|
|
32
|
+
>>>>>>> REPLACE
|
|
33
|
+
<<<<<<< SEARCH
|
|
34
|
+
line3
|
|
35
|
+
=======
|
|
36
|
+
new line3
|
|
37
|
+
>>>>>>> REPLACE`;
|
|
38
|
+
const result = replaceInFile(content, diff);
|
|
39
|
+
expect(result).toEqual({
|
|
40
|
+
content: `line1
|
|
41
|
+
new line2
|
|
42
|
+
new line3
|
|
43
|
+
line2`,
|
|
44
|
+
status: 'all_diff_applied',
|
|
45
|
+
appliedCount: 2,
|
|
46
|
+
totalCount: 2,
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
it('should handle whitespace variations', async () => {
|
|
50
|
+
const content = `line1
|
|
51
|
+
line2
|
|
52
|
+
line3`;
|
|
53
|
+
const diff = `<<<<<<< SEARCH
|
|
54
|
+
line2
|
|
55
|
+
=======
|
|
56
|
+
new line2
|
|
57
|
+
>>>>>>> REPLACE`;
|
|
58
|
+
const result = replaceInFile(content, diff);
|
|
59
|
+
expect(result).toEqual({
|
|
60
|
+
content: `line1
|
|
61
|
+
new line2
|
|
62
|
+
line3`,
|
|
63
|
+
status: 'all_diff_applied',
|
|
64
|
+
appliedCount: 1,
|
|
65
|
+
totalCount: 1,
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
it('should throw error when no blocks found', async () => {
|
|
69
|
+
const content = `line1
|
|
70
|
+
line2`;
|
|
71
|
+
const diff = 'invalid format';
|
|
72
|
+
expect(() => replaceInFile(content, diff)).toThrow('No valid diff blocks found');
|
|
73
|
+
});
|
|
74
|
+
it('should return no_diff_applied when search text not found', async () => {
|
|
75
|
+
const content = `line1
|
|
76
|
+
line2`;
|
|
77
|
+
const diff = `<<<<<<< SEARCH
|
|
78
|
+
line3
|
|
79
|
+
=======
|
|
80
|
+
new line3
|
|
81
|
+
>>>>>>> REPLACE`;
|
|
82
|
+
const result = replaceInFile(content, diff);
|
|
83
|
+
expect(result).toEqual({
|
|
84
|
+
content,
|
|
85
|
+
status: 'no_diff_applied',
|
|
86
|
+
appliedCount: 0,
|
|
87
|
+
totalCount: 1,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
it('should handle empty file', async () => {
|
|
91
|
+
const content = '';
|
|
92
|
+
const diff = `<<<<<<< SEARCH
|
|
93
|
+
line1
|
|
94
|
+
=======
|
|
95
|
+
new line1
|
|
96
|
+
>>>>>>> REPLACE`;
|
|
97
|
+
const result = replaceInFile(content, diff);
|
|
98
|
+
expect(result).toEqual({
|
|
99
|
+
content,
|
|
100
|
+
status: 'no_diff_applied',
|
|
101
|
+
appliedCount: 0,
|
|
102
|
+
totalCount: 1,
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
it('should handle empty replacement', async () => {
|
|
106
|
+
const content = `line1
|
|
107
|
+
line2`;
|
|
108
|
+
const diff = `<<<<<<< SEARCH
|
|
109
|
+
line2
|
|
110
|
+
=======
|
|
111
|
+
>>>>>>> REPLACE`;
|
|
112
|
+
const result = replaceInFile(content, diff);
|
|
113
|
+
expect(result).toEqual({
|
|
114
|
+
content: `line1
|
|
115
|
+
`,
|
|
116
|
+
status: 'all_diff_applied',
|
|
117
|
+
appliedCount: 1,
|
|
118
|
+
totalCount: 1,
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
it('should return some_diff_applied when some search text not found', () => {
|
|
122
|
+
const content = 'line1\nline2';
|
|
123
|
+
const diff = `<<<<<<< SEARCH
|
|
124
|
+
line1
|
|
125
|
+
=======
|
|
126
|
+
new line1
|
|
127
|
+
>>>>>>> REPLACE
|
|
128
|
+
<<<<<<< SEARCH
|
|
129
|
+
line3
|
|
130
|
+
=======
|
|
131
|
+
new line3
|
|
132
|
+
>>>>>>> REPLACE`;
|
|
133
|
+
const result = replaceInFile(content, diff);
|
|
134
|
+
expect(result).toEqual({
|
|
135
|
+
content: 'new line1\nline2',
|
|
136
|
+
status: 'some_diff_applied',
|
|
137
|
+
appliedCount: 1,
|
|
138
|
+
totalCount: 2,
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
it('should handle block with no space before SEARCH', () => {
|
|
142
|
+
const content = `line1
|
|
143
|
+
line2
|
|
144
|
+
line3`;
|
|
145
|
+
const diff = `<<<<<<<SEARCH
|
|
146
|
+
line2
|
|
147
|
+
=======
|
|
148
|
+
new line2
|
|
149
|
+
>>>>>>>REPLACE`;
|
|
150
|
+
const result = replaceInFile(content, diff);
|
|
151
|
+
expect(result).toEqual({
|
|
152
|
+
content: `line1
|
|
153
|
+
new line2
|
|
154
|
+
line3`,
|
|
155
|
+
status: 'all_diff_applied',
|
|
156
|
+
appliedCount: 1,
|
|
157
|
+
totalCount: 1,
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
it('should handle block with multiple spaces before SEARCH', () => {
|
|
161
|
+
const content = `line1
|
|
162
|
+
line2
|
|
163
|
+
line3`;
|
|
164
|
+
const diff = `<<<<<<< SEARCH
|
|
165
|
+
line2
|
|
166
|
+
=======
|
|
167
|
+
new line2
|
|
168
|
+
>>>>>>> REPLACE`;
|
|
169
|
+
const result = replaceInFile(content, diff);
|
|
170
|
+
expect(result).toEqual({
|
|
171
|
+
content: `line1
|
|
172
|
+
new line2
|
|
173
|
+
line3`,
|
|
174
|
+
status: 'all_diff_applied',
|
|
175
|
+
appliedCount: 1,
|
|
176
|
+
totalCount: 1,
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
it('should handle block with tab before SEARCH', () => {
|
|
180
|
+
const content = `line1
|
|
181
|
+
line2
|
|
182
|
+
line3`;
|
|
183
|
+
const diff = `<<<<<<< SEARCH
|
|
184
|
+
line2
|
|
185
|
+
=======
|
|
186
|
+
new line2
|
|
187
|
+
>>>>>>> REPLACE`;
|
|
188
|
+
const result = replaceInFile(content, diff);
|
|
189
|
+
expect(result).toEqual({
|
|
190
|
+
content: `line1
|
|
191
|
+
new line2
|
|
192
|
+
line3`,
|
|
193
|
+
status: 'all_diff_applied',
|
|
194
|
+
appliedCount: 1,
|
|
195
|
+
totalCount: 1,
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
it('should handle block with mixed whitespace before SEARCH', () => {
|
|
199
|
+
const content = `line1
|
|
200
|
+
line2
|
|
201
|
+
line3`;
|
|
202
|
+
const diff = `<<<<<< SEARCH
|
|
203
|
+
line2
|
|
204
|
+
=======
|
|
205
|
+
new line2
|
|
206
|
+
>>>>>> REPLACE`;
|
|
207
|
+
const result = replaceInFile(content, diff);
|
|
208
|
+
expect(result).toEqual({
|
|
209
|
+
content: `line1
|
|
210
|
+
new line2
|
|
211
|
+
line3`,
|
|
212
|
+
status: 'all_diff_applied',
|
|
213
|
+
appliedCount: 1,
|
|
214
|
+
totalCount: 1,
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
it('should handle multiple blocks with varying whitespace patterns', () => {
|
|
218
|
+
const content = `line1
|
|
219
|
+
line2
|
|
220
|
+
line3
|
|
221
|
+
line4`;
|
|
222
|
+
const diff = `<<<<<<<SEARCH
|
|
223
|
+
line2
|
|
224
|
+
=======
|
|
225
|
+
new line2
|
|
226
|
+
>>>>>>>REPLACE
|
|
227
|
+
<<<<<<< SEARCH
|
|
228
|
+
line3
|
|
229
|
+
=======
|
|
230
|
+
new line3
|
|
231
|
+
>>>>>>> REPLACE
|
|
232
|
+
<<<<<<< SEARCH
|
|
233
|
+
line4
|
|
234
|
+
=======
|
|
235
|
+
new line4
|
|
236
|
+
>>>>>>> REPLACE`;
|
|
237
|
+
const result = replaceInFile(content, diff);
|
|
238
|
+
expect(result).toEqual({
|
|
239
|
+
content: `line1
|
|
240
|
+
new line2
|
|
241
|
+
new line3
|
|
242
|
+
new line4`,
|
|
243
|
+
status: 'all_diff_applied',
|
|
244
|
+
appliedCount: 3,
|
|
245
|
+
totalCount: 3,
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
it('should handle whitespace-agnostic replacement with multiple spaces', () => {
|
|
249
|
+
// Test the bug fix: search text with irregular whitespace should match content with normalized whitespace
|
|
250
|
+
const content = `function test() {
|
|
251
|
+
const x = 1
|
|
252
|
+
return x
|
|
253
|
+
}`;
|
|
254
|
+
const diff = `<<<<<<< SEARCH
|
|
255
|
+
function test() {
|
|
256
|
+
const x = 1
|
|
257
|
+
return x
|
|
258
|
+
}
|
|
259
|
+
=======
|
|
260
|
+
function test() {
|
|
261
|
+
const y = 2
|
|
262
|
+
return y
|
|
263
|
+
}
|
|
264
|
+
>>>>>>> REPLACE`;
|
|
265
|
+
const result = replaceInFile(content, diff);
|
|
266
|
+
expect(result.status).toBe('all_diff_applied');
|
|
267
|
+
expect(result.appliedCount).toBe(1);
|
|
268
|
+
expect(result.content).toContain('const y = 2');
|
|
269
|
+
expect(result.content).toContain('return y');
|
|
270
|
+
});
|
|
271
|
+
it('should handle whitespace-agnostic replacement with tabs vs spaces', () => {
|
|
272
|
+
const content = `line1
|
|
273
|
+
line2
|
|
274
|
+
line3`;
|
|
275
|
+
const diff = `<<<<<<< SEARCH
|
|
276
|
+
line1
|
|
277
|
+
line2
|
|
278
|
+
line3
|
|
279
|
+
=======
|
|
280
|
+
line1
|
|
281
|
+
new line2
|
|
282
|
+
line3
|
|
283
|
+
>>>>>>> REPLACE`;
|
|
284
|
+
const result = replaceInFile(content, diff);
|
|
285
|
+
expect(result.status).toBe('all_diff_applied');
|
|
286
|
+
expect(result.appliedCount).toBe(1);
|
|
287
|
+
expect(result.content).toContain('new line2');
|
|
288
|
+
});
|
|
289
|
+
it('should handle whitespace-agnostic replacement with extra newlines', () => {
|
|
290
|
+
const content = `line1
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
line2
|
|
294
|
+
line3`;
|
|
295
|
+
const diff = `<<<<<<< SEARCH
|
|
296
|
+
line1
|
|
297
|
+
|
|
298
|
+
line2
|
|
299
|
+
=======
|
|
300
|
+
line1
|
|
301
|
+
line2
|
|
302
|
+
>>>>>>> REPLACE`;
|
|
303
|
+
const result = replaceInFile(content, diff);
|
|
304
|
+
expect(result.status).toBe('all_diff_applied');
|
|
305
|
+
expect(result.appliedCount).toBe(1);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
//# sourceMappingURL=replaceInFile.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replaceInFile.test.js","sourceRoot":"","sources":["../../../src/tools/utils/replaceInFile.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { createProviderErrorResponse as createProviderError } from './response-builders';
|
|
2
|
+
/**
|
|
3
|
+
* Simplify boolean string preprocessing
|
|
4
|
+
* Converts 'true'/'false' strings to actual booleans
|
|
5
|
+
*/
|
|
6
|
+
export declare function preprocessBoolean(val: unknown): unknown;
|
|
7
|
+
/**
|
|
8
|
+
* Create a file content XML element
|
|
9
|
+
*/
|
|
10
|
+
export declare function createFileElement(tagName: string, path: string, content?: string, attrs?: Record<string, string>): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Re-export from response-builders for backward compatibility
|
|
2
|
+
export { createProviderErrorResponse as createProviderError } from './response-builders';
|
|
3
|
+
/**
|
|
4
|
+
* Simplify boolean string preprocessing
|
|
5
|
+
* Converts 'true'/'false' strings to actual booleans
|
|
6
|
+
*/
|
|
7
|
+
export function preprocessBoolean(val) {
|
|
8
|
+
return typeof val === 'string' ? val.toLowerCase() === 'true' : val;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Create a file content XML element
|
|
12
|
+
*/
|
|
13
|
+
export function createFileElement(tagName, path, content, attrs) {
|
|
14
|
+
const allAttrs = { path, ...attrs };
|
|
15
|
+
const attrStr = Object.entries(allAttrs)
|
|
16
|
+
.map(([k, v]) => ` ${k}="${v}"`)
|
|
17
|
+
.join('');
|
|
18
|
+
if (content === undefined) {
|
|
19
|
+
return `<${tagName}${attrStr} />`;
|
|
20
|
+
}
|
|
21
|
+
const isEmpty = content.trim().length === 0;
|
|
22
|
+
if (isEmpty) {
|
|
23
|
+
return `<${tagName}${attrStr} is_empty="true" />`;
|
|
24
|
+
}
|
|
25
|
+
return `<${tagName}${attrStr}>${content}</${tagName}>`;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,OAAO,EAAE,2BAA2B,IAAI,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAExF;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC5C,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAA;AACrE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,IAAY,EAAE,OAAgB,EAAE,KAA8B;IAC/G,MAAM,QAAQ,GAAG,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,CAAA;IACnC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;SACrC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;SAC/B,IAAI,CAAC,EAAE,CAAC,CAAA;IAEX,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,IAAI,OAAO,GAAG,OAAO,KAAK,CAAA;IACnC,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAA;IAC3C,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,IAAI,OAAO,GAAG,OAAO,qBAAqB,CAAA;IACnD,CAAC;IAED,OAAO,IAAI,OAAO,GAAG,OAAO,IAAI,OAAO,KAAK,OAAO,GAAG,CAAA;AACxD,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ToolHandler } from '../tool';
|
|
3
|
+
import type { FilesystemProvider } from './provider';
|
|
4
|
+
export declare const toolInfo: {
|
|
5
|
+
readonly name: "writeToFile";
|
|
6
|
+
readonly description: "Request to write content to a file at the specified path.\n\nWhen to use:\n- Creating new files\n- Completely replacing file contents\n- When you have the complete intended content\n\nWhen NOT to use:\n- For modifying existing files: Use replaceInFile instead\n- For appending content: Use executeCommand with echo >> instead\n- For targeted edits: Use replaceInFile instead\n\nFeatures:\n- Automatically creates any directories needed\n- Overwrites existing files completely\n- Must provide complete file content (no truncation)\n\nIMPORTANT CONSTRAINT:\n- Always provide COMPLETE intended content (no omissions)\n- Ensure no incorrect escape sequences (<, >, &)\n- Ensure no unwanted CDATA tags in content";
|
|
7
|
+
readonly parameters: z.ZodObject<{
|
|
8
|
+
path: z.ZodString;
|
|
9
|
+
content: z.ZodString;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
};
|
|
12
|
+
export declare const handler: ToolHandler<typeof toolInfo, FilesystemProvider>;
|
|
13
|
+
declare const _default: {
|
|
14
|
+
handler: ToolHandler<{
|
|
15
|
+
readonly name: "writeToFile";
|
|
16
|
+
readonly description: "Request to write content to a file at the specified path.\n\nWhen to use:\n- Creating new files\n- Completely replacing file contents\n- When you have the complete intended content\n\nWhen NOT to use:\n- For modifying existing files: Use replaceInFile instead\n- For appending content: Use executeCommand with echo >> instead\n- For targeted edits: Use replaceInFile instead\n\nFeatures:\n- Automatically creates any directories needed\n- Overwrites existing files completely\n- Must provide complete file content (no truncation)\n\nIMPORTANT CONSTRAINT:\n- Always provide COMPLETE intended content (no omissions)\n- Ensure no incorrect escape sequences (<, >, &)\n- Ensure no unwanted CDATA tags in content";
|
|
17
|
+
readonly parameters: z.ZodObject<{
|
|
18
|
+
path: z.ZodString;
|
|
19
|
+
content: z.ZodString;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
}, FilesystemProvider>;
|
|
22
|
+
name: "writeToFile";
|
|
23
|
+
description: "Request to write content to a file at the specified path.\n\nWhen to use:\n- Creating new files\n- Completely replacing file contents\n- When you have the complete intended content\n\nWhen NOT to use:\n- For modifying existing files: Use replaceInFile instead\n- For appending content: Use executeCommand with echo >> instead\n- For targeted edits: Use replaceInFile instead\n\nFeatures:\n- Automatically creates any directories needed\n- Overwrites existing files completely\n- Must provide complete file content (no truncation)\n\nIMPORTANT CONSTRAINT:\n- Always provide COMPLETE intended content (no omissions)\n- Ensure no incorrect escape sequences (<, >, &)\n- Ensure no unwanted CDATA tags in content";
|
|
24
|
+
parameters: z.ZodObject<{
|
|
25
|
+
path: z.ZodString;
|
|
26
|
+
content: z.ZodString;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
};
|
|
29
|
+
export default _default;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createProviderError } from './utils';
|
|
3
|
+
export const toolInfo = {
|
|
4
|
+
name: 'writeToFile',
|
|
5
|
+
description: `Request to write content to a file at the specified path.
|
|
6
|
+
|
|
7
|
+
When to use:
|
|
8
|
+
- Creating new files
|
|
9
|
+
- Completely replacing file contents
|
|
10
|
+
- When you have the complete intended content
|
|
11
|
+
|
|
12
|
+
When NOT to use:
|
|
13
|
+
- For modifying existing files: Use replaceInFile instead
|
|
14
|
+
- For appending content: Use executeCommand with echo >> instead
|
|
15
|
+
- For targeted edits: Use replaceInFile instead
|
|
16
|
+
|
|
17
|
+
Features:
|
|
18
|
+
- Automatically creates any directories needed
|
|
19
|
+
- Overwrites existing files completely
|
|
20
|
+
- Must provide complete file content (no truncation)
|
|
21
|
+
|
|
22
|
+
IMPORTANT CONSTRAINT:
|
|
23
|
+
- Always provide COMPLETE intended content (no omissions)
|
|
24
|
+
- Ensure no incorrect escape sequences (<, >, &)
|
|
25
|
+
- Ensure no unwanted CDATA tags in content`,
|
|
26
|
+
parameters: z
|
|
27
|
+
.object({
|
|
28
|
+
path: z.string().describe('The path of the file to write to').meta({ usageValue: 'File path here' }),
|
|
29
|
+
content: z
|
|
30
|
+
.string()
|
|
31
|
+
.describe("The content to write to the file. ALWAYS provide the COMPLETE intended content of the file, without any truncation or omissions. You MUST include ALL parts of the file, even if they haven't been modified.")
|
|
32
|
+
.meta({ usageValue: 'Your file content here' }),
|
|
33
|
+
})
|
|
34
|
+
.meta({
|
|
35
|
+
examples: [
|
|
36
|
+
{
|
|
37
|
+
description: 'Request to write content to a file',
|
|
38
|
+
input: {
|
|
39
|
+
path: 'src/main.js',
|
|
40
|
+
content: `import React from 'react';
|
|
41
|
+
|
|
42
|
+
function App() {
|
|
43
|
+
return (
|
|
44
|
+
<div>
|
|
45
|
+
<h1>Hello, World!</h1>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default App;
|
|
51
|
+
`,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
}),
|
|
56
|
+
};
|
|
57
|
+
export const handler = async (provider, args) => {
|
|
58
|
+
if (!provider.writeFile) {
|
|
59
|
+
return createProviderError('write file');
|
|
60
|
+
}
|
|
61
|
+
const parsed = toolInfo.parameters.safeParse(args);
|
|
62
|
+
if (!parsed.success) {
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
message: {
|
|
66
|
+
type: 'error-text',
|
|
67
|
+
value: `Invalid arguments for writeToFile: ${parsed.error.message}`,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const { path, content } = parsed.data;
|
|
72
|
+
await provider.writeFile(path, content);
|
|
73
|
+
return {
|
|
74
|
+
success: true,
|
|
75
|
+
message: {
|
|
76
|
+
type: 'text',
|
|
77
|
+
value: `<write_to_file_path>${path}</write_to_file_path><status>Success</status>`,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
export default {
|
|
82
|
+
...toolInfo,
|
|
83
|
+
handler,
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=writeToFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeToFile.js","sourceRoot":"","sources":["../../src/tools/writeToFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAE7C,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;2CAoB4B;IACzC,UAAU,EAAE,CAAC;SACV,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC;QACpG,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,CACP,8MAA8M,CAC/M;aACA,IAAI,CAAC,EAAE,UAAU,EAAE,wBAAwB,EAAE,CAAC;KAClD,CAAC;SACD,IAAI,CAAC;QACJ,QAAQ,EAAE;YACR;gBACE,WAAW,EAAE,oCAAoC;gBACjD,KAAK,EAAE;oBACL,IAAI,EAAE,aAAa;oBACnB,OAAO,EAAE;;;;;;;;;;;CAWpB;iBACU;aACF;SACF;KACF,CAAC;CACuB,CAAA;AAE7B,MAAM,CAAC,MAAM,OAAO,GAAqD,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;IAChG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QACxB,OAAO,mBAAmB,CAAC,YAAY,CAAC,CAAA;IAC1C,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IAClD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE;gBACP,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,sCAAsC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE;aACpE;SACF,CAAA;IACH,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAA;IAErC,MAAM,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAEvC,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE;YACP,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,uBAAuB,IAAI,+CAA+C;SAClF;KACF,CAAA;AACH,CAAC,CAAA;AAED,eAAe;IACb,GAAG,QAAQ;IACX,OAAO;CACe,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, expect, it, spyOn } from 'bun:test';
|
|
2
|
+
import { MockProvider } from './provider';
|
|
3
|
+
import writeToFile from './writeToFile';
|
|
4
|
+
describe('writeToFile', () => {
|
|
5
|
+
it('should write file successfully', async () => {
|
|
6
|
+
const mockProvider = new MockProvider();
|
|
7
|
+
spyOn(mockProvider, 'writeFile').mockResolvedValue();
|
|
8
|
+
const result = await writeToFile.handler(mockProvider, {
|
|
9
|
+
path: 'test.txt',
|
|
10
|
+
content: 'Test content',
|
|
11
|
+
});
|
|
12
|
+
expect(result).toMatchSnapshot();
|
|
13
|
+
expect(mockProvider.writeFile).toHaveBeenCalledWith('test.txt', 'Test content');
|
|
14
|
+
});
|
|
15
|
+
it('should handle directory creation', async () => {
|
|
16
|
+
const mockProvider = new MockProvider();
|
|
17
|
+
spyOn(mockProvider, 'writeFile').mockResolvedValue();
|
|
18
|
+
const result = await writeToFile.handler(mockProvider, {
|
|
19
|
+
path: 'new-dir/test.txt',
|
|
20
|
+
content: 'Test content',
|
|
21
|
+
});
|
|
22
|
+
expect(result).toMatchSnapshot();
|
|
23
|
+
expect(mockProvider.writeFile).toHaveBeenCalledWith('new-dir/test.txt', 'Test content');
|
|
24
|
+
});
|
|
25
|
+
it('should handle write errors', async () => {
|
|
26
|
+
const mockProvider = new MockProvider();
|
|
27
|
+
spyOn(mockProvider, 'writeFile').mockRejectedValue(new Error('Write error'));
|
|
28
|
+
const result = writeToFile.handler(mockProvider, {
|
|
29
|
+
path: 'error.txt',
|
|
30
|
+
content: 'Test content',
|
|
31
|
+
});
|
|
32
|
+
expect(result).rejects.toMatchSnapshot();
|
|
33
|
+
expect(mockProvider.writeFile).toHaveBeenCalledWith('error.txt', 'Test content');
|
|
34
|
+
});
|
|
35
|
+
it('should write content with CDATA tags as-is', async () => {
|
|
36
|
+
const mockProvider = new MockProvider();
|
|
37
|
+
spyOn(mockProvider, 'writeFile').mockResolvedValue();
|
|
38
|
+
const result = await writeToFile.handler(mockProvider, {
|
|
39
|
+
path: 'cdata.txt',
|
|
40
|
+
content: '<![CDATA[Test content]]>',
|
|
41
|
+
});
|
|
42
|
+
expect(result).toMatchSnapshot();
|
|
43
|
+
expect(mockProvider.writeFile).toHaveBeenCalledWith('cdata.txt', '<![CDATA[Test content]]>');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=writeToFile.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeToFile.test.js","sourceRoot":"","sources":["../../src/tools/writeToFile.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,WAAW,MAAM,eAAe,CAAA;AAEvC,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAA;QACvC,KAAK,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,iBAAiB,EAAE,CAAA;QAEpD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE;YACrD,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,cAAc;SACxB,CAAC,CAAA;QAEF,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,EAAE,CAAA;QAChC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;IACjF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAA;QACvC,KAAK,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,iBAAiB,EAAE,CAAA;QAEpD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE;YACrD,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,cAAc;SACxB,CAAC,CAAA;QAEF,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,EAAE,CAAA;QAChC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAA;IACzF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAA;QACvC,KAAK,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,CAAA;QAE5E,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE;YAC/C,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,cAAc;SACxB,CAAC,CAAA;QAEF,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,CAAA;QACxC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,WAAW,EAAE,cAAc,CAAC,CAAA;IAClF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAA;QACvC,KAAK,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,iBAAiB,EAAE,CAAA;QAEpD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE;YACrD,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,0BAA0B;SACpC,CAAC,CAAA;QAEF,MAAM,CAAC,MAAM,CAAC,CAAC,eAAe,EAAE,CAAA;QAChC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,WAAW,EAAE,0BAA0B,CAAC,CAAA;IAC9F,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { deepMerge } from './merge';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep merge utility with EXPLICIT path specification
|
|
3
|
+
*
|
|
4
|
+
* This utility performs a shallow merge by default, with deep merging
|
|
5
|
+
* ONLY for paths explicitly specified. This prevents accidental deep
|
|
6
|
+
* merging of unexpected properties.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const config = { a: 1, b: { x: 1, y: 2 }, c: { z: 3 } }
|
|
11
|
+
* const override = { a: 2, b: { x: 10 }, c: 'not-an-object' }
|
|
12
|
+
*
|
|
13
|
+
* // Deep merge only 'b', shallow merge everything else
|
|
14
|
+
* const result = deepMerge(config, override, ['b'])
|
|
15
|
+
* // Result: { a: 2, b: { x: 10, y: 2 }, c: 'not-an-object' }
|
|
16
|
+
*
|
|
17
|
+
* // Note: 'c' was NOT deep merged because it's not in deepPaths
|
|
18
|
+
* // Note: 'b.x' was updated while 'b.y' was preserved (deep merge)
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @param base - The base object to merge into
|
|
22
|
+
* @param override - The object with values to override
|
|
23
|
+
* @param deepPaths - Array of keys that should be deep merged (must be plain objects)
|
|
24
|
+
* @returns A new object with merged values
|
|
25
|
+
*/
|
|
26
|
+
export declare function deepMerge<T extends object>(base: T, override: Partial<T>, deepPaths: Array<keyof T>): T;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Generated by polka.codes
|
|
2
|
+
/**
|
|
3
|
+
* Deep merge utility with EXPLICIT path specification
|
|
4
|
+
*
|
|
5
|
+
* This utility performs a shallow merge by default, with deep merging
|
|
6
|
+
* ONLY for paths explicitly specified. This prevents accidental deep
|
|
7
|
+
* merging of unexpected properties.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const config = { a: 1, b: { x: 1, y: 2 }, c: { z: 3 } }
|
|
12
|
+
* const override = { a: 2, b: { x: 10 }, c: 'not-an-object' }
|
|
13
|
+
*
|
|
14
|
+
* // Deep merge only 'b', shallow merge everything else
|
|
15
|
+
* const result = deepMerge(config, override, ['b'])
|
|
16
|
+
* // Result: { a: 2, b: { x: 10, y: 2 }, c: 'not-an-object' }
|
|
17
|
+
*
|
|
18
|
+
* // Note: 'c' was NOT deep merged because it's not in deepPaths
|
|
19
|
+
* // Note: 'b.x' was updated while 'b.y' was preserved (deep merge)
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @param base - The base object to merge into
|
|
23
|
+
* @param override - The object with values to override
|
|
24
|
+
* @param deepPaths - Array of keys that should be deep merged (must be plain objects)
|
|
25
|
+
* @returns A new object with merged values
|
|
26
|
+
*/
|
|
27
|
+
export function deepMerge(base, override, deepPaths) {
|
|
28
|
+
const result = { ...base, ...override };
|
|
29
|
+
// Explicit deep merge - only merge paths specified in deepPaths
|
|
30
|
+
for (const path of deepPaths) {
|
|
31
|
+
const baseValue = base[path];
|
|
32
|
+
const overrideValue = override[path];
|
|
33
|
+
// Only merge plain objects (not arrays, dates, null, etc.)
|
|
34
|
+
if (typeof baseValue === 'object' &&
|
|
35
|
+
baseValue !== null &&
|
|
36
|
+
!Array.isArray(baseValue) &&
|
|
37
|
+
typeof overrideValue === 'object' &&
|
|
38
|
+
overrideValue !== null &&
|
|
39
|
+
!Array.isArray(overrideValue)) {
|
|
40
|
+
result[path] = { ...baseValue, ...overrideValue };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/utils/merge.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,SAAS,CAAmB,IAAO,EAAE,QAAoB,EAAE,SAAyB;IAClG,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,EAAE,CAAA;IAEvC,gEAAgE;IAChE,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;QAEpC,2DAA2D;QAC3D,IACE,OAAO,SAAS,KAAK,QAAQ;YAC7B,SAAS,KAAK,IAAI;YAClB,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YACzB,OAAO,aAAa,KAAK,QAAQ;YACjC,aAAa,KAAK,IAAI;YACtB,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAC7B,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,GAAG,aAAa,EAAiC,CAAA;QAClF,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ToolSet } from 'ai';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import type { FullToolInfo, ToolResponse } from '../tool';
|
|
4
|
+
import type { JsonModelMessage, JsonResponseMessage, JsonUserModelMessage } from './json-ai-types';
|
|
5
|
+
import { type ExitReason, type TaskEvent } from './types';
|
|
6
|
+
import type { WorkflowFn } from './workflow';
|
|
7
|
+
export type AgentWorkflowInput = {
|
|
8
|
+
tools: Readonly<FullToolInfo[]>;
|
|
9
|
+
maxToolRoundTrips?: number;
|
|
10
|
+
userMessage: readonly JsonUserModelMessage[];
|
|
11
|
+
outputSchema?: z.ZodSchema;
|
|
12
|
+
model?: string;
|
|
13
|
+
} & ({
|
|
14
|
+
messages: JsonModelMessage[];
|
|
15
|
+
} | {
|
|
16
|
+
systemPrompt: string;
|
|
17
|
+
});
|
|
18
|
+
export type AgentToolRegistry = {
|
|
19
|
+
generateText: {
|
|
20
|
+
input: {
|
|
21
|
+
messages: JsonModelMessage[];
|
|
22
|
+
tools: ToolSet;
|
|
23
|
+
model?: string;
|
|
24
|
+
};
|
|
25
|
+
output: JsonResponseMessage[];
|
|
26
|
+
};
|
|
27
|
+
taskEvent: {
|
|
28
|
+
input: TaskEvent;
|
|
29
|
+
output: void;
|
|
30
|
+
};
|
|
31
|
+
invokeTool: {
|
|
32
|
+
input: {
|
|
33
|
+
toolName: string;
|
|
34
|
+
input: unknown;
|
|
35
|
+
};
|
|
36
|
+
output: ToolResponse;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export declare const agentWorkflow: WorkflowFn<AgentWorkflowInput, ExitReason, AgentToolRegistry>;
|