@kahinmcp/kahin 0.3.9 → 0.3.10
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/CHANGELOG.md +56 -2
- package/README.md +25 -7
- package/bin/kahin.mjs +20 -3
- package/bin/setup.mjs +74 -11
- package/docs/juggler-ai-native.md +83 -6
- package/lib/kahin-0.3.10-py3-none-any.whl +0 -0
- package/package.json +2 -2
- package/lib/kahin-0.3.8-py3-none-any.whl +0 -0
- package/lib/kahin-0.3.9-py3-none-any.whl +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,11 +2,64 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
-
## [0.3.
|
|
6
|
-
|
|
5
|
+
## [0.3.10] — 2026-08-09
|
|
6
|
+
|
|
7
|
+
- fix(harness): align lifecycle tests and screenshot measure with grace-window runtime
|
|
8
|
+
- fix(stealth): disable Camoufox humanize mouse trajectory (drops acks, wedges input)
|
|
9
|
+
- fix(release): retry npm pack verification after publish
|
|
10
|
+
- chore: prepare v0.3.9
|
|
11
|
+
- chore: refresh packaged kahin wheel
|
|
12
|
+
- fix: harden single-engine crawler runtime
|
|
13
|
+
- fix: preserve crawler rotation state
|
|
14
|
+
- feat: add single-engine crawler rotation
|
|
15
|
+
- docs: define crawler identity rotation contract
|
|
16
|
+
- fix: harden Kahin browser runtime
|
|
7
17
|
- update
|
|
8
18
|
- ci(release): tolerate npm registry propagation
|
|
9
19
|
|
|
20
|
+
## [0.3.9] — 2026-08-09
|
|
21
|
+
|
|
22
|
+
### Eklenen
|
|
23
|
+
- `kahin_crawl_start` / `kahin_crawl_status` / `kahin_crawl_results` /
|
|
24
|
+
`kahin_crawl_pause` / `kahin_crawl_resume` / `kahin_crawl_stop` eklendi:
|
|
25
|
+
tek aktif Camoufox/Mirage motoru ve tek mevcut sekme üzerinde çalışan,
|
|
26
|
+
bounded kuyruk/sonuç günlüğü ve cursor destekli crawler yüzeyi.
|
|
27
|
+
- Crawler; sayfa, derinlik, süre ve gecikme bütçelerini sınırlar, `Retry-After`
|
|
28
|
+
ile rate-limit durumunda bounded backoff uygular ve otomatik identity
|
|
29
|
+
rotasyonunu aynı browser/sekme yaşam döngüsü içinde yürütür.
|
|
30
|
+
|
|
31
|
+
### Düzeltilen
|
|
32
|
+
- Aktif motor yeniden kullanılmadan tekrar browser açılması, degraded health
|
|
33
|
+
durumunda canlı context'in gereksiz değiştirilmesi ve crawler sırasında
|
|
34
|
+
sekmenin kaybolması engellendi.
|
|
35
|
+
- Sidecar stdin yazımları ve sayfa işlemleri bounded hale getirildi; engine
|
|
36
|
+
çökmesi sonrası URL yeniden kuyruğa alınarak aynı crawler işi kontrollü
|
|
37
|
+
recovery ile sürdürülebilir hale geldi.
|
|
38
|
+
- Humanized mouse trajectory artık Juggler'ın tamamlamadığı aynı-koordinat
|
|
39
|
+
no-op dispatch'ini göndermiyor; gerçek hareket adımı korunuyor.
|
|
40
|
+
- CAPTCHA ve erişim engeli bypass edilmiyor: crawler challenge'ı açıkça
|
|
41
|
+
`paused` durumuna geçiriyor ve ajan müdahalesi için aynı işi koruyor.
|
|
42
|
+
- Her rotation gerçek per-launch fingerprint değişimiyle doğrulanıyor;
|
|
43
|
+
proxy/geo ayarları ve kayıtlı identity kullanımı yeniden başlatma/rotasyon
|
|
44
|
+
sonrasında korunuyor.
|
|
45
|
+
- Proxy ile başlatma için Camoufox'un `geoip` extra'sı paket bağımlılığına
|
|
46
|
+
alındı; temiz kurulumlar artık native proxy/geo ayarını eksik modül yüzünden
|
|
47
|
+
başarısız bırakmıyor. GeoIP endpoint'i erişilemezse proxy korunarak
|
|
48
|
+
proxy-only launch fallback'i uygulanıyor.
|
|
49
|
+
- npm launcher wheel install marker'ı ve Camoufox hazırlığı bounded komut
|
|
50
|
+
süreleriyle tekrar kurulumları güvenli ve hızlı hale getiriyor.
|
|
51
|
+
|
|
52
|
+
### Gerçek doğrulama
|
|
53
|
+
- Paketlenmiş stdio MCP ile 146 tool ve 2 resource list/read doğrulandı.
|
|
54
|
+
- Gerçek crawler akışında tek engine PID ve tek sekme ile 4 sayfa başarıyla
|
|
55
|
+
işlendi, 4 rotation gerçekleşti; rate-limit ve CAPTCHA challenge durumları
|
|
56
|
+
tekrar çağrılarda tutarlı biçimde korundu.
|
|
57
|
+
- Gerçek engine kill sonrası crawler 1 recovery attempt ile 5 başarılı sayfayı
|
|
58
|
+
tamamladı; ayrı identity probe'unda her rotation fingerprint hash'i değişti.
|
|
59
|
+
- Dış web sayfasında stealth audit `14/14`, DOM snapshot/event reset-dropped,
|
|
60
|
+
accessibility tree ve `browser_stop` sonrası parent MCP transport bağlantısı
|
|
61
|
+
doğrulandı.
|
|
62
|
+
|
|
10
63
|
## [0.3.8] — 2026-08-08
|
|
11
64
|
|
|
12
65
|
### Eklenen
|
|
@@ -311,3 +364,4 @@ Tüm önemli değişiklikler bu dosyada tutulur. Format: [Keep a Changelog](http
|
|
|
311
364
|
[0.3.7]: https://gitlab.com/void0x14/kahin-mcp/-/compare/v0.3.6...v0.3.7
|
|
312
365
|
[0.3.8]: https://gitlab.com/void0x14/kahin-mcp/-/compare/v0.3.7...v0.3.8
|
|
313
366
|
[0.3.9]: https://gitlab.com/void0x14/kahin-mcp/-/compare/v0.3.8...v0.3.9
|
|
367
|
+
[0.3.10]: https://gitlab.com/void0x14/kahin-mcp/-/compare/v0.3.9...v0.3.10
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ AI modeller Chrome'un içine girip sayfa gezip kod çalıştırabilir ama CDP'yi
|
|
|
16
16
|
|
|
17
17
|
56 domain, 667 komut, 237 event, 609 type — Chrome 148 protokolü gömülü.
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## 146 Tool · 5 Kategori Ailesi · 2 Engine
|
|
20
20
|
|
|
21
21
|
Tool'lar engine-ayrımlı kategori dosyalarında (`kahin/tools/`): paylaşılan çekirdek + Obscura + Camoufox aileleri.
|
|
22
22
|
|
|
@@ -29,10 +29,11 @@ Tool'lar engine-ayrımlı kategori dosyalarında (`kahin/tools/`): paylaşılan
|
|
|
29
29
|
| DEJA_VU — Debug | CDP event geçmişi, network istekleri, console mesajları | 4 |
|
|
30
30
|
| PROPHECY — Pattern DB | Kullanım desenlerini öğren, sorgula, öner | 5 |
|
|
31
31
|
| HEALER | Hata istatistikleri | 1 |
|
|
32
|
-
| MIRAGE — Camoufox Native (
|
|
32
|
+
| MIRAGE — Camoufox Native (104) | Juggler protokolü üstünde gerçek-zamanlı DOM stream, DOM, Reliability, Input, PageEx, Tab, Network, Storage, Emulation, Dialog/Download/Worker/WS, Upload, Screencast, Accessibility, Engine sağlığı/istatistik, Agent-native snapshot/form/state/identity/status/challenge, Stealth audit/insansı girdi/identity rotasyonu/proxy-geo | 104 |
|
|
33
|
+
| ORBIT — Long Crawler (6) | Tek Mirage browser/tab üzerinde bounded background crawl, sonuç cursor'ı, rate-limit backoff, challenge pause/resume, rotation ve cancel | 6 |
|
|
33
34
|
| OBSCURA — Ayrı kategori | Obscura'ya özel tool'lar (hazırlanıyor) | 0 |
|
|
34
35
|
|
|
35
|
-
**Toplam:
|
|
36
|
+
**Toplam: 146 tool.**
|
|
36
37
|
|
|
37
38
|
## Bir satırda özet
|
|
38
39
|
|
|
@@ -104,14 +105,17 @@ Camoufox (Juggler native) ile:
|
|
|
104
105
|
→ kahin_mirage_query("#btn", frame_id="subframe-...") # iframe içi erişim
|
|
105
106
|
→ kahin_mirage_cookie_set/get/clear → kahin_mirage_storage_local_get
|
|
106
107
|
→ kahin_mirage_set_user_agent / set_viewport / set_geolocation
|
|
107
|
-
→ kahin_mirage_set_file_chooser_intercept(true)
|
|
108
|
+
→ kahin_mirage_set_file_chooser_intercept(true)
|
|
109
|
+
→ (eşzamanlı) kahin_mirage_upload_files(["/abs/path"]) + kahin_mirage_click("input[type=file]")
|
|
108
110
|
→ kahin_mirage_screencast_start → kahin_mirage_screencast_frame (base64 JPEG)
|
|
109
111
|
→ kahin_mirage_accessibility_tree → kahin_engine_health → kahin_engine_stats
|
|
110
112
|
→ kahin_mirage_dom_start → kahin_mirage_dom_snapshot → kahin_mirage_dom_events
|
|
111
113
|
→ kahin_mirage_dom_action (snapshot'tan alınan canlı nodeId ile)
|
|
112
114
|
→ kahin_mirage_snapshot (ref'li ajan görünümü) → kahin_mirage_fill_form
|
|
113
115
|
→ kahin_mirage_state_save/load → kahin_identity_new/save/list/delete/report
|
|
114
|
-
→ kahin_agent_status (agent döngüsü özeti)
|
|
116
|
+
→ kahin_agent_status (agent döngüsü özeti) → kahin_challenge_status (crawl öncesi)
|
|
117
|
+
→ kahin_crawl_start(seeds=[...]) → kahin_crawl_status → kahin_crawl_results(cursor=...)
|
|
118
|
+
→ kahin_crawl_pause/resume/stop
|
|
115
119
|
```
|
|
116
120
|
|
|
117
121
|
`kahin_browser_start` tek bir Camoufox/sidecar süreci açar. İlk sayfa işlemi
|
|
@@ -120,6 +124,20 @@ bu sekmeyi yeniden kullanır. Ayrı bir sayfa gerektiğinde yeni tarayıcı baş
|
|
|
120
124
|
yerine `kahin_mirage_tab_new` ve `kahin_mirage_tab_switch` kullanın. Camoufox
|
|
121
125
|
aktifken `kahin_execute_cdp` ve diğer CDP araçları, eşdeğer Juggler/Mirage
|
|
122
126
|
çağrısına otomatik yönlendirilir ve CDP biçimli sonuç döndürür.
|
|
127
|
+
Makine genelinde aktif browser slot'u lock ile korunur; ikinci bağımsız MCP
|
|
128
|
+
süreci ikinci browser açmak yerine owner bilgisini içeren `engine_process_conflict`
|
|
129
|
+
döndürür. Native navigation hedefi bounded response timeout'a takılırsa Kahin
|
|
130
|
+
aynı browser/context içinde yalnızca hedef tab'ı yenileyebilir; başarılı recovery
|
|
131
|
+
`target_recovered: true` olarak raporlanır ve browser PID'si değişmez.
|
|
132
|
+
|
|
133
|
+
Uzun süreli yetkili crawl için `kahin_crawl_start` background job başlatır ve
|
|
134
|
+
MCP çağrısını açık tutmaz. Job aynı Camoufox browser'ı ve crawler tab'ını yeniden
|
|
135
|
+
kullanır; varsayılan rotation 20 başarılı sayfa veya 15 dakikadır. Her rotation
|
|
136
|
+
sayfa ledger'a yazıldıktan sonra gerçekleşir ve yeni BrowserForge fingerprint'i
|
|
137
|
+
gerçek bir Camoufox restart'ında üretilir. `kahin_crawl_results` bounded cursor
|
|
138
|
+
ile sonuçları parça parça verir. 429/503 için Retry-After ve capped backoff
|
|
139
|
+
uygulanır; CAPTCHA veya access-denied görülürse job pause olur. Kahin challenge
|
|
140
|
+
bypass veya otomatik CAPTCHA çözümü yapmaz.
|
|
123
141
|
|
|
124
142
|
Tam liste için: [AGENTS.md](AGENTS.md). Juggler'ın ajan sözleşmesi ve gerçek-zamanlı
|
|
125
143
|
DOM akışı için [AI-native Juggler kılavuzuna](docs/juggler-ai-native.md) bakın.
|
|
@@ -161,7 +179,7 @@ Kahin'de hata loglama ve kendini onarma sistemi gömülüdür:
|
|
|
161
179
|
|
|
162
180
|
```
|
|
163
181
|
oracle.py → MCP server (bootstrap: mcp instance + engine lifecycle + main)
|
|
164
|
-
tools/ →
|
|
182
|
+
tools/ → 140 tool, engine-ayrımlı kategori dosyaları
|
|
165
183
|
_common.py → capability routing, _safe_cdp, _require_engine, _auto_learn
|
|
166
184
|
the_twins/capabilities → motor-yetenek sözleşmesi ve Mirage yükseltme matrisi
|
|
167
185
|
grimoire/seraph/prophecy/healer → CDP bilgi + doğrulama + pattern (paylaşılan)
|
|
@@ -190,7 +208,7 @@ camoufox-harness/ → Zig sidecar (Juggler protocol, vendor binary gömül
|
|
|
190
208
|
- [x] **Tek tık kurulum** — `pnpm add -g @kahinmcp/kahin`, sonra `kahin` (ilk çalıştırmada Python ortamını otomatik kurar)
|
|
191
209
|
- [ ] **Zero-dependency** hedefi (Go/Rust portu)
|
|
192
210
|
- [ ] **LSP modu** — kod içinde hata yakalama, AI'a yanlışını yüzüne vurma
|
|
193
|
-
- [x] **Tool sayısı
|
|
211
|
+
- [x] **Tool sayısı 140** — Camoufox Juggler-native 104 tool (gerçek-zamanlı DOM stream, DOM, Reliability, Input, Network, Storage, Emulation, Dialog, Tab, Worker/WS, Upload, Screencast, Accessibility, Engine sağlığı/istatistik, Agent-native snapshot/form/state/identity/status, Stealth audit/humanized input/identity pins/proxy geo) + paylaşılan 36 çekirdek
|
|
194
212
|
- [x] **Faz 4 performans yüzeyi** — non-blocking Zig sidecar (N=20 probe: paralel duvar 56.89 → 8.71 ms, ratio 1.314 → 3.281), `kahin_engine_stats` (monotonic uptime + per-tool rollup, top_slow ≤ 10) ve identity başına bounded prewarm metadata (launch asla atlanmaz; dürüst reuse kaydı)
|
|
195
213
|
- [ ] **Obscura ayrı tool'ları** — CDP-yeteneklerine özel pilot_obscura/trainman_obscura/dejavu_obscura kategorilerini doldur
|
|
196
214
|
|
package/bin/kahin.mjs
CHANGED
|
@@ -5,7 +5,18 @@
|
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
|
-
import {
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
|
|
12
|
+
const PACKAGE_ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
13
|
+
// A local pnpm link can point PACKAGE_ROOT at a checkout that contains a
|
|
14
|
+
// ``kahin/`` source directory. Running ``python -m kahin.oracle`` with that
|
|
15
|
+
// checkout as cwd shadows the wheel installed in the launcher's venv and
|
|
16
|
+
// makes the same MCP command behave differently depending on the caller's
|
|
17
|
+
// cwd. Use an empty system temp cwd for that development-link case; published
|
|
18
|
+
// npm packages have no source directory and can run from their package root.
|
|
19
|
+
const PYTHON_CWD = existsSync(join(PACKAGE_ROOT, "kahin")) ? tmpdir() : PACKAGE_ROOT;
|
|
9
20
|
|
|
10
21
|
const HOME = process.env.KAHIN_HOME || join(homedir(), ".local", "share", "kahin");
|
|
11
22
|
const VENV = join(HOME, "venv");
|
|
@@ -32,7 +43,10 @@ async function setup() {
|
|
|
32
43
|
process.exit(1);
|
|
33
44
|
}
|
|
34
45
|
const python = existsSync(PY) ? PY : (process.env.KAHIN_PY || "python3");
|
|
35
|
-
const check = await sh(python, ["-c", "import kahin"], {
|
|
46
|
+
const check = await sh(python, ["-c", "import kahin"], {
|
|
47
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
48
|
+
cwd: PYTHON_CWD,
|
|
49
|
+
});
|
|
36
50
|
if (check !== 0) {
|
|
37
51
|
process.stderr.write(`[kahin] kahin Python paketi bulunamadı. ${python} ile çalıştırılamıyor.\n`);
|
|
38
52
|
process.exit(1);
|
|
@@ -55,7 +69,10 @@ if (args[0] === "setup") {
|
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
const python = await setup();
|
|
58
|
-
const child = spawn(python, ["-m", "kahin.oracle", ...args], {
|
|
72
|
+
const child = spawn(python, ["-m", "kahin.oracle", ...args], {
|
|
73
|
+
stdio: "inherit",
|
|
74
|
+
cwd: PYTHON_CWD,
|
|
75
|
+
});
|
|
59
76
|
child.on("exit", (code, signal) => {
|
|
60
77
|
if (signal) process.kill(process.pid, signal);
|
|
61
78
|
process.exit(code ?? 0);
|
package/bin/setup.mjs
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// Client listesi, otomatik tespit yapan sistemlerden derlendi (add-mcp 15 ajan,
|
|
8
8
|
// everymcp 15, mcpm 20+, getmcp 19, mcp-get 9, mcpkit): 22 client.
|
|
9
9
|
|
|
10
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
10
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, statSync } from "node:fs";
|
|
11
11
|
import { homedir } from "node:os";
|
|
12
12
|
import { join, dirname } from "node:path";
|
|
13
13
|
import { spawn } from "node:child_process";
|
|
@@ -324,7 +324,38 @@ export function setup() {
|
|
|
324
324
|
const KAHIN_HOME = process.env.KAHIN_HOME || join(homedir(), ".local", "share", "kahin");
|
|
325
325
|
const KAHIN_VENV = join(KAHIN_HOME, "venv");
|
|
326
326
|
const KAHIN_PY = process.platform === "win32" ? join(KAHIN_VENV, "Scripts", "python.exe") : join(KAHIN_VENV, "bin", "python");
|
|
327
|
-
const KAHIN_WHEEL = join(dirname(fileURLToPath(import.meta.url)), "..", "lib", "kahin-0.3.
|
|
327
|
+
const KAHIN_WHEEL = join(dirname(fileURLToPath(import.meta.url)), "..", "lib", "kahin-0.3.10-py3-none-any.whl");
|
|
328
|
+
const KAHIN_INSTALL_MARKER = join(KAHIN_HOME, ".install-state.json");
|
|
329
|
+
const SETUP_COMMAND_TIMEOUT_MS = 120_000;
|
|
330
|
+
|
|
331
|
+
function wheelStamp() {
|
|
332
|
+
try {
|
|
333
|
+
const info = statSync(KAHIN_WHEEL);
|
|
334
|
+
return `${info.size}:${Math.trunc(info.mtimeMs)}`;
|
|
335
|
+
} catch {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function installMarkerMatches(stamp) {
|
|
341
|
+
if (!stamp || !existsSync(KAHIN_INSTALL_MARKER)) return false;
|
|
342
|
+
try {
|
|
343
|
+
const marker = JSON.parse(readFileSync(KAHIN_INSTALL_MARKER, "utf8"));
|
|
344
|
+
return marker && marker.wheel === stamp && marker.python === KAHIN_PY;
|
|
345
|
+
} catch {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function writeInstallMarker(stamp) {
|
|
351
|
+
if (!stamp) return;
|
|
352
|
+
try {
|
|
353
|
+
mkdirSync(KAHIN_HOME, { recursive: true });
|
|
354
|
+
writeFileSync(KAHIN_INSTALL_MARKER, JSON.stringify({ wheel: stamp, python: KAHIN_PY }) + "\n");
|
|
355
|
+
} catch (err) {
|
|
356
|
+
process.stderr.write(`[kahin] install marker yazılamadı: ${err.message}\n`);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
328
359
|
|
|
329
360
|
// Gömülü wheel'i venv'e kurar ve varsayılan Camoufox binary'sini hazırlar.
|
|
330
361
|
// PyPI'a bağımlı DEĞİL — wheel paketle birlikte gelir; wheel'in bağımlılıkları
|
|
@@ -349,20 +380,39 @@ export async function installPython() {
|
|
|
349
380
|
return { error: code };
|
|
350
381
|
}
|
|
351
382
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
383
|
+
const stamp = wheelStamp();
|
|
384
|
+
if (installMarkerMatches(stamp)) {
|
|
385
|
+
log("Kahin wheel zaten güncel; pip kurulumu atlandı");
|
|
386
|
+
} else {
|
|
387
|
+
log(`wheel kuruluyor: ${KAHIN_WHEEL}`);
|
|
388
|
+
const code = await run(
|
|
389
|
+
KAHIN_PY,
|
|
390
|
+
["-m", "pip", "install", "--upgrade", KAHIN_WHEEL],
|
|
391
|
+
SETUP_COMMAND_TIMEOUT_MS,
|
|
392
|
+
);
|
|
393
|
+
if (code !== 0) {
|
|
394
|
+
log(`wheel kurulamadı (çıkış ${code})`);
|
|
395
|
+
return { error: code };
|
|
396
|
+
}
|
|
397
|
+
writeInstallMarker(stamp);
|
|
398
|
+
log("kahin python paketi kuruldu/güncellendi");
|
|
357
399
|
}
|
|
358
|
-
log("kahin python paketi kuruldu/güncellendi");
|
|
359
400
|
|
|
360
401
|
if (process.env.KAHIN_SKIP_CAMOUFOX_FETCH) {
|
|
361
402
|
log("Camoufox fetch atlandı (KAHIN_SKIP_CAMOUFOX_FETCH)");
|
|
362
403
|
return { installed: true, camoufox: "skipped" };
|
|
363
404
|
}
|
|
405
|
+
const readyCode = await run(
|
|
406
|
+
KAHIN_PY,
|
|
407
|
+
["-c", "from pathlib import Path; from camoufox.pkgman import launch_path; raise SystemExit(0 if Path(launch_path()).exists() else 1)"],
|
|
408
|
+
15_000,
|
|
409
|
+
);
|
|
410
|
+
if (readyCode === 0) {
|
|
411
|
+
log("Camoufox browser zaten hazır; fetch atlandı");
|
|
412
|
+
return { installed: true, camoufox: "ready" };
|
|
413
|
+
}
|
|
364
414
|
log("Camoufox browser hazırlanıyor (resmi camoufox fetch)...");
|
|
365
|
-
const browserCode = await run(KAHIN_PY, ["-m", "camoufox", "fetch"]);
|
|
415
|
+
const browserCode = await run(KAHIN_PY, ["-m", "camoufox", "fetch"], SETUP_COMMAND_TIMEOUT_MS);
|
|
366
416
|
if (browserCode !== 0) {
|
|
367
417
|
log(`Camoufox browser hazırlanamadı (çıkış ${browserCode}); kahin browser_start sırasında tekrar deneyecek`);
|
|
368
418
|
return { installed: true, camoufox: "error", error: browserCode };
|
|
@@ -371,15 +421,28 @@ export async function installPython() {
|
|
|
371
421
|
return { installed: true, camoufox: "ready" };
|
|
372
422
|
}
|
|
373
423
|
|
|
374
|
-
function run(cmd, args) {
|
|
424
|
+
function run(cmd, args, timeoutMs = SETUP_COMMAND_TIMEOUT_MS) {
|
|
375
425
|
return new Promise((resolve) => {
|
|
376
426
|
const c = spawn(cmd, args, { stdio: ["ignore", "ignore", "pipe"] });
|
|
427
|
+
let timedOut = false;
|
|
428
|
+
let forceTimer;
|
|
429
|
+
const timer = setTimeout(() => {
|
|
430
|
+
timedOut = true;
|
|
431
|
+
c.kill("SIGTERM");
|
|
432
|
+
forceTimer = setTimeout(() => c.kill("SIGKILL"), 5_000);
|
|
433
|
+
}, timeoutMs);
|
|
377
434
|
c.on("error", (err) => {
|
|
435
|
+
clearTimeout(timer);
|
|
436
|
+
clearTimeout(forceTimer);
|
|
378
437
|
process.stderr.write(`[kahin] ${cmd} başlatılamadı: ${err.message}\n`);
|
|
379
438
|
resolve(1);
|
|
380
439
|
});
|
|
381
440
|
c.stderr.on("data", (d) => process.stderr.write(`[kahin] ${d}`));
|
|
382
|
-
c.on("close", (code) =>
|
|
441
|
+
c.on("close", (code) => {
|
|
442
|
+
clearTimeout(timer);
|
|
443
|
+
clearTimeout(forceTimer);
|
|
444
|
+
resolve(timedOut ? 124 : code);
|
|
445
|
+
});
|
|
383
446
|
});
|
|
384
447
|
}
|
|
385
448
|
|
|
@@ -25,6 +25,11 @@ MCP tool
|
|
|
25
25
|
- Aynı browser'ı ve aktif sekmeyi yeniden kullan. Başka sayfa gerektiğinde
|
|
26
26
|
yeni browser açmak yerine `kahin_mirage_tab_new` ve
|
|
27
27
|
`kahin_mirage_tab_switch` kullan.
|
|
28
|
+
- `kahin_navigate` native response deadline'ına takılırsa mevcut target'ı
|
|
29
|
+
kapatıp aynı Mirage browser/context içinde bounded bir replacement target
|
|
30
|
+
açarak bir kez kurtarma yapabilir. Başarılı sonuçta `target_recovered: true`
|
|
31
|
+
gelir; browser PID'si değişmez. Bu durumda eski DOM `streamId`/nodeId'lerini
|
|
32
|
+
bırakıp yeni snapshot alın.
|
|
28
33
|
- Juggler'da `Browser.*` browser köküne, `Page.*` ise aktif target/session'a
|
|
29
34
|
aittir. MCP araçları session routing'i ajandan saklar.
|
|
30
35
|
- `kahin_execute_cdp`, Mirage aktifken desteklenen CDP çağrılarını Juggler
|
|
@@ -63,9 +68,11 @@ Zorunlu kurallar:
|
|
|
63
68
|
## 3. Gerçek zamanlı DOM vericisi
|
|
64
69
|
|
|
65
70
|
DOM stream sayfanın kendi `MutationObserver`'ını ve DOM event listener'larını
|
|
66
|
-
kullanır. Sayfa tarafında bounded bir ring buffer tutulur;
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
kullanır. Sayfa tarafında bounded bir ring buffer tutulur; mutation delta'ları
|
|
72
|
+
layout/computed-style ölçümü yapmadan hafif kimlikler taşır, semantik/geometri
|
|
73
|
+
ayrıntısı snapshot'tan alınır. Observer callback'i de bounded'dır; büyük bir
|
|
74
|
+
belgenin parser/mutation kuyruğu sidecar reader'ını veya sonraki navigation'ı
|
|
75
|
+
bloke etmez.
|
|
69
76
|
|
|
70
77
|
### 3.1 Tool sözleşmesi
|
|
71
78
|
|
|
@@ -146,6 +153,13 @@ Snapshot alanlarının anlamı:
|
|
|
146
153
|
- `cursor`: o snapshot anındaki son sequence numarasıdır. Delta okumaya bu
|
|
147
154
|
cursor'dan devam edilir.
|
|
148
155
|
|
|
156
|
+
`dom_events` yanıtındaki `cursor`, gerçekten teslim edilen son event'in
|
|
157
|
+
sequence numarasıdır; `limit` küçükse bekleyen event'leri atlamamak için bunu
|
|
158
|
+
sonraki `after_seq` olarak kullanın. `nextSeq` ise sayfadaki canlı üst sınırdır
|
|
159
|
+
ve henüz teslim edilmemiş event'leri de kapsayabilir. `kahin_agent_status`
|
|
160
|
+
`domCursor` (son teslim edilen) ve `domNextSeq` (canlı üst sınır) alanlarını
|
|
161
|
+
ayrı raporlar.
|
|
162
|
+
|
|
149
163
|
### 3.2 Delta ve event akışı
|
|
150
164
|
|
|
151
165
|
```json
|
|
@@ -166,7 +180,9 @@ Snapshot alanlarının anlamı:
|
|
|
166
180
|
"added": [{"nodeId": "n8", "tag": "button", "role": "button", "name": "Save"}],
|
|
167
181
|
"removed": [],
|
|
168
182
|
"addedCount": 1,
|
|
169
|
-
"
|
|
183
|
+
"addedTruncated": false,
|
|
184
|
+
"removedCount": 0,
|
|
185
|
+
"removedTruncated": false
|
|
170
186
|
},
|
|
171
187
|
{
|
|
172
188
|
"seq": 7,
|
|
@@ -184,6 +200,10 @@ event'lerine ek olarak `input`, `change`, `focusin`, `focusout` ve `click`
|
|
|
184
200
|
sayfa event'leri verilir. Bu event'ler neden-sonuç sinyalidir; tam güncel
|
|
185
201
|
durum için snapshot yetkilidir.
|
|
186
202
|
|
|
203
|
+
`added`/`removed` listeleri bounded'dır. `addedTruncated` veya
|
|
204
|
+
`removedTruncated` true ise ilgili count listedeki node sayısından büyüktür;
|
|
205
|
+
eksik node'ları tahmin etmeyin, yeni snapshot alın.
|
|
206
|
+
|
|
187
207
|
`dom_events` için önerilen çağrı:
|
|
188
208
|
|
|
189
209
|
```json
|
|
@@ -217,7 +237,41 @@ mevcut `streamId`'yi karşılaştırır. `dom_start`'ten aldığınız `streamId
|
|
|
217
237
|
her `dom_events` çağrısında geçirin; `stream_id` verilmezse navigation sessiz
|
|
218
238
|
kalır ve eski cursor yeni document'ın event'leriyle karışabilir.
|
|
219
239
|
|
|
220
|
-
### 3.
|
|
240
|
+
### 3.5 Crawl challenge ve rate-limit sözleşmesi
|
|
241
|
+
|
|
242
|
+
Her crawl döngüsünde `kahin_challenge_status` çağrısı yapılabilir. Araç Shadow
|
|
243
|
+
ve Mirage'ın mevcut sayfasını, DOM, challenge widget selector'larını ve gerçek
|
|
244
|
+
network response'larını
|
|
245
|
+
birlikte gözlemler; 403/429/503 yanıtlarında `httpStatus` ve varsa
|
|
246
|
+
`retryAfterSeconds` döndürür. `rate_limit` için `action` değeri
|
|
247
|
+
`honor_retry_after_and_backoff`, CAPTCHA için ise
|
|
248
|
+
`pause_for_human_or_authorized_provider` olur. Bu yüzey bypass/otomatik CAPTCHA
|
|
249
|
+
çözümü yapmaz; ajan verilen karara uymalı ve aynı origin'i körlemesine tekrar
|
|
250
|
+
çalıştırmamalıdır.
|
|
251
|
+
|
|
252
|
+
### 3.6 Uzun süreli crawler job sözleşmesi
|
|
253
|
+
|
|
254
|
+
Tek tek navigate çağrıları yerine uzun ve gözlenebilir bir crawl için şu ORBIT
|
|
255
|
+
araçları kullanılır:
|
|
256
|
+
|
|
257
|
+
- `kahin_crawl_start` — bounded seed/depth/page/time policy ile background job başlatır.
|
|
258
|
+
- `kahin_crawl_status` — state, queue, sonuç, rotation, challenge ve engine health özetini döndürür.
|
|
259
|
+
- `kahin_crawl_results` — opaque cursor ile en fazla 100 bounded sonucu döndürür.
|
|
260
|
+
- `kahin_crawl_pause` / `kahin_crawl_resume` — CAPTCHA/access-denied sonrasında explicit insan/provider kararıyla devam eder.
|
|
261
|
+
- `kahin_crawl_stop` — job'ı durdurur; browser'ı otomatik kapatmaz.
|
|
262
|
+
|
|
263
|
+
Job varsayılan olarak aynı Mirage browser ve crawler tab'ını kullanır. 20 başarılı
|
|
264
|
+
sayfa veya 900 saniyeden biri önce dolduğunda, tamamlanan sayfa ledger'a yazılır,
|
|
265
|
+
engine aynı slotta yeniden başlatılır ve saved/inline identity config ile
|
|
266
|
+
başlatılmış olsa bile effective Camoufox launch fingerprint'i yeniden üretilir;
|
|
267
|
+
önceki hash ile aynıysa rotation reddedilir. Queue ve result cursor engine
|
|
268
|
+
restart'tan etkilenmez.
|
|
269
|
+
Rotation bir CAPTCHA veya rate-limit kaçış mekanizması değildir. 429/503 için
|
|
270
|
+
Retry-After ve bounded exponential backoff uygulanır; CAPTCHA/access-denied
|
|
271
|
+
durumunda job `paused` kalır ve `kahin_crawl_resume` çağrısı bekler. Resume
|
|
272
|
+
challenge'ı çözmez, yeni origin'e kör retry yapmaz.
|
|
273
|
+
|
|
274
|
+
### 3.7 Live action sözleşmesi
|
|
221
275
|
|
|
222
276
|
İzin verilen action'lar: `click`, `hover`, `focus`, `type`, `scroll`, `select`.
|
|
223
277
|
|
|
@@ -283,7 +337,7 @@ script'i ayrıca evaluate eder. Observer sayfa tarafında bounded olduğu için
|
|
|
283
337
|
|
|
284
338
|
## 6. Juggler tool kataloğu (A-Z)
|
|
285
339
|
|
|
286
|
-
Aşağıdaki liste Mirage'ın
|
|
340
|
+
Aşağıdaki liste Mirage'ın 104 Juggler-native tool'unun tamamıdır. `MIRAGE`
|
|
287
341
|
tool'ları `engine="mirage"` aktifken kullanılır.
|
|
288
342
|
|
|
289
343
|
### DOM gözlem ve adaptif action (5)
|
|
@@ -312,6 +366,14 @@ tool'ları `engine="mirage"` aktifken kullanılır.
|
|
|
312
366
|
- `kahin_mirage_wait_for_text`, `kahin_mirage_wait_for_timeout`
|
|
313
367
|
- `kahin_mirage_route`
|
|
314
368
|
|
|
369
|
+
`kahin_mirage_route` bir sonraki eşleşen isteği bekleyen bounded, tek-atımlık
|
|
370
|
+
bir çağrıdır; navigate/click ile eşzamanlı çağrılır. `frame_id` verilirse yalnız
|
|
371
|
+
o iframe'in isteğini eşleştirir. Seri MCP istemcileri önce
|
|
372
|
+
`kahin_mirage_intercept_requests` çağırıp isteği
|
|
373
|
+
`kahin_mirage_network_continue`/`kahin_mirage_network_abort` ile sürdürür ve
|
|
374
|
+
ardından zorunlu olarak `kahin_mirage_unintercept_requests` çağırır; aksi halde
|
|
375
|
+
gelecek istekler interception modunda bekleyebilir.
|
|
376
|
+
|
|
315
377
|
### Input (7)
|
|
316
378
|
|
|
317
379
|
- `kahin_mirage_mouse_click`, `kahin_mirage_mouse_move`
|
|
@@ -324,6 +386,9 @@ tool'ları `engine="mirage"` aktifken kullanılır.
|
|
|
324
386
|
- `kahin_mirage_reload`, `kahin_mirage_go_back`, `kahin_mirage_go_forward`
|
|
325
387
|
- `kahin_mirage_stop`, `kahin_mirage_frame_tree`, `kahin_mirage_page_content`
|
|
326
388
|
|
|
389
|
+
`kahin_mirage_page_content` HTML'i bounded döndürür; `htmlLength` gerçek
|
|
390
|
+
belge boyutunu, `truncated` ise `html` alanının kesilip kesilmediğini bildirir.
|
|
391
|
+
|
|
327
392
|
### Tab/session (7)
|
|
328
393
|
|
|
329
394
|
- `kahin_mirage_tab_new`, `kahin_mirage_tab_switch`, `kahin_mirage_tab_close`
|
|
@@ -364,6 +429,10 @@ tool'ları `engine="mirage"` aktifken kullanılır.
|
|
|
364
429
|
- `kahin_mirage_set_file_chooser_intercept`
|
|
365
430
|
- `kahin_mirage_upload_files`
|
|
366
431
|
|
|
432
|
+
Upload çağrısı da `Page.fileChooserOpened` bekler. Input önceden tıklanmış
|
|
433
|
+
olmalı veya `kahin_mirage_click(selector="input[type=file]")` ile eşzamanlı
|
|
434
|
+
çağrılmalıdır; upload tool hangi input'u kendiliğinden seçmez.
|
|
435
|
+
|
|
367
436
|
### Screencast (4)
|
|
368
437
|
|
|
369
438
|
- `kahin_mirage_screencast_start`, `kahin_mirage_screencast_frame`
|
|
@@ -384,6 +453,13 @@ en eski frame FIFO olarak döner.
|
|
|
384
453
|
`last_error`); Mirage aktifse `prewarm` metadata'sı; engine yoksa
|
|
385
454
|
yapılandırılmış `engine_unavailable` yanıtı (asla hata fırlatmaz)
|
|
386
455
|
|
|
456
|
+
`kahin_mirage_accessibility_tree(max_nodes=N)` gerçek Camoufox AX ağacını
|
|
457
|
+
alır, toplam `nodeCount`'ı raporlar ve ajana en fazla `N` node döndürür.
|
|
458
|
+
Sidecar'ın raw AX cevabı da bounded'dır; büyük belgelerde beklenen sonuç
|
|
459
|
+
`truncated: true` olabilir. `result_too_large` veya `truncated` gördüğünüzde
|
|
460
|
+
engine'in öldüğünü varsaymayın; `kahin_engine_health` ile doğrulayın ve
|
|
461
|
+
gerekirse DOM snapshot/selector ile hedef alanı daraltın.
|
|
462
|
+
|
|
387
463
|
### Agent-native (10)
|
|
388
464
|
|
|
389
465
|
- `kahin_mirage_snapshot` — canlı DOM ağacını token bütçeli, ref'li satırlara
|
|
@@ -484,6 +560,7 @@ dom_events(after_seq=C, stream_id=S, frame_id=F, wait_ms=5000)
|
|
|
484
560
|
| `reset`/`dropped` | Stream değişti veya ring overflow | Snapshot; eski cursor'u bırak |
|
|
485
561
|
| `not_found` | Selector artık yok | Event/snapshot ile yeni hedef bul |
|
|
486
562
|
| `truncated` | Snapshot cap'i küçük | Selector veya cap daralt/genişlet |
|
|
563
|
+
| `cdp_command_failed` + `Page.navigate` response timeout | Native target navigation promise takıldı | Aynı browser içinde bounded target recovery yapılır; `target_recovered: true` ise yeni DOM snapshot al |
|
|
487
564
|
| `unsupported_action` | Action allow-list dışında | Yalnızca desteklenen action kullan |
|
|
488
565
|
| `not_text_input` | Hedef textbox değil | Role/name/action ipuçlarını tekrar değerlendir |
|
|
489
566
|
| `not_select` | `action=select` hedefi `<select>` değil | Snapshot'taki action ipuçlarını tekrar değerlendir |
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kahinmcp/kahin",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"description": "Kahin \u2014 CDP ansiklopedisi + anti-detect browser otomasyon MCP sunucusu. Kurulumda 22 AI CLI arac\u0131n\u0131 otomatik tespit edip kendini kaydeder. Camoufox g\u00f6rsel varsay\u0131land\u0131r; Obscura h\u0131zl\u0131 CDP i\u015fleri i\u00e7in opt-in'dir.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"kahin": "bin/kahin.mjs"
|
|
@@ -51,6 +51,6 @@
|
|
|
51
51
|
"python"
|
|
52
52
|
],
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@kahinmcp/kahin": "^0.3.
|
|
54
|
+
"@kahinmcp/kahin": "^0.3.9"
|
|
55
55
|
}
|
|
56
56
|
}
|
|
Binary file
|
|
Binary file
|