@aigencydev/cli 0.2.0 → 0.3.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.
Files changed (111) hide show
  1. package/README.md +234 -37
  2. package/dist/agent/checkpoints.js +147 -0
  3. package/dist/agent/chunker.js +1 -19
  4. package/dist/agent/history.js +0 -9
  5. package/dist/agent/instructions.js +94 -0
  6. package/dist/agent/loop.js +2 -34
  7. package/dist/agent/memory.js +197 -103
  8. package/dist/agent/session-store.js +160 -0
  9. package/dist/agent/task-list.js +102 -0
  10. package/dist/api-client/auth.js +0 -10
  11. package/dist/api-client/base.js +0 -16
  12. package/dist/api-client/stream.js +0 -25
  13. package/dist/api-client/updates.js +2 -9
  14. package/dist/api-client/usage.js +0 -4
  15. package/dist/auth/oauth.js +0 -31
  16. package/dist/auth/pkce.js +1 -9
  17. package/dist/auth/session.js +0 -16
  18. package/dist/auth/storage.js +1 -36
  19. package/dist/cli.js +8 -13
  20. package/dist/commands/chat.js +14 -19
  21. package/dist/commands/help.js +0 -4
  22. package/dist/commands/init.js +327 -30
  23. package/dist/commands/login.js +0 -30
  24. package/dist/commands/logout.js +0 -5
  25. package/dist/commands/update.js +0 -9
  26. package/dist/commands/usage.js +0 -10
  27. package/dist/config/bootstrap.js +52 -0
  28. package/dist/config/defaults.js +4 -15
  29. package/dist/config/hooks.js +1 -23
  30. package/dist/config/paths.js +95 -38
  31. package/dist/config/settings.js +0 -21
  32. package/dist/index.js +0 -11
  33. package/dist/security/command-filter.js +0 -35
  34. package/dist/security/sandbox.js +1 -39
  35. package/dist/security/sanitize.js +0 -21
  36. package/dist/tools/bash.js +49 -35
  37. package/dist/tools/diff.js +0 -7
  38. package/dist/tools/edit-file.js +4 -12
  39. package/dist/tools/list-files.js +0 -5
  40. package/dist/tools/memory-tools.js +126 -0
  41. package/dist/tools/read-file.js +1 -7
  42. package/dist/tools/registry.js +7 -9
  43. package/dist/tools/search-files.js +2 -11
  44. package/dist/tools/task-tools.js +74 -0
  45. package/dist/tools/types.js +0 -4
  46. package/dist/tools/write-file.js +5 -12
  47. package/dist/types/index.js +0 -7
  48. package/dist/ui/App.js +122 -39
  49. package/dist/ui/InputBar.js +0 -9
  50. package/dist/ui/MessageList.js +0 -9
  51. package/dist/ui/ModeIndicator.js +0 -11
  52. package/dist/ui/PermissionPrompt.js +0 -15
  53. package/dist/ui/StatusBar.js +0 -10
  54. package/dist/ui/theme.js +23 -61
  55. package/dist/utils/abort.js +0 -12
  56. package/dist/utils/errors.js +0 -7
  57. package/dist/utils/formatting.js +0 -8
  58. package/dist/utils/logger.js +107 -17
  59. package/dist/version.js +1 -8
  60. package/package.json +1 -1
  61. package/dist/agent/chunker.js.map +0 -1
  62. package/dist/agent/history.js.map +0 -1
  63. package/dist/agent/loop.js.map +0 -1
  64. package/dist/agent/memory.js.map +0 -1
  65. package/dist/api-client/auth.js.map +0 -1
  66. package/dist/api-client/base.js.map +0 -1
  67. package/dist/api-client/stream.js.map +0 -1
  68. package/dist/api-client/updates.js.map +0 -1
  69. package/dist/api-client/usage.js.map +0 -1
  70. package/dist/auth/oauth.js.map +0 -1
  71. package/dist/auth/pkce.js.map +0 -1
  72. package/dist/auth/session.js.map +0 -1
  73. package/dist/auth/storage.js.map +0 -1
  74. package/dist/cli.js.map +0 -1
  75. package/dist/commands/chat.js.map +0 -1
  76. package/dist/commands/help.js.map +0 -1
  77. package/dist/commands/init.js.map +0 -1
  78. package/dist/commands/login.js.map +0 -1
  79. package/dist/commands/logout.js.map +0 -1
  80. package/dist/commands/update.js.map +0 -1
  81. package/dist/commands/usage.js.map +0 -1
  82. package/dist/config/defaults.js.map +0 -1
  83. package/dist/config/hooks.js.map +0 -1
  84. package/dist/config/paths.js.map +0 -1
  85. package/dist/config/settings.js.map +0 -1
  86. package/dist/index.js.map +0 -1
  87. package/dist/security/command-filter.js.map +0 -1
  88. package/dist/security/sandbox.js.map +0 -1
  89. package/dist/security/sanitize.js.map +0 -1
  90. package/dist/tools/bash.js.map +0 -1
  91. package/dist/tools/diff.js.map +0 -1
  92. package/dist/tools/edit-file.js.map +0 -1
  93. package/dist/tools/list-files.js.map +0 -1
  94. package/dist/tools/read-file.js.map +0 -1
  95. package/dist/tools/registry.js.map +0 -1
  96. package/dist/tools/search-files.js.map +0 -1
  97. package/dist/tools/types.js.map +0 -1
  98. package/dist/tools/write-file.js.map +0 -1
  99. package/dist/types/index.js.map +0 -1
  100. package/dist/ui/App.js.map +0 -1
  101. package/dist/ui/InputBar.js.map +0 -1
  102. package/dist/ui/MessageList.js.map +0 -1
  103. package/dist/ui/ModeIndicator.js.map +0 -1
  104. package/dist/ui/PermissionPrompt.js.map +0 -1
  105. package/dist/ui/StatusBar.js.map +0 -1
  106. package/dist/ui/theme.js.map +0 -1
  107. package/dist/utils/abort.js.map +0 -1
  108. package/dist/utils/errors.js.map +0 -1
  109. package/dist/utils/formatting.js.map +0 -1
  110. package/dist/utils/logger.js.map +0 -1
  111. package/dist/version.js.map +0 -1
