tandem-mode 0.0.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/LICENSE +21 -0
- package/README.md +191 -0
- package/README.sr.md +194 -0
- package/dist/agent/clipboard.js +26 -0
- package/dist/agent/clipboard.js.map +1 -0
- package/dist/agent/loop.js +157 -0
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/pricing.js +21 -0
- package/dist/agent/pricing.js.map +1 -0
- package/dist/agent/session.js +78 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/agent/tools/edit.js +78 -0
- package/dist/agent/tools/edit.js.map +1 -0
- package/dist/agent/tools/gitDiff.js +42 -0
- package/dist/agent/tools/gitDiff.js.map +1 -0
- package/dist/agent/tools/index.js +24 -0
- package/dist/agent/tools/index.js.map +1 -0
- package/dist/agent/tools/listDir.js +29 -0
- package/dist/agent/tools/listDir.js.map +1 -0
- package/dist/agent/tools/readFile.js +40 -0
- package/dist/agent/tools/readFile.js.map +1 -0
- package/dist/agent/tools/search.js +51 -0
- package/dist/agent/tools/search.js.map +1 -0
- package/dist/agent/tools/shell.js +95 -0
- package/dist/agent/tools/shell.js.map +1 -0
- package/dist/agent/tools/types.js +11 -0
- package/dist/agent/tools/types.js.map +1 -0
- package/dist/agent/tools/viewImage.js +34 -0
- package/dist/agent/tools/viewImage.js.map +1 -0
- package/dist/agent/tools/webSearch.js +27 -0
- package/dist/agent/tools/webSearch.js.map +1 -0
- package/dist/agent/usage.js +36 -0
- package/dist/agent/usage.js.map +1 -0
- package/dist/benchmark/runner.js +176 -0
- package/dist/benchmark/runner.js.map +1 -0
- package/dist/benchmark/tasks/bitwiseBulkPriceWizard.js +50 -0
- package/dist/benchmark/tasks/bitwiseBulkPriceWizard.js.map +1 -0
- package/dist/benchmark/types.js +2 -0
- package/dist/benchmark/types.js.map +1 -0
- package/dist/cli.js +442 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/credentials.js +80 -0
- package/dist/config/credentials.js.map +1 -0
- package/dist/config/env.js +12 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/schema.js +6 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/store.js +35 -0
- package/dist/config/store.js.map +1 -0
- package/dist/deepseek/client.js +145 -0
- package/dist/deepseek/client.js.map +1 -0
- package/dist/deepseek/types.js +2 -0
- package/dist/deepseek/types.js.map +1 -0
- package/dist/deepseek/vision.js +59 -0
- package/dist/deepseek/vision.js.map +1 -0
- package/dist/deepseek/webSearch.js +43 -0
- package/dist/deepseek/webSearch.js.map +1 -0
- package/dist/orchestrator/orchestrate.js +63 -0
- package/dist/orchestrator/orchestrate.js.map +1 -0
- package/dist/orchestrator/planner.js +48 -0
- package/dist/orchestrator/planner.js.map +1 -0
- package/dist/orchestrator/repoMap.js +52 -0
- package/dist/orchestrator/repoMap.js.map +1 -0
- package/dist/orchestrator/reviewer.js +53 -0
- package/dist/orchestrator/reviewer.js.map +1 -0
- package/dist/orchestrator/types.js +18 -0
- package/dist/orchestrator/types.js.map +1 -0
- package/dist/repl/commands.js +139 -0
- package/dist/repl/commands.js.map +1 -0
- package/dist/repl/state.js +2 -0
- package/dist/repl/state.js.map +1 -0
- package/dist/repl/system-prompt.js +5 -0
- package/dist/repl/system-prompt.js.map +1 -0
- package/dist/repl/wizard.js +34 -0
- package/dist/repl/wizard.js.map +1 -0
- package/package.json +49 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { render, Text, Box, useApp } from "ink";
|
|
5
|
+
import readline from "node:readline";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { mkdir } from "node:fs/promises";
|
|
8
|
+
import { resolveApiKey, resolveBaseUrl } from "./config/env.js";
|
|
9
|
+
import { loadConfig } from "./config/store.js";
|
|
10
|
+
import { DEFAULT_CONFIG } from "./config/schema.js";
|
|
11
|
+
import { runFirstRunWizard } from "./repl/wizard.js";
|
|
12
|
+
import { handleCommand } from "./repl/commands.js";
|
|
13
|
+
import { SYSTEM_PROMPT } from "./repl/system-prompt.js";
|
|
14
|
+
import { runAgentLoop } from "./agent/loop.js";
|
|
15
|
+
import { UsageAccumulator } from "./agent/usage.js";
|
|
16
|
+
import { isPeakHour } from "./agent/pricing.js";
|
|
17
|
+
import { saveClipboardImage } from "./agent/clipboard.js";
|
|
18
|
+
import { runOrchestration } from "./orchestrator/orchestrate.js";
|
|
19
|
+
import { appendSessionMessage, createSession, findLatestSession, loadSessionMessages } from "./agent/session.js";
|
|
20
|
+
function TurnView({ state, turn, askApproval, onDone, }) {
|
|
21
|
+
const { exit } = useApp();
|
|
22
|
+
const [reasoning, setReasoning] = useState("");
|
|
23
|
+
const [content, setContent] = useState("");
|
|
24
|
+
const [toolLog, setToolLog] = useState([]);
|
|
25
|
+
const [pending, setPending] = useState(null);
|
|
26
|
+
const [usageLine, setUsageLine] = useState(null);
|
|
27
|
+
const [error, setError] = useState(null);
|
|
28
|
+
const [notice, setNotice] = useState(null);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
async function run() {
|
|
31
|
+
const approve = async (toolName, args) => {
|
|
32
|
+
if (state.autoApprove) {
|
|
33
|
+
console.error(`[--yes] auto-odobreno: ${toolName}(${JSON.stringify(args)})`);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
if (state.alwaysApprovedTools.has(toolName))
|
|
37
|
+
return true;
|
|
38
|
+
setPending({ toolName, args });
|
|
39
|
+
const response = await askApproval(toolName, args);
|
|
40
|
+
setPending(null);
|
|
41
|
+
if (response.always)
|
|
42
|
+
state.alwaysApprovedTools.add(toolName);
|
|
43
|
+
return response.approved;
|
|
44
|
+
};
|
|
45
|
+
for await (const event of runAgentLoop(turn.messages, {
|
|
46
|
+
env: state.env,
|
|
47
|
+
model: turn.model,
|
|
48
|
+
cwd: state.cwd,
|
|
49
|
+
session: state.session,
|
|
50
|
+
usage: state.usage,
|
|
51
|
+
approve,
|
|
52
|
+
...(turn.thinking !== undefined ? { thinking: turn.thinking } : {}),
|
|
53
|
+
...(turn.budgetUsd !== undefined ? { budgetUsd: turn.budgetUsd } : {}),
|
|
54
|
+
...(turn.signal !== undefined ? { signal: turn.signal } : {}),
|
|
55
|
+
})) {
|
|
56
|
+
handleEvent(event);
|
|
57
|
+
}
|
|
58
|
+
function handleEvent(event) {
|
|
59
|
+
switch (event.type) {
|
|
60
|
+
case "reasoning_delta":
|
|
61
|
+
setReasoning((prev) => prev + event.delta);
|
|
62
|
+
break;
|
|
63
|
+
case "content_delta":
|
|
64
|
+
setContent((prev) => prev + event.delta);
|
|
65
|
+
break;
|
|
66
|
+
case "tool_call_start":
|
|
67
|
+
setToolLog((prev) => [...prev, { id: event.id, name: event.name, args: event.args, status: "running" }]);
|
|
68
|
+
break;
|
|
69
|
+
case "tool_call_result":
|
|
70
|
+
setToolLog((prev) => prev.map((t) => t.id === event.id ? { ...t, status: "done", output: event.result.output, isError: event.result.isError } : t));
|
|
71
|
+
break;
|
|
72
|
+
case "tool_call_denied":
|
|
73
|
+
setToolLog((prev) => prev.map((t) => (t.id === event.id ? { ...t, status: "denied" } : t)));
|
|
74
|
+
break;
|
|
75
|
+
case "usage": {
|
|
76
|
+
const total = state.usage.totals();
|
|
77
|
+
setUsageLine(`tokens: ${total.promptTokens} in (${total.promptCacheHitTokens} cached) / ${total.completionTokens} out · ~$${state.usage.estimatedCostUsd().toFixed(4)} · ${state.usage.callCount} poziva`);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
case "final":
|
|
81
|
+
setContent(event.content);
|
|
82
|
+
break;
|
|
83
|
+
case "max_iterations_reached":
|
|
84
|
+
setNotice("Dostignut je maksimalan broj iteracija bez finalnog odgovora.");
|
|
85
|
+
break;
|
|
86
|
+
case "budget_exceeded":
|
|
87
|
+
setNotice(`Budžet od $${event.budgetUsd.toFixed(2)} je dostignut (potrošeno ~$${event.spentUsd.toFixed(4)}). Petlja je zaustavljena pre sledećeg poziva — sesija je sačuvana, poveci budžet sa /budget i nastavi.`);
|
|
88
|
+
break;
|
|
89
|
+
case "interrupted":
|
|
90
|
+
setNotice("⏹ Prekinuto (ESC). Sesija je sačuvana do ove tačke.");
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
run()
|
|
96
|
+
.catch((err) => {
|
|
97
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
98
|
+
})
|
|
99
|
+
.finally(() => {
|
|
100
|
+
exit();
|
|
101
|
+
onDone();
|
|
102
|
+
});
|
|
103
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
104
|
+
}, []);
|
|
105
|
+
return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [reasoning.length > 0 && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "\u273B Razmi\u0161ljam\u2026" }), _jsx(Text, { dimColor: true, children: reasoning })] })), toolLog.map((t) => {
|
|
106
|
+
const lines = t.output?.split("\n") ?? [];
|
|
107
|
+
const preview = lines.slice(0, 3).join("\n");
|
|
108
|
+
const more = lines.length > 3;
|
|
109
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: t.status === "denied" ? "yellow" : t.isError ? "red" : "cyan", children: ["\u23FA ", t.name, "(", JSON.stringify(t.args), ")", t.status === "running" ? "…" : t.status === "denied" ? " (odbijeno)" : ""] }), preview && (_jsxs(Text, { dimColor: true, children: [" ⎿ ", preview.slice(0, 400), more || preview.length > 400 ? ` … (${lines.length} linija)` : ""] }))] }, t.id));
|
|
110
|
+
}), pending && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [_jsxs(Text, { color: "yellow", bold: true, children: ["Destruktivna akcija: ", pending.toolName, "(", JSON.stringify(pending.args), ")"] }), _jsx(Text, { dimColor: true, children: "y = dozvoli, n = odbij, a = uvek dozvoli ovaj alat ovoj sesiji (odgovor ispod)" })] })), content.length > 0 && _jsx(Text, { children: content }), usageLine && _jsx(Text, { color: "gray", children: usageLine }), notice && _jsx(Text, { color: "yellow", children: notice }), error && _jsxs(Text, { color: "red", children: ["Gre\u0161ka: ", error] })] }));
|
|
111
|
+
}
|
|
112
|
+
function truncatePath(p, max = 50) {
|
|
113
|
+
return p.length > max ? `…${p.slice(-(max - 1))}` : p;
|
|
114
|
+
}
|
|
115
|
+
function Banner({ state }) {
|
|
116
|
+
const { exit } = useApp();
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
exit();
|
|
119
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
120
|
+
}, []);
|
|
121
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "\u273B Tandem Mode" }), _jsx(Text, { dimColor: true, children: truncatePath(state.cwd) })] }));
|
|
122
|
+
}
|
|
123
|
+
async function showBanner(state) {
|
|
124
|
+
await render(_jsx(Banner, { state: state })).waitUntilExit();
|
|
125
|
+
}
|
|
126
|
+
async function runTurnConfig(state, turn, askApproval) {
|
|
127
|
+
await new Promise((resolve) => {
|
|
128
|
+
render(_jsx(TurnView, { state: state, turn: turn, askApproval: askApproval, onDone: resolve }));
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async function runTurn(state, userText, askApproval, signal) {
|
|
132
|
+
const userMsg = { role: "user", content: userText };
|
|
133
|
+
state.messages.push(userMsg);
|
|
134
|
+
await appendSessionMessage(state.session, userMsg);
|
|
135
|
+
const thinking = state.thinkingEnabled ? { reasoningEffort: state.reasoningEffort } : undefined;
|
|
136
|
+
const turn = { messages: state.messages, model: state.model };
|
|
137
|
+
if (thinking !== undefined)
|
|
138
|
+
turn.thinking = thinking;
|
|
139
|
+
if (state.budgetUsd !== undefined)
|
|
140
|
+
turn.budgetUsd = state.budgetUsd;
|
|
141
|
+
if (signal !== undefined)
|
|
142
|
+
turn.signal = signal;
|
|
143
|
+
await runTurnConfig(state, turn, askApproval);
|
|
144
|
+
}
|
|
145
|
+
function isAbortError(err) {
|
|
146
|
+
return err instanceof Error && err.name === "AbortError";
|
|
147
|
+
}
|
|
148
|
+
async function runPlanTask(state, task, askApproval, signal) {
|
|
149
|
+
try {
|
|
150
|
+
await runOrchestration(task, {
|
|
151
|
+
cwd: state.cwd,
|
|
152
|
+
env: state.env,
|
|
153
|
+
maxReviewLoops: state.maxReviewLoops,
|
|
154
|
+
usage: state.usage,
|
|
155
|
+
...(signal !== undefined ? { signal } : {}),
|
|
156
|
+
runWorkerTurn: (turn) => runTurnConfig(state, turn, askApproval),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
if (isAbortError(err)) {
|
|
161
|
+
console.log("⏹ Orkestracija prekinuta (ESC).");
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
console.error(`Greška u orkestraciji: ${err instanceof Error ? err.message : String(err)}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function parseApprovalAnswer(raw) {
|
|
169
|
+
const lower = raw.trim().toLowerCase();
|
|
170
|
+
if (lower === "a" || lower === "always")
|
|
171
|
+
return { approved: true, always: true };
|
|
172
|
+
return { approved: lower === "y", always: false };
|
|
173
|
+
}
|
|
174
|
+
/** Za single-shot poteze: sopstveni for-await čitač linija samo za y/n/a odobrenja. */
|
|
175
|
+
function createLineApprover() {
|
|
176
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
177
|
+
const resolveRef = { current: null };
|
|
178
|
+
const consumeLines = async () => {
|
|
179
|
+
for await (const rawLine of rl) {
|
|
180
|
+
if (resolveRef.current) {
|
|
181
|
+
resolveRef.current(parseApprovalAnswer(rawLine));
|
|
182
|
+
resolveRef.current = null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
void consumeLines();
|
|
187
|
+
const approve = (toolName, args) => {
|
|
188
|
+
console.log(`\nDozvoli izvršavanje ${toolName}(${JSON.stringify(args)})? (y/n/a — a = uvek dozvoli ovaj alat)`);
|
|
189
|
+
return new Promise((resolve) => {
|
|
190
|
+
resolveRef.current = resolve;
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
return { approve, close: () => rl.close() };
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* `.question()` je nepouzdan na piped/non-TTY stdin-u posle prvog poziva
|
|
197
|
+
* (poznata Node quirka — drugi poziv nikad ne razrešava). Zato se čitanje
|
|
198
|
+
* linija radi isključivo preko `for await...of rl`, koje pouzdano isporučuje
|
|
199
|
+
* svaku liniju, uz ručni state-machine za odobrenje umesto ugnježdenog
|
|
200
|
+
* `.question()`.
|
|
201
|
+
*/
|
|
202
|
+
async function runRepl(state) {
|
|
203
|
+
await showBanner(state);
|
|
204
|
+
console.log("/help za komande, /exit za izlaz.\n");
|
|
205
|
+
if (isPeakHour(new Date())) {
|
|
206
|
+
console.log("⚠ Trenutno je peak sat (01–04h ili 06–10h UTC) — cene su duplo veće nego off-peak.\n");
|
|
207
|
+
}
|
|
208
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, prompt: "> " });
|
|
209
|
+
let closed = false;
|
|
210
|
+
rl.on("close", () => {
|
|
211
|
+
closed = true;
|
|
212
|
+
});
|
|
213
|
+
const showPrompt = () => {
|
|
214
|
+
if (!closed)
|
|
215
|
+
rl.prompt();
|
|
216
|
+
};
|
|
217
|
+
const approvalRef = { current: null };
|
|
218
|
+
let turnActive = false;
|
|
219
|
+
let lastTurn = Promise.resolve();
|
|
220
|
+
const askApproval = (toolName, args) => {
|
|
221
|
+
console.log(`\nDozvoli izvršavanje ${toolName}(${JSON.stringify(args)})? (y/n/a — a = uvek dozvoli ovaj alat)`);
|
|
222
|
+
return new Promise((resolve) => {
|
|
223
|
+
approvalRef.current = resolve;
|
|
224
|
+
});
|
|
225
|
+
};
|
|
226
|
+
// ESC prekida trenutni potez. Radi samo na pravom TTY-ju — piped/scriptovani
|
|
227
|
+
// unos ne generiše keypress evente, pa je interrupt tiho no-op tamo.
|
|
228
|
+
const abortRef = { current: null };
|
|
229
|
+
readline.emitKeypressEvents(process.stdin);
|
|
230
|
+
process.stdin.on("keypress", (_str, key) => {
|
|
231
|
+
if (key?.name === "escape" && abortRef.current) {
|
|
232
|
+
abortRef.current.abort();
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
showPrompt();
|
|
236
|
+
for await (const rawLine of rl) {
|
|
237
|
+
const line = rawLine.trim();
|
|
238
|
+
if (approvalRef.current) {
|
|
239
|
+
approvalRef.current(parseApprovalAnswer(line));
|
|
240
|
+
approvalRef.current = null;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (!line) {
|
|
244
|
+
showPrompt();
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (turnActive) {
|
|
248
|
+
console.log("Sačekaj da se trenutni potez završi.");
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
const beginTurn = (run) => {
|
|
252
|
+
turnActive = true;
|
|
253
|
+
const controller = new AbortController();
|
|
254
|
+
abortRef.current = controller;
|
|
255
|
+
lastTurn = run(controller.signal).finally(() => {
|
|
256
|
+
abortRef.current = null;
|
|
257
|
+
turnActive = false;
|
|
258
|
+
showPrompt();
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
if (line.startsWith("/plan ")) {
|
|
262
|
+
const task = line.slice("/plan ".length).trim();
|
|
263
|
+
if (!task) {
|
|
264
|
+
console.log("Upotreba: /plan <opis zadatka>");
|
|
265
|
+
showPrompt();
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
beginTurn((signal) => runPlanTask(state, task, askApproval, signal));
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (line === "/paste" || line.startsWith("/paste ")) {
|
|
272
|
+
const extra = line.slice("/paste".length).trim();
|
|
273
|
+
try {
|
|
274
|
+
const destDir = path.join(state.cwd, ".tandem", "tmp");
|
|
275
|
+
await mkdir(destDir, { recursive: true });
|
|
276
|
+
const destPath = path.join(destDir, `paste-${Date.now()}.png`);
|
|
277
|
+
const ok = await saveClipboardImage(destPath);
|
|
278
|
+
if (!ok) {
|
|
279
|
+
console.log("Nema slike u clipboard-u.");
|
|
280
|
+
showPrompt();
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
const relPath = path.relative(state.cwd, destPath);
|
|
284
|
+
const text = `[slika zalepljena iz clipboard-a: ${relPath}] ${extra || "Pogledaj sliku i opiši šta vidiš."}`;
|
|
285
|
+
beginTurn((signal) => runTurn(state, text, askApproval, signal));
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
console.log(`Greška: ${err instanceof Error ? err.message : String(err)}`);
|
|
289
|
+
showPrompt();
|
|
290
|
+
}
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
if (line.startsWith("/")) {
|
|
294
|
+
const outcome = await handleCommand(line, state);
|
|
295
|
+
if (outcome === "exit")
|
|
296
|
+
break;
|
|
297
|
+
showPrompt();
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
beginTurn((signal) => runTurn(state, line, askApproval, signal));
|
|
301
|
+
}
|
|
302
|
+
await lastTurn;
|
|
303
|
+
if (!closed)
|
|
304
|
+
rl.close();
|
|
305
|
+
}
|
|
306
|
+
function parseArgv(argv) {
|
|
307
|
+
const rest = [];
|
|
308
|
+
let resume = false;
|
|
309
|
+
let autoApprove = false;
|
|
310
|
+
let plan = false;
|
|
311
|
+
let model;
|
|
312
|
+
let effort;
|
|
313
|
+
let budgetUsd;
|
|
314
|
+
let maxReviewLoops;
|
|
315
|
+
for (let i = 0; i < argv.length; i++) {
|
|
316
|
+
const arg = argv[i];
|
|
317
|
+
if (arg === "--resume" || arg === "-r") {
|
|
318
|
+
resume = true;
|
|
319
|
+
}
|
|
320
|
+
else if (arg === "--yes" || arg === "-y") {
|
|
321
|
+
autoApprove = true;
|
|
322
|
+
}
|
|
323
|
+
else if (arg === "--plan") {
|
|
324
|
+
plan = true;
|
|
325
|
+
}
|
|
326
|
+
else if (arg === "--model") {
|
|
327
|
+
const value = argv[++i];
|
|
328
|
+
if (value === "deepseek-v4-pro" || value === "deepseek-v4-flash")
|
|
329
|
+
model = value;
|
|
330
|
+
}
|
|
331
|
+
else if (arg === "--effort") {
|
|
332
|
+
const value = argv[++i];
|
|
333
|
+
if (value === "low" || value === "high" || value === "max")
|
|
334
|
+
effort = value;
|
|
335
|
+
}
|
|
336
|
+
else if (arg === "--budget") {
|
|
337
|
+
const value = Number(argv[++i]);
|
|
338
|
+
if (Number.isFinite(value) && value > 0)
|
|
339
|
+
budgetUsd = value;
|
|
340
|
+
}
|
|
341
|
+
else if (arg === "--max-review-loops") {
|
|
342
|
+
const value = Number(argv[++i]);
|
|
343
|
+
if (Number.isFinite(value) && value > 0)
|
|
344
|
+
maxReviewLoops = value;
|
|
345
|
+
}
|
|
346
|
+
else if (arg !== undefined) {
|
|
347
|
+
rest.push(arg);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const parsed = { prompt: rest.join(" ").trim(), resume, autoApprove, plan };
|
|
351
|
+
if (model !== undefined)
|
|
352
|
+
parsed.model = model;
|
|
353
|
+
if (effort !== undefined)
|
|
354
|
+
parsed.effort = effort;
|
|
355
|
+
if (budgetUsd !== undefined)
|
|
356
|
+
parsed.budgetUsd = budgetUsd;
|
|
357
|
+
if (maxReviewLoops !== undefined)
|
|
358
|
+
parsed.maxReviewLoops = maxReviewLoops;
|
|
359
|
+
return parsed;
|
|
360
|
+
}
|
|
361
|
+
async function main() {
|
|
362
|
+
const cwd = process.cwd();
|
|
363
|
+
const parsed = parseArgv(process.argv.slice(2));
|
|
364
|
+
const config = await loadConfig(cwd);
|
|
365
|
+
let apiKey = await resolveApiKey();
|
|
366
|
+
if (!apiKey) {
|
|
367
|
+
if (!process.stdin.isTTY) {
|
|
368
|
+
console.error("Nema DeepSeek API ključa. Postavi DEEPSEEK_API_KEY env promenljivu ili pokreni tandem interaktivno da odradiš first-run wizard.");
|
|
369
|
+
process.exitCode = 1;
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const wizardConfig = await runFirstRunWizard();
|
|
373
|
+
Object.assign(config, wizardConfig);
|
|
374
|
+
apiKey = await resolveApiKey();
|
|
375
|
+
if (!apiKey) {
|
|
376
|
+
console.error("Ključ nije sačuvan ispravno — pokušaj ponovo.");
|
|
377
|
+
process.exitCode = 1;
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const env = { apiKey, baseUrl: resolveBaseUrl(config) };
|
|
382
|
+
let session;
|
|
383
|
+
let messages;
|
|
384
|
+
if (parsed.resume) {
|
|
385
|
+
const existing = await findLatestSession(cwd);
|
|
386
|
+
if (!existing) {
|
|
387
|
+
console.error("Nema prethodne sesije za nastavak u ovom direktorijumu.");
|
|
388
|
+
process.exitCode = 1;
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
session = existing;
|
|
392
|
+
messages = await loadSessionMessages(existing.filePath);
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
session = await createSession(cwd);
|
|
396
|
+
const systemMsg = { role: "system", content: SYSTEM_PROMPT };
|
|
397
|
+
messages = [systemMsg];
|
|
398
|
+
await appendSessionMessage(session, systemMsg);
|
|
399
|
+
}
|
|
400
|
+
const state = {
|
|
401
|
+
env,
|
|
402
|
+
cwd,
|
|
403
|
+
model: parsed.model ?? config.defaultModel ?? DEFAULT_CONFIG.defaultModel,
|
|
404
|
+
thinkingEnabled: true,
|
|
405
|
+
reasoningEffort: parsed.effort ?? config.defaultReasoningEffort ?? DEFAULT_CONFIG.defaultReasoningEffort,
|
|
406
|
+
maxReviewLoops: parsed.maxReviewLoops ?? config.maxReviewLoops ?? DEFAULT_CONFIG.maxReviewLoops,
|
|
407
|
+
autoApprove: parsed.autoApprove,
|
|
408
|
+
alwaysApprovedTools: new Set(),
|
|
409
|
+
session,
|
|
410
|
+
messages,
|
|
411
|
+
usage: new UsageAccumulator(),
|
|
412
|
+
};
|
|
413
|
+
const budgetUsd = parsed.budgetUsd ?? config.budgetUsd;
|
|
414
|
+
if (budgetUsd !== undefined)
|
|
415
|
+
state.budgetUsd = budgetUsd;
|
|
416
|
+
if (parsed.prompt) {
|
|
417
|
+
const approver = createLineApprover();
|
|
418
|
+
const controller = new AbortController();
|
|
419
|
+
if (process.stdin.isTTY) {
|
|
420
|
+
readline.emitKeypressEvents(process.stdin);
|
|
421
|
+
process.stdin.on("keypress", (_str, key) => {
|
|
422
|
+
if (key?.name === "escape")
|
|
423
|
+
controller.abort();
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
if (parsed.plan) {
|
|
427
|
+
await runPlanTask(state, parsed.prompt, approver.approve, controller.signal);
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
await runTurn(state, parsed.prompt, approver.approve, controller.signal);
|
|
431
|
+
}
|
|
432
|
+
approver.close();
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
await runRepl(state);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
main().catch((err) => {
|
|
439
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
440
|
+
process.exitCode = 1;
|
|
441
|
+
});
|
|
442
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
const CRED_PATH = path.join(os.homedir(), "AppData", "Local", "TandemMode", "credentials.dat");
|
|
5
|
+
// Nije tajna — samo dodatni ulaz pomešan sa DPAPI ključem vezanim za OS nalog,
|
|
6
|
+
// koji je stvarna zaštita.
|
|
7
|
+
const ENTROPY = "tandem-mode-v1";
|
|
8
|
+
/**
|
|
9
|
+
* DPAPI-šifrovan fajl umesto punog Windows Credential Manager-a — isti
|
|
10
|
+
* mehanizam (samo ovaj OS nalog može dešifrovati), ali direktan .NET poziv
|
|
11
|
+
* bez multi-platform auto-detekcije. `cross-keychain` je probana prva
|
|
12
|
+
* (M2) i odbačena: 15-18s po pozivu na ovoj mašini čak i sa native
|
|
13
|
+
* bindingom, jer njena detekcija backend-a proba sve platforme redom.
|
|
14
|
+
* Linux/macOS ide u good-first-issues, isto obrazloženje kao clipboard.ts.
|
|
15
|
+
*
|
|
16
|
+
* Ključ se ISKLJUČIVO prosleđuje kroz stdin, nikad kroz argumente komande —
|
|
17
|
+
* argumenti su vidljivi u listi procesa (Task Manager i sl.) dok proces traje.
|
|
18
|
+
*/
|
|
19
|
+
function assertWindows() {
|
|
20
|
+
if (process.platform !== "win32") {
|
|
21
|
+
throw new Error("Čuvanje API ključa je trenutno podržano samo na Windows-u.");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function runPs(script, stdin) {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
const child = spawn("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script]);
|
|
27
|
+
let stdout = "";
|
|
28
|
+
let stderr = "";
|
|
29
|
+
child.stdout.on("data", (d) => (stdout += d.toString("utf8")));
|
|
30
|
+
child.stderr.on("data", (d) => (stderr += d.toString("utf8")));
|
|
31
|
+
child.on("error", reject);
|
|
32
|
+
child.on("close", (code) => {
|
|
33
|
+
if (code === 0)
|
|
34
|
+
resolve(stdout.trim());
|
|
35
|
+
else
|
|
36
|
+
reject(new Error(`powershell exited with code ${code}: ${stderr.trim()}`));
|
|
37
|
+
});
|
|
38
|
+
if (stdin !== undefined)
|
|
39
|
+
child.stdin.write(stdin, "utf8");
|
|
40
|
+
child.stdin.end();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
export async function getStoredApiKey() {
|
|
44
|
+
assertWindows();
|
|
45
|
+
const script = `
|
|
46
|
+
Add-Type -AssemblyName System.Security
|
|
47
|
+
$path = '${CRED_PATH.replace(/'/g, "''")}'
|
|
48
|
+
if (-not (Test-Path $path)) { Write-Output '__NULL__'; exit }
|
|
49
|
+
try {
|
|
50
|
+
$protected = [System.IO.File]::ReadAllBytes($path)
|
|
51
|
+
$entropy = [System.Text.Encoding]::UTF8.GetBytes('${ENTROPY}')
|
|
52
|
+
$bytes = [System.Security.Cryptography.ProtectedData]::Unprotect($protected, $entropy, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
|
|
53
|
+
[System.Text.Encoding]::UTF8.GetString($bytes)
|
|
54
|
+
} catch {
|
|
55
|
+
Write-Output '__NULL__'
|
|
56
|
+
}`;
|
|
57
|
+
const result = await runPs(script);
|
|
58
|
+
return result === "__NULL__" || result === "" ? null : result;
|
|
59
|
+
}
|
|
60
|
+
export async function setStoredApiKey(key) {
|
|
61
|
+
assertWindows();
|
|
62
|
+
const dir = path.dirname(CRED_PATH);
|
|
63
|
+
const script = `
|
|
64
|
+
Add-Type -AssemblyName System.Security
|
|
65
|
+
New-Item -ItemType Directory -Force -Path '${dir.replace(/'/g, "''")}' | Out-Null
|
|
66
|
+
$key = [Console]::In.ReadToEnd()
|
|
67
|
+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($key)
|
|
68
|
+
$entropy = [System.Text.Encoding]::UTF8.GetBytes('${ENTROPY}')
|
|
69
|
+
$protected = [System.Security.Cryptography.ProtectedData]::Protect($bytes, $entropy, [System.Security.Cryptography.DataProtectionScope]::CurrentUser)
|
|
70
|
+
[System.IO.File]::WriteAllBytes('${CRED_PATH.replace(/'/g, "''")}', $protected)`;
|
|
71
|
+
await runPs(script, key);
|
|
72
|
+
}
|
|
73
|
+
export async function deleteStoredApiKey() {
|
|
74
|
+
assertWindows();
|
|
75
|
+
const script = `
|
|
76
|
+
$path = '${CRED_PATH.replace(/'/g, "''")}'
|
|
77
|
+
if (Test-Path $path) { Remove-Item $path -Force }`;
|
|
78
|
+
await runPs(script);
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/config/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getStoredApiKey } from "./credentials.js";
|
|
2
|
+
/** DEEPSEEK_API_KEY (env) ima prednost nad OS credential store-om — za CI/automatizaciju. */
|
|
3
|
+
export async function resolveApiKey() {
|
|
4
|
+
const envKey = process.env["DEEPSEEK_API_KEY"];
|
|
5
|
+
if (envKey)
|
|
6
|
+
return envKey;
|
|
7
|
+
return getStoredApiKey();
|
|
8
|
+
}
|
|
9
|
+
export function resolveBaseUrl(config) {
|
|
10
|
+
return process.env["DEEPSEEK_BASE_URL"] ?? config.baseUrl ?? "https://api.deepseek.com";
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAQnD,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC/C,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,OAAO,eAAe,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,OAAO,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,MAAM,CAAC,OAAO,IAAI,0BAA0B,CAAC;AAC1F,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,cAAc,GAA+F;IACxH,YAAY,EAAE,iBAAiB;IAC/B,sBAAsB,EAAE,MAAM;IAC9B,cAAc,EAAE,CAAC;CAClB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
function globalConfigPath() {
|
|
5
|
+
return path.join(os.homedir(), ".tandem", "config.json");
|
|
6
|
+
}
|
|
7
|
+
function projectConfigPath(cwd) {
|
|
8
|
+
return path.join(cwd, ".tandem", "config.json");
|
|
9
|
+
}
|
|
10
|
+
async function readConfigFile(filePath) {
|
|
11
|
+
try {
|
|
12
|
+
const raw = await readFile(filePath, "utf8");
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err.code === "ENOENT")
|
|
17
|
+
return {};
|
|
18
|
+
throw err;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Global < project. Session-level overrides (slash komande) žive u runtime stanju, ne ovde. */
|
|
22
|
+
export async function loadConfig(cwd) {
|
|
23
|
+
const [global, project] = await Promise.all([
|
|
24
|
+
readConfigFile(globalConfigPath()),
|
|
25
|
+
readConfigFile(projectConfigPath(cwd)),
|
|
26
|
+
]);
|
|
27
|
+
return { ...global, ...project };
|
|
28
|
+
}
|
|
29
|
+
export async function saveGlobalConfig(partial) {
|
|
30
|
+
const filePath = globalConfigPath();
|
|
31
|
+
const existing = await readConfigFile(filePath);
|
|
32
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
33
|
+
await writeFile(filePath, JSON.stringify({ ...existing, ...partial }, null, 2) + "\n", "utf8");
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/config/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,SAAS,gBAAgB;IACvB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACpC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;AAClD,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,QAAgB;IAC5C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAC;IACzC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QAChE,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,gGAAgG;AAChG,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1C,cAAc,CAAC,gBAAgB,EAAE,CAAC;QAClC,cAAc,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;KACvC,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAqB;IAC1D,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AACjG,CAAC"}
|