tandem-mode 0.1.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +37 -1
  2. package/README.sr.md +37 -1
  3. package/dist/agent/clipboard.js +4 -5
  4. package/dist/agent/clipboard.js.map +1 -1
  5. package/dist/agent/compact.js +80 -0
  6. package/dist/agent/compact.js.map +1 -0
  7. package/dist/agent/loop.js +2 -2
  8. package/dist/agent/loop.js.map +1 -1
  9. package/dist/agent/tools/edit.js +11 -11
  10. package/dist/agent/tools/edit.js.map +1 -1
  11. package/dist/agent/tools/gitDiff.js +41 -18
  12. package/dist/agent/tools/gitDiff.js.map +1 -1
  13. package/dist/agent/tools/listDir.js +4 -4
  14. package/dist/agent/tools/listDir.js.map +1 -1
  15. package/dist/agent/tools/readFile.js +7 -7
  16. package/dist/agent/tools/readFile.js.map +1 -1
  17. package/dist/agent/tools/search.js +10 -10
  18. package/dist/agent/tools/search.js.map +1 -1
  19. package/dist/agent/tools/shell.js +32 -14
  20. package/dist/agent/tools/shell.js.map +1 -1
  21. package/dist/agent/tools/viewImage.js +4 -4
  22. package/dist/agent/tools/viewImage.js.map +1 -1
  23. package/dist/agent/tools/webSearch.js +3 -3
  24. package/dist/agent/tools/webSearch.js.map +1 -1
  25. package/dist/benchmark/runner.js.map +1 -1
  26. package/dist/benchmark/tasks/{bitwiseBulkPriceWizard.js → bulkPriceWizard.js} +3 -3
  27. package/dist/benchmark/tasks/bulkPriceWizard.js.map +1 -0
  28. package/dist/cli.js +48 -22
  29. package/dist/cli.js.map +1 -1
  30. package/dist/config/credentials.js +5 -5
  31. package/dist/config/credentials.js.map +1 -1
  32. package/dist/config/profiles.js +108 -0
  33. package/dist/config/profiles.js.map +1 -0
  34. package/dist/config/schema.js.map +1 -1
  35. package/dist/deepseek/vision.js +4 -4
  36. package/dist/deepseek/vision.js.map +1 -1
  37. package/dist/deepseek/webSearch.js +1 -1
  38. package/dist/i18n/en.js +103 -0
  39. package/dist/i18n/en.js.map +1 -0
  40. package/dist/i18n/index.js +23 -0
  41. package/dist/i18n/index.js.map +1 -0
  42. package/dist/i18n/sr.js +101 -0
  43. package/dist/i18n/sr.js.map +1 -0
  44. package/dist/orchestrator/notify.js +38 -0
  45. package/dist/orchestrator/notify.js.map +1 -0
  46. package/dist/orchestrator/orchestrate.js +50 -19
  47. package/dist/orchestrator/orchestrate.js.map +1 -1
  48. package/dist/orchestrator/planner.js +10 -10
  49. package/dist/orchestrator/planner.js.map +1 -1
  50. package/dist/orchestrator/repoMap.js +1 -1
  51. package/dist/orchestrator/repoMap.js.map +1 -1
  52. package/dist/orchestrator/reviewer.js +20 -12
  53. package/dist/orchestrator/reviewer.js.map +1 -1
  54. package/dist/repl/commands.js +122 -37
  55. package/dist/repl/commands.js.map +1 -1
  56. package/dist/repl/system-prompt.js +13 -11
  57. package/dist/repl/system-prompt.js.map +1 -1
  58. package/dist/repl/wizard.js +17 -9
  59. package/dist/repl/wizard.js.map +1 -1
  60. package/package.json +1 -1
  61. package/dist/benchmark/tasks/bitwiseBulkPriceWizard.js.map +0 -1
package/README.md CHANGED
@@ -128,9 +128,13 @@ tandem "task" --model deepseek-v4-flash --effort low --budget 0.50 --yes
128
128
  | `/thinking [on\|off]` | Toggle thinking mode |
129
129
  | `/effort [low\|high\|max]` | Show or set reasoning effort |
130
130
  | `/status` | Current session/settings |
131
+ | `/diff [--staged] [path]` | Working-tree diff, no API call |
131
132
  | `/usage` | Tokens, cost, off-peak projection |
132
133
  | `/budget [amount]` | Show or set the session budget |
133
134
  | `/new` | Start a fresh session |
135
+ | `/save-profile <name>` | Save model, effort, budget and review loops as a named profile |
136
+ | `/profile [name]` | Load a saved profile, or list them |
137
+ | `/compact` | Summarize the history into a new session to free up context; the old session stays on disk |
134
138
  | `/fork` | New session, carrying over the current history |