package/README.md CHANGED
@@ -1,83 +1,280 @@
1
1
  # AIGENCY CLI
2
2
 
3
3
  Terminalden yapay zeka destekli kod üretimi, dosya yönetimi ve proje otomasyonu.
4
+ AIGENCY hesabınla bağlanır, projende çalışır, kodu senin onayınla yazar.
5
+
6
+ ```
7
+ ┌──────────────────────────────────────────┐
8
+ │ ✦ AIGENCY CLI v0.3.0 │
9
+ │ ● default · AIGENCY Pro · my-app │
10
+ │ │
11
+ │ ▸ Sana nasıl yardımcı olabilirim? │
12
+ └──────────────────────────────────────────┘
13
+ ```
14
+
15
+ ---
4
16
 
5
17
  ## Kurulum
6
18
 
7
- **macOS / Linux**
19
+ **npm ile (önerilen)**
20
+ ```bash
21
+ npm install -g @aigencydev/cli
22
+ ```
23
+
24
+ **macOS / Linux — shell installer**
8
25
  ```bash
9
26
  curl -fsSL https://aigency.dev/cli/install.sh | bash
10
27
  ```
11
28
 
12
- **Windows (PowerShell)**
29
+ **Windows PowerShell**
13
30
  ```powershell
14
31
  irm https://aigency.dev/cli/install.ps1 | iex
15
32
  ```
16
33
 
17
- **npm (alternatif)**
18
- ```bash
19
- npm install -g @aigencydev/cli
20
- ```
34
+ > **Not:** Node.js 18.18 veya üzeri gerekir. `node --version` ile kontrol edebilirsin.
35
+
36
+ ---
21
37
 
22
- ## Kullanım
38
+ ## Hızlı Başlangıç
23
39
 
24
40
  ```bash
25
- # Hesabınıza bağlanın
41
+ # 1) Hesabına bağlan (tarayıcı açılır)
26
42
  aigency login
27
43
 
28
- # Mevcut dizinde .aigency/ proje klasörü oluşturun
44
+ # 2) Bir proje dizinine gir ve .aigency/ iskeletini oluştur
45
+ cd ~/projects/my-app
29
46
  aigency init
30
47
 
31
- # Aylık kullanımınızı görün
32
- aigency usage
48
+ # 3) Ajanla konuşmaya başla
49
+ aigency "bana bir Next.js CV sitesi oluştur, Apple tarzı"
33
50
 
34
- # Sürüm kontrolü
35
- aigency update
36
-
37
- # Yardım
38
- aigency help
51
+ # ya da interaktif modda
52
+ aigency
39
53
  ```
