@nodetool-ai/cli-chat 0.0.0-stage → 0.8.9-beta.1
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 +13 -2
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/ExecutionTree.d.ts +20 -0
- package/dist/ExecutionTree.d.ts.map +1 -0
- package/dist/ExecutionTree.js +100 -0
- package/dist/ExecutionTree.js.map +1 -0
- package/dist/agent-toolbelt.d.ts +15 -0
- package/dist/agent-toolbelt.d.ts.map +1 -0
- package/dist/agent-toolbelt.js +28 -0
- package/dist/agent-toolbelt.js.map +1 -0
- package/dist/app.d.ts +40 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +1070 -0
- package/dist/app.js.map +1 -0
- package/dist/bash-tool.d.ts +13 -0
- package/dist/bash-tool.d.ts.map +1 -0
- package/dist/bash-tool.js +85 -0
- package/dist/bash-tool.js.map +1 -0
- package/dist/chat-codeact.d.ts +93 -0
- package/dist/chat-codeact.d.ts.map +1 -0
- package/dist/chat-codeact.js +179 -0
- package/dist/chat-codeact.js.map +1 -0
- package/dist/chat-context.d.ts +18 -0
- package/dist/chat-context.d.ts.map +1 -0
- package/dist/chat-context.js +32 -0
- package/dist/chat-context.js.map +1 -0
- package/dist/chat-entry.d.ts +13 -0
- package/dist/chat-entry.d.ts.map +1 -0
- package/dist/chat-entry.js +233 -0
- package/dist/chat-entry.js.map +1 -0
- package/dist/chat-media.d.ts +3 -0
- package/dist/chat-media.d.ts.map +1 -0
- package/dist/chat-media.js +46 -0
- package/dist/chat-media.js.map +1 -0
- package/dist/chat-prompts.d.ts +20 -0
- package/dist/chat-prompts.d.ts.map +1 -0
- package/dist/chat-prompts.js +42 -0
- package/dist/chat-prompts.js.map +1 -0
- package/dist/chat-sessions.d.ts +25 -0
- package/dist/chat-sessions.d.ts.map +1 -0
- package/dist/chat-sessions.js +153 -0
- package/dist/chat-sessions.js.map +1 -0
- package/dist/commands/agent.d.ts +33 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +516 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/tools.d.ts +11 -0
- package/dist/commands/tools.d.ts.map +1 -0
- package/dist/commands/tools.js +206 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/diagnose.d.ts +139 -0
- package/dist/diagnose.d.ts.map +1 -0
- package/dist/diagnose.js +435 -0
- package/dist/diagnose.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown.d.ts +9 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +53 -0
- package/dist/markdown.js.map +1 -0
- package/dist/nodetool.d.ts +3 -0
- package/dist/nodetool.d.ts.map +1 -0
- package/dist/nodetool.js +4 -0
- package/dist/nodetool.js.map +1 -0
- package/dist/permission-gate.d.ts +55 -0
- package/dist/permission-gate.d.ts.map +1 -0
- package/dist/permission-gate.js +118 -0
- package/dist/permission-gate.js.map +1 -0
- package/dist/readline-input.d.ts +23 -0
- package/dist/readline-input.d.ts.map +1 -0
- package/dist/readline-input.js +210 -0
- package/dist/readline-input.js.map +1 -0
- package/dist/settings.d.ts +19 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +146 -0
- package/dist/settings.js.map +1 -0
- package/dist/stdin.d.ts +52 -0
- package/dist/stdin.d.ts.map +1 -0
- package/dist/stdin.js +363 -0
- package/dist/stdin.js.map +1 -0
- package/dist/terminal-clipboard.d.ts +3 -0
- package/dist/terminal-clipboard.d.ts.map +1 -0
- package/dist/terminal-clipboard.js +24 -0
- package/dist/terminal-clipboard.js.map +1 -0
- package/dist/terminal-mouse.d.ts +24 -0
- package/dist/terminal-mouse.d.ts.map +1 -0
- package/dist/terminal-mouse.js +84 -0
- package/dist/terminal-mouse.js.map +1 -0
- package/dist/terminal-screen.d.ts +41 -0
- package/dist/terminal-screen.d.ts.map +1 -0
- package/dist/terminal-screen.js +228 -0
- package/dist/terminal-screen.js.map +1 -0
- package/dist/tool-format.d.ts +54 -0
- package/dist/tool-format.d.ts.map +1 -0
- package/dist/tool-format.js +360 -0
- package/dist/tool-format.js.map +1 -0
- package/dist/useExecutionState.d.ts +44 -0
- package/dist/useExecutionState.d.ts.map +1 -0
- package/dist/useExecutionState.js +285 -0
- package/dist/useExecutionState.js.map +1 -0
- package/dist/websocket-client.d.ts +159 -0
- package/dist/websocket-client.d.ts.map +1 -0
- package/dist/websocket-client.js +677 -0
- package/dist/websocket-client.js.map +1 -0
- package/package.json +73 -4
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Box, Text, useInput, useStdout } from "ink";
|
|
4
|
+
import { stripVTControlCharacters } from "node:util";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import wrapAnsi from "wrap-ansi";
|
|
7
|
+
import stringWidth from "string-width";
|
|
8
|
+
import { copyTerminalText } from "./terminal-clipboard.js";
|
|
9
|
+
import { friendlyToolName, formatToolParams, formatToolDiff, formatToolCode } from "./tool-format.js";
|
|
10
|
+
/** Remove terminal commands from external text before adding our own styling. */
|
|
11
|
+
export function terminalText(text) {
|
|
12
|
+
return stripVTControlCharacters(text).replace(/\p{Cc}/gu, (character) => character === "\n" || character === "\t" ? character : "");
|
|
13
|
+
}
|
|
14
|
+
export function terminalLines(text, width) {
|
|
15
|
+
return wrapAnsi(text, Math.max(1, width), { hard: true, trim: false }).split("\n");
|
|
16
|
+
}
|
|
17
|
+
export function useTerminalSize() {
|
|
18
|
+
const { stdout } = useStdout();
|
|
19
|
+
const [size, setSize] = useState(() => ({
|
|
20
|
+
columns: stdout.columns || 80,
|
|
21
|
+
rows: stdout.rows || 24
|
|
22
|
+
}));
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const resize = () => setSize({ columns: stdout.columns || 80, rows: stdout.rows || 24 });
|
|
25
|
+
stdout.on("resize", resize);
|
|
26
|
+
return () => {
|
|
27
|
+
stdout.off("resize", resize);
|
|
28
|
+
};
|
|
29
|
+
}, [stdout]);
|
|
30
|
+
return size;
|
|
31
|
+
}
|
|
32
|
+
/** Restore the caller's screen even when Ink exits through a signal. */
|
|
33
|
+
export function enterTerminalScreen(output) {
|
|
34
|
+
if (!output.isTTY) {
|
|
35
|
+
return () => { };
|
|
36
|
+
}
|
|
37
|
+
output.write("\u001b[?1049h\u001b[H\u001b[?25l\u001b[?2004h\u001b[?1000h\u001b[?1002h\u001b[?1006h");
|
|
38
|
+
let restored = false;
|
|
39
|
+
return () => {
|
|
40
|
+
if (restored) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
restored = true;
|
|
44
|
+
output.write("\u001b[?1006l\u001b[?1002l\u001b[?1000l\u001b[?2004l\u001b[?25h\u001b[?1049l");
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function messageLines(message, width, details) {
|
|
48
|
+
const content = terminalText(message.content);
|
|
49
|
+
if (message.role === "tool") {
|
|
50
|
+
const name = message.toolName ?? "tool";
|
|
51
|
+
const title = `${friendlyToolName(name)} ${formatToolParams(name, message.toolArgs)}`;
|
|
52
|
+
const body = details ? content : content.split("\n").slice(0, 2).join("\n");
|
|
53
|
+
const lines = [
|
|
54
|
+
chalk.cyan(terminalText(title)),
|
|
55
|
+
...terminalLines(body, width).map((line) => chalk.dim(line))
|
|
56
|
+
];
|
|
57
|
+
if (details && message.toolArgs) {
|
|
58
|
+
lines.push(...terminalLines(terminalText(JSON.stringify(message.toolArgs, null, 2)), width).map((line) => chalk.dim(line)));
|
|
59
|
+
}
|
|
60
|
+
if (details) {
|
|
61
|
+
for (const line of formatToolCode(name, message.toolArgs) ?? []) {
|
|
62
|
+
lines.push(chalk.dim(terminalText(line)));
|
|
63
|
+
}
|
|
64
|
+
for (const line of formatToolDiff(name, message.toolArgs) ?? []) {
|
|
65
|
+
const text = terminalText(`${line.sign} ${line.text}`);
|
|
66
|
+
lines.push(line.sign === "+"
|
|
67
|
+
? chalk.green(text)
|
|
68
|
+
: line.sign === "-"
|
|
69
|
+
? chalk.red(text)
|
|
70
|
+
: chalk.dim(text));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return ["", ...lines.flatMap((line) => terminalLines(line, width))];
|
|
74
|
+
}
|
|
75
|
+
if (message.role === "system") {
|
|
76
|
+
return terminalLines(chalk.dim(content), width);
|
|
77
|
+
}
|
|
78
|
+
const heading = message.role === "user"
|
|
79
|
+
? chalk.cyan.bold("You")
|
|
80
|
+
: chalk.green.bold("NodeTool");
|
|
81
|
+
return ["", heading, ...terminalLines(message.rendered ?? content, width)];
|
|
82
|
+
}
|
|
83
|
+
const graphemes = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
84
|
+
function plainLine(line) {
|
|
85
|
+
return stripVTControlCharacters(line);
|
|
86
|
+
}
|
|
87
|
+
function columnIndex(line, column) {
|
|
88
|
+
let cell = 0;
|
|
89
|
+
for (const part of graphemes.segment(line)) {
|
|
90
|
+
if (cell >= column)
|
|
91
|
+
return part.index;
|
|
92
|
+
cell += stringWidth(part.segment);
|
|
93
|
+
}
|
|
94
|
+
return line.length;
|
|
95
|
+
}
|
|
96
|
+
export function selectedTranscriptText(lines, from, to) {
|
|
97
|
+
const [first, last] = from.line < to.line || (from.line === to.line && from.column <= to.column)
|
|
98
|
+
? [from, to] : [to, from];
|
|
99
|
+
return lines.slice(first.line, last.line + 1).map((raw, offset) => {
|
|
100
|
+
const line = plainLine(raw);
|
|
101
|
+
const start = offset === 0 ? columnIndex(line, first.column) : 0;
|
|
102
|
+
const end = first.line + offset === last.line ? columnIndex(line, last.column) : line.length;
|
|
103
|
+
return line.slice(start, end);
|
|
104
|
+
}).join("\n");
|
|
105
|
+
}
|
|
106
|
+
function highlightLine(raw, lineNumber, from, to) {
|
|
107
|
+
const [first, last] = from.line < to.line || (from.line === to.line && from.column <= to.column)
|
|
108
|
+
? [from, to] : [to, from];
|
|
109
|
+
if (lineNumber < first.line || lineNumber > last.line)
|
|
110
|
+
return raw;
|
|
111
|
+
const line = plainLine(raw);
|
|
112
|
+
const start = lineNumber === first.line ? columnIndex(line, first.column) : 0;
|
|
113
|
+
const end = lineNumber === last.line ? columnIndex(line, last.column) : line.length;
|
|
114
|
+
return line.slice(0, start) + chalk.inverse(line.slice(start, end)) + line.slice(end);
|
|
115
|
+
}
|
|
116
|
+
const layoutCache = new WeakMap();
|
|
117
|
+
export function transcriptLines(messages, width, details) {
|
|
118
|
+
const lines = [];
|
|
119
|
+
for (const message of messages) {
|
|
120
|
+
let cached = layoutCache.get(message);
|
|
121
|
+
if (!cached || cached.width !== width || cached.details !== details) {
|
|
122
|
+
cached = { width, details, lines: messageLines(message, width, details) };
|
|
123
|
+
layoutCache.set(message, cached);
|
|
124
|
+
}
|
|
125
|
+
for (const line of cached.lines) {
|
|
126
|
+
lines.push(line);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return lines;
|
|
130
|
+
}
|
|
131
|
+
export function Transcript({ messages, live, width, height, details, resetKey, startAtTop = false, mouseEvents, screenY = 4, screenX = 2 }) {
|
|
132
|
+
const [top, setTop] = useState(startAtTop ? 0 : null);
|
|
133
|
+
const [selection, setSelection] = useState(null);
|
|
134
|
+
const [copyNotice, setCopyNotice] = useState(false);
|
|
135
|
+
const noticeTimer = useRef(null);
|
|
136
|
+
const dragging = useRef(null);
|
|
137
|
+
useEffect(() => () => {
|
|
138
|
+
if (noticeTimer.current)
|
|
139
|
+
clearTimeout(noticeTimer.current);
|
|
140
|
+
}, []);
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
setTop(startAtTop ? 0 : null);
|
|
143
|
+
setSelection(null);
|
|
144
|
+
setCopyNotice(false);
|
|
145
|
+
if (noticeTimer.current)
|
|
146
|
+
clearTimeout(noticeTimer.current);
|
|
147
|
+
}, [resetKey, startAtTop]);
|
|
148
|
+
const lines = transcriptLines(messages, width, details);
|
|
149
|
+
if (live) {
|
|
150
|
+
lines.push("", chalk.green("NodeTool"), ...terminalLines(terminalText(live), width));
|
|
151
|
+
}
|
|
152
|
+
if (!lines.length) {
|
|
153
|
+
lines.push("", chalk.cyan.bold("What would you like to make?"), "", ...terminalLines("Build a workflow, create media, explore your files, or ask a question.", width), "", chalk.dim("/model Choose a model"), chalk.dim("/sessions Continue a conversation"), chalk.dim("/help Commands and keyboard shortcuts"));
|
|
154
|
+
}
|
|
155
|
+
const contentHeight = Math.max(1, height - 1);
|
|
156
|
+
const bottom = Math.max(0, lines.length - contentHeight);
|
|
157
|
+
const start = top === null ? bottom : Math.min(top, bottom);
|
|
158
|
+
const current = useRef({ lines, start, bottom, contentHeight, width });
|
|
159
|
+
current.current = { lines, start, bottom, contentHeight, width };
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
if (!mouseEvents)
|
|
162
|
+
return;
|
|
163
|
+
const onMouse = (event) => {
|
|
164
|
+
const view = current.current;
|
|
165
|
+
if (event.action === "wheel") {
|
|
166
|
+
if (event.y >= screenY && event.y < screenY + view.contentHeight && event.x >= screenX && event.x < screenX + view.width) {
|
|
167
|
+
const next = Math.max(0, Math.min(view.bottom, view.start + (event.direction ?? 1) * 3));
|
|
168
|
+
setTop(next === view.bottom ? null : next);
|
|
169
|
+
setSelection(null);
|
|
170
|
+
}
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const inside = event.y >= screenY && event.y < screenY + view.contentHeight && event.x >= screenX && event.x < screenX + view.width;
|
|
174
|
+
if (!inside && !dragging.current)
|
|
175
|
+
return;
|
|
176
|
+
const position = {
|
|
177
|
+
line: Math.max(0, Math.min(view.lines.length - 1, view.start + event.y - screenY)),
|
|
178
|
+
column: Math.max(0, Math.min(view.width, event.x - screenX))
|
|
179
|
+
};
|
|
180
|
+
if (event.action === "down" && inside) {
|
|
181
|
+
dragging.current = position;
|
|
182
|
+
setSelection({ from: position, to: position });
|
|
183
|
+
}
|
|
184
|
+
else if (dragging.current && event.action === "move") {
|
|
185
|
+
setSelection({ from: dragging.current, to: position });
|
|
186
|
+
}
|
|
187
|
+
else if (dragging.current && event.action === "up") {
|
|
188
|
+
const from = dragging.current;
|
|
189
|
+
dragging.current = null;
|
|
190
|
+
setSelection(null);
|
|
191
|
+
const value = selectedTranscriptText(view.lines, from, position);
|
|
192
|
+
if (value) {
|
|
193
|
+
void copyTerminalText(value, process.stdout).then(() => {
|
|
194
|
+
setCopyNotice(true);
|
|
195
|
+
if (noticeTimer.current)
|
|
196
|
+
clearTimeout(noticeTimer.current);
|
|
197
|
+
noticeTimer.current = setTimeout(() => {
|
|
198
|
+
setCopyNotice(false);
|
|
199
|
+
noticeTimer.current = null;
|
|
200
|
+
}, 1800);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
mouseEvents.on("mouse", onMouse);
|
|
206
|
+
return () => { mouseEvents.off("mouse", onMouse); };
|
|
207
|
+
}, [mouseEvents, screenX, screenY]);
|
|
208
|
+
useInput((input, key) => {
|
|
209
|
+
if (key.pageUp) {
|
|
210
|
+
setTop(Math.max(0, start - contentHeight));
|
|
211
|
+
}
|
|
212
|
+
if (key.pageDown) {
|
|
213
|
+
setTop(start + contentHeight >= bottom ? null : start + contentHeight);
|
|
214
|
+
}
|
|
215
|
+
if (key.ctrl && key.home) {
|
|
216
|
+
setTop(0);
|
|
217
|
+
}
|
|
218
|
+
if ((key.ctrl && key.end) || (key.ctrl && input === "g")) {
|
|
219
|
+
setTop(null);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
return (_jsxs(Box, { flexDirection: "column", width: width, height: height, overflow: "hidden", children: [_jsx(Box, { height: contentHeight, flexDirection: "column", flexShrink: 0, children: _jsx(Text, { children: lines.slice(start, start + contentHeight).map((line, offset) => selection ? highlightLine(line, start + offset, selection.from, selection.to) : line).join("\n") }) }), _jsx(Text, { dimColor: true, wrap: "truncate", children: copyNotice
|
|
223
|
+
? "Copied to clipboard"
|
|
224
|
+
: start < bottom
|
|
225
|
+
? `History · ${bottom - start} lines below · Ctrl+G latest`
|
|
226
|
+
: "" })] }));
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=terminal-screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-screen.js","sourceRoot":"","sources":["../src/terminal-screen.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAErD,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACf,MAAM,kBAAkB,CAAC;AAW1B,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,EAAE,CACtE,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAC1D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,KAAa;IACvD,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAC1E,IAAI,CACL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IAC/B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;QACtC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;QAC7B,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;KACxB,CAAC,CAAC,CAAC;IACJ,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,MAAM,GAAG,GAAS,EAAE,CACxB,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC5B,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACb,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,mBAAmB,CAAC,MAA0B;IAC5D,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,sFAAsF,CAAC,CAAC;IACrG,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,OAAO,GAAG,EAAE;QACV,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,QAAQ,GAAG,IAAI,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,8EAA8E,CAAC,CAAC;IAC/F,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,OAAoB,EACpB,KAAa,EACb,OAAgB;IAEhB,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC;QACxC,MAAM,KAAK,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvF,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5E,MAAM,KAAK,GAAG;YACZ,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;SAC7D,CAAC;QACF,IAAI,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CACR,GAAG,aAAa,CACd,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EACvD,KAAK,CACN,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CACjC,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC5C,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChE,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBACvD,KAAK,CAAC,IAAI,CACR,IAAI,CAAC,IAAI,KAAK,GAAG;oBACf,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;oBACnB,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG;wBACjB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;wBACjB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CACtB,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,OAAO,GACX,OAAO,CAAC,IAAI,KAAK,MAAM;QACrB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QACxB,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;AAC7E,CAAC;AAgBD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;AAE7E,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,MAAc;IAC/C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,IAAI,IAAI,MAAM;YAAE,OAAO,IAAI,CAAC,KAAK,CAAC;QACtC,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAwB,EAAE,IAAc,EAAE,EAAY;IAC3F,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,MAAM,CAAC;QAC9F,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC5B,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QAChE,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7F,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,UAAkB,EAAE,IAAc,EAAE,EAAY;IAClF,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,MAAM,CAAC;QAC9F,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC5B,IAAI,UAAU,GAAG,KAAK,CAAC,IAAI,IAAI,UAAU,GAAG,IAAI,CAAC,IAAI;QAAE,OAAO,GAAG,CAAC;IAClE,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,UAAU,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,MAAM,GAAG,GAAG,UAAU,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IACpF,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACxF,CAAC;AAED,MAAM,WAAW,GAAG,IAAI,OAAO,EAG5B,CAAC;AAEJ,MAAM,UAAU,eAAe,CAC7B,QAAgC,EAChC,KAAa,EACb,OAAgB;IAEhB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;YACpE,MAAM,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;YAC1E,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,MAAM,EACN,OAAO,EACP,QAAQ,EACR,UAAU,GAAG,KAAK,EAClB,WAAW,EACX,OAAO,GAAG,CAAC,EACX,OAAO,GAAG,CAAC,EACK;IAChB,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAgB,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACrE,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAA0C,IAAI,CAAC,CAAC;IAC1F,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,WAAW,GAAG,MAAM,CAAuC,IAAI,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,MAAM,CAAkB,IAAI,CAAC,CAAC;IAC/C,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE;QACnB,IAAI,WAAW,CAAC,OAAO;YAAE,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7D,CAAC,EAAE,EAAE,CAAC,CAAC;IACP,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9B,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,WAAW,CAAC,OAAO;YAAE,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7D,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;IAC3B,MAAM,KAAK,GAAG,eAAe,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACxD,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,IAAI,CACR,EAAE,EACF,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,EACvB,GAAG,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAC5C,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CACR,EAAE,EACF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,EAC/C,EAAE,EACF,GAAG,aAAa,CACd,wEAAwE,EACxE,KAAK,CACN,EACD,EAAE,EACF,KAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,EACnC,KAAK,CAAC,GAAG,CAAC,oCAAoC,CAAC,EAC/C,KAAK,CAAC,GAAG,CAAC,wCAAwC,CAAC,CACpD,CAAC;IACJ,CAAC;IACD,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,aAAa,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,OAAO,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;IACjE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,WAAW;YAAE,OAAO;QACzB,MAAM,OAAO,GAAG,CAAC,KAAiB,EAAQ,EAAE;YAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;YAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC7B,IAAI,KAAK,CAAC,CAAC,IAAI,OAAO,IAAI,KAAK,CAAC,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC,aAAa,IAAI,KAAK,CAAC,CAAC,IAAI,OAAO,IAAI,KAAK,CAAC,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;oBACzH,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBACzF,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC3C,YAAY,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;gBACD,OAAO;YACT,CAAC;YACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,OAAO,IAAI,KAAK,CAAC,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC,aAAa,IAAI,KAAK,CAAC,CAAC,IAAI,OAAO,IAAI,KAAK,CAAC,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;YACpI,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO;gBAAE,OAAO;YACzC,MAAM,QAAQ,GAAG;gBACf,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;gBAClF,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;aAC7D,CAAC;YACF,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,EAAE,CAAC;gBACtC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC;gBAC5B,YAAY,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;YACjD,CAAC;iBAAM,IAAI,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBACvD,YAAY,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;YACzD,CAAC;iBAAM,IAAI,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;gBACrD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC;gBAC9B,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;gBACxB,YAAY,CAAC,IAAI,CAAC,CAAC;gBACnB,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;gBACjE,IAAI,KAAK,EAAE,CAAC;oBACV,KAAK,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;wBACrD,aAAa,CAAC,IAAI,CAAC,CAAC;wBACpB,IAAI,WAAW,CAAC,OAAO;4BAAE,YAAY,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;wBAC3D,WAAW,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;4BACpC,aAAa,CAAC,KAAK,CAAC,CAAC;4BACrB,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;wBAC7B,CAAC,EAAE,IAAI,CAAC,CAAC;oBACX,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QACF,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACjC,OAAO,GAAG,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACpC,QAAQ,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACtB,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YACjB,MAAM,CAAC,KAAK,GAAG,aAAa,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,aAAa,CAAC,CAAC;QACzE,CAAC;QACD,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YACzB,MAAM,CAAC,CAAC,CAAC,CAAC;QACZ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC;YACzD,MAAM,CAAC,IAAI,CAAC,CAAC;QACf,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAC,QAAQ,aACzE,KAAC,GAAG,IAAC,MAAM,EAAE,aAAa,EAAE,aAAa,EAAC,QAAQ,EAAC,UAAU,EAAE,CAAC,YAC9D,KAAC,IAAI,cAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAQ,GAC3K,EACN,KAAC,IAAI,IAAC,QAAQ,QAAC,IAAI,EAAC,UAAU,YAC3B,UAAU;oBACT,CAAC,CAAC,qBAAqB;oBACvB,CAAC,CAAC,KAAK,GAAG,MAAM;wBACd,CAAC,CAAC,aAAa,MAAM,GAAG,KAAK,8BAA8B;wBAC3D,CAAC,CAAC,EAAE,GACH,IACH,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact, Claude-Code-style formatting for the builtin "basic" tools
|
|
3
|
+
* (read/write/edit/list/glob/grep) and CodeAct's `execute_code`. For these,
|
|
4
|
+
* the chat UI shows a friendly verb, a tight one-line parameter summary,
|
|
5
|
+
* and a `⎿` result line derived from the tool's structured output — e.g.
|
|
6
|
+
*
|
|
7
|
+
* ● Read(src/app.tsx)
|
|
8
|
+
* ⎿ Read 47 lines
|
|
9
|
+
*
|
|
10
|
+
* ● Run Rendering product images from CSV
|
|
11
|
+
* const listed = await nodetool.workflows.list();
|
|
12
|
+
* ⎿ { count: 3 } · 1 tool call
|
|
13
|
+
*
|
|
14
|
+
* Every other tool keeps the generic `name(key: value)` + raw preview render.
|
|
15
|
+
*/
|
|
16
|
+
/** True when the tool gets the compact Claude-Code-style treatment. */
|
|
17
|
+
export declare function isBasicTool(name: string): boolean;
|
|
18
|
+
/** True when the tool is CodeAct's `execute_code` action. */
|
|
19
|
+
export declare function isCodeAction(name: string): boolean;
|
|
20
|
+
/** True when the result should go through {@link formatToolResult}. */
|
|
21
|
+
export declare function isFormattedTool(name: string): boolean;
|
|
22
|
+
/** Friendly verb for a formatted tool, or the raw name otherwise. */
|
|
23
|
+
export declare function friendlyToolName(name: string): string;
|
|
24
|
+
/** Live status label: the action title for `execute_code`, else the verb. */
|
|
25
|
+
export declare function toolStatusLabel(name: string, args?: Record<string, unknown>): string;
|
|
26
|
+
/**
|
|
27
|
+
* The parenthesized header text for a basic tool — just the salient
|
|
28
|
+
* argument(s), not the full `key: JSON` dump.
|
|
29
|
+
*/
|
|
30
|
+
export declare function formatToolParams(name: string, args?: Record<string, unknown>): string;
|
|
31
|
+
/**
|
|
32
|
+
* The `⎿` summary line for a basic tool, derived from its structured result.
|
|
33
|
+
* Falls back to a generic one-line preview for unexpected shapes (e.g. the
|
|
34
|
+
* WebSocket path delivers results as pre-serialized strings).
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatToolResult(name: string, _args: Record<string, unknown> | undefined, result: unknown): string;
|
|
37
|
+
/**
|
|
38
|
+
* Dedented program lines for an `execute_code` call, or null when there is
|
|
39
|
+
* no code to show. Caps long programs the way {@link formatToolDiff} does.
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatToolCode(name: string, args?: Record<string, unknown>): string[] | null;
|
|
42
|
+
interface DiffLine {
|
|
43
|
+
/** "-" removed, "+" added, " " a meta/context note. */
|
|
44
|
+
sign: "-" | "+" | " ";
|
|
45
|
+
text: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Lines for the colored diff shown below an edit's summary, or null when
|
|
49
|
+
* there's nothing useful to render. Only `edit_file` is diffed — writes show
|
|
50
|
+
* just their one-line summary.
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatToolDiff(name: string, args?: Record<string, unknown>): DiffLine[] | null;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=tool-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-format.d.ts","sourceRoot":"","sources":["../src/tool-format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAcH,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD;AAyCD,6EAA6E;AAC7E,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CAMR;AAQD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CA0CR;AAeD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC1C,MAAM,EAAE,OAAO,GACd,MAAM,CAuDR;AAsFD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,EAAE,GAAG,IAAI,CAWjB;AAQD,UAAU,QAAQ;IAChB,uDAAuD;IACvD,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AA2CD;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,QAAQ,EAAE,GAAG,IAAI,CAGnB"}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact, Claude-Code-style formatting for the builtin "basic" tools
|
|
3
|
+
* (read/write/edit/list/glob/grep) and CodeAct's `execute_code`. For these,
|
|
4
|
+
* the chat UI shows a friendly verb, a tight one-line parameter summary,
|
|
5
|
+
* and a `⎿` result line derived from the tool's structured output — e.g.
|
|
6
|
+
*
|
|
7
|
+
* ● Read(src/app.tsx)
|
|
8
|
+
* ⎿ Read 47 lines
|
|
9
|
+
*
|
|
10
|
+
* ● Run Rendering product images from CSV
|
|
11
|
+
* const listed = await nodetool.workflows.list();
|
|
12
|
+
* ⎿ { count: 3 } · 1 tool call
|
|
13
|
+
*
|
|
14
|
+
* Every other tool keeps the generic `name(key: value)` + raw preview render.
|
|
15
|
+
*/
|
|
16
|
+
const EXECUTE_CODE_TOOL_NAME = "execute_code";
|
|
17
|
+
/** Map from canonical builtin tool name → the verb shown in the UI. */
|
|
18
|
+
const FRIENDLY_NAMES = {
|
|
19
|
+
read_file: "Read",
|
|
20
|
+
write_file: "Write",
|
|
21
|
+
edit_file: "Edit",
|
|
22
|
+
list_directory: "List",
|
|
23
|
+
glob: "Search",
|
|
24
|
+
grep: "Grep",
|
|
25
|
+
};
|
|
26
|
+
/** True when the tool gets the compact Claude-Code-style treatment. */
|
|
27
|
+
export function isBasicTool(name) {
|
|
28
|
+
return name in FRIENDLY_NAMES;
|
|
29
|
+
}
|
|
30
|
+
/** True when the tool is CodeAct's `execute_code` action. */
|
|
31
|
+
export function isCodeAction(name) {
|
|
32
|
+
return name === EXECUTE_CODE_TOOL_NAME;
|
|
33
|
+
}
|
|
34
|
+
/** True when the result should go through {@link formatToolResult}. */
|
|
35
|
+
export function isFormattedTool(name) {
|
|
36
|
+
return isBasicTool(name) || isCodeAction(name);
|
|
37
|
+
}
|
|
38
|
+
/** Friendly verb for a formatted tool, or the raw name otherwise. */
|
|
39
|
+
export function friendlyToolName(name) {
|
|
40
|
+
if (isCodeAction(name))
|
|
41
|
+
return "Run";
|
|
42
|
+
return FRIENDLY_NAMES[name] ?? name;
|
|
43
|
+
}
|
|
44
|
+
function str(v) {
|
|
45
|
+
if (isStr(v))
|
|
46
|
+
return v;
|
|
47
|
+
if (v == null)
|
|
48
|
+
return "";
|
|
49
|
+
return String(v);
|
|
50
|
+
}
|
|
51
|
+
function isObj(v) {
|
|
52
|
+
return typeof v === "object" && v !== null;
|
|
53
|
+
}
|
|
54
|
+
function isStr(v) {
|
|
55
|
+
return typeof v === "string";
|
|
56
|
+
}
|
|
57
|
+
function isNum(v) {
|
|
58
|
+
return typeof v === "number";
|
|
59
|
+
}
|
|
60
|
+
function isBool(v) {
|
|
61
|
+
return typeof v === "boolean";
|
|
62
|
+
}
|
|
63
|
+
function firstLine(s) {
|
|
64
|
+
const i = s.indexOf("\n");
|
|
65
|
+
return i === -1 ? s : s.slice(0, i);
|
|
66
|
+
}
|
|
67
|
+
function truncate(s, max) {
|
|
68
|
+
return s.length > max ? s.slice(0, max) + "…" : s;
|
|
69
|
+
}
|
|
70
|
+
function safeJson(v) {
|
|
71
|
+
try {
|
|
72
|
+
return JSON.stringify(v);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return String(v);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** Live status label: the action title for `execute_code`, else the verb. */
|
|
79
|
+
export function toolStatusLabel(name, args) {
|
|
80
|
+
if (isCodeAction(name)) {
|
|
81
|
+
const title = str(args?.title).trim();
|
|
82
|
+
return title || "Run";
|
|
83
|
+
}
|
|
84
|
+
return friendlyToolName(name);
|
|
85
|
+
}
|
|
86
|
+
/** One-line fallback preview for an arbitrary result value. */
|
|
87
|
+
function genericPreview(result) {
|
|
88
|
+
const s = isStr(result) ? result : safeJson(result);
|
|
89
|
+
return truncate(firstLine(s), 200);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The parenthesized header text for a basic tool — just the salient
|
|
93
|
+
* argument(s), not the full `key: JSON` dump.
|
|
94
|
+
*/
|
|
95
|
+
export function formatToolParams(name, args) {
|
|
96
|
+
if (!args)
|
|
97
|
+
return "";
|
|
98
|
+
switch (name) {
|
|
99
|
+
case "read_file": {
|
|
100
|
+
const path = str(args.file_path);
|
|
101
|
+
const offset = args.offset;
|
|
102
|
+
const limit = args.limit;
|
|
103
|
+
if (isNum(offset) || isNum(limit)) {
|
|
104
|
+
const start = isNum(offset) ? offset : 1;
|
|
105
|
+
const range = isNum(limit)
|
|
106
|
+
? `${start}-${start + limit - 1}`
|
|
107
|
+
: `${start}+`;
|
|
108
|
+
return `${path}, lines ${range}`;
|
|
109
|
+
}
|
|
110
|
+
return path;
|
|
111
|
+
}
|
|
112
|
+
case "write_file":
|
|
113
|
+
return str(args.file_path);
|
|
114
|
+
case "edit_file":
|
|
115
|
+
return str(args.path);
|
|
116
|
+
case "list_directory":
|
|
117
|
+
return str(args.path) || ".";
|
|
118
|
+
case "glob": {
|
|
119
|
+
const pattern = str(args.pattern);
|
|
120
|
+
const path = str(args.path);
|
|
121
|
+
return path ? `${pattern} in ${path}` : pattern;
|
|
122
|
+
}
|
|
123
|
+
case "grep": {
|
|
124
|
+
let s = `"${str(args.pattern)}"`;
|
|
125
|
+
const include = str(args.include);
|
|
126
|
+
const path = str(args.path);
|
|
127
|
+
if (include)
|
|
128
|
+
s += `, ${include}`;
|
|
129
|
+
if (path)
|
|
130
|
+
s += ` in ${path}`;
|
|
131
|
+
return s;
|
|
132
|
+
}
|
|
133
|
+
case EXECUTE_CODE_TOOL_NAME:
|
|
134
|
+
return str(args.title).trim();
|
|
135
|
+
default:
|
|
136
|
+
return Object.entries(args)
|
|
137
|
+
.map(([k, v]) => `${k}: ${JSON.stringify(v)}`)
|
|
138
|
+
.join(", ");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** Thousands-grouped count, e.g. 1234 → "1,234". */
|
|
142
|
+
function num(n) {
|
|
143
|
+
return n.toLocaleString("en-US");
|
|
144
|
+
}
|
|
145
|
+
function plural(n, one, many) {
|
|
146
|
+
return `${num(n)} ${n === 1 ? one : many}`;
|
|
147
|
+
}
|
|
148
|
+
function errorLine(result) {
|
|
149
|
+
return truncate(`Error: ${firstLine(str(result.error))}`, 200);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The `⎿` summary line for a basic tool, derived from its structured result.
|
|
153
|
+
* Falls back to a generic one-line preview for unexpected shapes (e.g. the
|
|
154
|
+
* WebSocket path delivers results as pre-serialized strings).
|
|
155
|
+
*/
|
|
156
|
+
export function formatToolResult(name, _args, result) {
|
|
157
|
+
switch (name) {
|
|
158
|
+
case "read_file":
|
|
159
|
+
if (isStr(result)) {
|
|
160
|
+
if (result.startsWith("Error:"))
|
|
161
|
+
return firstLine(result);
|
|
162
|
+
const body = result.split("\n\n[")[0];
|
|
163
|
+
const n = body === "" ? 0 : body.split("\n").length;
|
|
164
|
+
return `Read ${plural(n, "line", "lines")}`;
|
|
165
|
+
}
|
|
166
|
+
break;
|
|
167
|
+
case "write_file":
|
|
168
|
+
// Already a clean summary: "Created X" / "Updated X" / "Error: …".
|
|
169
|
+
if (isStr(result))
|
|
170
|
+
return firstLine(result);
|
|
171
|
+
break;
|
|
172
|
+
case "list_directory":
|
|
173
|
+
if (isStr(result)) {
|
|
174
|
+
if (result.startsWith("Error:"))
|
|
175
|
+
return firstLine(result);
|
|
176
|
+
if (result.startsWith("(empty)"))
|
|
177
|
+
return "Empty directory";
|
|
178
|
+
const n = result.split("\n").filter(Boolean).length;
|
|
179
|
+
return `Listed ${plural(n, "item", "items")}`;
|
|
180
|
+
}
|
|
181
|
+
break;
|
|
182
|
+
case "edit_file":
|
|
183
|
+
if (isObj(result)) {
|
|
184
|
+
if (result.success === false)
|
|
185
|
+
return errorLine(result);
|
|
186
|
+
if (result.created)
|
|
187
|
+
return `Created ${str(result.path)}`;
|
|
188
|
+
const n = isNum(result.replacements) ? result.replacements : 1;
|
|
189
|
+
return `Updated ${str(result.path)} (${plural(n, "edit", "edits")})`;
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
case "glob":
|
|
193
|
+
if (isObj(result)) {
|
|
194
|
+
if (result.success === false)
|
|
195
|
+
return errorLine(result);
|
|
196
|
+
const n = isNum(result.match_count) ? result.match_count : 0;
|
|
197
|
+
return `Found ${plural(n, "file", "files")}${result.truncated ? " (truncated)" : ""}`;
|
|
198
|
+
}
|
|
199
|
+
break;
|
|
200
|
+
case "grep":
|
|
201
|
+
if (isObj(result)) {
|
|
202
|
+
if (result.success === false)
|
|
203
|
+
return errorLine(result);
|
|
204
|
+
const n = isNum(result.match_count) ? result.match_count : 0;
|
|
205
|
+
return `Found ${plural(n, "match", "matches")}${result.truncated ? " (truncated)" : ""}`;
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
case EXECUTE_CODE_TOOL_NAME:
|
|
209
|
+
return formatExecuteCodeResult(result);
|
|
210
|
+
}
|
|
211
|
+
return genericPreview(result);
|
|
212
|
+
}
|
|
213
|
+
function parseObservation(result) {
|
|
214
|
+
let value = result;
|
|
215
|
+
if (isStr(result)) {
|
|
216
|
+
const trimmed = result.trim();
|
|
217
|
+
if (!trimmed.startsWith("{"))
|
|
218
|
+
return null;
|
|
219
|
+
try {
|
|
220
|
+
value = JSON.parse(trimmed);
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (!isObj(value))
|
|
227
|
+
return null;
|
|
228
|
+
if (isBool(value.ok) ||
|
|
229
|
+
"error" in value ||
|
|
230
|
+
"result" in value ||
|
|
231
|
+
"toolCalls" in value ||
|
|
232
|
+
"logs" in value) {
|
|
233
|
+
return value;
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
function compactValue(value) {
|
|
238
|
+
if (isStr(value))
|
|
239
|
+
return firstLine(value);
|
|
240
|
+
if (isNum(value) || isBool(value)) {
|
|
241
|
+
return String(value);
|
|
242
|
+
}
|
|
243
|
+
if (value == null)
|
|
244
|
+
return String(value);
|
|
245
|
+
return safeJson(value);
|
|
246
|
+
}
|
|
247
|
+
/** Observation envelope → one headline plus optional log lines. */
|
|
248
|
+
function formatExecuteCodeResult(result) {
|
|
249
|
+
const obs = parseObservation(result);
|
|
250
|
+
if (!obs)
|
|
251
|
+
return genericPreview(result);
|
|
252
|
+
if (obs.ok === false || isStr(obs.error)) {
|
|
253
|
+
const err = str(obs.error) || "failed";
|
|
254
|
+
return truncate(`Error: ${firstLine(err)}`, 200);
|
|
255
|
+
}
|
|
256
|
+
const parts = [];
|
|
257
|
+
if (obs.result !== undefined) {
|
|
258
|
+
parts.push(truncate(compactValue(obs.result), 160));
|
|
259
|
+
}
|
|
260
|
+
if (isNum(obs.toolCalls) && obs.toolCalls > 0) {
|
|
261
|
+
parts.push(plural(obs.toolCalls, "tool call", "tool calls"));
|
|
262
|
+
}
|
|
263
|
+
const logs = Array.isArray(obs.logs)
|
|
264
|
+
? obs.logs.filter(isStr)
|
|
265
|
+
: [];
|
|
266
|
+
if (logs.length > 0) {
|
|
267
|
+
parts.push(plural(logs.length, "log", "logs"));
|
|
268
|
+
}
|
|
269
|
+
const lines = [parts.join(" · ") || "Done"];
|
|
270
|
+
for (const log of logs.slice(0, 3)) {
|
|
271
|
+
lines.push(truncate(firstLine(log), 160));
|
|
272
|
+
}
|
|
273
|
+
if (logs.length > 3) {
|
|
274
|
+
const more = logs.length - 3;
|
|
275
|
+
lines.push(`… +${more} more ${more === 1 ? "log" : "logs"}`);
|
|
276
|
+
}
|
|
277
|
+
return lines.join("\n");
|
|
278
|
+
}
|
|
279
|
+
const MAX_CODE_LINES = 12;
|
|
280
|
+
function dedentCode(code) {
|
|
281
|
+
const normalized = code.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
282
|
+
const lines = normalized.replace(/\t/g, " ").split("\n");
|
|
283
|
+
while (lines.length > 0 && lines[0].trim() === "")
|
|
284
|
+
lines.shift();
|
|
285
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
286
|
+
lines.pop();
|
|
287
|
+
}
|
|
288
|
+
const indents = lines
|
|
289
|
+
.filter((line) => line.trim().length > 0)
|
|
290
|
+
.map((line) => line.match(/^ */)?.[0].length ?? 0);
|
|
291
|
+
const pad = indents.length > 0 ? Math.min(...indents) : 0;
|
|
292
|
+
return lines.map((line) => line.slice(pad));
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Dedented program lines for an `execute_code` call, or null when there is
|
|
296
|
+
* no code to show. Caps long programs the way {@link formatToolDiff} does.
|
|
297
|
+
*/
|
|
298
|
+
export function formatToolCode(name, args) {
|
|
299
|
+
if (!args || !isCodeAction(name))
|
|
300
|
+
return null;
|
|
301
|
+
const raw = str(args.code);
|
|
302
|
+
if (!raw.trim())
|
|
303
|
+
return null;
|
|
304
|
+
const lines = dedentCode(raw);
|
|
305
|
+
if (lines.length === 0)
|
|
306
|
+
return null;
|
|
307
|
+
if (lines.length <= MAX_CODE_LINES)
|
|
308
|
+
return lines;
|
|
309
|
+
const shown = lines.slice(0, MAX_CODE_LINES);
|
|
310
|
+
const more = lines.length - MAX_CODE_LINES;
|
|
311
|
+
shown.push(`… +${more} more ${more === 1 ? "line" : "lines"}`);
|
|
312
|
+
return shown;
|
|
313
|
+
}
|
|
314
|
+
const MAX_DIFF_LINES = 8;
|
|
315
|
+
function cap(lines) {
|
|
316
|
+
if (lines.length === 0)
|
|
317
|
+
return null;
|
|
318
|
+
if (lines.length <= MAX_DIFF_LINES)
|
|
319
|
+
return lines;
|
|
320
|
+
const shown = lines.slice(0, MAX_DIFF_LINES);
|
|
321
|
+
const more = lines.length - MAX_DIFF_LINES;
|
|
322
|
+
shown.push({ sign: " ", text: `… +${more} more ${more === 1 ? "line" : "lines"}` });
|
|
323
|
+
return shown;
|
|
324
|
+
}
|
|
325
|
+
/** Block diff with shared leading/trailing lines trimmed off. */
|
|
326
|
+
function diffBlock(oldStr, newStr) {
|
|
327
|
+
const oldLines = oldStr === "" ? [] : oldStr.split("\n");
|
|
328
|
+
const newLines = newStr === "" ? [] : newStr.split("\n");
|
|
329
|
+
let start = 0;
|
|
330
|
+
while (start < oldLines.length &&
|
|
331
|
+
start < newLines.length &&
|
|
332
|
+
oldLines[start] === newLines[start]) {
|
|
333
|
+
start++;
|
|
334
|
+
}
|
|
335
|
+
let oEnd = oldLines.length;
|
|
336
|
+
let nEnd = newLines.length;
|
|
337
|
+
while (oEnd > start &&
|
|
338
|
+
nEnd > start &&
|
|
339
|
+
oldLines[oEnd - 1] === newLines[nEnd - 1]) {
|
|
340
|
+
oEnd--;
|
|
341
|
+
nEnd--;
|
|
342
|
+
}
|
|
343
|
+
const lines = [];
|
|
344
|
+
for (let i = start; i < oEnd; i++)
|
|
345
|
+
lines.push({ sign: "-", text: oldLines[i] });
|
|
346
|
+
for (let i = start; i < nEnd; i++)
|
|
347
|
+
lines.push({ sign: "+", text: newLines[i] });
|
|
348
|
+
return cap(lines);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Lines for the colored diff shown below an edit's summary, or null when
|
|
352
|
+
* there's nothing useful to render. Only `edit_file` is diffed — writes show
|
|
353
|
+
* just their one-line summary.
|
|
354
|
+
*/
|
|
355
|
+
export function formatToolDiff(name, args) {
|
|
356
|
+
if (!args || name !== "edit_file")
|
|
357
|
+
return null;
|
|
358
|
+
return diffBlock(str(args.old_string), str(args.new_string));
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=tool-format.js.map
|