135
139
  | `/resume [id]` | Continue the latest (or a named) session |
136
140
  | `/paste [message]` | Send a clipboard image to the agent |
@@ -170,10 +174,42 @@ in the current directory) > **global** (`~/.tandem/config.json`).
170
174
  "defaultModel": "deepseek-v4-pro",
171
175
  "defaultReasoningEffort": "high",
172
176
  "budgetUsd": 5,
173
- "maxReviewLoops": 3
177
+ "maxReviewLoops": 3,
178
+ "verifyCommand": "pnpm typecheck && pnpm test",
179
+ "notifyCommand": "curl -s -d \"Tandem: $TANDEM_OUTCOME\" https://ntfy.sh/my-topic",
180
+ "language": "en"
174
181
  }
175
182
  ```
176
183
 
184
+ `verifyCommand` runs before each `/plan` review round and its result goes to
185
+ the reviewer. `language` is the UI language (`en` or `sr`, default `en`); the
186
+ `--lang` flag and the `TANDEM_LANG` environment variable override it, in that
187
+ order. The first-run wizard asks for it.
188
+
189
+ `notifyCommand` runs when a `/plan` run ends: reviewer approved, `max_review_loops`
190
+ reached, or an error (not when you interrupt it with ESC). The details come in as
191
+ environment variables, never spliced into the command text: `TANDEM_OUTCOME`
192
+ (`approved`, `max_review_loops` or `error`), `TANDEM_TASK`, `TANDEM_NOTES` (the
193
+ reviewer's notes, or the error message), `TANDEM_REVIEW_LOOPS` and `TANDEM_COST_USD`.
194
+ The command runs in your shell (PowerShell on Windows, `sh` elsewhere) with a 15 s
195
+ limit, and a failure only prints a warning. Any shell command works, so Slack,
196
+ ntfy, a desktop notification or a webhook are all just examples:
197
+
198
+ ```json
199
+ { "notifyCommand": "curl -s -d \"Tandem: $TANDEM_OUTCOME\" https://ntfy.sh/my-topic" }
200
+ ```
201
+
202
+ On Windows (PowerShell) the variables are written `$env:TANDEM_OUTCOME`.
203
+
204
+ Like `verifyCommand`, `notifyCommand` runs without asking, so only put it in a
205
+ project's `.tandem/config.json` if you trust that project.
206
+
207
+ **Profiles:** `/save-profile <name>` stores the current model, reasoning effort,
208
+ budget and review loops in `~/.tandem/profiles/<name>.json`, and `/profile <name>`
209
+ loads them back into the running session (only the fields present in the file are
210
+ applied). `/profile` alone lists the saved ones. Names use `a-z`, `0-9`, `-` and `_`.
211
+ Profiles never include `verifyCommand` or the API key.
212
+
177
213
  The API key is never stored in these files — it lives in the OS credential
178
214
  store (or `DEEPSEEK_API_KEY` env var, which takes priority, for CI use).
179
215
 
package/README.sr.md CHANGED
@@ -130,9 +130,13 @@ tandem "task" --model deepseek-v4-flash --effort low --budget 0.50 --yes
130
130
  | `/thinking [on\|off]` | Uključi/isključi thinking mode |
131
131
  | `/effort [low\|high\|max]` | Prikaži ili postavi reasoning effort |
132
132
  | `/status` | Trenutna sesija/podešavanja |
133
+ | `/diff [--staged] [putanja]` | Diff radnog stabla, bez API poziva |
133
134
  | `/usage` | Tokeni, cena, off-peak projekcija |
134
135
  | `/budget [iznos]` | Prikaži ili postavi budžet sesije |
135
136
  | `/new` | Nova sesija |
137
+ | `/save-profile <ime>` | Sačuvaj model, effort, budžet i review krugove kao imenovan profil |
138
+ | `/profile [ime]` | Učitaj sačuvan profil, ili prikaži listu |
139
+ | `/compact` | Sažmi istoriju u novu sesiju da se oslobodi kontekst; stara sesija ostaje na disku |
136
140
  | `/fork` | Nova sesija sa kopijom trenutne istorije |
137
141
  | `/resume [id]` | Nastavi poslednju (ili navedenu) sesiju |
138
142
  | `/paste [poruka]` | Pošalji sliku iz clipboard-a agentu |
@@ -173,10 +177,42 @@ Slojevito: **sesija** (komande u REPL-u) > **projekat**
173
177
  "defaultModel": "deepseek-v4-pro",
174
178
  "defaultReasoningEffort": "high",
175
179
  "budgetUsd": 5,
176
- "maxReviewLoops": 3
180
+ "maxReviewLoops": 3,
181
+ "verifyCommand": "pnpm typecheck && pnpm test",
182
+ "notifyCommand": "curl -s -d \"Tandem: $TANDEM_OUTCOME\" https://ntfy.sh/my-topic",
183
+ "language": "sr"
177
184
  }
178
185
  ```
