@aigencydev/cli 0.1.0 → 0.3.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 (110) hide show
  1. package/dist/agent/checkpoints.js +147 -0
  2. package/dist/agent/chunker.js +1 -19
  3. package/dist/agent/history.js +0 -9
  4. package/dist/agent/instructions.js +94 -0
  5. package/dist/agent/loop.js +3 -34
  6. package/dist/agent/memory.js +197 -103
  7. package/dist/agent/session-store.js +160 -0
  8. package/dist/agent/task-list.js +102 -0
  9. package/dist/api-client/auth.js +0 -10
  10. package/dist/api-client/base.js +0 -16
  11. package/dist/api-client/stream.js +0 -25
  12. package/dist/api-client/updates.js +2 -9
  13. package/dist/api-client/usage.js +0 -4
  14. package/dist/auth/oauth.js +0 -31
  15. package/dist/auth/pkce.js +1 -9
  16. package/dist/auth/session.js +0 -16
  17. package/dist/auth/storage.js +1 -36
  18. package/dist/cli.js +8 -13
  19. package/dist/commands/chat.js +14 -19
  20. package/dist/commands/help.js +0 -4
  21. package/dist/commands/init.js +327 -30
  22. package/dist/commands/login.js +0 -30
  23. package/dist/commands/logout.js +0 -5
  24. package/dist/commands/update.js +0 -9
  25. package/dist/commands/usage.js +0 -10
  26. package/dist/config/bootstrap.js +52 -0
  27. package/dist/config/defaults.js +4 -15
  28. package/dist/config/hooks.js +1 -23
  29. package/dist/config/paths.js +95 -38
  30. package/dist/config/settings.js +0 -21
  31. package/dist/index.js +0 -11
  32. package/dist/security/command-filter.js +0 -35
  33. package/dist/security/sandbox.js +1 -39
  34. package/dist/security/sanitize.js +0 -21
  35. package/dist/tools/bash.js +186 -32
  36. package/dist/tools/diff.js +0 -7
  37. package/dist/tools/edit-file.js +4 -12
  38. package/dist/tools/list-files.js +0 -5
  39. package/dist/tools/memory-tools.js +126 -0
  40. package/dist/tools/read-file.js +1 -7
  41. package/dist/tools/registry.js +7 -9
  42. package/dist/tools/search-files.js +2 -11
  43. package/dist/tools/task-tools.js +74 -0
  44. package/dist/tools/types.js +0 -4
  45. package/dist/tools/write-file.js +5 -12
  46. package/dist/types/index.js +0 -7
  47. package/dist/ui/App.js +160 -36
  48. package/dist/ui/InputBar.js +8 -9
  49. package/dist/ui/MessageList.js +25 -33
  50. package/dist/ui/ModeIndicator.js +6 -18
  51. package/dist/ui/PermissionPrompt.js +28 -29
  52. package/dist/ui/StatusBar.js +17 -17
  53. package/dist/ui/theme.js +112 -38
  54. package/dist/utils/abort.js +0 -12
  55. package/dist/utils/errors.js +0 -7
  56. package/dist/utils/formatting.js +0 -8
  57. package/dist/utils/logger.js +107 -17
  58. package/dist/version.js +1 -8
  59. package/package.json +1 -1
  60. package/dist/agent/chunker.js.map +0 -1
  61. package/dist/agent/history.js.map +0 -1
  62. package/dist/agent/loop.js.map +0 -1
  63. package/dist/agent/memory.js.map +0 -1
  64. package/dist/api-client/auth.js.map +0 -1
  65. package/dist/api-client/base.js.map +0 -1
  66. package/dist/api-client/stream.js.map +0 -1
  67. package/dist/api-client/updates.js.map +0 -1
  68. package/dist/api-client/usage.js.map +0 -1
  69. package/dist/auth/oauth.js.map +0 -1
  70. package/dist/auth/pkce.js.map +0 -1
  71. package/dist/auth/session.js.map +0 -1
  72. package/dist/auth/storage.js.map +0 -1
  73. package/dist/cli.js.map +0 -1
  74. package/dist/commands/chat.js.map +0 -1
  75. package/dist/commands/help.js.map +0 -1
  76. package/dist/commands/init.js.map +0 -1
  77. package/dist/commands/login.js.map +0 -1
  78. package/dist/commands/logout.js.map +0 -1
  79. package/dist/commands/update.js.map +0 -1
  80. package/dist/commands/usage.js.map +0 -1
  81. package/dist/config/defaults.js.map +0 -1
  82. package/dist/config/hooks.js.map +0 -1
  83. package/dist/config/paths.js.map +0 -1
  84. package/dist/config/settings.js.map +0 -1
  85. package/dist/index.js.map +0 -1
  86. package/dist/security/command-filter.js.map +0 -1
  87. package/dist/security/sandbox.js.map +0 -1
  88. package/dist/security/sanitize.js.map +0 -1
  89. package/dist/tools/bash.js.map +0 -1
  90. package/dist/tools/diff.js.map +0 -1
  91. package/dist/tools/edit-file.js.map +0 -1
  92. package/dist/tools/list-files.js.map +0 -1
  93. package/dist/tools/read-file.js.map +0 -1
  94. package/dist/tools/registry.js.map +0 -1
  95. package/dist/tools/search-files.js.map +0 -1
  96. package/dist/tools/types.js.map +0 -1
  97. package/dist/tools/write-file.js.map +0 -1
  98. package/dist/types/index.js.map +0 -1
  99. package/dist/ui/App.js.map +0 -1
  100. package/dist/ui/InputBar.js.map +0 -1
  101. package/dist/ui/MessageList.js.map +0 -1
  102. package/dist/ui/ModeIndicator.js.map +0 -1
  103. package/dist/ui/PermissionPrompt.js.map +0 -1
  104. package/dist/ui/StatusBar.js.map +0 -1
  105. package/dist/ui/theme.js.map +0 -1
  106. package/dist/utils/abort.js.map +0 -1
  107. package/dist/utils/errors.js.map +0 -1
  108. package/dist/utils/formatting.js.map +0 -1
  109. package/dist/utils/logger.js.map +0 -1
  110. package/dist/version.js.map +0 -1