40
54
 
41
- ## Paketler
55
+ ---
56
+
57
+ ## Komutlar
58
+
59
+ | Komut | Açıklama |
60
+ |---|---|
61
+ | `aigency` | İnteraktif sohbet modu (varsayılan) |
62
+ | `aigency "<prompt>"` | Tek seferlik prompt çalıştır |
63
+ | `aigency login` | AIGENCY hesabına OAuth ile bağlan |
64
+ | `aigency logout` | Oturumu kapat, yerel token'ları sil |
65
+ | `aigency init` | Mevcut dizinde `.aigency/` yapısını kur |
66
+ | `aigency usage` | Aylık token kullanımını göster |
67
+ | `aigency update` | En son sürümü kontrol et |
68
+ | `aigency help` | Komut yardımı |
69
+ | `aigency --version` | Sürümü göster |
70
+
71
+ **Flag'ler:**
72
+ - `--mode <default\|plan\|accept_edits\|auto>` — başlangıç izin modu
73
+ - `--model <pro\|max>` — AIGENCY paket seviyesi
42
74
 
43
- | Paket | Fiyat | Aylık token |
44
- |---|---|---|
45
- | AIGENCY CLI Pro | 1.500 ₺/ay | 1.000.000 |
46
- | AIGENCY CLI Max | 3.000 ₺/ay | 5.000.000 + öncelikli kuyruk + Auto mode |
75
+ ---
47
76
 
48
- ## İzin Modları (Faz 4'te aktif)
77
+ ## İzin Modları
49
78
 
50
79
  | Mod | Davranış |
51
80
  |---|---|