179
186
 
187
+ `verifyCommand` se pokreće pre svakog `/plan` review kruga, a njegov rezultat
188
+ ide reviewer-u. `language` je jezik interfejsa (`en` ili `sr`, podrazumevano
189
+ `en`); `--lang` flag i `TANDEM_LANG` env promenljiva ga nadjačavaju, tim
190
+ redom. First-run wizard ga pita.
191
+
192
+ `notifyCommand` se pokreće kad se `/plan` završi: reviewer odobrio, dostignut
193
+ `max_review_loops`, ili greška (ne i kad ga prekineš sa ESC). Detalji dolaze kao
194
+ promenljive okruženja, nikad ubačeni u tekst komande: `TANDEM_OUTCOME`
195
+ (`approved`, `max_review_loops` ili `error`), `TANDEM_TASK`, `TANDEM_NOTES`
196
+ (beleške reviewer-a, ili poruka greške), `TANDEM_REVIEW_LOOPS` i `TANDEM_COST_USD`.
197
+ Komanda radi u tvojoj školjki (PowerShell na Windows-u, `sh` drugde) sa limitom
198
+ od 15 s, a neuspeh samo ispiše upozorenje. Može bilo koja shell komanda, pa su
199
+ Slack, ntfy, desktop obaveštenje ili webhook samo primeri:
200
+
201
+ ```json
202
+ { "notifyCommand": "curl -s -d \"Tandem: $TANDEM_OUTCOME\" https://ntfy.sh/my-topic" }
203
+ ```
204
+
205
+ Na Windows-u (PowerShell) promenljive se pišu `$env:TANDEM_OUTCOME`.
206
+
207
+ Kao i `verifyCommand`, `notifyCommand` se pokreće bez pitanja, pa ga stavljaj u
208
+ `.tandem/config.json` projekta samo ako tom projektu veruješ.
209
+
210
+ **Profili:** `/save-profile <ime>` čuva trenutni model, reasoning effort, budžet i
211
+ review krugove u `~/.tandem/profiles/<ime>.json`, a `/profile <ime>` ih vraća u
212
+ sesiju koja radi (primenjuju se samo polja koja postoje u fajlu). `/profile` bez
213
+ argumenta prikazuje sačuvane. Imena koriste `a-z`, `0-9`, `-` i `_`.
214
+ Profili nikad ne sadrže `verifyCommand` ni API ključ.
215
+
180
216
  API ključ se nikad ne čuva u ovim fajlovima — živi u OS-ovom skladištu
181
217
  kredencijala (ili u `DEEPSEEK_API_KEY` env promenljivoj, koja ima
182
218
  prioritet, za CI upotrebu).
@@ -1,4 +1,5 @@
1
1
  import { execFile, spawn } from "node:child_process";
2
+ import { t } from "../i18n/index.js";
2
3
  import { promisify } from "node:util";
3
4
  import { unlink } from "node:fs/promises";
4
5
  const execFileAsync = promisify(execFile);
@@ -88,10 +89,8 @@ async function saveClipboardImageLinux(destPath) {
88
89
  : ["-selection", "clipboard", "-t", "image/png", "-o"];
89
90
  const result = await readBinaryStdout(cmd, args);
90
91
  if (result.kind === "not-found") {
91
- const hint = isWayland
92
- ? "Instaliraj wl-clipboard (npr. sudo apt install wl-clipboard)."
93
- : "Instaliraj xclip (npr. sudo apt install xclip).";
94
- throw new Error(`Komanda "${cmd}" nije pronađena. ${hint}`);
92
+ const hint = isWayland ? t("clipboardInstallWl") : t("clipboardInstallXclip");
93
+ throw new Error(t("clipboardCmdNotFound", { cmd, hint }));
95
94
  }
96
95
  if (result.kind === "empty")
97
96
  return false;
@@ -108,7 +107,7 @@ export async function saveClipboardImage(destPath) {
108
107
  case "linux":
109
108
  return saveClipboardImageLinux(destPath);
110
109
  default:
111
- throw new Error(`Clipboard paste slike nije podržan na platformi "${process.platform}".`);
110
+ throw new Error(t("clipboardUnsupported", { platform: process.platform }));
112
111
  }
113
112
  }
114
113
  //# sourceMappingURL=clipboard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/agent/clipboard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/agent/clipboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { chatCompletionOnce } from "../deepseek/client.js";
