beast-agent 2.15.0 → 2.17.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/package.json +1 -1
- package/src/agent/engine.js +505 -156
- package/src/agent/opencode/agents.js +161 -0
- package/src/agent/opencode/askperm.js +135 -0
- package/src/agent/opencode/index.js +51 -0
- package/src/agent/opencode/permission.js +108 -0
- package/src/agent/opencode/prompts/anthropic.txt +105 -0
- package/src/agent/opencode/prompts/beast.txt +147 -0
- package/src/agent/opencode/prompts/build-switch.txt +5 -0
- package/src/agent/opencode/prompts/codex.txt +79 -0
- package/src/agent/opencode/prompts/default.txt +95 -0
- package/src/agent/opencode/prompts/edit.txt +10 -0
- package/src/agent/opencode/prompts/explore.txt +18 -0
- package/src/agent/opencode/prompts/gemini.txt +155 -0
- package/src/agent/opencode/prompts/glob.txt +6 -0
- package/src/agent/opencode/prompts/gpt.txt +107 -0
- package/src/agent/opencode/prompts/grep.txt +8 -0
- package/src/agent/opencode/prompts/kimi.txt +95 -0
- package/src/agent/opencode/prompts/max-steps.txt +16 -0
- package/src/agent/opencode/prompts/meta.txt +65 -0
- package/src/agent/opencode/prompts/plan.txt +26 -0
- package/src/agent/opencode/prompts/read.txt +14 -0
- package/src/agent/opencode/prompts/skill.txt +5 -0
- package/src/agent/opencode/prompts/task.txt +19 -0
- package/src/agent/opencode/prompts/todowrite.txt +44 -0
- package/src/agent/opencode/prompts/trinity.txt +97 -0
- package/src/agent/opencode/prompts/webfetch.txt +13 -0
- package/src/agent/opencode/prompts/websearch.txt +14 -0
- package/src/agent/opencode/prompts/write.txt +8 -0
- package/src/agent/opencode/systemprompt.js +157 -0
- package/src/agent/opencode/toolmap.js +316 -0
- package/src/agent/supermemory.js +132 -0
- package/src/main.js +135 -41
- package/src/preload.js +5 -0
- package/src/renderer/renderer.js +59 -15
package/src/main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
const { app, BrowserWindow, WebContentsView, ipcMain, shell, dialog, Tray, Menu, nativeImage, desktopCapturer, session, net: electronNet, clipboard } = require('electron');
|
|
4
4
|
const path = require('path');
|
|
@@ -426,6 +426,11 @@ function parseSettingsText(text) {
|
|
|
426
426
|
const parsed = JSON.parse(text);
|
|
427
427
|
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error('bozuk yapı');
|
|
428
428
|
if (!parsed.roleModels) parsed.roleModels = {};
|
|
429
|
+
/* Supermemory (lokal) DEFAULT AÇIK — sunucu ayaktayken daha akıllı bellek;
|
|
430
|
+
ayakta değilken klasik hafıza sorunsuz çalışır (engine fallback) */
|
|
431
|
+
if (!parsed.supermemory || typeof parsed.supermemory !== 'object') {
|
|
432
|
+
parsed.supermemory = { enabled: true, baseUrl: 'http://localhost:6767', apiKey: '', containerTag: 'beast' };
|
|
433
|
+
}
|
|
429
434
|
return parsed;
|
|
430
435
|
}
|
|
431
436
|
|
|
@@ -1335,6 +1340,18 @@ function resolveApproval(id, ok, always) {
|
|
|
1335
1340
|
}
|
|
1336
1341
|
|
|
1337
1342
|
function resolveFirstApproval(ok, always) {
|
|
1343
|
+
/* opencode permission (BC): önce opencode izin istekleri yanıtlanır —
|
|
1344
|
+
cevap 'once' | 'always' | 'reject' üçlüsüdür (permission/reply portu) */
|
|
1345
|
+
if (engine && typeof engine.replyPermission === 'function') {
|
|
1346
|
+
try {
|
|
1347
|
+
const pend = engine._perm && engine._perm.list ? engine._perm.list() : [];
|
|
1348
|
+
if (pend.length) {
|
|
1349
|
+
const action = ok ? (always ? 'always' : 'once') : 'reject';
|
|
1350
|
+
const r = engine.replyPermission(pend[0].id, action);
|
|
1351
|
+
if (r && r.ok) return { ok: true, tool: pend[0].permission };
|
|
1352
|
+
}
|
|
1353
|
+
} catch {}
|
|
1354
|
+
}
|
|
1338
1355
|
const first = pendingApprovals.keys().next();
|
|
1339
1356
|
if (first.done) return { ok: false, error: 'bekleyen onay yok' };
|
|
1340
1357
|
return resolveApproval(first.value, ok, always);
|
|
@@ -1677,17 +1694,17 @@ async function tryWaSlash(jid, rawText, senderNum, payload0) {
|
|
|
1677
1694
|
`Tekrar kodlamak için: /beastcode`;
|
|
1678
1695
|
}
|
|
1679
1696
|
} else if (waBcMode.has(jid) && (cmd === 'plan' || cmd === 'build' || cmd === 'auto')) {
|
|
1680
|
-
/*
|
|
1697
|
+
/* opencode ajan değişimi (WA): /plan → plan ajanı (salt-okur),
|
|
1698
|
+
/build · /auto → build ajanı (varsayılan; auto opencode'da yoktur) */
|
|
1681
1699
|
const sid = waChats.get(jid);
|
|
1682
1700
|
const s = sid ? engine.cache.get(sid) : null;
|
|
1683
1701
|
if (s && s.bcCode) {
|
|
1684
|
-
s.
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
? '*🔍 PLAN MODU* — dosyaları inceler, kod YAZMAZ; adım adım uygulama planı verir.'
|
|
1702
|
+
const agent = engine.setBcAgent(s.id, cmd === 'plan' ? 'plan' : 'build');
|
|
1703
|
+
out = agent === 'plan'
|
|
1704
|
+
? '*🔍 PLAN AJANI* (opencode plan) — salt-okur: dosyaları okur/inceler, kod YAZMAZ; adım adım uygulama planı verir. Uygulamak için /build yaz.'
|
|
1688
1705
|
: cmd === 'build'
|
|
1689
|
-
? '*🛠 BUILD
|
|
1690
|
-
: '*⚡
|
|
1706
|
+
? '*🛠 BUILD AJANI* (opencode build) — bağlamı inceler, todowrite ile planlar, uygular, doğrular.'
|
|
1707
|
+
: '*⚡ BUILD AJANI* (opencode build) — kısa plan + hemen uygulama + doğrulama.';
|
|
1691
1708
|
} else {
|
|
1692
1709
|
out = 'Bu komut yalnız BeastCode modunda çalışır — önce /beastcode yaz.';
|
|
1693
1710
|
}
|
|
@@ -2441,14 +2458,12 @@ async function processWaMessage(jid, payload, senderNum, requeues = 0) {
|
|
|
2441
2458
|
}
|
|
2442
2459
|
engine.setSessionModel(sid, botCfg && !botCfg.admin ? (botCfg.model || null) : null);
|
|
2443
2460
|
/* BEASTCODE MODU: sohbet uzaktan kodlama modundaysa oturumu Beast Code
|
|
2444
|
-
olarak tazele — restart sonrası bcCode/workspace bayrakları dosyadan
|
|
2461
|
+
olarak tazele — restart sonrası bcCode/bcAgent/workspace bayrakları dosyadan
|
|
2445
2462
|
yüklenmediği için masaüstü bcFlush disipliniyle her mesajda bindirilir */
|
|
2446
2463
|
if (waBcMode.has(jid)) {
|
|
2447
2464
|
const bs = engine.cache.get(sid);
|
|
2448
2465
|
if (bs) {
|
|
2449
|
-
bs
|
|
2450
|
-
bs.workspace = waBcWorkspace();
|
|
2451
|
-
engine.cache.set(sid, bs);
|
|
2466
|
+
bcBindOc(bs, waBcWorkspace());
|
|
2452
2467
|
}
|
|
2453
2468
|
}
|
|
2454
2469
|
waLog(`perm=${fmtPerm(perm)} bot=${botId} sid=${sid}${waBcMode.has(jid) ? ' beastcode=1' : ''}`);
|
|
@@ -3065,6 +3080,10 @@ function reloadBackend() {
|
|
|
3065
3080
|
nightReflectAt: settings.nightReflectAt || null,
|
|
3066
3081
|
approvals: settings.security && settings.security.approvals ? approvalsBridge : null,
|
|
3067
3082
|
alwaysAllowTools: (settings.security && settings.security.alwaysAllow) || [],
|
|
3083
|
+
/* Supermemory (lokal) bellek katmanı — default açıktır (parseSettingsText);
|
|
3084
|
+
sunucu ayakta değilse engine klasik hafızaya düşer. Kapamak:
|
|
3085
|
+
settings.json → supermemory.enabled = false */
|
|
3086
|
+
supermemory: settings.supermemory || { enabled: true, baseUrl: 'http://localhost:6767', apiKey: '', containerTag: 'beast' },
|
|
3068
3087
|
crashFile: FALLOUT_CRASH_FILE,
|
|
3069
3088
|
notifyOwnerFail: settings.notifyOwnerFail !== false,
|
|
3070
3089
|
fileSend: deliverFile,
|
|
@@ -3100,6 +3119,21 @@ function reloadBackend() {
|
|
|
3100
3119
|
},
|
|
3101
3120
|
emit: (ev) => {
|
|
3102
3121
|
if (win && !win.isDestroyed()) win.webContents.send('agent:event', ev);
|
|
3122
|
+
/* opencode permission (BC): ask kanalı UI'a zaten yukarıda düştü — WA
|
|
3123
|
+
sahibine de tek satır bildir gitsin (/approve · /approve always · /deny) */
|
|
3124
|
+
if (ev.type === 'permission.asked' && ev.request && wa && wa.connected) {
|
|
3125
|
+
try {
|
|
3126
|
+
const own = waOwnerNum();
|
|
3127
|
+
if (own) {
|
|
3128
|
+
const pats = Array.isArray(ev.request.patterns) ? ev.request.patterns.join(', ') : '*';
|
|
3129
|
+
sendWaSafe(
|
|
3130
|
+
own + '@s.whatsapp.net',
|
|
3131
|
+
'\u26A0\uFE0F *\u0130zin bekleniyor* \u2014 `' + String(ev.request.permission) + '`\n' +
|
|
3132
|
+
String(pats).slice(0, 160) + '\n\nOnayla: `/approve`\nBu desen i\u00e7in bir daha sorma: `/approve always`\nReddet: `/deny`'
|
|
3133
|
+
).catch(() => {});
|
|
3134
|
+
}
|
|
3135
|
+
} catch {}
|
|
3136
|
+
}
|
|
3103
3137
|
try { empatiRememberFromEvent(ev); } catch {} /* empati hafızası: sohbet → kayıt + ilgi öğrenme */
|
|
3104
3138
|
empatiFlushInjectsOnDone(ev); /* tur ortasında kuyruğa düşen proaktif bildirimleri iş bitince geçmişe bas */
|
|
3105
3139
|
flushDesktopOnDone(ev); /* biriken desktop mesajlarını sıraya bas */
|
|
@@ -6005,7 +6039,54 @@ ipcMain.handle('sec:set', (_e, cfg) => {
|
|
|
6005
6039
|
log.info('sec', `güvenlik: onay kapısı ${settings.security.approvals ? 'AÇIK' : 'KAPALI (her şey serbest)'}`);
|
|
6006
6040
|
return { approvals: settings.security.approvals, alwaysAllow: settings.security.alwaysAllow };
|
|
6007
6041
|
});
|
|
6008
|
-
|
|
6042
|
+
|
|
6043
|
+
/* Supermemory (lokal) ayarları: engine'e canlı yansıt + sağlık önbelleğini tazele */
|
|
6044
|
+
ipcMain.handle('supermemory:set', (_e, cfg) => {
|
|
6045
|
+
try {
|
|
6046
|
+
const base = String((cfg && cfg.baseUrl) || '').trim() || 'http://localhost:6767';
|
|
6047
|
+
settings.supermemory = {
|
|
6048
|
+
enabled: !!(cfg && cfg.enabled),
|
|
6049
|
+
baseUrl: base.replace(/\/+$/, ''),
|
|
6050
|
+
apiKey: String((cfg && cfg.apiKey) || '').trim(),
|
|
6051
|
+
containerTag: String((cfg && cfg.containerTag) || 'beast').trim() || 'beast',
|
|
6052
|
+
};
|
|
6053
|
+
saveSettings();
|
|
6054
|
+
if (engine) {
|
|
6055
|
+
engine.supermemory = settings.supermemory;
|
|
6056
|
+
engine._smUp = null;
|
|
6057
|
+
engine._smCheckedAt = 0;
|
|
6058
|
+
engine._smWarned = false;
|
|
6059
|
+
}
|
|
6060
|
+
return { ok: true, supermemory: settings.supermemory };
|
|
6061
|
+
} catch (e) {
|
|
6062
|
+
return { ok: false, error: String((e && e.message) || e) };
|
|
6063
|
+
}
|
|
6064
|
+
});
|
|
6065
|
+
ipcMain.handle('supermemory:get', () => {
|
|
6066
|
+
const sm = settings.supermemory || {};
|
|
6067
|
+
return {
|
|
6068
|
+
enabled: sm.enabled !== false,
|
|
6069
|
+
baseUrl: sm.baseUrl || 'http://localhost:6767',
|
|
6070
|
+
apiKey: sm.apiKey || '',
|
|
6071
|
+
containerTag: sm.containerTag || 'beast',
|
|
6072
|
+
up: engine ? !!engine._smUp : null,
|
|
6073
|
+
};
|
|
6074
|
+
});
|
|
6075
|
+
ipcMain.handle('approval:respond', (_e, { id, ok, always }) => resolveApproval(id, ok, always));
|
|
6076
|
+
/* opencode permission reply (BC): UI kartı üçlü cevap verir —
|
|
6077
|
+
'once' | 'always' | 'reject' (+ opsiyonel geri bildirim) */
|
|
6078
|
+
ipcMain.handle('permission:reply', (_e, payload) => {
|
|
6079
|
+
try {
|
|
6080
|
+
if (!engine || typeof engine.replyPermission !== 'function') return { ok: false, error: 'ajan hazır değil' };
|
|
6081
|
+
return engine.replyPermission(
|
|
6082
|
+
String((payload && payload.requestId) || ''),
|
|
6083
|
+
String((payload && payload.action) || 'once'),
|
|
6084
|
+
String((payload && payload.message) || '')
|
|
6085
|
+
);
|
|
6086
|
+
} catch (e) {
|
|
6087
|
+
return { ok: false, error: String((e && e.message) || e) };
|
|
6088
|
+
}
|
|
6089
|
+
});
|
|
6009
6090
|
|
|
6010
6091
|
/* ---------------- #Update IPC ---------------- */
|
|
6011
6092
|
ipcMain.handle('update:status', async () => {
|
|
@@ -7419,6 +7500,23 @@ ipcMain.handle('terminal:stop', () => {
|
|
|
7419
7500
|
panele orada akıtılır. */
|
|
7420
7501
|
const bcSessions = new Map(); /* klasör yolu → sessionId */
|
|
7421
7502
|
|
|
7503
|
+
/* opencode bayrak bindirme (bcCode disiplini): bcCode/bcAgent runtime
|
|
7504
|
+
bayrakları restart sonrası jsonl'den gelmez — her mesajda yeniden bindirilir.
|
|
7505
|
+
Ajan: 'plan' | 'build' | 'sandbox' (bcMode:'plan' oturumları geriye uyumlu
|
|
7506
|
+
plan'a düşer; Sandbox oturumları sandbox ajanına sabitlenir) */
|
|
7507
|
+
function bcBindOc(s, folder, agent) {
|
|
7508
|
+
s.workspace = folder;
|
|
7509
|
+
s.bcCode = true;
|
|
7510
|
+
const known = s.bcAgent === 'plan' || s.bcAgent === 'build' || s.bcAgent === 'sandbox';
|
|
7511
|
+
if (agent) {
|
|
7512
|
+
s.bcAgent = agent;
|
|
7513
|
+
} else if (!known) {
|
|
7514
|
+
s.bcAgent = String(s.bcMode || '').toLowerCase() === 'plan' ? 'plan' : 'build';
|
|
7515
|
+
}
|
|
7516
|
+
engine.cache.set(s.id, s);
|
|
7517
|
+
return s;
|
|
7518
|
+
}
|
|
7519
|
+
|
|
7422
7520
|
function bcGetSession(folder) {
|
|
7423
7521
|
let sid = bcSessions.get(folder);
|
|
7424
7522
|
if (sid) {
|
|
@@ -7431,7 +7529,8 @@ function bcGetSession(folder) {
|
|
|
7431
7529
|
const s = engine._load(engine.createSession().id);
|
|
7432
7530
|
s.messages = s.messages || [];
|
|
7433
7531
|
s.bgTitle = 'Beast Code'; /* _view.isBg → sohbet geçmişi listesinde gizli */
|
|
7434
|
-
s.bcCode = true; /*
|
|
7532
|
+
s.bcCode = true; /* opencode ajan sistemi: build/plan ajanları engine'de koşar */
|
|
7533
|
+
s.bcAgent = 'build'; /* opencode varsayılan ajanı (agent.ts:141) */
|
|
7435
7534
|
try {
|
|
7436
7535
|
fs.appendFileSync(
|
|
7437
7536
|
engine._file(s.id),
|
|
@@ -7500,9 +7599,7 @@ function bcFlush(folder) {
|
|
|
7500
7599
|
clearTimeout(q.timer);
|
|
7501
7600
|
return;
|
|
7502
7601
|
}
|
|
7503
|
-
s
|
|
7504
|
-
s.bcCode = true;
|
|
7505
|
-
engine.cache.set(s.id, s);
|
|
7602
|
+
bcBindOc(s, folder);
|
|
7506
7603
|
const payload = mergedAtts ? { text: merged, attachments: mergedAtts } : merged;
|
|
7507
7604
|
if (engine.send(s.id, payload, { userAction: true })) {
|
|
7508
7605
|
bcQueue.delete(folder);
|
|
@@ -7543,25 +7640,21 @@ ipcMain.handle('beastcode:send', async (_e, payload) => {
|
|
|
7543
7640
|
|
|
7544
7641
|
if (!engine.publicState().hasModel) return { ok: false, error: 'model yok — Ayarlar → Provider sekmesinden ekle' };
|
|
7545
7642
|
/* oturumu HEMEN aç: cevap daima gerçek sessionId taşır — renderer paneli bu id ile
|
|
7546
|
-
|
|
7547
|
-
const s = bcGetSession(ws);
|
|
7548
|
-
s.workspace = ws; /* soldaki klasörde çalış */
|
|
7549
|
-
s.bcCode = true; /* todo disiplini + iş sonu hızlı kapanış (engine) */
|
|
7550
|
-
engine.cache.set(s.id, s);
|
|
7643
|
+
eşler; boşta/kuyrukta olsa bile id yoksa panel olayları eşleyemez ve ölü kalır */
|
|
7644
|
+
const s = bcBindOc(bcGetSession(ws), ws);
|
|
7551
7645
|
const busy = engine.isBusy(s.id);
|
|
7552
7646
|
if (modeM) {
|
|
7553
|
-
/*
|
|
7554
|
-
|
|
7647
|
+
/* opencode ajan değişimi (agent.ts: plan/build primary ajanlar) — anında
|
|
7648
|
+
uygulanır, meşgulken de (yalnız ajan bayrağı; koşan tur çakışmaz) */
|
|
7649
|
+
const agent = engine.setBcAgent(s.id, modeM[1].toLowerCase() === 'plan' ? 'plan' : 'build');
|
|
7555
7650
|
if (win && !win.isDestroyed()) {
|
|
7556
|
-
const body =
|
|
7557
|
-
? 'PLAN
|
|
7558
|
-
:
|
|
7559
|
-
|
|
7560
|
-
: 'OTOMATİK MOD — önce kısa plan, sonra uygulama + doğrulama (OpenCode disiplini).';
|
|
7561
|
-
win.webContents.send('agent:event', { sessionId: s.id, type: 'bc-mode', mode: s.bcMode, body });
|
|
7651
|
+
const body = agent === 'plan'
|
|
7652
|
+
? 'PLAN AJANI (opencode plan) — salt-okur: dosyaları okur/inceler, KOD YAZMAZ; adım adım uygulama planı verir. Uygulamak için /build.'
|
|
7653
|
+
: 'BUILD AJANI (opencode build) — bağlamı inceler, todowrite ile planlar, uygular, doğrular.';
|
|
7654
|
+
win.webContents.send('agent:event', { sessionId: s.id, type: 'bc-agent', agent, body });
|
|
7562
7655
|
}
|
|
7563
|
-
return { ok: true, sessionId: s.id, mode:
|
|
7564
|
-
}
|
|
7656
|
+
return { ok: true, sessionId: s.id, agent, mode: agent };
|
|
7657
|
+
}
|
|
7565
7658
|
if (busy) {
|
|
7566
7659
|
/* OPENCODE STEER: koşan tur varken mesaj kuyrukta BEKLEMEZ — engine.send
|
|
7567
7660
|
konuşmaya ekler, koşan tur sonraki istekte görür (ana chat ile aynı) */
|
|
@@ -7655,8 +7748,7 @@ ipcMain.handle('bc:open', async (_e, payload) => {
|
|
|
7655
7748
|
if (s.bgTitle && s.bgTitle !== 'Beast Code') return { ok: false, error: 'bu oturum Beast Code oturumu değil' };
|
|
7656
7749
|
/* mevcut klasöre bağlan: sonraki mesajlar BU oturumda sürer */
|
|
7657
7750
|
const ws = ideRoot();
|
|
7658
|
-
s
|
|
7659
|
-
s.bcCode = true;
|
|
7751
|
+
bcBindOc(s, ws);
|
|
7660
7752
|
bcMarkWs(s, ws);
|
|
7661
7753
|
engine.cache.set(s.id, s);
|
|
7662
7754
|
bcSessions.set(ws, s.id);
|
|
@@ -7671,7 +7763,8 @@ ipcMain.handle('bc:open', async (_e, payload) => {
|
|
|
7671
7763
|
ok: true,
|
|
7672
7764
|
sessionId: s.id,
|
|
7673
7765
|
busy: !!engine.isBusy(s.id),
|
|
7674
|
-
|
|
7766
|
+
agent: s.bcAgent || 'build',
|
|
7767
|
+
mode: s.bcAgent || 'build',
|
|
7675
7768
|
messages: msgs.slice(-200),
|
|
7676
7769
|
};
|
|
7677
7770
|
});
|
|
@@ -8773,8 +8866,9 @@ function sandboxGetSession(folder) {
|
|
|
8773
8866
|
const s = engine._load(engine.createSession().id);
|
|
8774
8867
|
s.messages = s.messages || [];
|
|
8775
8868
|
s.bgTitle = 'Beast Sandbox'; /* _view.isBg → sohbet geçmişinde gizli */
|
|
8776
|
-
s.bcCode = true; /*
|
|
8777
|
-
s.sbSandbox = true; /* engine:
|
|
8869
|
+
s.bcCode = true; /* opencode ajan sistemi: sandbox ajanı engine'de koşar */
|
|
8870
|
+
s.sbSandbox = true; /* engine: 'sandbox' ajanı çözümlemesi */
|
|
8871
|
+
s.bcAgent = 'sandbox'; /* opencode custom-agent: repo disiplini + panel_run */
|
|
8778
8872
|
try {
|
|
8779
8873
|
fs.appendFileSync(
|
|
8780
8874
|
engine._file(s.id),
|
|
@@ -8817,10 +8911,10 @@ function sbFlush(folder) {
|
|
|
8817
8911
|
clearTimeout(q.timer);
|
|
8818
8912
|
return;
|
|
8819
8913
|
}
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
s.sbSandbox = true;
|
|
8823
|
-
|
|
8914
|
+
/* opencode mantığı: Sandbox da ajan sistemiyle koşar — 'sandbox' ajanı
|
|
8915
|
+
(repo disiplini + panel_run izni, opencode/agents.js'te tanımlı) */
|
|
8916
|
+
s.sbSandbox = true; /* engine: sandbox ajanı çözümlemesi + ÇALIŞTIR paneli köprüsü */
|
|
8917
|
+
bcBindOc(s, folder, 'sandbox');
|
|
8824
8918
|
const payload = mergedAtts ? { text: merged, attachments: mergedAtts } : merged;
|
|
8825
8919
|
engine.send(s.id, payload, { userAction: true });
|
|
8826
8920
|
sbQueue.delete(folder);
|
package/src/preload.js
CHANGED
|
@@ -87,6 +87,11 @@ contextBridge.exposeInMainWorld('beast', {
|
|
|
87
87
|
bcOpen: (id) => ipcRenderer.invoke('bc:open', { id }),
|
|
88
88
|
bcDelete: (id) => ipcRenderer.invoke('bc:delete', { id }),
|
|
89
89
|
bcDeleteAll: () => ipcRenderer.invoke('bc:deleteAll'),
|
|
90
|
+
/* opencode permission (BC): UI kartı cevabı — 'once' | 'always' | 'reject' */
|
|
91
|
+
permissionReply: (requestId, action, message) => ipcRenderer.invoke('permission:reply', { requestId, action, message }),
|
|
92
|
+
/* Supermemory (lokal) bellek katmanı ayarları */
|
|
93
|
+
supermemoryGet: () => ipcRenderer.invoke('supermemory:get'),
|
|
94
|
+
supermemorySet: (cfg) => ipcRenderer.invoke('supermemory:set', cfg),
|
|
90
95
|
studioSend: (msg, attachments) => ipcRenderer.invoke('studio:send', { msg, attachments }),
|
|
91
96
|
studioStop: () => ipcRenderer.invoke('studio:stop'),
|
|
92
97
|
studioNew: () => ipcRenderer.invoke('studio:new'),
|
package/src/renderer/renderer.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
/* Beast renderer — vanilla JS, event-driven via window.beast IPC bridge. */
|
|
4
4
|
|
|
@@ -762,7 +762,7 @@ function closeChatToolGroup() {
|
|
|
762
762
|
function argSummary(name, args) {
|
|
763
763
|
try {
|
|
764
764
|
if (name === 'run_command') return String(args.command || '');
|
|
765
|
-
if (name === 'read_file' || name === 'write_file' || name === 'edit_file') return String(args.path || '');
|
|
765
|
+
if (name === 'read_file' || name === 'write_file' || name === 'edit_file' || name === 'read' || name === 'write' || name === 'edit') return String(args.path || args.filePath || '');
|
|
766
766
|
if (name === 'grep') return String(args.pattern || '');
|
|
767
767
|
if (name === 'glob') return String(args.pattern || '');
|
|
768
768
|
if (name === 'list_dir') return String(args.path || '.');
|
|
@@ -3126,8 +3126,39 @@ async function renderUpdatePane(autoCheck) {
|
|
|
3126
3126
|
if (autoCheck) beast.updateCheck().catch(() => {});
|
|
3127
3127
|
}
|
|
3128
3128
|
|
|
3129
|
-
/*
|
|
3130
|
-
|
|
3129
|
+
/* opencode permission kartı (BC): izin isteği — Bir kez / Her zaman / Reddet.
|
|
3130
|
+
ev: {id, permission, patterns, metadata, always, tool} */
|
|
3131
|
+
function showPermissionCard(req, inBc) {
|
|
3132
|
+
const toolName = (req.tool && req.tool.name) || req.permission || 'izin';
|
|
3133
|
+
let preview = '';
|
|
3134
|
+
try {
|
|
3135
|
+
preview = JSON.stringify(req.metadata || {}).slice(0, 200);
|
|
3136
|
+
} catch {}
|
|
3137
|
+
const card = document.createElement('div');
|
|
3138
|
+
card.className = 'tool-card';
|
|
3139
|
+
card.innerHTML =
|
|
3140
|
+
`<div class="tool-head"><span class="tool-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></span>` +
|
|
3141
|
+
`<span class="tool-name">${escapeHtml(String(req.permission || 'izin'))}</span>` +
|
|
3142
|
+
`<span class="tool-arg">${escapeHtml(String(Array.isArray(req.patterns) ? req.patterns.join(', ') : '*').slice(0, 160))}</span></div>` +
|
|
3143
|
+
`<div class="tool-body open" style="display:flex;gap:8px;align-items:center">` +
|
|
3144
|
+
`<button class="btn ap-ok">${_t('sec_ok')}</button>` +
|
|
3145
|
+
`<button class="btn ghost ap-always">${_t('sec_always')}</button>` +
|
|
3146
|
+
`<button class="btn ghost ap-no">${_t('sec_no')}</button>` +
|
|
3147
|
+
`</div>`;
|
|
3148
|
+
const done = (txt) => {
|
|
3149
|
+
card.querySelector('.tool-body').innerHTML = `<span class="sub">${escapeHtml(txt)}</span>`;
|
|
3150
|
+
};
|
|
3151
|
+
card.querySelector('.ap-ok').addEventListener('click', async () => { await beast.permissionReply(req.id, 'once'); done(_t('sec_ok_done')); });
|
|
3152
|
+
card.querySelector('.ap-always').addEventListener('click', async () => { await beast.permissionReply(req.id, 'always'); done(_t('sec_always_done')); });
|
|
3153
|
+
card.querySelector('.ap-no').addEventListener('click', async () => { await beast.permissionReply(req.id, 'reject'); done(_t('sec_no_done')); });
|
|
3154
|
+
if (inBc && typeof bcLine === 'function') {
|
|
3155
|
+
bcLine('t-dim', '⏳ izin bekleniyor: ' + toolName + (preview ? ' — ' + preview : ''));
|
|
3156
|
+
}
|
|
3157
|
+
els.msgs.appendChild(card);
|
|
3158
|
+
scrollDown(true);
|
|
3159
|
+
}
|
|
3160
|
+
|
|
3161
|
+
/* Sohbete onay kartı düşürür — Onayla / Her zaman / Reddet */function showApprovalCard(ev) { streamEl = null;
|
|
3131
3162
|
const card = document.createElement('div');
|
|
3132
3163
|
card.className = 'tool-card';
|
|
3133
3164
|
card.innerHTML =
|
|
@@ -5061,6 +5092,15 @@ function onEvent(ev) {
|
|
|
5061
5092
|
return;
|
|
5062
5093
|
}
|
|
5063
5094
|
if (ev.type === 'install-progress') { updateInstallPct(ev); return; }
|
|
5095
|
+
/* opencode permission (BC): izin kartı — Bir kez / Her zaman / Reddet.
|
|
5096
|
+
BC oturumunda kart IDE panel akışına düşer; diğerlerinde sohbete */
|
|
5097
|
+
if (ev.type === 'permission.asked') {
|
|
5098
|
+
const req = ev.request || {};
|
|
5099
|
+
const isBc = bcSessionId && ev.sessionId === bcSessionId;
|
|
5100
|
+
if (!isBc && ev.sessionId && ev.sessionId !== activeId) return;
|
|
5101
|
+
showPermissionCard(req, isBc);
|
|
5102
|
+
return;
|
|
5103
|
+
}
|
|
5064
5104
|
/* Headroom durum değişimi → açık olan sekmeyi tazele (Token Sıkıştırma / Kurulum) */
|
|
5065
5105
|
if (ev.type === 'headroom-status') {
|
|
5066
5106
|
try {
|
|
@@ -5187,7 +5227,7 @@ function onEvent(ev) {
|
|
|
5187
5227
|
setStatus(ev.name + '…');
|
|
5188
5228
|
termAgentEvent(ev);
|
|
5189
5229
|
/* ajan dosya yazarsa/editlerse açık IDE sekmesini izlemeye al */
|
|
5190
|
-
if ((ev.name === 'write_file' || ev.name === 'edit_file') && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
|
|
5230
|
+
if ((ev.name === 'write_file' || ev.name === 'edit_file' || ev.name === 'write' || ev.name === 'edit') && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
|
|
5191
5231
|
break;
|
|
5192
5232
|
case 'tool-end':
|
|
5193
5233
|
finishToolCard(ev.callId, ev.ok, ev.result, ev.diff);
|
|
@@ -9388,7 +9428,7 @@ function bcIngest(ev) {
|
|
|
9388
9428
|
bcSetBusy(true); /* kuyruktan tetiklenen işte panel kendini kilitler */
|
|
9389
9429
|
bcToolBoxStart(ev.callId, ev.name, ev.args);
|
|
9390
9430
|
/* ajan dosya yazarsa/editlerse açık IDE sekmesini izlemeye al */
|
|
9391
|
-
if ((ev.name === 'write_file' || ev.name === 'edit_file') && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
|
|
9431
|
+
if ((ev.name === 'write_file' || ev.name === 'edit_file' || ev.name === 'write' || ev.name === 'edit') && ev.args && ev.args.path) codeWriteWatch.set(ev.callId, ev.args.path);
|
|
9392
9432
|
break;
|
|
9393
9433
|
case 'tool-end':
|
|
9394
9434
|
bcToolBoxEnd(ev.callId, ev.ok, ev.result, ev.diff);
|
|
@@ -9398,7 +9438,7 @@ function bcIngest(ev) {
|
|
|
9398
9438
|
codeReloadIfOpen(wp);
|
|
9399
9439
|
}
|
|
9400
9440
|
/* dosya/klasör üreten araçlardan sonra soldaki ağaç otomatik tazelensin */
|
|
9401
|
-
if (ev.name === 'write_file' || ev.name === 'edit_file' || ev.name === 'run_command' || ev.name === 'python_run') {
|
|
9441
|
+
if (ev.name === 'write_file' || ev.name === 'edit_file' || ev.name === 'write' || ev.name === 'edit' || ev.name === 'run_command' || ev.name === 'python_run') {
|
|
9402
9442
|
ideRefreshTree();
|
|
9403
9443
|
}
|
|
9404
9444
|
break;
|
|
@@ -9411,13 +9451,17 @@ function bcIngest(ev) {
|
|
|
9411
9451
|
bcQrShow(ev.qr, ev.url);
|
|
9412
9452
|
break;
|
|
9413
9453
|
case 'bc-mode':
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9454
|
+
case 'bc-agent':
|
|
9455
|
+
/* opencode ajan değişimi: başlıkta rozet + panelde bilgi satırı */
|
|
9456
|
+
{
|
|
9457
|
+
const agentName = ev.agent || ev.mode || '';
|
|
9458
|
+
if (els.bcTitle) {
|
|
9459
|
+
els.bcTitle.textContent =
|
|
9460
|
+
agentName === 'plan' ? 'BEAST CODE · PLAN' :
|
|
9461
|
+
agentName === 'build' ? 'BEAST CODE · BUILD' : 'BEAST CODE';
|
|
9462
|
+
}
|
|
9463
|
+
bcLine('t-dim', '[' + (ev.body || agentName || 'ajan değişti') + ']');
|
|
9419
9464
|
}
|
|
9420
|
-
bcLine('t-dim', '[' + (ev.body || ev.mode || 'mod değişti') + ']');
|
|
9421
9465
|
break;
|
|
9422
9466
|
case 'done':
|
|
9423
9467
|
bcFlushStream();
|
|
@@ -9863,7 +9907,7 @@ function stIngest(ev) {
|
|
|
9863
9907
|
break;
|
|
9864
9908
|
case 'tool-end':
|
|
9865
9909
|
stToolBoxEnd(ev.callId, ev.ok, ev.result, ev.diff);
|
|
9866
|
-
if (ev.name === 'write_file' || ev.name === 'edit_file' || ev.name === 'run_command' || ev.name === 'python_run') {
|
|
9910
|
+
if (ev.name === 'write_file' || ev.name === 'edit_file' || ev.name === 'write' || ev.name === 'edit' || ev.name === 'run_command' || ev.name === 'python_run') {
|
|
9867
9911
|
ideRefreshTree(); /* ffmpeg çıktısı anında ağaca düşer */
|
|
9868
9912
|
}
|
|
9869
9913
|
break;
|
|
@@ -10094,7 +10138,7 @@ function sbIngest(ev) {
|
|
|
10094
10138
|
const ok = ev.ok !== false;
|
|
10095
10139
|
sbLine(ok ? 't-dim' : 't-err', (ok ? ' \u2713 ' : ' \u2717 ') + String(ev.result || '').replace(/\s+/g, ' ').slice(0, 160));
|
|
10096
10140
|
/* ajan dosya yazarsa/editlerse soldaki repo ağacı canlı tazelenir */
|
|
10097
|
-
if (ev.name === 'write_file' || ev.name === 'edit_file' || ev.name === 'run_command') ideRefreshTree();
|
|
10141
|
+
if (ev.name === 'write_file' || ev.name === 'edit_file' || ev.name === 'write' || ev.name === 'edit' || ev.name === 'run_command') ideRefreshTree();
|
|
10098
10142
|
break;
|
|
10099
10143
|
}
|
|
10100
10144
|
case 'status':
|