beast-agent 2.63.9 → 2.64.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.
@@ -28,9 +28,19 @@ function cfg() {
28
28
  return {
29
29
  apiKey: String(c.apiKey || '').trim(),
30
30
  model: String(c.model || '').trim() || DEFAULT_MODEL,
31
+ enabled: c.enabled !== false,
31
32
  };
32
33
  }
33
34
 
35
+ /* Ayar kapısı: anahtar yoksa ya da anahtar Ayarlar → TypeSafe'te KAPALIYSA
36
+ hiçbir TypeSafe çağrısı yapılmaz. Boş dönüş = hazır; dolu dönüş = hata metni. */
37
+ function unavailable() {
38
+ const c = cfg();
39
+ if (!c.apiKey) return 'TypeSafe API anahtarı yok — Ayarlar → TypeSafe sekmesinden gir';
40
+ if (!c.enabled) return 'TypeSafe kapalı — Ayarlar → TypeSafe sekmesinden aç';
41
+ return '';
42
+ }
43
+
34
44
  function errorForStatus(status, bodyText) {
35
45
  const detail = String(bodyText || '').slice(0, 240);
36
46
  if (status === 401 || status === 403) return 'TypeSafe API anahtarı geçersiz (Ayarlar → TypeSafe sekmesinden kontrol et)' + (detail ? ' — ' + detail : '');
@@ -77,46 +87,87 @@ function normalizeQuestions(questions) {
77
87
  return out;
78
88
  }
79
89
 
80
- /* systemOne çağrısı: state + questions → answers */
90
+ /* systemOne çağrısı: state + questions → answers.
91
+ Geçici hatalarda (429/5xx/ağ/zaman aşımı) kısa backoff ile 2 kez yeniden
92
+ denenir — tek dalgalı hata tüm Jev döngüsünü düşürmesin. */
93
+ const RETRY_DELAYS_MS = [400, 1000];
94
+
95
+ function sleep(ms, signal) {
96
+ return new Promise((resolve, reject) => {
97
+ if (signal && signal.aborted) return reject(new Error('TypeSafe çağrısı iptal edildi'));
98
+ const t = setTimeout(() => {
99
+ if (signal && typeof signal.removeEventListener === 'function') signal.removeEventListener('abort', onAbort);
100
+ resolve();
101
+ }, ms);
102
+ function onAbort() {
103
+ clearTimeout(t);
104
+ reject(new Error('TypeSafe çağrısı iptal edildi'));
105
+ }
106
+ if (signal && typeof signal.addEventListener === 'function') signal.addEventListener('abort', onAbort, { once: true });
107
+ });
108
+ }
109
+
81
110
  async function systemOne({ state, questions, model, timeoutMs, signal } = {}) {
82
111
  const c = cfg();
83
- if (!c.apiKey) throw new Error('TypeSafe API anahtarı yok — Ayarlar → TypeSafe sekmesinden gir');
112
+ const gate = unavailable();
113
+ if (gate) throw new Error(gate);
84
114
  if (state == null || (typeof state === 'string' && !state.trim())) {
85
115
  throw new Error('state boş — değerlendirilecek içerik gerekli (metin ya da JSON nesne/dizi)');
86
116
  }
87
117
  const qs = normalizeQuestions(questions);
88
118
  const body = { state, model: String(model || '').trim() || c.model, questions: qs };
89
- const ctrl = new AbortController();
90
- const timer = setTimeout(() => ctrl.abort(), Number(timeoutMs) > 0 ? Number(timeoutMs) : DEFAULT_TIMEOUT_MS);
91
- const onAbort = () => ctrl.abort();
92
- if (signal && typeof signal.addEventListener === 'function') signal.addEventListener('abort', onAbort, { once: true });
93
- try {
94
- const res = await fetch(BASE_URL + '/v1/systemone', {
95
- method: 'POST',
96
- headers: { 'content-type': 'application/json', authorization: 'Bearer ' + c.apiKey },
97
- body: JSON.stringify(body),
98
- signal: ctrl.signal,
99
- });
100
- if (!res.ok) {
101
- const txt = await res.text().catch(() => '');
102
- throw new Error(errorForStatus(res.status, txt));
103
- }
104
- const data = await res.json();
105
- return {
106
- model: String((data && data.model) || body.model),
107
- answers: (data && data.answers) || {},
108
- usage: (data && data.usage) || null,
109
- };
110
- } catch (e) {
111
- if (e && (e.name === 'AbortError' || e.name === 'TimeoutError')) {
112
- if (signal && signal.aborted) throw new Error('TypeSafe çağrısı iptal edildi');
113
- throw new Error('TypeSafe zaman aşımı — istek ' + Math.round((Number(timeoutMs) > 0 ? Number(timeoutMs) : DEFAULT_TIMEOUT_MS) / 1000) + ' sn içinde yanıtlanmadı');
119
+ const perTry = Number(timeoutMs) > 0 ? Number(timeoutMs) : DEFAULT_TIMEOUT_MS;
120
+ let lastError = null;
121
+ for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {
122
+ if (signal && signal.aborted) throw new Error('TypeSafe çağrısı iptal edildi');
123
+ const ctrl = new AbortController();
124
+ const timer = setTimeout(() => ctrl.abort(), perTry);
125
+ const onAbort = () => ctrl.abort();
126
+ if (signal && typeof signal.addEventListener === 'function') signal.addEventListener('abort', onAbort, { once: true });
127
+ try {
128
+ const res = await fetch(BASE_URL + '/v1/systemone', {
129
+ method: 'POST',
130
+ headers: { 'content-type': 'application/json', authorization: 'Bearer ' + c.apiKey },
131
+ body: JSON.stringify(body),
132
+ signal: ctrl.signal,
133
+ });
134
+ if (!res.ok) {
135
+ const txt = await res.text().catch(() => '');
136
+ const err = new Error(errorForStatus(res.status, txt));
137
+ err.status = res.status;
138
+ throw err;
139
+ }
140
+ const data = await res.json();
141
+ return {
142
+ model: String((data && data.model) || body.model),
143
+ answers: (data && data.answers) || {},
144
+ usage: (data && data.usage) || null,
145
+ };
146
+ } catch (e) {
147
+ const abortedByUser = !!(signal && signal.aborted);
148
+ if (abortedByUser) throw new Error('TypeSafe çağrısı iptal edildi');
149
+ const timedOut = !!(e && (e.name === 'AbortError' || e.name === 'TimeoutError'));
150
+ const network = e instanceof TypeError;
151
+ const retryable = timedOut || network || e.status === 429 || (Number(e.status) >= 500 && Number(e.status) <= 599);
152
+ lastError = e;
153
+ if (retryable && attempt < RETRY_DELAYS_MS.length) {
154
+ try {
155
+ await sleep(RETRY_DELAYS_MS[attempt], signal);
156
+ } catch (abortErr) {
157
+ throw new Error('TypeSafe çağrısı iptal edildi');
158
+ }
159
+ continue;
160
+ }
161
+ if (timedOut) {
162
+ throw new Error('TypeSafe zaman aşımı — istek ' + Math.round(perTry / 1000) + ' sn içinde yanıtlanmadı');
163
+ }
164
+ throw e;
165
+ } finally {
166
+ clearTimeout(timer);
167
+ if (signal && typeof signal.removeEventListener === 'function') signal.removeEventListener('abort', onAbort);
114
168
  }
115
- throw e;
116
- } finally {
117
- clearTimeout(timer);
118
- if (signal && typeof signal.removeEventListener === 'function') signal.removeEventListener('abort', onAbort);
119
169
  }
170
+ throw lastError || new Error('TypeSafe çağrısı başarısız');
120
171
  }
121
172
 
122
173
  /* Anahtar testi: tek soruluk ucuz systemOne çağrısı (bağlantı + auth doğrular) */
@@ -222,10 +273,8 @@ function summarize(answers) {
222
273
 
223
274
  async function handler(args, ctx) {
224
275
  const a = args && typeof args === 'object' ? args : {};
225
- const c = cfg();
226
- if (!c.apiKey) {
227
- return { ok: false, error: 'TypeSafe API anahtarı yok — Ayarlar → TypeSafe sekmesinden gir (kullanıcıya bunu söyle)' };
228
- }
276
+ const gate = unavailable();
277
+ if (gate) return { ok: false, error: gate + ' (kullanıcıya bunu söyle)' };
229
278
  let state = a.state;
230
279
  if (typeof state === 'string') {
231
280
  const s = state.trim();
@@ -272,6 +321,7 @@ module.exports = {
272
321
  probe,
273
322
  setConfig,
274
323
  cfg,
324
+ unavailable,
275
325
  normalizeQuestions,
276
326
  BASE_URL,
277
327
  DEFAULT_MODEL,
@@ -42,6 +42,8 @@ const TOOL_LABELS = {
42
42
  },
43
43
  http_fetch: (a) => `Sayfa: ${a.url || ''}`,
44
44
  browser_open: (a) => `Tarayıcı aç: ${a.url || ''}`,
45
+ browser_agent: (a) => `T3SFast ajan: ${String(a.goal || a.task || '').slice(0, 80)}`,
46
+ computer_agent: (a) => `T3SFast PC: ${String(a.goal || a.task || '').slice(0, 80)}`,
45
47
  browser_click: (a) => `Tıkla: ${a.ref ?? ''}`,
46
48
  browser_type: (a) => `Yaz: ${String(a.text || '').slice(0, 60)}`,
47
49
  browser_select: (a) => `Seç: ${a.ref ?? ''}`,