2
+ // Tool output is where long sessions grow (file dumps, shell output), so it is
3
+ // cut hard in the transcript the summarizer sees. The summary only needs the gist.
4
+ const MAX_TOOL_OUTPUT_CHARS = 1_500;
5
+ const MAX_TOOL_ARGS_CHARS = 300;
6
+ const MAX_TRANSCRIPT_CHARS = 300_000;
7
+ export const SUMMARY_MODEL = "deepseek-v4-flash";
8
+ const SUMMARIZER_SYSTEM_PROMPT = `You compact the history of a coding-agent session so work can continue from your
9
+ summary alone. Write a dense summary with these parts, skipping any that are empty:
10
+ - Goal: what the user is trying to achieve, plus constraints and preferences they stated.
11
+ - Done: files read or changed (exact paths), commands run and their results.
12
+ - Decisions: what was decided and why.
13
+ - State: where things stand right now, including failing tests or errors still open.
14
+ - Next: what was about to happen or is still to do.
15
+ Keep exact file paths, identifiers and error messages that matter. Do not invent anything
16
+ that is not in the conversation. No preamble. Reply in the language the user wrote in.`;
17
+ export const SUMMARY_PREFIX = "Summary of our conversation so far (the earlier messages were compacted to save context):";
18
+ const SUMMARY_ACK = "Understood. I'll continue from this summary.";
19
+ function truncate(text, max) {
20
+ return text.length > max ? `${text.slice(0, max)} … (truncated, ${text.length} chars)` : text;
21
+ }
22
+ /** Plain-text rendering of the history. Text avoids tool_call/tool pairing rules in the summarizer request. */
23
+ export function buildTranscript(messages) {
24
+ const toolNames = new Map();
25
+ for (const m of messages) {
26
+ for (const call of m.toolCalls ?? [])
27
+ toolNames.set(call.id, call.function.name);
28
+ }
29
+ const parts = [];
30
+ for (const m of messages) {
31
+ if (m.role === "system")
32
+ continue;
33
+ if (m.role === "user") {
34
+ parts.push(`USER:\n${m.content ?? ""}`);
35
+ }
36
+ else if (m.role === "assistant") {
37
+ const calls = (m.toolCalls ?? [])
38
+ .map((c) => `[called ${c.function.name}(${truncate(c.function.arguments, MAX_TOOL_ARGS_CHARS)})]`)
39
+ .join("\n");
40
+ const text = [m.content ?? "", calls].filter(Boolean).join("\n");
41
+ if (text)
42
+ parts.push(`ASSISTANT:\n${text}`);
43
+ }
44
+ else {
45
+ const name = (m.toolCallId && toolNames.get(m.toolCallId)) || "tool";
46
+ parts.push(`TOOL RESULT (${name}):\n${truncate(m.content ?? "", MAX_TOOL_OUTPUT_CHARS)}`);
47
+ }
48
+ }
49
+ const transcript = parts.join("\n\n");
50
+ if (transcript.length <= MAX_TRANSCRIPT_CHARS)
51
+ return transcript;
52
+ // Too long even after trimming tool output: keep the most recent part.
53
+ return `[earlier part of the conversation omitted]\n\n${transcript.slice(-MAX_TRANSCRIPT_CHARS)}`;
54
+ }
55
+ /** One model call. Throws on API errors or an empty summary; the caller's history is never touched here. */
56
+ export async function compactConversation(env, messages, systemPrompt, signal) {
57
+ const response = await chatCompletionOnce(env, {
58
+ model: SUMMARY_MODEL,
59
+ messages: [
60
+ { role: "system", content: SUMMARIZER_SYSTEM_PROMPT },
61
+ { role: "user", content: `Conversation to summarize:\n\n${buildTranscript(messages)}` },
62
+ ],
63
+ ...(signal ? { signal } : {}),
64
+ });
65
+ const summary = response.content.trim();
66
+ if (!summary)
67
+ throw new Error("The model returned an empty summary.");
68
+ // The acknowledgement keeps user/assistant alternation, so the next user turn
69
+ // never follows another user message.
70
+ return {
71
+ messages: [
72
+ { role: "system", content: systemPrompt },
73
+ { role: "user", content: `${SUMMARY_PREFIX}\n\n${summary}` },
74
+ { role: "assistant", content: SUMMARY_ACK },
75
+ ],
76
+ summary,
77
+ usage: response.usage,
78
+ };
79
+ }
80
+ //# sourceMappingURL=compact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compact.js","sourceRoot":"","sources":["../../src/agent/compact.ts"],"names":[],"mappings":"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"}
@@ -127,7 +127,7 @@ export async function* runAgentLoop(messages, opts) {
127
127
  const toolMsg = {
128
128
  role: "tool",
129
129
  toolCallId: call.id,
130
- content: `Nepoznat alat: ${call.function.name}`,
130
+ content: `Unknown tool: ${call.function.name}`,
131
131
  };
132
132
  messages.push(toolMsg);
133
133
  await appendSessionMessage(opts.session, toolMsg);
@@ -141,7 +141,7 @@ export async function* runAgentLoop(messages, opts) {
141
141
  const toolMsg = {
142
142
  role: "tool",
143
143
  toolCallId: call.id,
144
- content: "Korisnik je odbio izvršavanje ovog alata.",
144
+ content: "The user denied running this tool.",
145
145
  };
146
146
  messages.push(toolMsg);
147
147
  await appendSessionMessage(opts.session, toolMsg);
@@ -1 +1 @@
1
- {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"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"}
@@ -16,14 +16,14 @@ function countOccurrences(haystack, needle) {
16
16
  }
17
17
  export const editTool = {
18
18
  name: "edit",
19
- description: "Zameni tačan string u fajlu novim stringom. `oldString` mora biti jedinstven u fajlu osim ako je replaceAll=true. Čuva originalni stil kraja linije (CRLF/LF).",
19
+ description: "Replace an exact string in a file with a new string. `oldString` must be unique in the file unless replaceAll=true. Preserves the original line-ending style (CRLF/LF).",
20
20
  parameters: {
21
21
  type: "object",
22
22
  properties: {
23
- path: { type: "string", description: "Putanja do fajla." },
24
- oldString: { type: "string", description: "Tačan tekst koji se menja (sa dovoljno konteksta da bude jedinstven)." },
25
- newString: { type: "string", description: "Tekst kojim se zamenjuje." },
26
- replaceAll: { type: "boolean", description: "Zameni sve pojave umesto zahteva za jedinstvenost." },
23
+ path: { type: "string", description: "Path to the file." },
24
+ oldString: { type: "string", description: "Exact text to replace (with enough context to be unique)." },
25
+ newString: { type: "string", description: "Replacement text." },
26
+ replaceAll: { type: "boolean", description: "Replace all occurrences instead of requiring uniqueness." },
27
27
  },
28
28
  required: ["path", "oldString", "newString"],
29
29
  },
@@ -36,14 +36,14 @@ export const editTool = {
36
36
  const replaceAll = Boolean(args["replaceAll"]);
37
37
  const resolved = path.resolve(ctx.cwd, filePath);
38
38
  if (oldString === newString) {
39
- return { output: "oldString i newString su identični — nema izmene.", isError: true };
39
+ return { output: "oldString and newString are identical — nothing to change.", isError: true };
40
40
  }
41
41
  let raw;
42
42
  try {
43
43
  raw = await readFile(resolved, "utf8");
44
44
  }
45
45
  catch (err) {
46
- return { output: `Greška pri čitanju ${resolved}: ${err.message}`, isError: true };
46
+ return { output: `Error reading ${resolved}: ${err.message}`, isError: true };
47
47
  }
48
48
  const eol = raw.includes("\r\n") ? "\r\n" : "\n";
49
49
  const normalized = raw.replace(/\r\n/g, "\n");
@@ -51,11 +51,11 @@ export const editTool = {
51
51
  const replacement = newString.replace(/\r\n/g, "\n");
52
52
  const occurrences = countOccurrences(normalized, needle);
53
53
  if (occurrences === 0) {
54
- return { output: `oldString nije pronađen u ${filePath}.`, isError: true };
54
+ return { output: `oldString not found in ${filePath}.`, isError: true };
55
55
  }
56
56
  if (occurrences > 1 && !replaceAll) {
57
57
  return {
58
- output: `oldString se pojavljuje ${occurrences} puta u ${filePath} — dodaj više konteksta da bude jedinstven, ili prosledi replaceAll=true.`,
58
+ output: `oldString appears ${occurrences} times in ${filePath} — add more context to make it unique, or pass replaceAll=true.`,
59
59
  isError: true,
60
60
  };
61
61
  }
@@ -67,10 +67,10 @@ export const editTool = {
67
67
  await writeFile(resolved, finalContent, "utf8");
68
68
  }
69
69
  catch (err) {
70
- return { output: `Greška pri upisu ${resolved}: ${err.message}`, isError: true };
70
+ return { output: `Error writing ${resolved}: ${err.message}`, isError: true };
71
71
  }
72
72
  return {
73
- output: `Izmenjeno ${filePath} (${occurrences} ${occurrences === 1 ? "zamena" : "zamena"}).`,
73
+ output: `Edited ${filePath} (${occurrences} ${occurrences === 1 ? "replacement" : "replacements"}).`,
74
74
  isError: false,
75
75
  };
76
76
  },
@@ -1 +1 @@
1
- {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/agent/tools/edit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/agent/tools/edit.ts"],"names":[],"mappings":"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"}
@@ -2,14 +2,19 @@ import { execFile } from "node:child_process";
2
2
  import { promisify } from "node:util";
3
3
  const execFileAsync = promisify(execFile);
4
4
  const MAX_OUTPUT_CHARS = 30_000;
5
+ // Tandem's own session logs and pasted images live under .tandem/ in the working
6
+ // directory. They are not part of the user's change, and in repos that don't
7
+ // ignore .tandem they would show up as untracked files in every diff.
8
+ // `**/` also covers a .tandem in a subdirectory that Tandem was started from earlier.
9
+ const SELF_PATHSPECS = [":(exclude,glob)**/.tandem/sessions/**", ":(exclude,glob)**/.tandem/tmp/**"];
5
10
  export const gitDiffTool = {
6
11
  name: "git_diff",
7
- description: "Prikaži git diff za radni direktorijum (neustavljene izmene), opciono za jednu putanju.",
12
+ description: "Show the git diff for the working directory (unstaged changes), optionally for a single path.",
8
13
  parameters: {
9
14
  type: "object",
10
15
  properties: {
11
- path: { type: "string", description: "Ograniči diff na ovu putanju." },
12
- staged: { type: "boolean", description: "Prikaži staged izmene (--cached) umesto working tree." },
16
+ path: { type: "string", description: "Limit the diff to this path." },
17
+ staged: { type: "boolean", description: "Show staged changes (--cached) instead of the working tree." },
13
18
  },
14
19
  required: [],
15
20
  },
@@ -17,25 +22,43 @@ export const gitDiffTool = {
17
22
  async execute(args, ctx) {
18
23
  const staged = Boolean(args["staged"]);
19
24
  const scopePath = args["path"] ? String(args["path"]) : undefined;
20
- const gitArgs = ["diff", ...(staged ? ["--cached"] : []), ...(scopePath ? ["--", scopePath] : [])];
21
- // Plain `git diff` ne prikazuje potpuno nove (untracked) fajlove.
22
- // --intent-to-add ih markira u indeksu bez stage-ovanja sadržaja, pa se
23
- // pojave u diff-u kao dodati fajlovi — bezopasno i reverzibilno.
24
- try {
25
- await execFileAsync("git", ["add", "--intent-to-add", "--all", ...(scopePath ? ["--", scopePath] : [])], {
26
- cwd: ctx.cwd,
27
- });
28
- }
29
- catch {
30
- // Nije git repo ili git nije dostupan — poziv ispod će to jasno prijaviti.
31
- }
25
+ const pathspecs = ["--", ...(scopePath ? [scopePath] : []), ...SELF_PATHSPECS];
26
+ const gitArgs = ["diff", ...(staged ? ["--cached"] : []), ...pathspecs];
32
27
  try {
33
28
  const { stdout } = await execFileAsync("git", gitArgs, { cwd: ctx.cwd, maxBuffer: 10 * 1024 * 1024 });
34
- const output = stdout.length > MAX_OUTPUT_CHARS ? stdout.slice(0, MAX_OUTPUT_CHARS) + "\n... (isečeno)" : stdout;
35
- return { output: output.trim() || "(nema izmena)", isError: false };
29
+ if (staged) {
30
+ const output = stdout.length > MAX_OUTPUT_CHARS ? stdout.slice(0, MAX_OUTPUT_CHARS) + "\n... (truncated)" : stdout;
31
+ return { output: output.trim() || "(no changes)", isError: false };
32
+ }
33
+ const { stdout: untracked } = await execFileAsync("git", ["ls-files", "--others", "--exclude-standard", "-z", ...pathspecs], { cwd: ctx.cwd });
34
+ const files = untracked.split("\0").filter(Boolean);
35
+ const untrackedDiffs = new Array(files.length).fill("");
36
+ let nextFile = 0;
37
+ const worker = async () => {
38
+ while (nextFile < files.length) {
39
+ const index = nextFile++;
40
+ const file = files[index];
41
+ if (!file) {
42
+ continue;
43
+ }
44
+ try {
45
+ await execFileAsync("git", ["diff", "--no-index", "--", "/dev/null", file], {
46
+ cwd: ctx.cwd,
47
+ maxBuffer: 10 * 1024 * 1024,
48
+ });
49
+ }
50
+ catch (err) {
51
+ untrackedDiffs[index] = err.stdout ?? "";
52
+ }
53
+ }
54
+ };
55
+ await Promise.all(Array.from({ length: Math.min(8, files.length) }, () => worker()));
56
+ const output = [stdout, ...untrackedDiffs].join("");
57
+ const truncated = output.length > MAX_OUTPUT_CHARS ? output.slice(0, MAX_OUTPUT_CHARS) + "\n... (truncated)" : output;
58
+ return { output: truncated.trim() || "(no changes)", isError: false };
36
59
  }
37
60
  catch (err) {
38
- return { output: `Greška pri git diff: ${err.message}`, isError: true };
61
+ return { output: `git diff error: ${err.message}`, isError: true };
39
62
  }
40
63
  },
41
64
  };
@@ -1 +1 @@
1
- {"version":3,"file":"gitDiff.js","sourceRoot":"","sources":["../../../src/agent/tools/gitDiff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAC1C,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC,MAAM,CAAC,MAAM,WAAW,GAAmB;IACzC,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,yFAAyF;IACtG,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,+BAA+B,EAAE;YACtE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,uDAAuD,EAAE;SAClG;QACD,QAAQ,EAAE,EAAE;KACb;IACD,aAAa,EAAE,GAAG,EAAE,CAAC,KAAK;IAC1B,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACvC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAClE,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEnG,kEAAkE;QAClE,wEAAwE;QACxE,iEAAiE;QACjE,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;gBACvG,GAAG,EAAE,GAAG,CAAC,GAAG;aACb,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,2EAA2E;QAC7E,CAAC;QAED,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;YACtG,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC;YACjH,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACtE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,MAAM,EAAE,wBAAyB,GAAa,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"gitDiff.js","sourceRoot":"","sources":["../../../src/agent/tools/gitDiff.ts"],"names":[],"mappings":"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"}
@@ -2,11 +2,11 @@ import { readdir } from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  export const listDirTool = {
4
4
  name: "list_dir",
5
- description: "Izlistaj sadržaj direktorijuma (ne rekurzivno).",
5
+ description: "List the contents of a directory (non-recursive).",
6
6
  parameters: {
7
7
  type: "object",
8
8
  properties: {
9
- path: { type: "string", description: "Putanja do direktorijuma. Podrazumevano radni direktorijum." },
9
+ path: { type: "string", description: "Path to the directory. Defaults to the working directory." },
10
10
  },
11
11
  required: [],
12
12
  },
@@ -19,10 +19,10 @@ export const listDirTool = {
19
19
  const lines = entries
20
20
  .map((e) => `${e.isDirectory() ? "d" : "-"} ${e.name}`)
21
21
  .sort();
22
- return { output: lines.join("\n") || "(prazno)", isError: false };
22
+ return { output: lines.join("\n") || "(empty)", isError: false };
23
23
  }
24
24
  catch (err) {
25
- return { output: `Greška pri listanju ${resolved}: ${err.message}`, isError: true };
25
+ return { output: `Error listing ${resolved}: ${err.message}`, isError: true };
26
26
  }
27
27
  },
28
28
  };
@@ -1 +1 @@
1
- {"version":3,"file":"listDir.js","sourceRoot":"","sources":["../../../src/agent/tools/listDir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,CAAC,MAAM,WAAW,GAAmB;IACzC,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,iDAAiD;IAC9D,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6DAA6D,EAAE;SACrG;QACD,QAAQ,EAAE,EAAE;KACb;IACD,aAAa,EAAE,GAAG,EAAE,CAAC,KAAK;IAC1B,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAEhD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YACjE,MAAM,KAAK,GAAG,OAAO;iBAClB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;iBACtD,IAAI,EAAE,CAAC;YACV,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACpE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,MAAM,EAAE,uBAAuB,QAAQ,KAAM,GAAa,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACjG,CAAC;IACH,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"listDir.js","sourceRoot":"","sources":["../../../src/agent/tools/listDir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,CAAC,MAAM,WAAW,GAAmB;IACzC,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,mDAAmD;IAChE,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2DAA2D,EAAE;SACnG;QACD,QAAQ,EAAE,EAAE;KACb;IACD,aAAa,EAAE,GAAG,EAAE,CAAC,KAAK;IAC1B,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAEhD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YACjE,MAAM,KAAK,GAAG,OAAO;iBAClB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;iBACtD,IAAI,EAAE,CAAC;YACV,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACnE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,MAAM,EAAE,iBAAiB,QAAQ,KAAM,GAAa,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3F,CAAC;IACH,CAAC;CACF,CAAC"}
@@ -4,13 +4,13 @@ const MAX_LINES = 2000;
4
4
  const MAX_FILE_BYTES = 10 * 1024 * 1024;
5
5
  export const readFileTool = {
6
6
  name: "read_file",
7
- description: "Pročitaj sadržaj fajla sa brojevima linija (cat -n stil). Putanja može biti relativna na radni direktorijum.",
7
+ description: "Read a file's contents with line numbers (cat -n style). The path may be relative to the working directory.",
8
8
  parameters: {
9
9
  type: "object",
10
10
  properties: {
11
- path: { type: "string", description: "Putanja do fajla." },
12
- offset: { type: "integer", description: "Linija od koje se počinje (1-indeksirano). Podrazumevano 1." },
13
- limit: { type: "integer", description: `Maksimalan broj linija za čitanje. Podrazumevano ${MAX_LINES}.` },
11
+ path: { type: "string", description: "Path to the file." },
12
+ offset: { type: "integer", description: "Line to start from (1-indexed). Defaults to 1." },
13
+ limit: { type: "integer", description: `Maximum number of lines to read. Defaults to ${MAX_LINES}.` },
14
14
  },
15
15
  required: ["path"],
16
16
  },
@@ -24,7 +24,7 @@ export const readFileTool = {
24
24
  const stats = await stat(resolved);
25
25
  if (stats.size > MAX_FILE_BYTES) {
26
26
  return {
27
- output: `Fajl je prevelik za čitanje (${stats.size} bajtova, limit ${MAX_FILE_BYTES}). Verovatno nije tekstualni izvorni fajl (npr. state/binarni/vendored fajl) — proveri putanju ili koristi shell alat sa limitiranim izlazom.`,
27
+ output: `File is too large to read (${stats.size} bytes, limit ${MAX_FILE_BYTES}). It is probably not a text source file (e.g. a state/binary/vendored file) — check the path or use the shell tool with limited output.`,
28
28
  isError: true,
29
29
  };
30
30
  }
@@ -36,12 +36,12 @@ export const readFileTool = {
36
36
  .join("\n");
37
37
  const truncated = offset - 1 + limit < lines.length;
38
38
  return {
39
- output: numbered + (truncated ? `\n... (isečeno, ukupno ${lines.length} linija)` : ""),
39
+ output: numbered + (truncated ? `\n... (truncated, ${lines.length} lines total)` : ""),
40
40
  isError: false,
41
41
  };
42
42
  }
43
43
  catch (err) {
44
- return { output: `Greška pri čitanju ${resolved}: ${err.message}`, isError: true };
44
+ return { output: `Error reading ${resolved}: ${err.message}`, isError: true };
45
45
  }
46
46
  },
47
47
  };
@@ -1 +1 @@
1
- {"version":3,"file":"readFile.js","sourceRoot":"","sources":["../../../src/agent/tools/readFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAExC,MAAM,CAAC,MAAM,YAAY,GAAmB;IAC1C,IAAI,EAAE,WAAW;IACjB,WAAW,EACT,8GAA8G;IAChH,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;YAC1D,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,6DAA6D,EAAE;YACvG,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,oDAAoD,SAAS,GAAG,EAAE;SAC1G;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;IACD,aAAa,EAAE,GAAG,EAAE,CAAC,KAAK;IAC1B,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,KAAK,CAAC,IAAI,GAAG,cAAc,EAAE,CAAC;gBAChC,OAAO;oBACL,MAAM,EAAE,gCAAgC,KAAK,CAAC,IAAI,mBAAmB,cAAc,+IAA+I;oBAClO,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACnC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;YAC1D,MAAM,QAAQ,GAAG,KAAK;iBACnB,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;iBACnE,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;YACpD,OAAO;gBACL,MAAM,EAAE,QAAQ,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,0BAA0B,KAAK,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtF,OAAO,EAAE,KAAK;aACf,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,MAAM,EAAE,sBAAsB,QAAQ,KAAM,GAAa,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAChG,CAAC;IACH,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"readFile.js","sourceRoot":"","sources":["../../../src/agent/tools/readFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAExC,MAAM,CAAC,MAAM,YAAY,GAAmB;IAC1C,IAAI,EAAE,WAAW;IACjB,WAAW,EACT,6GAA6G;IAC/G,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;YAC1D,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,gDAAgD,EAAE;YAC1F,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,gDAAgD,SAAS,GAAG,EAAE;SACtG;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;IACD,aAAa,EAAE,GAAG,EAAE,CAAC,KAAK;IAC1B,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;QACrB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,KAAK,CAAC,IAAI,GAAG,cAAc,EAAE,CAAC;gBAChC,OAAO;oBACL,MAAM,EAAE,8BAA8B,KAAK,CAAC,IAAI,iBAAiB,cAAc,0IAA0I;oBACzN,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACnC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;YAC1D,MAAM,QAAQ,GAAG,KAAK;iBACnB,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;iBACnE,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;YACpD,OAAO;gBACL,MAAM,EAAE,QAAQ,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,qBAAqB,KAAK,CAAC,MAAM,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtF,OAAO,EAAE,KAAK;aACf,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,MAAM,EAAE,iBAAiB,QAAQ,KAAM,GAAa,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3F,CAAC;IACH,CAAC;CACF,CAAC"}