social-agent-cli 1.8.2 → 1.9.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.
package/ai/mapper.ts CHANGED
@@ -235,7 +235,11 @@ ${domSnapshot}
235
235
  Kurallar:
236
236
  - ARIA snapshot'taki role ve name bilgilerini kullanarak selector oluştur
237
237
  - aria-label, role, data-testid, id tercih et
238
- - Dosya/görsel/video yükleme için "upload" action kullan (click DEĞİL). Upload action hidden input[type=file]'a dosyayı programatik olarak set eder, file picker açmaz. value alanına {{IMAGE}} yaz.
238
+ - Dosya/görsel/video yükleme için "upload" action kullan. Upload action şöyle çalışır:
239
+ - selector'da medya/fotoğraf ekleme BUTONUNU ver (ör: button[aria-label*='Fotoğraf'], button[aria-label*='Add media'])
240
+ - Sistem butona tıklayıp fileChooser'ı yakalayacak ve dosyayı programatik olarak set edecek, file picker açılmayacak
241
+ - Eğer selector verilmezse sayfadaki input[type=file]'a direkt set eder
242
+ - value alanına {{IMAGE}} yaz
239
243
  - Her adım için 2+ fallback selector
240
244
  - Parametreler için placeholder kullan: {{CONTENT}} = metin, {{USERNAME}} = kullanıcı adı, {{URL}} = link, vs.
241
245
  - Hangi parametreleri kullandığını "parameters" alanında listele
@@ -342,7 +346,7 @@ GÖREV: Ekranın mevcut durumunu analiz et. Amaca ulaşmak için kalan adımlar
342
346
  - Belki farklı bir yol izlenmeli
343
347
  - {{CONTENT}} = post metni placeholder'ı
344
348
  - data-testid, aria-label, role tercih et, her adıma 2+ fallback selector ver
345
- - Dosya yükleme için "upload" action kullan (click DEĞİL). value: {{IMAGE}}`;
349
+ - Dosya yükleme için "upload" action kullan. selector'a medya ekleme butonunu ver, value: {{IMAGE}}`;
346
350
 
347
351
  console.log(`\n[heal] AI ekranı analiz ediyor (effort: ${effort})...\n`);
348
352
 
package/ai/runner.ts CHANGED
@@ -84,35 +84,7 @@ export async function runCommand(
84
84
 
85
85
  let steps = [...map.steps];
86
86
 
87
- // IMAGE parametresi var ama map'te upload step'i yok → gönder butonundan önce upload ekle
88
- if (imageParam && !steps.some(s => s.action === "upload")) {
89
- // Gönder butonunun index'ini bul (genelde son click)
90
- const sendIdx = steps.findLastIndex((s: any) => s.action === "click" && s.description?.toLowerCase().match(/gönder|post|tweet|paylaş|send|submit/));
91
- if (sendIdx > -1) {
92
- steps.splice(sendIdx, 0,
93
- {
94
- action: "upload" as const,
95
- description: "Görsel yükle",
96
- selector: "input[type='file']",
97
- value: "{{IMAGE}}",
98
- fallbackSelectors: ["[data-testid='fileInput']", "input[accept*='image']", "input[type='file'][accept]"],
99
- },
100
- {
101
- action: "wait" as const,
102
- description: "Görsel yüklenmesini bekle",
103
- waitMs: 2000,
104
- }
105
- );
106
- console.log(` [auto] Görsel yükleme adımı eklendi (map'e kaydedilecek)`);
107
-
108
- // Map'i güncelle - sonraki isteklerde de kullanılsın
109
- const { saveMap } = await import("./mapper.js");
110
- map.steps = steps;
111
- map.parameters = [...(map.parameters || []), "{{IMAGE}}"];
112
- map.version++;
113
- saveMap(map);
114
- }
115
- }
87
+ // IMAGE parametresi var ama map'te upload yok → planner learn_new ile öğretecek
116
88
  let stepIdx = 0;
117
89
  let healAttempt = 0;
118
90
 
@@ -327,10 +299,44 @@ async function executeMapStep(
327
299
  const filePath = rp(step.value || "{{IMAGE}}");
328
300
  if (!filePath || filePath.includes("{{")) break; // dosya yoksa atla
329
301
 
330
- // Hidden input[type=file]'a direkt setInputFiles - butona tıklamadan
331
- const fileInput = page.locator('input[type="file"]').first();
332
- await fileInput.setInputFiles(filePath);
302
+ let uploaded = false;
303
+
304
+ // 1. Selector varsa önce o butona tıkla (medya butonu gibi) ve fileChooser yakala
305
+ if (selectors.length > 0 && !selectors[0].includes("input[type")) {
306
+ for (const sel of selectors) {
307
+ try {
308
+ const [fileChooser] = await Promise.all([
309
+ page.waitForEvent("filechooser", { timeout: 5000 }),
310
+ page.click(sel),
311
+ ]);
312
+ await fileChooser.setFiles(filePath);
313
+ uploaded = true;
314
+ break;
315
+ } catch {}
316
+ }
317
+ }
318
+
319
+ // 2. Sayfadaki input[type=file]'a direkt set et
320
+ if (!uploaded) {
321
+ try {
322
+ const fileInput = page.locator('input[type="file"]').first();
323
+ await fileInput.waitFor({ timeout: 3000 });
324
+ await fileInput.setInputFiles(filePath);
325
+ uploaded = true;
326
+ } catch {}
327
+ }
328
+
329
+ // 3. Tüm input[type=file]'ları dene
330
+ if (!uploaded) {
331
+ try {
332
+ const inputs = await page.locator('input[type="file"]').all();
333
+ for (const input of inputs) {
334
+ try { await input.setInputFiles(filePath); uploaded = true; break; } catch {}
335
+ }
336
+ } catch {}
337
+ }
333
338
 
339
+ if (!uploaded) throw new Error(`Upload failed: ${filePath}`);
334
340
  if (step.waitMs) await page.waitForTimeout(step.waitMs);
335
341
  break;
336
342
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "social-agent-cli",
3
- "version": "1.8.2",
3
+ "version": "1.9.0",
4
4
  "description": "AI-powered social media agent - free APIs + browser automation with self-healing selectors",
5
5
  "type": "module",
6
6
  "bin": {