beast-agent 0.23.8 → 0.23.9

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "beast-agent",
3
3
  "productName": "Beast Agent",
4
- "version": "0.23.8",
4
+ "version": "0.23.9",
5
5
  "description": "Ultra-fast local agent shell for Windows.",
6
6
  "author": "algokodcom (AlgoKod)",
7
7
  "license": "MIT",
@@ -220,7 +220,10 @@ class Engine {
220
220
  this.tokRatio = 1; // gerçek prompt_tokens ile kalibre edilir
221
221
  this._codeIndex = new Map(); // kısa oturum kodu -> session id
222
222
  /* yansıma: oturumda 5+ yeni araç çağrısında skill taslağı denenir */
223
- this.reflection = { enabled: opts.reflection !== false, minTools: 5 };
223
+ this.reflection = { enabled: opts.reflection !== false, minTools: 3 };
224
+ /* OTOMATİK SKİLL SİSTEMİ: öğrenilen prosedür taslak onayı beklemeden
225
+ kurulu skill olur; mevcut skillin daha iyisi bulunursa üzerine günceller */
226
+ this.autoSkills = opts.autoSkills !== false;
224
227
  this.historyTokenBudget = Number(opts.historyTokenBudget) || HISTORY_TOKEN_BUDGET;
225
228
  this.browser = opts.browser || null; // dahili tarayıcı kancaları
226
229
  this.fileSend = opts.fileSend || null; // #26 dosya gönderim köprüsü (chat/WA)
@@ -2479,12 +2482,25 @@ class Engine {
2479
2482
  );
2480
2483
  if (transcript.length < 400) return null; // çok kısa deneyim değmez
2481
2484
 
2485
+ /* OTOMATİK SKİLL SİSTEMİ: kurulu skill listesi de prompta girer —
2486
+ ajan "eski skillden daha kolay/better yol buldum" diyebilmesin, KARAR VERİP
2487
+ skilli GÜNCELLESİN. action: create (yeni) | update (mevcutu iyileştir) | none */
2488
+ const skills = require('./skills');
2489
+ const existing = skills
2490
+ .scan()
2491
+ .map((s) => `- ${s.name}: ${(s.description || '').slice(0, 100)}`)
2492
+ .join('\n');
2493
+
2482
2494
  const prompt =
2483
- 'Aşağıdaki agent oturumunda TEKRARLANABİLİR, yeniden kullanılabilir bir prosedür/bilgi ' +
2484
- 'birikti mi? Kullanıcıya özel geçici detaylar sayılmaz. Karar: evet ise SKILL.md taslağı üret.\n\n' +
2495
+ 'Aşağıdaki agent oturumunda TEKRARLANABİLİR, yeniden kullanılabilir bir prosedür/bilgi birikti mi?\n' +
2496
+ 'Bir kurulu skill, bu oturumda öğrenilen DAHA KOLAY/DAHA İYİ yöntemle güncellenmeyi hak ediyor mu?\n' +
2497
+ 'Kullanıcıya özel geçici detaylar (tarih, şehir, numara gibi) skill\u2019e YAZILMAZ — genel yöntem yazılır.\n\n' +
2498
+ '# KURULU SKİLLER\n' + (existing || '(yok)') + '\n\n' +
2485
2499
  'SADECE şu JSON formatında cevap ver, başka metin yok:\n' +
2486
- '{"create": true|false, "name": "kisa-kebab-ad", "description": "tek cümle ne işe yarar", ' +
2487
- '"body": "# Başlık\\n\\nmaddeler halinde adım adım prosedür"}\n\n' +
2500
+ '{"action": "none" | "create" | "update", "name": "kisa-kebab-ad", "description": "tek cümle ne işe yarar", "body": "# Başlık\\n\\nmaddeler halinde adım adım prosedür"}\n\n' +
2501
+ 'action=create → yeni skill (body: baştan sona tam prosedür)\n' +
2502
+ 'action=update → "name" MEVCUT skillin adı; body o skillin GÜNCELLENMİŞ TAM HALI (eskiden iyi olan adımları koru, yeni kolaylığı işle)\n' +
2503
+ 'action=none → değerlenecek bir şey yok\n\n' +
2488
2504
  '# OTURUM ÖZETİ\n' + transcript.slice(0, 6000);
2489
2505
 
2490
2506
  const res = await chatOnce(
@@ -2493,8 +2509,30 @@ class Engine {
2493
2509
  {}
2494
2510
  );
2495
2511
  const draft = parseReflectionJson(res.content || '');
2496
- if (!draft || !draft.create || !draft.name || !draft.body) return null;
2497
- const skills = require('./skills');
2512
+ if (!draft || !draft.name || !draft.body) return null;
2513
+
2514
+ const action = String(draft.action || (draft.create ? 'create' : 'none')).toLowerCase();
2515
+ if (action !== 'create' && action !== 'update') return null;
2516
+
2517
+ if (action === 'update') {
2518
+ /* mevcut skillin GÜNCELLENMİŞ hali — doğrudan üzerine (eski hali .bak) */
2519
+ const r = skills.upsertSkill({
2520
+ name: String(draft.name),
2521
+ description: String(draft.description || ''),
2522
+ body: String(draft.body),
2523
+ });
2524
+ return r.ok ? skills.slugify(draft.name) + ' (güncellendi)' : null;
2525
+ }
2526
+
2527
+ /* create: otomatik skill modu AÇIKSA taslak beklemeden direkt kur */
2528
+ if (this.autoSkills) {
2529
+ const r = skills.upsertSkill({
2530
+ name: String(draft.name),
2531
+ description: String(draft.description || ''),
2532
+ body: String(draft.body),
2533
+ });
2534
+ return r.ok ? skills.slugify(draft.name) : null;
2535
+ }
2498
2536
  const r = skills.addDraft({
2499
2537
  name: String(draft.name),
2500
2538
  description: String(draft.description || ''),
@@ -487,6 +487,33 @@ function dropDraft(id) {
487
487
  }
488
488
  }
489
489
 
490
+ /* OTOMATIK SKILL SİSTEMİ: yansımadan doğan prosedürü DOĞRUDAN kurulu skill olarak
491
+ yazar (taslak onayı beklemeden). Aynı isimde skill varsa GÜNCELLENİR:
492
+ eski içerik .bak'a alınır, created korunur, updated damgası vurulur. */
493
+ function upsertSkill({ name, description, body }) {
494
+ try {
495
+ const nm = String(name || '').trim() || 'yetenek';
496
+ const folder = slugify(nm);
497
+ const d = path.join(dir(), folder);
498
+ const file = path.join(d, 'SKILL.md');
499
+ fs.mkdirSync(d, { recursive: true });
500
+ let fm = `---\nname: ${nm}\ndescription: ${String(description || '').trim().slice(0, 160)}\n`;
501
+ let updated = false;
502
+ if (fs.existsSync(file)) {
503
+ const old = fs.readFileSync(file, 'utf8');
504
+ const oldFm = parseFrontmatter(old);
505
+ fm += `created: ${oldFm.created || oldFm.generatedAt || new Date().toISOString()}\n`;
506
+ fs.writeFileSync(file + '.bak', old);
507
+ updated = true;
508
+ }
509
+ fm += `updated: ${new Date().toISOString()}\n---\n\n`;
510
+ fs.writeFileSync(file, fm + String(body || '').trim() + '\n');
511
+ return { ok: true, folder, file, updated };
512
+ } catch (e) {
513
+ return { ok: false, error: String((e && e.message) || e) };
514
+ }
515
+ }
516
+
490
517
  /* Kurulu bir skill'e madde ekler (#3 kural hattı): "## Kurallar" altına yazılır. */
491
518
  function appendRuleToSkill(nameOrFolder, ruleText) {
492
519
  try {
@@ -520,4 +547,5 @@ module.exports = {
520
547
  acceptDraft,
521
548
  dropDraft,
522
549
  appendRuleToSkill,
550
+ upsertSkill,
523
551
  };
package/src/main.js CHANGED
@@ -2071,6 +2071,9 @@ function reloadBackend() {
2071
2071
  thinkLevel: settings.thinkLevel || 0,
2072
2072
  fallout: settings.fallout || null,
2073
2073
  limits: settings.limits || null,
2074
+ /* OTOMATİK SKİLL SİSTEMİ: ayarlardan kapatılmadıysa öğrenilen prosedürler
2075
+ otomatik skill olur, mevcutların daha iyisi bulunursa güncellenir */
2076
+ autoSkills: settings.autoSkills !== false,
2074
2077
  approvals: settings.security && settings.security.approvals ? approvalsBridge : null,
2075
2078
  alwaysAllowTools: (settings.security && settings.security.alwaysAllow) || [],
2076
2079
  crashFile: FALLOUT_CRASH_FILE,
@@ -3828,6 +3831,16 @@ ipcMain.handle('memory:save', (_e, { file, content }) => memory.save(file, conte
3828
3831
 
3829
3832
  ipcMain.handle('skills:list', () => skillsMod.scan());
3830
3833
 
3834
+ /* OTOMATİK SKİLL SİSTEMİ: açıkken öğrenilen prosedürler direkt kurulur,
3835
+ mevcut skillin daha iyisi bulunursa güncellenir */
3836
+ ipcMain.handle('skills:auto:get', () => settings.autoSkills !== false);
3837
+ ipcMain.handle('skills:auto:set', (_e, v) => {
3838
+ settings.autoSkills = !!v;
3839
+ saveSettings();
3840
+ if (engine) engine.autoSkills = !!v;
3841
+ return settings.autoSkills;
3842
+ });
3843
+
3831
3844
  /* taslak skill'ler (#2 yansıma ürünleri) */
3832
3845
  ipcMain.handle('skills:drafts:list', () => skillsMod.listDrafts());
3833
3846
  ipcMain.handle('skills:drafts:accept', (_e, id) => {
package/src/preload.js CHANGED
@@ -25,6 +25,8 @@ contextBridge.exposeInMainWorld('beast', {
25
25
  clearNotes: (id) => ipcRenderer.invoke('notes:clear', id),
26
26
  saveMemory: (file, content) => ipcRenderer.invoke('memory:save', { file, content }),
27
27
  listSkills: () => ipcRenderer.invoke('skills:list'),
28
+ skillsGetAuto: () => ipcRenderer.invoke('skills:auto:get'),
29
+ skillsSetAuto: (v) => ipcRenderer.invoke('skills:auto:set', v),
28
30
  openSkillsFolder: () => ipcRenderer.invoke('skills:openFolder'),
29
31
  draftsList: () => ipcRenderer.invoke('skills:drafts:list'),
30
32
  draftAccept: (id) => ipcRenderer.invoke('skills:drafts:accept', id),
@@ -164,6 +164,7 @@
164
164
  mem_saved: 'Memory kaydedildi — SOUL.md dahil',
165
165
  sk_h2: 'Skills',
166
166
  sk_sub: 'SKILL.md indeksi — tam metin model tarafından okunur',
167
+ sk_auto: 'Otomatik skill: ajan öğrendiği yeni yöntemleri taslak onayı beklemeden kurar; bir skillin daha kolay/daha iyi yolunu bulursa mevcut skilli kendisi günceller',
167
168
  sk_rules_h2: 'Kalıcı Kurallar',
168
169
  sk_rules_sub: 'Agent\u2019ın her sohbette uyduğu talimatlar — WA\u2019dan /rule ile de eklenir',
169
170
  sk_no_rule: 'Henüz kural yok.',
@@ -678,6 +679,7 @@
678
679
  mem_saved: 'Memory saved — including SOUL.md',
679
680
  sk_h2: 'Skills',
680
681
  sk_sub: 'SKILL.md index — full text is read by the model',
682
+ sk_auto: 'Auto skills: the agent installs learned procedures without draft approval and updates existing skills when it finds an easier or better way',
681
683
  sk_rules_h2: 'Persistent Rules',
682
684
  sk_rules_sub: 'Instructions the agent follows in every chat — also addable via /rule on WA',
683
685
  sk_no_rule: 'No rules yet.',
@@ -1255,6 +1255,16 @@ async function renderFalloutPane() {
1255
1255
  async function renderSkillsPane() {
1256
1256
  const pane = $('#tab-skills');
1257
1257
  pane.innerHTML = '<h2>' + _t('sk_h2') + '</h2><div class="sub">' + _t('sk_sub') + '</div>';
1258
+ /* OTOMATİK SKİLL SİSTEMİ: öğrenilen prosedürler otomatik kurulur/güncellenir */
1259
+ const auto = await beast.skillsGetAuto().catch(() => true);
1260
+ pane.insertAdjacentHTML(
1261
+ 'afterbegin',
1262
+ `<div class="fo-toggles" style="margin-bottom:12px"><label class="lock-row"><input type="checkbox" id="autoSkillsOn" ${auto ? 'checked' : ''}/><span>${_t('sk_auto')}</span></label></div>`
1263
+ );
1264
+ pane.querySelector('#autoSkillsOn').addEventListener('change', async (e) => {
1265
+ await beast.skillsSetAuto(e.target.checked);
1266
+ toast((e.target.checked ? 'Otomatik skill: AÇIK' : 'Otomatik skill: KAPALI'));
1267
+ });
1258
1268
  const list = await beast.listSkills();
1259
1269
  for (const s of list) {
1260
1270
  const row = document.createElement('div');