52
- | `default` | Dosya okuma otomatik, yazma ve komut onay ister |
53
- | `plan` | Dry-run — hiçbir şey yazılmaz, sadece plan gösterilir |
54
- | `accept_edits` | Dosya yazma otomatik, komut hâlâ onay ister |
55
- | `auto` | Sınıflandırıcı destekli tam otomatik (sadece Max tier) |
81
+ | `default` | Dosya okuma otomatik, yazma ve komut için onay sorulur |
82
+ | `plan` | Dry-run — hiçbir şey yazılmaz, sadece yapılacakların planı gösterilir |
83
+ | `accept_edits` | Dosya yazma otomatik, shell komutları hâlâ onay ister |
84
+ | `auto` | Sınıflandırıcı destekli tam otomatik (yalnızca **Max** tier) |
85
+
86
+ Mod'u çalışırken değiştirmek için **Shift+Tab** bas.
87
+
88
+ ---
89
+
90
+ ## Kısayollar
91
+
92
+ | Tuş | İşlev |
93
+ |---|---|
94
+ | `Shift+Tab` | İzin modlarını döngüle (default → plan → accept_edits → auto) |
95
+ | `ESC` | Aktif ajan işlemini iptal et |
96
+ | `Ctrl+C` | Çalışıyorsa iptal, boştaysa çıkış |
97
+ | `/` | Slash komut başlat |
98
+
99
+ ---
100
+
101
+ ## Slash Komutları
102
+
103
+ | Komut | İşlev |
104
+ |---|---|
105
+ | `/help` | Komut listesi |
106
+ | `/clear` | Sohbet geçmişini ve onay cache'ini temizle |
107
+ | `/mode [default\|plan\|accept_edits\|auto]` | Modu değiştir veya göster |
108
+ | `/cost` | Bu oturumda kullanılan token sayısı |
109
+ | `/undo` | Son dosya düzenlemesini geri al (checkpoint'ten) |
110
+ | `/exit` veya `/quit` | Çıkış |
111
+
112
+ ---
113
+
114
+ ## Araçlar (Ajanın Kullanabildiği Tool'lar)
115
+
116
+ Ajan projenizde aşağıdaki işlemleri yapabilir (izin modunuza göre onay ister):
117
+
118
+ **Dosya sistemi**
119
+ - `read_file` — Dosya içeriği okur
120
+ - `list_files` — Dizin listeler (gitignore'a saygı duyar)
121
+ - `search_files` — Regex ile içerik arar
122
+ - `write_file` — Yeni dosya yazar veya tamamen değiştirir
123
+ - `edit_file` — Mevcut dosyada cerrahi değişiklik yapar
124
+
125
+ **Shell**
126
+ - `bash_execute` — İnteraktif olmayan shell komutu çalıştırır (5 dk timeout, canlı çıktı akışı)
127
+
128
+ **Hafıza (kalıcı, makineye özel)**
129
+ - `save_memory` — Önemli bilgiyi oturumlar arası sakla
130
+ - `read_memory` — Detay hafıza dosyasını oku
131
+ - `delete_memory` — Artık geçerli olmayan bilgiyi sil
132
+
133
+ **Görev planlama**
134
+ - `write_tasks` — Büyük görevleri adımlara böl, ilerlemeyi canlı göster
135
+ - `read_tasks` — Mevcut görev listesini oku
136
+
137
+ **Sandbox:** `.git/`, `.env*`, `~/.ssh/`, `node_modules/`, `.next/` gibi hassas yollar
138
+ otomatik reddedilir. `sudo`, `rm -rf /`, `curl | sh` gibi tehlikeli komutlar
139
+ engellenir.
140
+
141
+ ---
142
+
143
+ ## Proje Yapılandırması (`.aigency/`)
144
+
145
+ `aigency init` çalıştırdığında projenizde aşağıdaki yapı oluşturulur:
146
+
147
+ ```
148
+ <proje>/.aigency/
149
+ ├── AIGENCY.md # Proje talimatları (ajan her oturum başında okur)
150
+ ├── PROGRESS.md # İlerleme takibi (opsiyonel)
151
+ ├── settings.json # İzin modu, allow/deny listeleri
152
+ ├── settings.local.json # Kişisel override (gitignored)
153
+ ├── rules/ # Path-scoped kurallar
154
+ │ └── example.md
155
+ ├── hooks/ # PreToolUse/PostToolUse script'leri
156
+ │ ├── hooks.json
157
+ │ └── README.md
158
+ ├── logs/ # Günlük JSONL logları (gitignored)
159
+ └── .gitignore
160
+ ```
161
+
162
+ **AIGENCY.md** en önemli dosyadır — projenizin teknoloji yığını, kodlama kuralları,
163
+ stil tercihleri ve "dokunulmaması gereken yerler"i buraya yazın. Ajan her oturum
164
+ başında bu dosyayı okur ve yazdığı kod bunlarla hizalanır.
165
+
166
+ ---
167
+
168
+ ## Kalıcı Hafıza ve Oturum Verileri
169
+
170
+ AIGENCY CLI, **makineye özel** veriler için kullanıcının home dizininde ayrı
171
+ bir alan kullanır:
172
+
173
+ ```
174
+ ~/.aigency/
175
+ ├── cli.json # Auth metadata
176
+ ├── credentials.enc # AES-256-GCM şifreli token'lar
177
+ ├── settings.json # Kullanıcı seviyesi ayarlar
178
+ ├── AIGENCY.md # Tüm projelerde geçerli global talimatlar
179
+ ├── cli.log # Rotating log (5 MB × 3 yedek)
180
+ ├── cache/ # LLM response, hash cache
181
+ ├── temp/ # Oturum scratch alanı
182
+ └── projects/
183
+ └── <proje-hash>/ # Git remote veya yola göre hash
184
+ ├── memory/
185
+ │ ├── MEMORY.md # Hafıza index'i
186
+ │ ├── user_*.md # Kullanıcı hakkında
187
+ │ ├── feedback_*.md # Davranış kuralları
188
+ │ ├── project_*.md # Proje bağlamı
189
+ │ └── reference_*.md # Harici kaynak pointer'ları
190
+ ├── sessions/
191
+ │ └── <id>.jsonl # Oturum transkriptleri
192
+ └── checkpoints/ # Dosya edit snapshot'ları (undo için)
193
+ ```
194
+
195
+ Bu alan **git'e commit edilmez** ve senkronize de olmaz — her makinede ayrı.
196
+ `.aigency/` (proje klasörü) ise git'e eklenebilir, takımla paylaşılır.
197
+
198
+ ---
199
+
200
+ ## Paketler
201
+
202
+ | Paket | Fiyat | Aylık Token | Ek Özellikler |
203
+ |---|---|---|---|
204
+ | **AIGENCY CLI Pro** | 1.500 ₺/ay | 1.000.000 | Standart |
205
+ | **AIGENCY CLI Max** | 3.000 ₺/ay | 5.000.000 | Öncelikli kuyruk, Auto mode |
206
+
207
+ Paketleri [aigency.dev/developer/cli](https://aigency.dev/developer/cli) üzerinden
208
+ yönetebilir, kullanımınızı canlı izleyebilirsiniz.
209
+
210
+ ---
56
211
 
57
212
  ## Yapılandırma
58
213
 
59
214
  ### Ortam değişkenleri
60
215
 
61
- - `AIGENCY_CLI_API_URL` API sunucu URL'i (varsayılan `https://aigency.dev`)
62
- - `AIGENCY_CLI_DEBUG=1` — ayrıntılı debug log'ları
216
+ | Değişken | Açıklama |
217
+ |---|---|
218
+ | `AIGENCY_CLI_API_URL` | API sunucu adresi (varsayılan `https://aigency.dev`) |
219
+ | `AIGENCY_CLI_DEBUG` | `1` verilirse ayrıntılı debug log'lar |
63
220
 
64
- ### Dosyalar
221
+ ### `.aigency/settings.json` Örneği
65
222
 
66
- - `~/.aigency/config.json` — kullanıcı düzeyinde varsayılan ayarlar
67
- - `~/.aigency/credentials.enc` — şifrelenmiş oturum token'ları (AES-256-GCM)
68
- - `<proje>/.aigency/settings.json` — proje düzeyinde ayar override
223
+ ```json
224
+ {
225
+ "permissions": {
226
+ "defaultMode": "default",
227
+ "allow": [
228
+ "Read(**/*)",
229
+ "Bash(npm run *)",
230
+ "Bash(git status)"
231
+ ],
232
+ "ask": [
233
+ "Write(**/*)",
234
+ "Edit(**/*)",
235
+ "Bash(*)"
236
+ ],
237
+ "deny": [
238
+ "Read(.env)",
239
+ "Write(.git/**)",
240
+ "Bash(rm -rf *)",
241
+ "Bash(sudo *)"
242
+ ]
243
+ },
244
+ "memory": {
245
+ "enabled": true
246
+ },
247
+ "hooks": {
248
+ "enabled": false
249
+ }
250
+ }
251
+ ```
252
+
253
+ ---
69
254
 
70
- ## Geliştirme
255
+ ## Geliştirme (Contributing)
71
256
 
72
257
  ```bash
73
- cd aigency-cli
258
+ git clone https://github.com/aigencydev/cli.git
259
+ cd cli
74
260
  npm install
261
+
75
262
  npm run dev -- help # tsx ile direkt çalıştır
76
- npm run typecheck # tip kontrolü
263
+ npm run typecheck # TypeScript tip kontrolü
264
+ npm run test # Vitest
77
265
  npm run build # dist/ üret
78
- node dist/index.js help # derlenmiş halini çalıştır
79
266
  ```
80
267
 
268
+ ---
269
+
270
+ ## Destek
271
+
272
+ - **Web**: [aigency.dev/developer/cli](https://aigency.dev/developer/cli)
273
+ - **Tanıtım**: [aigency.dev/forge](https://aigency.dev/forge)
274
+ - **Sorun / öneri**: [aigency.dev/contact](https://aigency.dev/contact)
275
+
276
+ ---
277
+
81
278
  ## Lisans
82
279
 
83
- Özel — AIGENCY.
280
+ Özel — AIGENCY. Tüm hakları saklıdır.
@@ -0,0 +1,147 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import crypto from "node:crypto";
4
+ import { getCheckpointDir } from "../config/paths.js";
5
+ import { log } from "../utils/logger.js";
6
+ const MAX_CHECKPOINT_BYTES = 2 * 1024 * 1024;
7
+ export async function captureCheckpoint(sessionId, absPath, operation, projectRoot) {
8
+ try {
9
+ let beforeContent = "";
10
+ let existed = false;
11
+ let size = 0;
12
+ try {
13
+ const stat = await fs.stat(absPath);
14
+ if (stat.isFile()) {
15
+ size = stat.size;
16
+ if (size > MAX_CHECKPOINT_BYTES) {
17
+ log.debug(`checkpoint: ${absPath} çok büyük (${size}b), snapshot atlandı`);
18
+ return null;
19
+ }
20
+ beforeContent = await fs.readFile(absPath, "utf8");
21
+ existed = true;
22
+ }
23
+ }
24
+ catch {
25
+ }
26
+ const relPath = path.relative(projectRoot, absPath) || path.basename(absPath);
27
+ const checkpoint = {
28
+ relPath,
29
+ absPath,
30
+ ts: new Date().toISOString(),
31
+ operation,
32
+ beforeContent,
33
+ existed,
34
+ };
35
+ const pathHash = crypto
36
+ .createHash("sha256")
37
+ .update(absPath)
38
+ .digest("hex")
39
+ .slice(0, 12);
40
+ const ts = Date.now();
41
+ const snapshotFile = path.join(getCheckpointDir(sessionId, projectRoot), `${pathHash}-${ts}.snapshot`);
42
+ await fs.mkdir(path.dirname(snapshotFile), { recursive: true });
43
+ await fs.writeFile(snapshotFile, JSON.stringify(checkpoint), "utf8");
44
+ return {
45
+ relPath,
46
+ ts: checkpoint.ts,
47
+ operation,
48
+ existed,
49
+ snapshotFile,
50
+ };
51
+ }
52
+ catch (err) {
53
+ log.debug(`checkpoint hatası: ${err.message}`);
54
+ return null;
55
+ }
56
+ }
57
+ export async function findLatestCheckpoint(sessionId, projectRoot) {
58
+ const dir = getCheckpointDir(sessionId, projectRoot);
59
+ let entries;
60
+ try {
61
+ entries = await fs.readdir(dir);
62
+ }
63
+ catch {
64
+ return null;
65
+ }
66
+ const files = entries.filter((f) => f.endsWith(".snapshot"));
67
+ if (files.length === 0)
68
+ return null;
69
+ let latest = null;
70
+ for (const file of files) {
71
+ const match = /-(\d+)\.snapshot$/.exec(file);
72
+ if (!match)
73
+ continue;
74
+ const ts = parseInt(match[1], 10);
75
+ if (!latest || ts > latest.ts) {
76
+ latest = { file, ts };
77
+ }
78
+ }
79
+ if (!latest)
80
+ return null;
81
+ try {
82
+ const raw = await fs.readFile(path.join(dir, latest.file), "utf8");
83
+ return JSON.parse(raw);
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ }
89
+ export async function restoreCheckpoint(checkpoint) {
90
+ try {
91
+ if (checkpoint.existed) {
92
+ await fs.mkdir(path.dirname(checkpoint.absPath), { recursive: true });
93
+ await fs.writeFile(checkpoint.absPath, checkpoint.beforeContent, "utf8");
94
+ return {
95
+ ok: true,
96
+ message: `${checkpoint.relPath} önceki haline geri döndürüldü`,
97
+ };
98
+ }
99
+ else {
100
+ try {
101
+ await fs.unlink(checkpoint.absPath);
102
+ }
103
+ catch {
104
+ }
105
+ return {
106
+ ok: true,
107
+ message: `${checkpoint.relPath} silindi (yeni oluşturulmuştu)`,
108
+ };
109
+ }
110
+ }
111
+ catch (err) {
112
+ return {
113
+ ok: false,
114
+ error: `Geri alma hatası: ${err.message}`,
115
+ };
116
+ }
117
+ }
118
+ export async function listCheckpoints(sessionId, projectRoot) {
119
+ const dir = getCheckpointDir(sessionId, projectRoot);
120
+ let entries;
121
+ try {
122
+ entries = await fs.readdir(dir);
123
+ }
124
+ catch {
125
+ return [];
126
+ }
127
+ const metadata = [];
128
+ for (const file of entries) {
129
+ if (!file.endsWith(".snapshot"))
130
+ continue;
131
+ try {
132
+ const raw = await fs.readFile(path.join(dir, file), "utf8");
133
+ const cp = JSON.parse(raw);
134
+ metadata.push({
135
+ relPath: cp.relPath,
136
+ ts: cp.ts,
137
+ operation: cp.operation,
138
+ existed: cp.existed,
139
+ snapshotFile: path.join(dir, file),
140
+ });
141
+ }
142
+ catch {
143
+ continue;
144
+ }
145
+ }
146
+ return metadata.sort((a, b) => (a.ts > b.ts ? -1 : 1));
147
+ }
@@ -1,25 +1,9 @@
1
- /**
2
- * AIGENCY CLI — kullanıcı prompt'u ve history için basit chunker.
3
- *
4
- * Faz 4 scope'u: basit token budget kontrolü + history trim.
5
- * Faz 5'te gelişmiş chunked streaming (proje dosyalarını parçalara bölüp
6
- * ardışık stream istekleriyle göndermek) eklenecek.
7
- *
8
- * Şu an:
9
- * - Toplam token (history + prompt) tahmin et
10
- * - Budget üstü ise en eski mesajları kırp
11
- * - Kalan budget prompt + 20% response için yeterli değilse uyar
12
- */
13
- /** Basit token tahmini — 1 token ≈ 4 karakter */
14
1
  export function approxTokens(text) {
15
2
  return Math.ceil(text.length / 4);
16
3
  }
17
- const DEFAULT_MAX_CONTEXT = 120_000; // Güvenli sınır — çoğu model destekler
4
+ const DEFAULT_MAX_CONTEXT = 120_000;
18
5
  const DEFAULT_RESERVE_RESPONSE = 8_000;
19
6
  const DEFAULT_RESERVE_SYSTEM = 4_000;
20
- /**
21
- * History'yi budget'a sığdırır — eskiden başlayarak kırpar.
22
- */
23
7
  export function prepareChunk(prompt, history, options = {}) {
24
8
  const maxContext = options.maxContextTokens || DEFAULT_MAX_CONTEXT;
25
9
  const reserveResponse = options.reserveForResponse || DEFAULT_RESERVE_RESPONSE;
@@ -34,7 +18,6 @@ export function prepareChunk(prompt, history, options = {}) {
34
18
  warning: `Prompt tek başına ${promptTokens} token — context limiti (${available}) aşılıyor. Komutunuzu kısaltın.`,
35
19
  };
36
20
  }
37
- // Sondan başa doğru ekle (son mesajlar daha önemli)
38
21
  const reversed = [...history].reverse();
39
22
  const selected = [];
40
23
  let total = promptTokens;
@@ -56,4 +39,3 @@ export function prepareChunk(prompt, history, options = {}) {
56
39
  warning,
57
40
  };
58
41
  }
59
- //# sourceMappingURL=chunker.js.map
@@ -1,16 +1,9 @@
1
- /**
2
- * AIGENCY CLI — sohbet geçmişi ring buffer.
3
- *
4
- * Kullanıcı + asistan mesajlarını tutar. /clear komutu sıfırlar.
5
- * Chunked streaming sırasında bu history stream endpoint'ine gönderilir.
6
- */
7
1
  const MAX_HISTORY = 40;
8
2
  export class ChatHistory {
9
3
  messages = [];
10
4
  push(msg) {
11
5
  const approxTokens = msg.approxTokens ?? Math.ceil((msg.content || "").length / 4);
12
6
  this.messages.push({ ...msg, approxTokens });
13
- // Ring buffer — en eski mesajları kırp
14
7
  while (this.messages.length > MAX_HISTORY) {
15
8
  this.messages.shift();
16
9
  }
@@ -24,7 +17,6 @@ export class ChatHistory {
24
17
  length() {
25
18
  return this.messages.length;
26
19
  }
27
- /** Son N mesajı döner — stream endpoint'ine bunu gönderiyoruz */
28
20
  tail(n) {
29
21
  return this.messages.slice(-n);
30
22
  }
@@ -32,4 +24,3 @@ export class ChatHistory {
32
24
  return this.messages.reduce((acc, m) => acc + (m.approxTokens || 0), 0);
33
25
  }
34
26
  }
35
- //# sourceMappingURL=history.js.map
@@ -0,0 +1,94 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { getUserInstructionsFile, getProjectInstructionsFile, getProjectAigencyDir, } from "../config/paths.js";
4
+ import { log } from "../utils/logger.js";
5
+ const MAX_PER_FILE = 32 * 1024;
6
+ const MAX_TOTAL = 96 * 1024;
7
+ const MAX_WALK_DEPTH = 10;
8
+ export async function loadInstructions(projectRoot, cwd = process.cwd()) {
9
+ const sources = [];
10
+ let totalBytes = 0;
11
+ const tryAdd = async (label, filePath) => {
12
+ if (totalBytes >= MAX_TOTAL)
13
+ return;
14
+ const content = await readFileIfExists(filePath);
15
+ if (!content)
16
+ return;
17
+ const trimmed = content.slice(0, MAX_PER_FILE);
18
+ const remaining = MAX_TOTAL - totalBytes;
19
+ const finalContent = trimmed.slice(0, remaining);
20
+ sources.push({
21
+ label,
22
+ path: filePath,
23
+ content: finalContent,
24
+ sizeBytes: finalContent.length,
25
+ });
26
+ totalBytes += finalContent.length;
27
+ };
28
+ await tryAdd("global", getUserInstructionsFile());
29
+ await tryAdd("project", getProjectInstructionsFile(projectRoot));
30
+ await tryAdd("local", path.join(getProjectAigencyDir(projectRoot), "AIGENCY.local.md"));
31
+ const rootInstructions = path.join(projectRoot, "AIGENCY.md");
32
+ if (rootInstructions !== getProjectInstructionsFile(projectRoot)) {
33
+ await tryAdd("project-root", rootInstructions);
34
+ }
35
+ if (isInside(cwd, projectRoot) && cwd !== projectRoot) {
36
+ let current = path.resolve(cwd);
37
+ const root = path.resolve(projectRoot);
38
+ let depth = 0;
39
+ while (current !== root && depth < MAX_WALK_DEPTH) {
40
+ const local = path.join(current, ".aigency", "AIGENCY.md");
41
+ const bare = path.join(current, "AIGENCY.md");
42
+ await tryAdd(`cwd:${path.relative(root, current)}`, local);
43
+ await tryAdd(`cwd-root:${path.relative(root, current)}`, bare);
44
+ const parent = path.dirname(current);
45
+ if (parent === current)
46
+ break;
47
+ current = parent;
48
+ depth++;
49
+ }
50
+ }
51
+ return {
52
+ sources,
53
+ totalBytes,
54
+ combinedText: buildCombinedText(sources),
55
+ };
56
+ }
57
+ async function readFileIfExists(p) {
58
+ try {
59
+ const stat = await fs.stat(p);
60
+ if (!stat.isFile())
61
+ return null;
62
+ const raw = await fs.readFile(p, "utf8");
63
+ return raw.includes("\u0000") ? null : raw;
64
+ }
65
+ catch (err) {
66
+ const code = err?.code;
67
+ if (code && code !== "ENOENT") {
68
+ log.debug(`AIGENCY.md okuma hatası: ${err.message}`);
69
+ }
70
+ return null;
71
+ }
72
+ }
73
+ function isInside(child, parent) {
74
+ const rel = path.relative(path.resolve(parent), path.resolve(child));
75
+ return !rel.startsWith("..") && !path.isAbsolute(rel);
76
+ }
77
+ function buildCombinedText(sources) {
78
+ if (sources.length === 0)
79
+ return "";
80
+ const parts = [
81
+ "## Kullanıcı Talimatları (AIGENCY.md)",
82
+ "Projede geçerli olan ve her oturumda zorunlu uygulanan talimatlar aşağıdadır.",
83
+ "",
84
+ ];
85
+ for (const src of sources) {
86
+ parts.push(`### Kaynak: ${src.label}`);
87
+ parts.push("```markdown");
88
+ parts.push(src.content.trim());
89
+ parts.push("```");
90
+ parts.push("");
91
+ }
92
+ parts.push("Yukarıdaki talimatlar SİSTEM KURALLARINDAN sonra, kullanıcı mesajından ÖNCE geçerlidir.", "Birden fazla kaynak çelişirse: lokal (kişisel) > proje > global sırasıyla öncelik ver.");
93
+ return parts.join("\n");
94
+ }