@travisennis/acai 0.0.10 → 0.0.12
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 +7 -4
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +29 -27
- package/dist/cli/stdin.d.ts +2 -1
- package/dist/cli/stdin.d.ts.map +1 -1
- package/dist/commands/generate-rules/service.d.ts +3 -2
- package/dist/commands/generate-rules/service.d.ts.map +1 -1
- package/dist/commands/health/utils.d.ts +3 -2
- package/dist/commands/health/utils.d.ts.map +1 -1
- package/dist/commands/init-project/utils.d.ts +2 -1
- package/dist/commands/init-project/utils.d.ts.map +1 -1
- package/dist/commands/init-project/utils.js +0 -11
- package/dist/commands/manager.d.ts.map +1 -1
- package/dist/commands/manager.js +6 -1
- package/dist/commands/resources/index.d.ts.map +1 -1
- package/dist/commands/resources/index.js +4 -1
- package/dist/commands/review/utils.d.ts +6 -1
- package/dist/commands/review/utils.d.ts.map +1 -1
- package/dist/commands/session/index.d.ts.map +1 -1
- package/dist/commands/session/index.js +6 -0
- package/dist/commands/session/types.d.ts +1 -0
- package/dist/commands/session/types.d.ts.map +1 -1
- package/dist/commands/tools/index.d.ts +3 -0
- package/dist/commands/tools/index.d.ts.map +1 -0
- package/dist/commands/tools/index.js +190 -0
- package/dist/commands/tools/templates.d.ts +6 -0
- package/dist/commands/tools/templates.d.ts.map +1 -0
- package/dist/commands/tools/templates.js +97 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +41 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -3
- package/dist/models/anthropic-provider.d.ts +1 -1
- package/dist/models/deepseek-provider.d.ts +3 -3
- package/dist/models/deepseek-provider.js +17 -17
- package/dist/models/google-provider.d.ts +2 -4
- package/dist/models/google-provider.d.ts.map +1 -1
- package/dist/models/google-provider.js +2 -17
- package/dist/models/groq-provider.d.ts +2 -4
- package/dist/models/groq-provider.d.ts.map +1 -1
- package/dist/models/groq-provider.js +3 -21
- package/dist/models/opencode-go-provider.d.ts +35 -0
- package/dist/models/opencode-go-provider.d.ts.map +1 -0
- package/dist/models/opencode-go-provider.js +214 -0
- package/dist/models/opencode-zen-provider.d.ts +5 -5
- package/dist/models/opencode-zen-provider.d.ts.map +1 -1
- package/dist/models/opencode-zen-provider.js +41 -47
- package/dist/models/openrouter-provider.d.ts +5 -13
- package/dist/models/openrouter-provider.d.ts.map +1 -1
- package/dist/models/openrouter-provider.js +34 -138
- package/dist/models/providers.d.ts +3 -3
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/models/providers.js +6 -0
- package/dist/models/xai-provider.d.ts +1 -2
- package/dist/models/xai-provider.d.ts.map +1 -1
- package/dist/models/xai-provider.js +0 -13
- package/dist/prompts/manager.d.ts.map +1 -1
- package/dist/prompts/manager.js +5 -1
- package/dist/prompts/mentions.d.ts.map +1 -1
- package/dist/prompts/mentions.js +35 -6
- package/dist/prompts/system-prompt.d.ts +1 -0
- package/dist/prompts/system-prompt.d.ts.map +1 -1
- package/dist/prompts/system-prompt.js +20 -5
- package/dist/repl/index.d.ts +1 -2
- package/dist/repl/index.d.ts.map +1 -1
- package/dist/repl/index.js +14 -53
- package/dist/sessions/manager.d.ts +3 -3
- package/dist/sessions/manager.d.ts.map +1 -1
- package/dist/sessions/manager.js +1 -1
- package/dist/skills/activated-tracker.d.ts +11 -0
- package/dist/skills/activated-tracker.d.ts.map +1 -0
- package/dist/skills/activated-tracker.js +16 -0
- package/dist/skills/index.d.ts +3 -2
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +7 -1
- package/dist/subagents/index.d.ts +2 -1
- package/dist/subagents/index.d.ts.map +1 -1
- package/dist/terminal/table/utils.d.ts +1 -1
- package/dist/terminal/table/utils.d.ts.map +1 -1
- package/dist/terminal/wrap-ansi.js +2 -2
- package/dist/tools/agent.js +1 -1
- package/dist/tools/apply-patch.d.ts +62 -0
- package/dist/tools/apply-patch.d.ts.map +1 -0
- package/dist/tools/apply-patch.js +377 -0
- package/dist/tools/bash.d.ts +4 -4
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +40 -8
- package/dist/tools/directory-tree.d.ts +4 -4
- package/dist/tools/directory-tree.d.ts.map +1 -1
- package/dist/tools/directory-tree.js +3 -1
- package/dist/tools/dynamic-tool-loader.d.ts +12 -3
- package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-loader.js +299 -39
- package/dist/tools/edit-file.d.ts +2 -2
- package/dist/tools/edit-file.d.ts.map +1 -1
- package/dist/tools/edit-file.js +188 -79
- package/dist/tools/glob.d.ts +16 -16
- package/dist/tools/glob.d.ts.map +1 -1
- package/dist/tools/glob.js +30 -15
- package/dist/tools/grep.d.ts +14 -14
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +50 -29
- package/dist/tools/index.d.ts +57 -84
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +20 -5
- package/dist/tools/ls.d.ts +2 -2
- package/dist/tools/ls.d.ts.map +1 -1
- package/dist/tools/ls.js +2 -1
- package/dist/tools/read-file.d.ts +9 -11
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +21 -16
- package/dist/tools/save-file.d.ts +4 -4
- package/dist/tools/save-file.d.ts.map +1 -1
- package/dist/tools/save-file.js +26 -21
- package/dist/tools/skill.d.ts +2 -1
- package/dist/tools/skill.d.ts.map +1 -1
- package/dist/tools/skill.js +55 -12
- package/dist/tools/types.d.ts +8 -2
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/web-fetch.d.ts +6 -18
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +45 -9
- package/dist/tools/web-search.d.ts +4 -22
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +1 -1
- package/dist/tui/autocomplete/file-search-provider.js +1 -1
- package/dist/tui/autocomplete/utils.d.ts +2 -1
- package/dist/tui/autocomplete/utils.d.ts.map +1 -1
- package/dist/tui/autocomplete/utils.js +25 -23
- package/dist/tui/components/editor.d.ts +2 -1
- package/dist/tui/components/editor.d.ts.map +1 -1
- package/dist/tui/components/editor.js +1 -1
- package/dist/tui/components/footer.d.ts +0 -2
- package/dist/tui/components/footer.d.ts.map +1 -1
- package/dist/tui/components/footer.js +1 -17
- package/dist/tui/components/markdown.d.ts +2 -2
- package/dist/tui/components/markdown.d.ts.map +1 -1
- package/dist/tui/components/welcome.d.ts +2 -1
- package/dist/tui/components/welcome.d.ts.map +1 -1
- package/dist/tui/editor-launcher.d.ts +3 -2
- package/dist/tui/editor-launcher.d.ts.map +1 -1
- package/dist/tui/index.d.ts +0 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/tui.d.ts +1 -0
- package/dist/tui/tui.d.ts.map +1 -1
- package/dist/tui/tui.js +9 -0
- package/dist/tui/utils.d.ts +1 -5
- package/dist/tui/utils.d.ts.map +1 -1
- package/dist/tui/utils.js +271 -44
- package/dist/utils/binary-output.d.ts +32 -0
- package/dist/utils/binary-output.d.ts.map +1 -0
- package/dist/utils/binary-output.js +127 -0
- package/dist/utils/command-protection.d.ts.map +1 -1
- package/dist/utils/command-protection.js +92 -9
- package/dist/utils/parsing.d.ts +1 -1
- package/dist/utils/parsing.d.ts.map +1 -1
- package/package.json +28 -26
- package/dist/commands/add-directory/types.d.ts +0 -6
- package/dist/commands/add-directory/types.d.ts.map +0 -1
- package/dist/commands/add-directory/types.js +0 -1
- package/dist/commands/copy/types.d.ts +0 -3
- package/dist/commands/copy/types.d.ts.map +0 -1
- package/dist/commands/copy/types.js +0 -1
- package/dist/commands/review/types.d.ts +0 -12
- package/dist/commands/review/types.d.ts.map +0 -1
- package/dist/commands/review/types.js +0 -1
- package/dist/modes/manager.d.ts +0 -23
- package/dist/modes/manager.d.ts.map +0 -1
- package/dist/modes/manager.js +0 -77
- package/dist/modes/prompts.d.ts +0 -2
- package/dist/modes/prompts.d.ts.map +0 -1
- package/dist/modes/prompts.js +0 -143
- package/dist/tools/code-search.d.ts +0 -41
- package/dist/tools/code-search.d.ts.map +0 -1
- package/dist/tools/code-search.js +0 -195
- package/dist/utils/iterables.d.ts +0 -2
- package/dist/utils/iterables.d.ts.map +0 -1
- package/dist/utils/iterables.js +0 -6
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import fsp from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { createTwoFilesPatch } from "diff";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { config } from "../config/index.js";
|
|
7
|
+
import { clearProjectStatusCache } from "../repl/project-status.js";
|
|
8
|
+
import style from "../terminal/style.js";
|
|
9
|
+
import { validateFileNotReadOnly, validatePath, } from "../utils/filesystem/security.js";
|
|
10
|
+
export const ApplyPatchTool = {
|
|
11
|
+
name: "ApplyPatch",
|
|
12
|
+
};
|
|
13
|
+
const inputSchema = z.object({
|
|
14
|
+
patchText: z
|
|
15
|
+
.string()
|
|
16
|
+
.describe("The full apply_patch text between *** Begin Patch and *** End Patch markers"),
|
|
17
|
+
});
|
|
18
|
+
// Patch parsing functions
|
|
19
|
+
function parsePatchHeader(lines, startIdx) {
|
|
20
|
+
const line = lines[startIdx];
|
|
21
|
+
if (line.startsWith("*** Add File:")) {
|
|
22
|
+
const filePath = line.split(":", 2)[1]?.trim();
|
|
23
|
+
return filePath ? { filePath, nextIdx: startIdx + 1 } : null;
|
|
24
|
+
}
|
|
25
|
+
if (line.startsWith("*** Delete File:")) {
|
|
26
|
+
const filePath = line.split(":", 2)[1]?.trim();
|
|
27
|
+
return filePath ? { filePath, nextIdx: startIdx + 1 } : null;
|
|
28
|
+
}
|
|
29
|
+
if (line.startsWith("*** Update File:")) {
|
|
30
|
+
const filePath = line.split(":", 2)[1]?.trim();
|
|
31
|
+
let movePath;
|
|
32
|
+
let nextIdx = startIdx + 1;
|
|
33
|
+
if (nextIdx < lines.length && lines[nextIdx].startsWith("*** Move to:")) {
|
|
34
|
+
movePath = lines[nextIdx].split(":", 2)[1]?.trim();
|
|
35
|
+
nextIdx++;
|
|
36
|
+
}
|
|
37
|
+
return filePath ? { filePath, movePath, nextIdx } : null;
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
function parseUpdateFileChunks(lines, startIdx) {
|
|
42
|
+
const chunks = [];
|
|
43
|
+
let i = startIdx;
|
|
44
|
+
while (i < lines.length && !lines[i].startsWith("***")) {
|
|
45
|
+
if (lines[i].startsWith("@@")) {
|
|
46
|
+
const contextLine = lines[i].substring(2).trim();
|
|
47
|
+
i++;
|
|
48
|
+
const oldLines = [];
|
|
49
|
+
const newLines = [];
|
|
50
|
+
let isEndOfFile = false;
|
|
51
|
+
while (i < lines.length && !lines[i].startsWith("@@")) {
|
|
52
|
+
const changeLine = lines[i];
|
|
53
|
+
// Check for end of file marker first (before general *** check)
|
|
54
|
+
if (changeLine === "*** End of File") {
|
|
55
|
+
isEndOfFile = true;
|
|
56
|
+
i++;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
// Check for other *** markers (new file operations)
|
|
60
|
+
if (changeLine.startsWith("***")) {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
if (changeLine.startsWith(" ")) {
|
|
64
|
+
const content = changeLine.substring(1);
|
|
65
|
+
oldLines.push(content);
|
|
66
|
+
newLines.push(content);
|
|
67
|
+
}
|
|
68
|
+
else if (changeLine.startsWith("-")) {
|
|
69
|
+
oldLines.push(changeLine.substring(1));
|
|
70
|
+
}
|
|
71
|
+
else if (changeLine.startsWith("+")) {
|
|
72
|
+
newLines.push(changeLine.substring(1));
|
|
73
|
+
}
|
|
74
|
+
i++;
|
|
75
|
+
}
|
|
76
|
+
chunks.push({
|
|
77
|
+
oldLines,
|
|
78
|
+
newLines,
|
|
79
|
+
changeContext: contextLine || undefined,
|
|
80
|
+
isEndOfFile: isEndOfFile || undefined,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
i++;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return { chunks, nextIdx: i };
|
|
88
|
+
}
|
|
89
|
+
function parseAddFileContent(lines, startIdx) {
|
|
90
|
+
let content = "";
|
|
91
|
+
let i = startIdx;
|
|
92
|
+
while (i < lines.length && !lines[i].startsWith("***")) {
|
|
93
|
+
if (lines[i].startsWith("+")) {
|
|
94
|
+
content += `${lines[i].substring(1)}\n`;
|
|
95
|
+
}
|
|
96
|
+
i++;
|
|
97
|
+
}
|
|
98
|
+
if (content.endsWith("\n"))
|
|
99
|
+
content = content.slice(0, -1);
|
|
100
|
+
return { content, nextIdx: i };
|
|
101
|
+
}
|
|
102
|
+
export function parsePatch(patchText) {
|
|
103
|
+
const lines = patchText.split("\n");
|
|
104
|
+
const hunks = [];
|
|
105
|
+
const beginMarker = "*** Begin Patch";
|
|
106
|
+
const endMarker = "*** End Patch";
|
|
107
|
+
const beginIdx = lines.findIndex((l) => l.trim() === beginMarker);
|
|
108
|
+
const endIdx = lines.findIndex((l) => l.trim() === endMarker);
|
|
109
|
+
if (beginIdx === -1 || endIdx === -1 || beginIdx >= endIdx) {
|
|
110
|
+
throw new Error("Invalid patch format: missing Begin/End markers");
|
|
111
|
+
}
|
|
112
|
+
let i = beginIdx + 1;
|
|
113
|
+
while (i < endIdx) {
|
|
114
|
+
const header = parsePatchHeader(lines, i);
|
|
115
|
+
if (!header) {
|
|
116
|
+
i++;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (lines[i].startsWith("*** Add File:")) {
|
|
120
|
+
const { content, nextIdx } = parseAddFileContent(lines, header.nextIdx);
|
|
121
|
+
hunks.push({ type: "add", path: header.filePath, contents: content });
|
|
122
|
+
i = nextIdx;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (lines[i].startsWith("*** Delete File:")) {
|
|
126
|
+
hunks.push({ type: "delete", path: header.filePath });
|
|
127
|
+
i = header.nextIdx;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (lines[i].startsWith("*** Update File:")) {
|
|
131
|
+
const { chunks: parsedChunks, nextIdx } = parseUpdateFileChunks(lines, header.nextIdx);
|
|
132
|
+
hunks.push({
|
|
133
|
+
type: "update",
|
|
134
|
+
path: header.filePath,
|
|
135
|
+
movePath: header.movePath,
|
|
136
|
+
chunks: parsedChunks,
|
|
137
|
+
});
|
|
138
|
+
i = nextIdx;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
i++;
|
|
142
|
+
}
|
|
143
|
+
return { hunks };
|
|
144
|
+
}
|
|
145
|
+
function resolvePathInRoot(rootAbs, p) {
|
|
146
|
+
// Relative paths are resolved against rootAbs
|
|
147
|
+
// Absolute paths are used as-is (but validated later)
|
|
148
|
+
const abs = path.isAbsolute(p) ? path.normalize(p) : path.resolve(rootAbs, p);
|
|
149
|
+
const rel = path.relative(rootAbs, abs) || ".";
|
|
150
|
+
return { abs, rel };
|
|
151
|
+
}
|
|
152
|
+
function seekSequence(lines, pattern, startIndex) {
|
|
153
|
+
if (pattern.length === 0)
|
|
154
|
+
return -1;
|
|
155
|
+
for (let i = startIndex; i <= lines.length - pattern.length; i++) {
|
|
156
|
+
let matches = true;
|
|
157
|
+
for (let j = 0; j < pattern.length; j++) {
|
|
158
|
+
if (lines[i + j] !== pattern[j]) {
|
|
159
|
+
matches = false;
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (matches)
|
|
164
|
+
return i;
|
|
165
|
+
}
|
|
166
|
+
return -1;
|
|
167
|
+
}
|
|
168
|
+
function applyReplacements(lines, replacements) {
|
|
169
|
+
const result = [...lines];
|
|
170
|
+
for (let i = replacements.length - 1; i >= 0; i--) {
|
|
171
|
+
const [startIdx, oldLen, newSegment] = replacements[i];
|
|
172
|
+
result.splice(startIdx, oldLen);
|
|
173
|
+
for (let j = 0; j < newSegment.length; j++)
|
|
174
|
+
result.splice(startIdx + j, 0, newSegment[j]);
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
function computeReplacements(originalLines, filePath, chunks) {
|
|
179
|
+
const replacements = [];
|
|
180
|
+
let lineIndex = 0;
|
|
181
|
+
for (const chunk of chunks) {
|
|
182
|
+
if (chunk.changeContext) {
|
|
183
|
+
const contextIdx = seekSequence(originalLines, [chunk.changeContext], lineIndex);
|
|
184
|
+
if (contextIdx === -1) {
|
|
185
|
+
throw new Error(`Failed to find context '${chunk.changeContext}' in ${filePath}`);
|
|
186
|
+
}
|
|
187
|
+
lineIndex = contextIdx + 1;
|
|
188
|
+
}
|
|
189
|
+
if (chunk.oldLines.length === 0) {
|
|
190
|
+
const insertionIdx = originalLines.length > 0 &&
|
|
191
|
+
originalLines[originalLines.length - 1] === ""
|
|
192
|
+
? originalLines.length - 1
|
|
193
|
+
: originalLines.length;
|
|
194
|
+
replacements.push([insertionIdx, 0, chunk.newLines]);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
let pattern = chunk.oldLines;
|
|
198
|
+
let newSlice = chunk.newLines;
|
|
199
|
+
let found = seekSequence(originalLines, pattern, lineIndex);
|
|
200
|
+
if (found === -1 &&
|
|
201
|
+
pattern.length > 0 &&
|
|
202
|
+
pattern[pattern.length - 1] === "") {
|
|
203
|
+
pattern = pattern.slice(0, -1);
|
|
204
|
+
if (newSlice.length > 0 && newSlice[newSlice.length - 1] === "")
|
|
205
|
+
newSlice = newSlice.slice(0, -1);
|
|
206
|
+
found = seekSequence(originalLines, pattern, lineIndex);
|
|
207
|
+
}
|
|
208
|
+
if (found !== -1) {
|
|
209
|
+
replacements.push([found, pattern.length, newSlice]);
|
|
210
|
+
lineIndex = found + pattern.length;
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
throw new Error(`Failed to find expected lines in ${filePath}:\n${chunk.oldLines.join("\n")}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
replacements.sort((a, b) => a[0] - b[0]);
|
|
217
|
+
return replacements;
|
|
218
|
+
}
|
|
219
|
+
function generateUnifiedDiff(oldContent, newContent, filePath) {
|
|
220
|
+
return createTwoFilesPatch(filePath, filePath, oldContent, newContent, "original", "modified");
|
|
221
|
+
}
|
|
222
|
+
function deriveNewContentsFromChunks(fileAbsPath, chunks) {
|
|
223
|
+
let originalContent;
|
|
224
|
+
try {
|
|
225
|
+
originalContent = fs.readFileSync(fileAbsPath, "utf-8");
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
throw new Error(`Failed to read file ${fileAbsPath}: ${String(error)}`);
|
|
229
|
+
}
|
|
230
|
+
const originalLines = originalContent.split("\n");
|
|
231
|
+
if (originalLines.length > 0 &&
|
|
232
|
+
originalLines[originalLines.length - 1] === "")
|
|
233
|
+
originalLines.pop();
|
|
234
|
+
const replacements = computeReplacements(originalLines, fileAbsPath, chunks);
|
|
235
|
+
const newLines = applyReplacements(originalLines, replacements);
|
|
236
|
+
// ensure trailing newline
|
|
237
|
+
if (newLines.length === 0 || newLines[newLines.length - 1] !== "")
|
|
238
|
+
newLines.push("");
|
|
239
|
+
const newContent = newLines.join("\n");
|
|
240
|
+
return {
|
|
241
|
+
unifiedDiff: generateUnifiedDiff(originalContent, newContent, fileAbsPath),
|
|
242
|
+
content: newContent,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
async function applyChanges(changes, signal) {
|
|
246
|
+
const changed = [];
|
|
247
|
+
for (const change of changes) {
|
|
248
|
+
if (signal?.aborted)
|
|
249
|
+
throw new Error("Cancelled");
|
|
250
|
+
if (change.type === "add") {
|
|
251
|
+
const dir = path.dirname(change.path);
|
|
252
|
+
if (dir !== "." && dir !== "/")
|
|
253
|
+
await fsp.mkdir(dir, { recursive: true });
|
|
254
|
+
await fsp.writeFile(change.path, change.content, "utf-8");
|
|
255
|
+
changed.push(change.path);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (change.type === "delete") {
|
|
259
|
+
await fsp.unlink(change.path).catch(() => { });
|
|
260
|
+
changed.push(change.path);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
// update
|
|
264
|
+
if (change.movePath) {
|
|
265
|
+
const dir = path.dirname(change.movePath);
|
|
266
|
+
if (dir !== "." && dir !== "/")
|
|
267
|
+
await fsp.mkdir(dir, { recursive: true });
|
|
268
|
+
await fsp.writeFile(change.movePath, change.newContent, "utf-8");
|
|
269
|
+
await fsp.unlink(change.path).catch(() => { });
|
|
270
|
+
changed.push(change.movePath);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
await fsp.writeFile(change.path, change.newContent, "utf-8");
|
|
274
|
+
changed.push(change.path);
|
|
275
|
+
}
|
|
276
|
+
return changed;
|
|
277
|
+
}
|
|
278
|
+
export const createApplyPatchTool = async (options) => {
|
|
279
|
+
const { primaryDir, allowedDirs } = options.workspace;
|
|
280
|
+
const allowedDirectories = allowedDirs ?? [primaryDir];
|
|
281
|
+
const projectConfig = await config.getConfig();
|
|
282
|
+
return {
|
|
283
|
+
toolDef: {
|
|
284
|
+
description: "Apply a high-level apply_patch diff to modify files.\n\n" +
|
|
285
|
+
"Input must be in the apply_patch format surrounded by markers:\n\n" +
|
|
286
|
+
"*** Begin Patch\n" +
|
|
287
|
+
"*** Update File: path/to/file\n" +
|
|
288
|
+
"@@ optional context line\n" +
|
|
289
|
+
" unchanged line\n" +
|
|
290
|
+
"- removed line\n" +
|
|
291
|
+
"+ added line\n" +
|
|
292
|
+
"*** End Patch\n\n" +
|
|
293
|
+
"Supported operations:\n" +
|
|
294
|
+
"- *** Add File: path/to/file (content lines prefixed with +)\n" +
|
|
295
|
+
"- *** Update File (with optional *** Move to: new/path)\n" +
|
|
296
|
+
"- *** Delete File: path/to/file\n\n" +
|
|
297
|
+
"File paths may be absolute or relative to the project directory.",
|
|
298
|
+
inputSchema,
|
|
299
|
+
},
|
|
300
|
+
display({ patchText }) {
|
|
301
|
+
// Extract number of files being modified from patch text
|
|
302
|
+
try {
|
|
303
|
+
const { hunks } = parsePatch(patchText);
|
|
304
|
+
return `${style.cyan("apply patch")} (${hunks.length} file${hunks.length === 1 ? "" : "s"})`;
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
return `${style.cyan("apply patch")}`;
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
async execute({ patchText }, { abortSignal }) {
|
|
311
|
+
if (abortSignal?.aborted) {
|
|
312
|
+
throw new Error("Apply patch aborted");
|
|
313
|
+
}
|
|
314
|
+
const root = path.resolve(primaryDir);
|
|
315
|
+
const { hunks } = parsePatch(patchText);
|
|
316
|
+
if (hunks.length === 0) {
|
|
317
|
+
return "No changes found in patch.";
|
|
318
|
+
}
|
|
319
|
+
// Build a list of resolved file changes (absolute paths), and a diff preview.
|
|
320
|
+
const changes = [];
|
|
321
|
+
let diffOutput = "";
|
|
322
|
+
for (const hunk of hunks) {
|
|
323
|
+
if (abortSignal?.aborted)
|
|
324
|
+
throw new Error("Cancelled");
|
|
325
|
+
const p = resolvePathInRoot(root, hunk.path);
|
|
326
|
+
// Validate path is within allowed directories
|
|
327
|
+
const validPath = await validatePath(p.abs, allowedDirectories, {
|
|
328
|
+
requireExistence: hunk.type !== "add",
|
|
329
|
+
abortSignal,
|
|
330
|
+
});
|
|
331
|
+
if (hunk.type === "add") {
|
|
332
|
+
changes.push({
|
|
333
|
+
type: "add",
|
|
334
|
+
path: validPath,
|
|
335
|
+
content: hunk.contents,
|
|
336
|
+
});
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
if (hunk.type === "delete") {
|
|
340
|
+
// Validate file is not read-only before deletion
|
|
341
|
+
validateFileNotReadOnly(validPath, projectConfig, primaryDir);
|
|
342
|
+
changes.push({ type: "delete", path: validPath });
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
// update - validate file is not read-only
|
|
346
|
+
validateFileNotReadOnly(validPath, projectConfig, primaryDir);
|
|
347
|
+
let moveAbs;
|
|
348
|
+
if (hunk.movePath) {
|
|
349
|
+
const moveP = resolvePathInRoot(root, hunk.movePath);
|
|
350
|
+
moveAbs = await validatePath(moveP.abs, allowedDirectories, {
|
|
351
|
+
requireExistence: false,
|
|
352
|
+
abortSignal,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
const upd = deriveNewContentsFromChunks(validPath, hunk.chunks);
|
|
356
|
+
changes.push({
|
|
357
|
+
type: "update",
|
|
358
|
+
path: validPath,
|
|
359
|
+
movePath: moveAbs,
|
|
360
|
+
newContent: upd.content,
|
|
361
|
+
unifiedDiff: upd.unifiedDiff,
|
|
362
|
+
});
|
|
363
|
+
if (upd.unifiedDiff) {
|
|
364
|
+
diffOutput += `*** Update File: ${path.relative(root, moveAbs ?? validPath)}\n`;
|
|
365
|
+
diffOutput += `${upd.unifiedDiff}\n`;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
// Apply changes
|
|
369
|
+
const changedAbs = await applyChanges(changes, abortSignal);
|
|
370
|
+
const changedRel = changedAbs.map((p) => path.relative(root, p));
|
|
371
|
+
clearProjectStatusCache();
|
|
372
|
+
const summary = `${changedRel.length} file(s) changed`;
|
|
373
|
+
const filesList = changedRel.map((x) => ` ${x}`).join("\n");
|
|
374
|
+
return `Patch applied successfully. ${summary}\n${filesList}\n\n${diffOutput}`;
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
};
|
package/dist/tools/bash.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ export declare const BashTool: {
|
|
|
6
6
|
};
|
|
7
7
|
declare const inputSchema: z.ZodObject<{
|
|
8
8
|
command: z.ZodString;
|
|
9
|
-
cwd: z.
|
|
10
|
-
timeout: z.
|
|
9
|
+
cwd: z.ZodPreprocess<z.ZodNullable<z.ZodString>>;
|
|
10
|
+
timeout: z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
|
|
11
11
|
background: z.ZodOptional<z.ZodBoolean>;
|
|
12
12
|
}, z.core.$strip>;
|
|
13
13
|
type BashInputSchema = z.infer<typeof inputSchema>;
|
|
@@ -19,8 +19,8 @@ export declare const createBashTool: (options: {
|
|
|
19
19
|
description: string;
|
|
20
20
|
inputSchema: z.ZodObject<{
|
|
21
21
|
command: z.ZodString;
|
|
22
|
-
cwd: z.
|
|
23
|
-
timeout: z.
|
|
22
|
+
cwd: z.ZodPreprocess<z.ZodNullable<z.ZodString>>;
|
|
23
|
+
timeout: z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>;
|
|
24
24
|
background: z.ZodOptional<z.ZodBoolean>;
|
|
25
25
|
}, z.core.$strip>;
|
|
26
26
|
};
|
package/dist/tools/bash.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../source/tools/bash.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../source/tools/bash.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAepD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA0CvD,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AA6MF,QAAA,MAAM,WAAW;;;;;iBAkBf,CAAC;AAEH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,eAAO,MAAM,cAAc,GAAU,SAAS;IAC5C,SAAS,EAAE,gBAAgB,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;;;;;;;;;;yBAyGwB,eAAe;mDAIK,eAAe,mBACrC,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;EA6BrB,CAAC"}
|
package/dist/tools/bash.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// import { execSync } from "node:child_process";
|
|
2
1
|
import { randomBytes } from "node:crypto";
|
|
3
2
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
4
3
|
import { dirname } from "node:path";
|
|
@@ -6,6 +5,7 @@ import { z } from "zod";
|
|
|
6
5
|
import { initExecutionEnvironment } from "../execution/index.js";
|
|
7
6
|
import style from "../terminal/style.js";
|
|
8
7
|
import { resolveCwd, validatePaths } from "../utils/bash.js";
|
|
8
|
+
import { formatBinaryMessage, isBinaryOutput, saveBinaryOutput, } from "../utils/binary-output.js";
|
|
9
9
|
import { detectDestructiveCommand, formatBlockedCommandMessage, } from "../utils/command-protection.js";
|
|
10
10
|
import { expandEnvVars } from "../utils/env-expand.js";
|
|
11
11
|
import { logger } from "../utils/logger.js";
|
|
@@ -18,7 +18,7 @@ import { convertNullString } from "../utils/zod.js";
|
|
|
18
18
|
function detectMultilineGitCommit(command) {
|
|
19
19
|
const trimmed = command.trim();
|
|
20
20
|
// Check if it's a git commit command
|
|
21
|
-
if (!trimmed.startsWith("git commit")
|
|
21
|
+
if (!trimmed.startsWith("git commit")) {
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
// Look for -m or -am flags with a message containing newlines
|
|
@@ -209,6 +209,22 @@ export const BashTool = {
|
|
|
209
209
|
const simpleDescription = "Run terminal commands.";
|
|
210
210
|
// Command execution timeout in milliseconds
|
|
211
211
|
const DEFAULT_TIMEOUT = 1.5 * 60 * 1000; // 1.5 minutes
|
|
212
|
+
// Maximum output size in bytes (50KB) to prevent context window exhaustion
|
|
213
|
+
const MAX_OUTPUT_SIZE = 50 * 1024;
|
|
214
|
+
/**
|
|
215
|
+
* Truncates output if it exceeds MAX_OUTPUT_SIZE and adds a clear message.
|
|
216
|
+
* This prevents extremely large outputs from exhausting the context window.
|
|
217
|
+
* The footer is always appended at the end, even when output is truncated.
|
|
218
|
+
*/
|
|
219
|
+
function truncateOutput(output, footer) {
|
|
220
|
+
if (output.length <= MAX_OUTPUT_SIZE) {
|
|
221
|
+
return `${output}\n${footer}`;
|
|
222
|
+
}
|
|
223
|
+
const truncatedLength = MAX_OUTPUT_SIZE;
|
|
224
|
+
const originalLength = output.length;
|
|
225
|
+
const truncated = output.slice(0, truncatedLength);
|
|
226
|
+
return `${truncated}\n\n[OUTPUT TRUNCATED: ${originalLength.toLocaleString()} characters total, showing first ${truncatedLength.toLocaleString()} characters. The output was too large and was truncated to prevent context window exhaustion. Consider using commands that produce smaller output (e.g., head, tail with line limits, or redirecting to a file).]\n${footer}`;
|
|
227
|
+
}
|
|
212
228
|
const inputSchema = z.object({
|
|
213
229
|
command: z.string().describe("Full CLI command to execute."),
|
|
214
230
|
cwd: z
|
|
@@ -268,7 +284,8 @@ export const createBashTool = async (options) => {
|
|
|
268
284
|
return `Background process started with PID: ${proc.pid}`;
|
|
269
285
|
}
|
|
270
286
|
async function executeSync(cmd, cwd, timeout, signal) {
|
|
271
|
-
const
|
|
287
|
+
const startTime = Date.now();
|
|
288
|
+
const { output, exitCode, error } = await execEnv.executeCommand(cmd, {
|
|
272
289
|
cwd,
|
|
273
290
|
timeout,
|
|
274
291
|
abortSignal: signal,
|
|
@@ -276,10 +293,25 @@ export const createBashTool = async (options) => {
|
|
|
276
293
|
captureStderr: true,
|
|
277
294
|
throwOnError: false,
|
|
278
295
|
});
|
|
296
|
+
const elapsedMs = Date.now() - startTime;
|
|
297
|
+
const timeStr = elapsedMs < 1000 ? `${elapsedMs}ms` : `${(elapsedMs / 1000).toFixed(1)}s`;
|
|
298
|
+
const metadataFooter = `[exit:${exitCode} | ${timeStr}]`;
|
|
279
299
|
if (exitCode !== 0) {
|
|
280
|
-
|
|
300
|
+
const errorMessage = error
|
|
301
|
+
? error.message
|
|
302
|
+
: `Command exited with code ${exitCode}`;
|
|
303
|
+
const combinedOutput = output
|
|
304
|
+
? `${errorMessage}\n${output}`
|
|
305
|
+
: errorMessage;
|
|
306
|
+
throw new Error(truncateOutput(combinedOutput, metadataFooter));
|
|
307
|
+
}
|
|
308
|
+
// Check for binary output and handle specially
|
|
309
|
+
if (isBinaryOutput(output)) {
|
|
310
|
+
const saveResult = saveBinaryOutput(output);
|
|
311
|
+
const binaryMessage = formatBinaryMessage(saveResult);
|
|
312
|
+
return `${binaryMessage}\n${metadataFooter}`;
|
|
281
313
|
}
|
|
282
|
-
return output;
|
|
314
|
+
return truncateOutput(output, metadataFooter);
|
|
283
315
|
}
|
|
284
316
|
return {
|
|
285
317
|
toolDef: {
|
|
@@ -411,9 +443,9 @@ function fixRgCommand(command) {
|
|
|
411
443
|
// If it's just alphanumeric with maybe some regex chars, it's probably a pattern
|
|
412
444
|
// Common pattern chars: ., *, +, ?, [, ], ^, $, (, ), |, \\
|
|
413
445
|
// But we want to be conservative - if it looks like a filename without path, add .
|
|
414
|
-
if (!lastToken.includes("/") &&
|
|
415
|
-
|
|
416
|
-
|
|
446
|
+
if (!lastToken.includes("/") &&
|
|
447
|
+
!lastToken.includes("*") &&
|
|
448
|
+
!lastToken.includes(".")) {
|
|
417
449
|
logger.debug(`Adding '.' to rg command: ${command}`);
|
|
418
450
|
return `${command} .`;
|
|
419
451
|
}
|
|
@@ -6,8 +6,8 @@ export declare const DirectoryTreeTool: {
|
|
|
6
6
|
};
|
|
7
7
|
declare const inputSchema: z.ZodObject<{
|
|
8
8
|
path: z.ZodString;
|
|
9
|
-
maxResults: z.
|
|
10
|
-
maxDepth: z.
|
|
9
|
+
maxResults: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
10
|
+
maxDepth: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
11
11
|
}, z.core.$strip>;
|
|
12
12
|
type DirectoryTreeInputSchema = z.infer<typeof inputSchema>;
|
|
13
13
|
export declare const createDirectoryTreeTool: (options: {
|
|
@@ -17,8 +17,8 @@ export declare const createDirectoryTreeTool: (options: {
|
|
|
17
17
|
description: string;
|
|
18
18
|
inputSchema: z.ZodObject<{
|
|
19
19
|
path: z.ZodString;
|
|
20
|
-
maxResults: z.
|
|
21
|
-
maxDepth: z.
|
|
20
|
+
maxResults: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
21
|
+
maxDepth: z.ZodDefault<z.ZodPreprocess<z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
22
22
|
}, z.core.$strip>;
|
|
23
23
|
};
|
|
24
24
|
display({ path, maxDepth, maxResults }: DirectoryTreeInputSchema): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory-tree.d.ts","sourceRoot":"","sources":["../../source/tools/directory-tree.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAKvD,eAAO,MAAM,iBAAiB;;CAE7B,CAAC;AAEF,QAAA,MAAM,WAAW;;;;
|
|
1
|
+
{"version":3,"file":"directory-tree.d.ts","sourceRoot":"","sources":["../../source/tools/directory-tree.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAKvD,eAAO,MAAM,iBAAiB;;CAE7B,CAAC;AAEF,QAAA,MAAM,WAAW;;;;iBAcf,CAAC;AAEH,KAAK,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAE5D,eAAO,MAAM,uBAAuB,GAAU,SAAS;IACrD,SAAS,EAAE,gBAAgB,CAAC;CAC7B;;;;;;;;;4CAS2C,wBAAwB;4CAY9B,wBAAwB,mBACvC,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;EAyBrB,CAAC"}
|
|
@@ -15,9 +15,11 @@ const inputSchema = z.object({
|
|
|
15
15
|
path: z.string().describe("The path"),
|
|
16
16
|
maxResults: z
|
|
17
17
|
.preprocess((val) => convertNullString(val), z.coerce.number().nullable())
|
|
18
|
+
.default(null)
|
|
18
19
|
.describe(`Maximum number of items (files + directories) to return. Set to 0 for no limit. (default: ${DEFAULT_ITEM_LIMIT})`),
|
|
19
20
|
maxDepth: z
|
|
20
21
|
.preprocess((val) => convertNullString(val), z.coerce.number().nullable())
|
|
22
|
+
.default(null)
|
|
21
23
|
.describe(`Maximum recursion depth. Set to 0 for no limit. (default: ${DEFAULT_DEPTH_LIMIT})`),
|
|
22
24
|
});
|
|
23
25
|
export const createDirectoryTreeTool = async (options) => {
|
|
@@ -25,7 +27,7 @@ export const createDirectoryTreeTool = async (options) => {
|
|
|
25
27
|
const allowedDirectory = allowedDirs ?? [primaryDir];
|
|
26
28
|
return {
|
|
27
29
|
toolDef: {
|
|
28
|
-
description: "Show directory structure as a tree.",
|
|
30
|
+
description: "Show directory structure as a recursive tree. Use this to explore nested directories and understand the overall project structure. For a simple flat list of a single directory, use LS instead.",
|
|
29
31
|
inputSchema,
|
|
30
32
|
},
|
|
31
33
|
display({ path, maxDepth, maxResults }) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import type { ToolExecutionOptions } from "./types.ts";
|
|
2
|
+
import type { SessionContext, ToolExecutionOptions } from "./types.ts";
|
|
3
3
|
declare const toolMetadataSchema: z.ZodObject<{
|
|
4
4
|
name: z.ZodString;
|
|
5
5
|
description: z.ZodString;
|
|
@@ -16,7 +16,15 @@ declare const toolMetadataSchema: z.ZodObject<{
|
|
|
16
16
|
}, z.core.$strip>>;
|
|
17
17
|
needsApproval: z.ZodDefault<z.ZodBoolean>;
|
|
18
18
|
}, z.core.$strip>;
|
|
19
|
-
|
|
19
|
+
type ToolMetadata = z.infer<typeof toolMetadataSchema>;
|
|
20
|
+
interface InterpreterResult {
|
|
21
|
+
command: string;
|
|
22
|
+
args: string[];
|
|
23
|
+
}
|
|
24
|
+
export declare function getShebang(scriptPath: string): string | null;
|
|
25
|
+
export declare function parseShebang(shebang: string, scriptPath: string): InterpreterResult;
|
|
26
|
+
export declare function resolveToolInterpreter(scriptPath: string): InterpreterResult | null;
|
|
27
|
+
export declare function parseTextSchema(content: string): ToolMetadata | null;
|
|
20
28
|
export declare function parseToolMetadata(output: string): ToolMetadata;
|
|
21
29
|
interface DynamicToolObject {
|
|
22
30
|
toolDef: {
|
|
@@ -25,9 +33,10 @@ interface DynamicToolObject {
|
|
|
25
33
|
};
|
|
26
34
|
execute: (input: Record<string, unknown>, options: ToolExecutionOptions) => Promise<string>;
|
|
27
35
|
}
|
|
28
|
-
export declare function loadDynamicTools({ baseDir, existingToolNames, }: {
|
|
36
|
+
export declare function loadDynamicTools({ baseDir, existingToolNames, sessionContext, }: {
|
|
29
37
|
baseDir: string;
|
|
30
38
|
existingToolNames?: string[];
|
|
39
|
+
sessionContext?: SessionContext;
|
|
31
40
|
}): Promise<Record<string, DynamicToolObject>>;
|
|
32
41
|
export {};
|
|
33
42
|
//# sourceMappingURL=dynamic-tool-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-tool-loader.d.ts","sourceRoot":"","sources":["../../source/tools/dynamic-tool-loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"dynamic-tool-loader.d.ts","sourceRoot":"","sources":["../../source/tools/dynamic-tool-loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvE,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;iBAatB,CAAC;AAEH,KAAK,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAMvD,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAyBD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAc5D;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,iBAAiB,CAUnB;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,GACjB,iBAAiB,GAAG,IAAI,CA0B1B;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAwFpE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAS9D;AAsOD,UAAU,iBAAiB;IACzB,OAAO,EAAE;QACP,WAAW,EAAE,MAAM,CAAC;QAEpB,WAAW,EAAE,GAAG,CAAC;KAClB,CAAC;IACF,OAAO,EAAE,CACP,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,oBAAoB,KAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;CACtB;AAwED,wBAAsB,gBAAgB,CAAC,EACrC,OAAO,EACP,iBAAsB,EACtB,cAAc,GACf,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC,8CAuJA"}
|