@@ -1,22 +1,109 @@
1
- /**
2
- * bash_execute — sandboxed shell komutu.
3
- *
4
- * Windows'ta cmd.exe, Unix'te sh kullanır. 120 saniye timeout, 50 KB çıktı sınırı.
5
- * Plan modda her şey yasak, default'ta permission prompt, auto'da classifier.
6
- */
7
1
  import { spawn } from "node:child_process";
8
2
  import { checkCommand, autoModeDecision } from "../security/command-filter.js";
9
3
  import { checkPath } from "../security/sandbox.js";
10
4
  const MAX_OUTPUT_BYTES = 50_000;
11
- const DEFAULT_TIMEOUT_MS = 120_000;
12
- function runShell(command, cwd, timeoutMs, signal) {
5
+ const DEFAULT_TIMEOUT_MS = 300_000;
6
+ const LIVE_OUTPUT_THROTTLE_MS = 150;
7
+ const INTERACTIVE_PATTERNS = [
8
+ {
9
+ regex: /\bcreate-next-app\b(?![^|]*(?:--ts|--javascript|--yes|-y\b))/i,
10
+ reason: "create-next-app interaktif modda çalıştırılıyor (sorulara cevap verilemez)",
11
+ suggestion: 'Non-interactive flag\'lerle çağırın, örn.:\n npx create-next-app@latest proje-adi --typescript --tailwind --eslint --app --src-dir --import-alias "@/*" --use-npm --yes',
12
+ },
13
+ {
14
+ regex: /\bcreate-react-app\b/i,
15
+ reason: "create-react-app interaktif",
16
+ suggestion: 'npx create-react-app proje-adi --template typescript',
17
+ },
18
+ {
19
+ regex: /\bnpm\s+init\b(?!\s+-y\b)(?!\s+--yes\b)/i,
20
+ reason: "npm init interaktif modda",
21
+ suggestion: "npm init -y",
22
+ },
23
+ {
24
+ regex: /\byarn\s+create\b(?![^|]*--yes)/i,
25
+ reason: "yarn create interaktif",
26
+ suggestion: "yarn create <template> --yes",
27
+ },
28
+ {
29
+ regex: /\bpnpm\s+create\b(?![^|]*--yes)/i,
30
+ reason: "pnpm create interaktif",
31
+ suggestion: "pnpm create <template> --yes",
32
+ },
33
+ {
34
+ regex: /\bgit\s+commit\b(?!\s+-m\b)(?!\s+--message\b)(?!\s+--no-edit\b)/i,
35
+ reason: "git commit mesajsız → editör açılır (interaktif)",
36
+ suggestion: 'git commit -m "mesajınız"',
37
+ },
38
+ {
39
+ regex: /\b(?:npm|yarn|pnpm)\s+(?:run\s+)?dev\b/i,
40
+ reason: "Dev server sonsuz çalışır, bash_execute bunu yönetemez",
41
+ suggestion: "Kullanıcıya dev server'ı manuel başlatmasını söyleyin:\n cd proje-adi && npm run dev",
42
+ },
43
+ {
44
+ regex: /\b(?:next|vite|nuxt|remix)\s+dev\b/i,
45
+ reason: "Dev server sonsuz çalışır, bash_execute bunu yönetemez",
46
+ suggestion: "Kullanıcıya dev server'ı manuel başlatmasını söyleyin:\n cd proje-adi && npm run dev",
47
+ },
48
+ {
49
+ regex: /\bnodemon\b/i,
50
+ reason: "nodemon sonsuz çalışır (watch modu)",
51
+ suggestion: "Kullanıcıya nodemon'u manuel başlatmasını söyleyin",
52
+ },
53
+ {
54
+ regex: /\b(?:python|python3)\s+(?:-m\s+)?(?:manage\.py\s+runserver|http\.server)\b/i,
55
+ reason: "Python dev server sonsuz çalışır",
56
+ suggestion: "Kullanıcıya sunucuyu manuel başlatmasını söyleyin",
57
+ },
58
+ {
59
+ regex: /\b(?:rails|bundle\s+exec\s+rails)\s+server\b/i,
60
+ reason: "Rails server sonsuz çalışır",
61
+ suggestion: "Kullanıcıya Rails server'ı manuel başlatmasını söyleyin",
62
+ },
63
+ {
64
+ regex: /\bphp\s+artisan\s+serve\b/i,
65
+ reason: "Laravel serve sonsuz çalışır",
66
+ suggestion: "Kullanıcıya Laravel sunucusunu manuel başlatmasını söyleyin",
67
+ },
68
+ {
69
+ regex: /\bdocker(?:-|\s+)compose\s+up\b(?!\s+-d\b)(?!\s+--detach\b)/i,
70
+ reason: "docker compose up (detach'sız) foreground'da sonsuz çalışır",
71
+ suggestion: "docker compose up -d (detached mod)",
72
+ },
73
+ {
74
+ regex: /\btail\s+-f\b/i,
75
+ reason: "tail -f sürekli dosya takibi yapar",
76
+ suggestion: "tail -n 100 (son 100 satır için)",
77
+ },
78
+ {
79
+ regex: /\bwatch\s+/i,
80
+ reason: "watch komutu sürekli döngü",
81
+ suggestion: "Tek seferlik çağrı yapın",
82
+ },
83
+ ];
84
+ function detectInteractive(command) {
85
+ for (const pattern of INTERACTIVE_PATTERNS) {
86
+ if (pattern.regex.test(command)) {
87
+ return { ok: false, reason: pattern.reason, suggestion: pattern.suggestion };
88
+ }
89
+ }
90
+ return { ok: true };
91
+ }
92
+ function runShell(command, cwd, timeoutMs, signal, onLive) {
13
93
  return new Promise((resolve) => {
14
94
  const isWin = process.platform === "win32";
15
95
  const shell = isWin ? "cmd.exe" : "/bin/sh";
16
96
  const args = isWin ? ["/d", "/s", "/c", command] : ["-c", command];
17
97
  const child = spawn(shell, args, {
18
98
  cwd,
19
- env: process.env,
99
+ stdio: ["ignore", "pipe", "pipe"],
100
+ env: {
101
+ ...process.env,
102
+ CI: "1",
103
+ NO_COLOR: "0",
104
+ npm_config_yes: "true",
105
+ DEBIAN_FRONTEND: "noninteractive",
106
+ },
20
107
  windowsHide: true,
21
108
  });
22
109
  let stdout = "";
@@ -24,13 +111,44 @@ function runShell(command, cwd, timeoutMs, signal) {
24
111
  let outBytes = 0;
25
112
  let errBytes = 0;
26
113
  let timedOut = false;
114
+ let stdoutBuffer = "";
115
+ let stderrBuffer = "";
116
+ let flushTimer = null;
117
+ const scheduleFlush = () => {
118
+ if (flushTimer || !onLive)
119
+ return;
120
+ flushTimer = setTimeout(() => {
121
+ flushTimer = null;
122
+ if (stdoutBuffer) {
123
+ onLive("stdout", stdoutBuffer);
124
+ stdoutBuffer = "";
125
+ }
126
+ if (stderrBuffer) {
127
+ onLive("stderr", stderrBuffer);
128
+ stderrBuffer = "";
129
+ }
130
+ }, LIVE_OUTPUT_THROTTLE_MS);
131
+ };
132
+ const finalFlush = () => {
133
+ if (flushTimer) {
134
+ clearTimeout(flushTimer);
135
+ flushTimer = null;
136
+ }
137
+ if (onLive && stdoutBuffer) {
138
+ onLive("stdout", stdoutBuffer);
139
+ stdoutBuffer = "";
140
+ }
141
+ if (onLive && stderrBuffer) {
142
+ onLive("stderr", stderrBuffer);
143
+ stderrBuffer = "";
144
+ }
145
+ };
27
146
  const timeoutHandle = setTimeout(() => {
28
147
  timedOut = true;
29
148
  try {
30
149
  child.kill("SIGKILL");
31
150
  }
32
151
  catch {
33
- // ignore
34
152
  }
35
153
  }, timeoutMs);
36
154
  const onAbort = () => {
@@ -38,7 +156,6 @@ function runShell(command, cwd, timeoutMs, signal) {
38
156
  child.kill("SIGKILL");
39
157
  }
40
158
  catch {
41
- // ignore
42
159
  }
43
160
  };
44
161
  if (signal) {
@@ -48,23 +165,34 @@ function runShell(command, cwd, timeoutMs, signal) {
48
165
  signal.addEventListener("abort", onAbort, { once: true });
49
166
  }
50
167
  child.stdout.on("data", (chunk) => {
51
- if (outBytes >= MAX_OUTPUT_BYTES)
52
- return;
53
- const remaining = MAX_OUTPUT_BYTES - outBytes;
54
- const text = chunk.toString("utf8").slice(0, remaining);
55
- stdout += text;
56
- outBytes += text.length;
168
+ const text = chunk.toString("utf8");
169
+ if (outBytes < MAX_OUTPUT_BYTES) {
170
+ const remaining = MAX_OUTPUT_BYTES - outBytes;
171
+ const trimmed = text.slice(0, remaining);
172
+ stdout += trimmed;
173
+ outBytes += trimmed.length;
174
+ }
175
+ if (onLive) {
176
+ stdoutBuffer += text;
177
+ scheduleFlush();
178
+ }
57
179
  });
58
180
  child.stderr.on("data", (chunk) => {
59
- if (errBytes >= MAX_OUTPUT_BYTES)
60
- return;
61
- const remaining = MAX_OUTPUT_BYTES - errBytes;
62
- const text = chunk.toString("utf8").slice(0, remaining);
63
- stderr += text;
64
- errBytes += text.length;
181
+ const text = chunk.toString("utf8");
182
+ if (errBytes < MAX_OUTPUT_BYTES) {
183
+ const remaining = MAX_OUTPUT_BYTES - errBytes;
184
+ const trimmed = text.slice(0, remaining);
185
+ stderr += trimmed;
186
+ errBytes += trimmed.length;
187
+ }
188
+ if (onLive) {
189
+ stderrBuffer += text;
190
+ scheduleFlush();
191
+ }
65
192
  });
66
193
  child.on("error", (err) => {
67
194
  clearTimeout(timeoutHandle);
195
+ finalFlush();
68
196
  resolve({
69
197
  stdout,
70
198
  stderr: `${stderr}\nSpawn hatası: ${err.message}`,
@@ -76,6 +204,7 @@ function runShell(command, cwd, timeoutMs, signal) {
76
204
  clearTimeout(timeoutHandle);
77
205
  if (signal)
78
206
  signal.removeEventListener("abort", onAbort);
207
+ finalFlush();
79
208
  resolve({
80
209
  stdout,
81
210
  stderr,
@@ -90,7 +219,7 @@ export const bashTool = async (params, ctx) => {
90
219
  const command = (params.command || "");
91
220
  const rawCwd = (params.working_directory || ctx.cwd);
92
221
  const timeoutMs = Number.isInteger(params.timeout_ms)
93
- ? Math.min(DEFAULT_TIMEOUT_MS, Number(params.timeout_ms))
222
+ ? Math.min(600_000, Math.max(5_000, Number(params.timeout_ms)))
94
223
  : DEFAULT_TIMEOUT_MS;
95
224
  if (!command) {
96
225
  return {
@@ -100,7 +229,6 @@ export const bashTool = async (params, ctx) => {
100
229
  duration: Date.now() - start,
101
230
  };
102
231
  }
103
- // Command filter
104
232
  const filterResult = checkCommand(command);
105
233
  if (filterResult.verdict === "block") {
106
234
  return {
@@ -112,7 +240,22 @@ export const bashTool = async (params, ctx) => {
112
240
  duration: Date.now() - start,
113
241
  };
114
242
  }
115
- // Plan modda sadece dry-run
243
+ const interactiveCheck = detectInteractive(command);
244
+ if (!interactiveCheck.ok) {
245
+ return {
246
+ success: false,
247
+ output: "",
248
+ error: `${interactiveCheck.reason}\n\n` +
249
+ `Öneri:\n${interactiveCheck.suggestion}\n\n` +
250
+ `Lütfen non-interactive flag'lerle tekrar deneyin.`,
251
+ metadata: {
252
+ blocked_by: "interactive_detector",
253
+ suggestion: interactiveCheck.suggestion,
254
+ },
255
+ approvalState: 0,
256
+ duration: Date.now() - start,
257
+ };
258
+ }
116
259
  if (ctx.mode === "plan") {
117
260
  return {
118
261
  success: true,
@@ -122,7 +265,6 @@ export const bashTool = async (params, ctx) => {
122
265
  duration: Date.now() - start,
123
266
  };
124
267
  }
125
- // Working directory sandbox kontrolü
126
268
  const cwdCheck = checkPath(rawCwd, ctx.cwd, { mustExist: true });
127
269
  if (!cwdCheck.ok || !cwdCheck.realPath) {
128
270
  return {
@@ -132,7 +274,6 @@ export const bashTool = async (params, ctx) => {
132
274
  duration: Date.now() - start,
133
275
  };
134
276
  }
135
- // Permission akışı
136
277
  let approvalState = 2;
137
278
  const needsPrompt = ctx.mode === "default" ||
138
279
  ctx.mode === "accept_edits" ||
@@ -173,7 +314,19 @@ export const bashTool = async (params, ctx) => {
173
314
  }
174
315
  approvalState = 1;
175
316
  }
176
- const result = await runShell(command, cwdCheck.realPath, timeoutMs, ctx.signal);
317
+ const onLive = typeof ctx.onLiveOutput === "function"
318
+ ? (kind, chunk) => {
319
+ ctx.onLiveOutput({ toolName: "bash_execute", kind, chunk });
320
+ }
321
+ : null;
322
+ if (ctx.onLiveOutput) {
323
+ ctx.onLiveOutput({
324
+ toolName: "bash_execute",
325
+ kind: "status",
326
+ chunk: `$ ${command}`,
327
+ });
328
+ }
329
+ const result = await runShell(command, cwdCheck.realPath, timeoutMs, ctx.signal, onLive);
177
330
  const output = [
178
331
  result.stdout && `--- stdout ---\n${result.stdout}`,
179
332
  result.stderr && `--- stderr ---\n${result.stderr}`,
@@ -184,8 +337,10 @@ export const bashTool = async (params, ctx) => {
184
337
  return {
185
338
  success: false,
186
339
  output,
187
- error: `Komut zaman aşımına uğradı (${timeoutMs}ms)`,
188
- metadata: { exit_code: result.exitCode, timed_out: true },
340
+ error: `Komut zaman aşımına uğradı (${Math.floor(timeoutMs / 1000)}s)\n\n` +
341
+ `Uzun süren komutlar için timeout_ms parametresini artırabilirsiniz (maks 600000 = 10 dk).\n` +
342
+ `Veya komutu arka planda çalıştırın (& ile) ve durumunu ayrı bir komutla kontrol edin.`,
343
+ metadata: { exit_code: result.exitCode, timed_out: true, timeout_ms: timeoutMs },
189
344
  approvalState,
190
345
  duration: Date.now() - start,
191
346
  };
@@ -203,4 +358,3 @@ export const bashTool = async (params, ctx) => {
203
358
  duration: Date.now() - start,
204
359
  };
205
360
  };
206
- //# sourceMappingURL=bash.js.map
@@ -1,9 +1,3 @@
1
- /**
2
- * AIGENCY CLI — basit unified diff üretici.
3
- *
4
- * Dış bağımlılık (diff paketi) kullanmadan okunabilir bir +/- diff üretir.
5
- * Myers algoritması yerine satır bazlı basit farklı bulma — çoğu use case için yeterli.
6
- */
7
1
  export function simpleDiff(oldContent, newContent, maxLines = 40) {
8
2
  const oldLines = oldContent.split(/\r?\n/);
9
3
  const newLines = newContent.split(/\r?\n/);
@@ -53,4 +47,3 @@ export function summarizeDiff(oldContent, newContent) {
53
47
  }
54
48
  return { added, removed };
55
49
  }
56
- //# sourceMappingURL=diff.js.map
@@ -1,14 +1,7 @@
1
- /**
2
- * edit_file — mevcut dosyada old_string'i new_string ile değiştir.
3
- *
4
- * Kurallar (benzersiz edit):
5
- * - old_string tam olarak dosyada 1 kez geçmeli
6
- * - 0 veya 1'den fazla eşleşme varsa reddedilir
7
- * - Plan modda yasak, diğer modlarda permission prompt
8
- */
9
1
  import fs from "node:fs/promises";
10
2
  import { checkWritePath } from "../security/sandbox.js";
11
3
  import { simpleDiff, summarizeDiff } from "./diff.js";
4
+ import { captureCheckpoint } from "../agent/checkpoints.js";
12
5
  export const editFileTool = async (params, ctx) => {
13
6
  const start = Date.now();
14
7
  const rawPath = (params.path || params.filePath || "");
@@ -63,7 +56,6 @@ export const editFileTool = async (params, ctx) => {
63
56
  duration: Date.now() - start,
64
57
  };
65
58
  }
66
- // Mevcut içeriği oku
67
59
  let existing;
68
60
  try {
69
61
  existing = await fs.readFile(check.realPath, "utf8");
@@ -76,7 +68,6 @@ export const editFileTool = async (params, ctx) => {
76
68
  duration: Date.now() - start,
77
69
  };
78
70
  }
79
- // Benzersizlik kontrolü
80
71
  const firstIdx = existing.indexOf(oldString);
81
72
  if (firstIdx === -1) {
82
73
  return {
@@ -100,7 +91,6 @@ export const editFileTool = async (params, ctx) => {
100
91
  existing.slice(firstIdx + oldString.length);
101
92
  const diff = summarizeDiff(existing, updated);
102
93
  const previewLines = simpleDiff(existing, updated, 20);
103
- // Permission
104
94
  let approvalState = 2;
105
95
  if (ctx.mode === "default") {
106
96
  if (!ctx.requestPermission) {
@@ -139,6 +129,9 @@ export const editFileTool = async (params, ctx) => {
139
129
  approvalState = 1;
140
130
  }
141
131
  try {
132
+ if (ctx.sessionId && ctx.projectRoot) {
133
+ await captureCheckpoint(ctx.sessionId, check.realPath, "edit", ctx.projectRoot);
134
+ }
142
135
  await fs.writeFile(check.realPath, updated, "utf8");
143
136
  }
144
137
  catch (err) {
@@ -162,4 +155,3 @@ export const editFileTool = async (params, ctx) => {
162
155
  duration: Date.now() - start,
163
156
  };
164
157
  };
165
- //# sourceMappingURL=edit-file.js.map
@@ -1,12 +1,8 @@
1
- /**
2
- * list_files — dizin listeleme tool'u (yerel).
3
- */
4
1
  import fs from "node:fs/promises";
5
2
  import path from "node:path";
6
3
  import { checkPath } from "../security/sandbox.js";
7
4
  const MAX_ENTRIES = 500;
8
5
  const MAX_DEPTH = 4;
9
- // Varsayılan olarak atlanacak isimler (yasak segmentlerle aynı mantık)
10
6
  const SKIP_NAMES = new Set([
11
7
  ".git",
12
8
  "node_modules",
@@ -113,4 +109,3 @@ export const listFilesTool = async (params, ctx) => {
113
109
  duration: Date.now() - start,
114
110
  };
115
111
  };
116
- //# sourceMappingURL=list-files.js.map
@@ -0,0 +1,126 @@
1
+ import { saveMemoryEntry, readMemoryTopic, deleteMemoryEntry, loadMemorySnapshot, } from "../agent/memory.js";
2
+ const VALID_TYPES = new Set(["user", "feedback", "project", "reference"]);
3
+ export const saveMemoryToolHandler = async (params, ctx) => {
4
+ const start = Date.now();
5
+ const filename = String(params.filename || "").trim();
6
+ const name = String(params.name || "").trim();
7
+ const description = String(params.description || "").trim();
8
+ const type = String(params.type || "").trim();
9
+ const content = String(params.content || "").trim();
10
+ if (!filename || !name || !description || !type || !content) {
11
+ return {
12
+ success: false,
13
+ output: "",
14
+ error: "save_memory: filename, name, description, type ve content alanları zorunludur",
15
+ duration: Date.now() - start,
16
+ };
17
+ }
18
+ if (!VALID_TYPES.has(type)) {
19
+ return {
20
+ success: false,
21
+ output: "",
22
+ error: `save_memory: geçersiz tip '${type}' (user|feedback|project|reference olmalı)`,
23
+ duration: Date.now() - start,
24
+ };
25
+ }
26
+ const result = await saveMemoryEntry({ filename, name, description, type, content }, ctx.cwd);
27
+ if (!result.ok) {
28
+ return {
29
+ success: false,
30
+ output: "",
31
+ error: result.error,
32
+ duration: Date.now() - start,
33
+ };
34
+ }
35
+ return {
36
+ success: true,
37
+ output: `Memory kaydedildi: ${result.filename} (${type})`,
38
+ metadata: { filename: result.filename, type },
39
+ approvalState: 2,
40
+ duration: Date.now() - start,
41
+ };
42
+ };
43
+ export const readMemoryToolHandler = async (params, ctx) => {
44
+ const start = Date.now();
45
+ const filename = String(params.filename || "").trim();
46
+ if (!filename) {
47
+ return {
48
+ success: false,
49
+ output: "",
50
+ error: "read_memory: filename zorunlu",
51
+ duration: Date.now() - start,
52
+ };
53
+ }
54
+ const entry = await readMemoryTopic(filename, ctx.cwd);
55
+ if (!entry) {
56
+ return {
57
+ success: false,
58
+ output: "",
59
+ error: `read_memory: '${filename}' bulunamadı veya frontmatter eksik`,
60
+ duration: Date.now() - start,
61
+ };
62
+ }
63
+ const output = [
64
+ `# ${entry.frontmatter.name}`,
65
+ `Tip: ${entry.frontmatter.type}`,
66
+ `Açıklama: ${entry.frontmatter.description}`,
67
+ `Son güncelleme: ${entry.modifiedAt.toISOString()}`,
68
+ "",
69
+ "---",
70
+ "",
71
+ entry.body.trim(),
72
+ ].join("\n");
73
+ return {
74
+ success: true,
75
+ output,
76
+ metadata: {
77
+ filename: entry.filename,
78
+ type: entry.frontmatter.type,
79
+ sizeBytes: entry.sizeBytes,
80
+ },
81
+ approvalState: 2,
82
+ duration: Date.now() - start,
83
+ };
84
+ };
85
+ export const deleteMemoryToolHandler = async (params, ctx) => {
86
+ const start = Date.now();
87
+ const filename = String(params.filename || "").trim();
88
+ if (!filename) {
89
+ return {
90
+ success: false,
91
+ output: "",
92
+ error: "delete_memory: filename zorunlu",
93
+ duration: Date.now() - start,
94
+ };
95
+ }
96
+ try {
97
+ const deleted = await deleteMemoryEntry(filename, ctx.cwd);
98
+ if (!deleted) {
99
+ return {
100
+ success: false,
101
+ output: "",
102
+ error: `delete_memory: '${filename}' bulunamadı`,
103
+ duration: Date.now() - start,
104
+ };
105
+ }
106
+ return {
107
+ success: true,
108
+ output: `Memory silindi: ${filename}`,
109
+ metadata: { filename },
110
+ approvalState: 2,
111
+ duration: Date.now() - start,
112
+ };
113
+ }
114
+ catch (err) {
115
+ return {
116
+ success: false,
117
+ output: "",
118
+ error: `delete_memory hatası: ${err.message}`,
119
+ duration: Date.now() - start,
120
+ };
121
+ }
122
+ };
123
+ export async function listMemoryEntries(cwd = process.cwd()) {
124
+ const snapshot = await loadMemorySnapshot(cwd);
125
+ return snapshot.entries.map((e) => `${e.filename} [${e.frontmatter.type}] — ${e.frontmatter.description}`);
126
+ }
@@ -1,9 +1,6 @@
1
- /**
2
- * read_file — dosya okuma tool'u (yerel).
3
- */
4
1
  import fs from "node:fs/promises";
5
2
  import { checkPath } from "../security/sandbox.js";
6
- const MAX_BYTES = 512 * 1024; // 512 KB
3
+ const MAX_BYTES = 512 * 1024;
7
4
  const DEFAULT_LINE_LIMIT = 2000;
8
5
  export const readFileTool = async (params, ctx) => {
9
6
  const start = Date.now();
@@ -71,7 +68,6 @@ export const readFileTool = async (params, ctx) => {
71
68
  duration: Date.now() - start,
72
69
  };
73
70
  }
74
- // NULL byte → binary dosya
75
71
  if (content.includes("\u0000")) {
76
72
  return {
77
73
  success: false,
@@ -80,7 +76,6 @@ export const readFileTool = async (params, ctx) => {
80
76
  duration: Date.now() - start,
81
77
  };
82
78
  }
83
- // Satır aralığı uygula
84
79
  const lines = content.split(/\r?\n/);
85
80
  const startIdx = startLine && startLine > 0 ? startLine - 1 : 0;
86
81
  const endIdx = endLine && endLine > 0 ? Math.min(endLine, lines.length) : startIdx + DEFAULT_LINE_LIMIT;
@@ -104,4 +99,3 @@ export const readFileTool = async (params, ctx) => {
104
99
  duration: Date.now() - start,
105
100
  };
106
101
  };
107
- //# sourceMappingURL=read-file.js.map
@@ -1,16 +1,11 @@
1
- /**
2
- * AIGENCY CLI — Yerel tool registry.
3
- *
4
- * Sunucu tarafında `lib/agent/cli-tool-registry.ts` LLM'e şemaları sunar.
5
- * CLI burada tool'ları **yerel çalıştırır**. Sunucudan gelen cli_tool_dispatch
6
- * event'i bu registry üzerinden dispatch edilir.
7
- */
8
1
  import { readFileTool } from "./read-file.js";
9
2
  import { listFilesTool } from "./list-files.js";
10
3
  import { searchFilesTool } from "./search-files.js";
11
4
  import { writeFileTool } from "./write-file.js";
12
5
  import { editFileTool } from "./edit-file.js";
13
6
  import { bashTool } from "./bash.js";
7
+ import { saveMemoryToolHandler, readMemoryToolHandler, deleteMemoryToolHandler, } from "./memory-tools.js";
8
+ import { writeTasksHandler, readTasksHandler } from "./task-tools.js";
14
9
  const HANDLERS = {
15
10
  read_file: readFileTool,
16
11
  list_files: listFilesTool,
@@ -18,6 +13,11 @@ const HANDLERS = {
18
13
  write_file: writeFileTool,
19
14
  edit_file: editFileTool,
20
15
  bash_execute: bashTool,
16
+ save_memory: saveMemoryToolHandler,
17
+ read_memory: readMemoryToolHandler,
18
+ delete_memory: deleteMemoryToolHandler,
19
+ write_tasks: writeTasksHandler,
20
+ read_tasks: readTasksHandler,
21
21
  };
22
22
  export function hasLocalTool(name) {
23
23
  return name in HANDLERS;
@@ -38,7 +38,6 @@ export async function dispatchLocalTool(toolName, params, ctx) {
38
38
  }
39
39
  catch (err) {
40
40
  const message = err.message || "Bilinmeyen hata";
41
- // Path/username gibi sızıntıları temizle
42
41
  const safe = message.replace(/[A-Z]:\\[^\s"')]+/gi, "[gizli]").slice(0, 200);
43
42
  return {
44
43
  success: false,
@@ -51,4 +50,3 @@ export async function dispatchLocalTool(toolName, params, ctx) {
51
50
  export function listLocalTools() {
52
51
  return Object.keys(HANDLERS);
53
52
  }
54
- //# sourceMappingURL=registry.js.map
@@ -1,16 +1,9 @@
1
- /**
2
- * search_files — proje içi regex/literal arama (ripgrep benzeri).
3
- *
4
- * Not: Harici ripgrep kullanmak için exec yapmıyoruz (Bun compile'da bağımlı
5
- * olmak istemiyoruz); kendi basit arama fonksiyonumuzu yazıyoruz. Büyük
6
- * projelerde yavaş olabilir ama yazma/izin katmanı için yeterli.
7
- */
8
1
  import fs from "node:fs/promises";
9
2
  import path from "node:path";
10
3
  import { checkPath } from "../security/sandbox.js";
11
4
  const MAX_MATCHES = 200;
12
5
  const MAX_FILES_SCANNED = 2000;
13
- const MAX_FILE_SIZE = 512 * 1024; // 512 KB
6
+ const MAX_FILE_SIZE = 512 * 1024;
14
7
  const SKIP_NAMES = new Set([
15
8
  ".git",
16
9
  "node_modules",
@@ -25,7 +18,6 @@ const SKIP_NAMES = new Set([
25
18
  ".cache",
26
19
  ]);
27
20
  function globToRegex(glob) {
28
- // Çok basit glob → regex: *, **, ?
29
21
  const escaped = glob
30
22
  .replace(/[.+^${}()|[\]\\]/g, "\\$&")
31
23
  .replace(/\*\*/g, "::DOUBLE_STAR::")
@@ -121,7 +113,7 @@ export const searchFilesTool = async (params, ctx) => {
121
113
  continue;
122
114
  }
123
115
  if (content.includes("\u0000"))
124
- continue; // binary
116
+ continue;
125
117
  const lines = content.split(/\r?\n/);
126
118
  for (let i = 0; i < lines.length; i++) {
127
119
  if (matches.length >= MAX_MATCHES)
@@ -156,4 +148,3 @@ export const searchFilesTool = async (params, ctx) => {
156
148
  duration: Date.now() - start,
157
149
  };
158
150
  };
159
- //# sourceMappingURL=search-files.js.map