beast-agent 2.15.0 → 2.16.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 +417 -154
- 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/main.js +93 -41
- package/src/preload.js +2 -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');
|
|
@@ -1335,6 +1335,18 @@ function resolveApproval(id, ok, always) {
|
|
|
1335
1335
|
}
|
|
1336
1336
|
|
|
1337
1337
|
function resolveFirstApproval(ok, always) {
|
|
1338
|
+
/* opencode permission (BC): önce opencode izin istekleri yanıtlanır —
|
|
1339
|
+
cevap 'once' | 'always' | 'reject' üçlüsüdür (permission/reply portu) */
|
|
1340
|
+
if (engine && typeof engine.replyPermission === 'function') {
|
|
1341
|
+
try {
|
|
1342
|
+
const pend = engine._perm && engine._perm.list ? engine._perm.list() : [];
|
|
1343
|
+
if (pend.length) {
|
|
1344
|
+
const action = ok ? (always ? 'always' : 'once') : 'reject';
|
|
1345
|
+
const r = engine.replyPermission(pend[0].id, action);
|
|
1346
|
+
if (r && r.ok) return { ok: true, tool: pend[0].permission };
|
|
1347
|
+
}
|
|
1348
|
+
} catch {}
|
|
1349
|
+
}
|
|
1338
1350
|
const first = pendingApprovals.keys().next();
|
|
1339
1351
|
if (first.done) return { ok: false, error: 'bekleyen onay yok' };
|
|
1340
1352
|
return resolveApproval(first.value, ok, always);
|
|
@@ -1677,17 +1689,17 @@ async function tryWaSlash(jid, rawText, senderNum, payload0) {
|
|
|
1677
1689
|
`Tekrar kodlamak için: /beastcode`;
|
|
1678
1690
|
}
|
|
1679
1691
|
} else if (waBcMode.has(jid) && (cmd === 'plan' || cmd === 'build' || cmd === 'auto')) {
|
|
1680
|
-
/*
|
|
1692
|
+
/* opencode ajan değişimi (WA): /plan → plan ajanı (salt-okur),
|
|
1693
|
+
/build · /auto → build ajanı (varsayılan; auto opencode'da yoktur) */
|
|
1681
1694
|
const sid = waChats.get(jid);
|
|
1682
1695
|
const s = sid ? engine.cache.get(sid) : null;
|
|
1683
1696
|
if (s && s.bcCode) {
|
|
1684
|
-
s.
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
? '*🔍 PLAN MODU* — dosyaları inceler, kod YAZMAZ; adım adım uygulama planı verir.'
|
|
1697
|
+
const agent = engine.setBcAgent(s.id, cmd === 'plan' ? 'plan' : 'build');
|
|
1698
|
+
out = agent === 'plan'
|
|
1699
|
+
? '*🔍 PLAN AJANI* (opencode plan) — salt-okur: dosyaları okur/inceler, kod YAZMAZ; adım adım uygulama planı verir. Uygulamak için /build yaz.'
|
|
1688
1700
|
: cmd === 'build'
|
|
1689
|
-
? '*🛠 BUILD
|
|
1690
|
-
: '*⚡
|
|
1701
|
+
? '*🛠 BUILD AJANI* (opencode build) — bağlamı inceler, todowrite ile planlar, uygular, doğrular.'
|
|
1702
|
+
: '*⚡ BUILD AJANI* (opencode build) — kısa plan + hemen uygulama + doğrulama.';
|
|
1691
1703
|
} else {
|
|
1692
1704
|
out = 'Bu komut yalnız BeastCode modunda çalışır — önce /beastcode yaz.';
|
|
1693
1705
|
}
|
|
@@ -2441,14 +2453,12 @@ async function processWaMessage(jid, payload, senderNum, requeues = 0) {
|
|
|
2441
2453
|
}
|
|
2442
2454
|
engine.setSessionModel(sid, botCfg && !botCfg.admin ? (botCfg.model || null) : null);
|
|
2443
2455
|
/* BEASTCODE MODU: sohbet uzaktan kodlama modundaysa oturumu Beast Code
|
|
2444
|
-
olarak tazele — restart sonrası bcCode/workspace bayrakları dosyadan
|
|
2456
|
+
olarak tazele — restart sonrası bcCode/bcAgent/workspace bayrakları dosyadan
|
|
2445
2457
|
yüklenmediği için masaüstü bcFlush disipliniyle her mesajda bindirilir */
|
|
2446
2458
|
if (waBcMode.has(jid)) {
|
|
2447
2459
|
const bs = engine.cache.get(sid);
|
|
2448
2460
|
if (bs) {
|
|
2449
|
-
bs
|
|
2450
|
-
bs.workspace = waBcWorkspace();
|
|
2451
|
-
engine.cache.set(sid, bs);
|
|
2461
|
+
bcBindOc(bs, waBcWorkspace());
|
|
2452
2462
|
}
|
|
2453
2463
|
}
|
|
2454
2464
|
waLog(`perm=${fmtPerm(perm)} bot=${botId} sid=${sid}${waBcMode.has(jid) ? ' beastcode=1' : ''}`);
|
|
@@ -3100,6 +3110,21 @@ function reloadBackend() {
|
|
|
3100
3110
|
},
|
|
3101
3111
|
emit: (ev) => {
|
|
3102
3112
|
if (win && !win.isDestroyed()) win.webContents.send('agent:event', ev);
|
|
3113
|
+
/* opencode permission (BC): ask kanalı UI'a zaten yukarıda düştü — WA
|
|
3114
|
+
sahibine de tek satır bildir gitsin (/approve · /approve always · /deny) */
|
|
3115
|
+
if (ev.type === 'permission.asked' && ev.request && wa && wa.connected) {
|
|
3116
|
+
try {
|
|
3117
|
+
const own = waOwnerNum();
|
|
3118
|
+
if (own) {
|
|
3119
|
+
const pats = Array.isArray(ev.request.patterns) ? ev.request.patterns.join(', ') : '*';
|
|
3120
|
+
sendWaSafe(
|
|
3121
|
+
own + '@s.whatsapp.net',
|
|
3122
|
+
'\u26A0\uFE0F *\u0130zin bekleniyor* \u2014 `' + String(ev.request.permission) + '`\n' +
|
|
3123
|
+
String(pats).slice(0, 160) + '\n\nOnayla: `/approve`\nBu desen i\u00e7in bir daha sorma: `/approve always`\nReddet: `/deny`'
|
|
3124
|
+
).catch(() => {});
|
|
3125
|
+
}
|
|
3126
|
+
} catch {}
|
|
3127
|
+
}
|
|
3103
3128
|
try { empatiRememberFromEvent(ev); } catch {} /* empati hafızası: sohbet → kayıt + ilgi öğrenme */
|
|
3104
3129
|
empatiFlushInjectsOnDone(ev); /* tur ortasında kuyruğa düşen proaktif bildirimleri iş bitince geçmişe bas */
|
|
3105
3130
|
flushDesktopOnDone(ev); /* biriken desktop mesajlarını sıraya bas */
|
|
@@ -6005,7 +6030,21 @@ ipcMain.handle('sec:set', (_e, cfg) => {
|
|
|
6005
6030
|
log.info('sec', `güvenlik: onay kapısı ${settings.security.approvals ? 'AÇIK' : 'KAPALI (her şey serbest)'}`);
|
|
6006
6031
|
return { approvals: settings.security.approvals, alwaysAllow: settings.security.alwaysAllow };
|
|
6007
6032
|
});
|
|
6008
|
-
ipcMain.handle('approval:respond', (_e, { id, ok, always }) => resolveApproval(id, ok, always));
|
|
6033
|
+
ipcMain.handle('approval:respond', (_e, { id, ok, always }) => resolveApproval(id, ok, always));
|
|
6034
|
+
/* opencode permission reply (BC): UI kartı üçlü cevap verir —
|
|
6035
|
+
'once' | 'always' | 'reject' (+ opsiyonel geri bildirim) */
|
|
6036
|
+
ipcMain.handle('permission:reply', (_e, payload) => {
|
|
6037
|
+
try {
|
|
6038
|
+
if (!engine || typeof engine.replyPermission !== 'function') return { ok: false, error: 'ajan hazır değil' };
|
|
6039
|
+
return engine.replyPermission(
|
|
6040
|
+
String((payload && payload.requestId) || ''),
|
|
6041
|
+
String((payload && payload.action) || 'once'),
|
|
6042
|
+
String((payload && payload.message) || '')
|
|
6043
|
+
);
|
|
6044
|
+
} catch (e) {
|
|
6045
|
+
return { ok: false, error: String((e && e.message) || e) };
|
|
6046
|
+
}
|
|
6047
|
+
});
|
|
6009
6048
|
|
|
6010
6049
|
/* ---------------- #Update IPC ---------------- */
|
|
6011
6050
|
ipcMain.handle('update:status', async () => {
|
|
@@ -7419,6 +7458,23 @@ ipcMain.handle('terminal:stop', () => {
|
|
|
7419
7458
|
panele orada akıtılır. */
|
|
7420
7459
|
const bcSessions = new Map(); /* klasör yolu → sessionId */
|
|
7421
7460
|
|
|
7461
|
+
/* opencode bayrak bindirme (bcCode disiplini): bcCode/bcAgent runtime
|
|
7462
|
+
bayrakları restart sonrası jsonl'den gelmez — her mesajda yeniden bindirilir.
|
|
7463
|
+
Ajan: 'plan' | 'build' | 'sandbox' (bcMode:'plan' oturumları geriye uyumlu
|
|
7464
|
+
plan'a düşer; Sandbox oturumları sandbox ajanına sabitlenir) */
|
|
7465
|
+
function bcBindOc(s, folder, agent) {
|
|
7466
|
+
s.workspace = folder;
|
|
7467
|
+
s.bcCode = true;
|
|
7468
|
+
const known = s.bcAgent === 'plan' || s.bcAgent === 'build' || s.bcAgent === 'sandbox';
|
|
7469
|
+
if (agent) {
|
|
7470
|
+
s.bcAgent = agent;
|
|
7471
|
+
} else if (!known) {
|
|
7472
|
+
s.bcAgent = String(s.bcMode || '').toLowerCase() === 'plan' ? 'plan' : 'build';
|
|
7473
|
+
}
|
|
7474
|
+
engine.cache.set(s.id, s);
|
|
7475
|
+
return s;
|
|
7476
|
+
}
|
|
7477
|
+
|
|
7422
7478
|
function bcGetSession(folder) {
|
|
7423
7479
|
let sid = bcSessions.get(folder);
|
|
7424
7480
|
if (sid) {
|
|
@@ -7431,7 +7487,8 @@ function bcGetSession(folder) {
|
|
|
7431
7487
|
const s = engine._load(engine.createSession().id);
|
|
7432
7488
|
s.messages = s.messages || [];
|
|
7433
7489
|
s.bgTitle = 'Beast Code'; /* _view.isBg → sohbet geçmişi listesinde gizli */
|
|
7434
|
-
s.bcCode = true; /*
|
|
7490
|
+
s.bcCode = true; /* opencode ajan sistemi: build/plan ajanları engine'de koşar */
|
|
7491
|
+
s.bcAgent = 'build'; /* opencode varsayılan ajanı (agent.ts:141) */
|
|
7435
7492
|
try {
|
|
7436
7493
|
fs.appendFileSync(
|
|
7437
7494
|
engine._file(s.id),
|
|
@@ -7500,9 +7557,7 @@ function bcFlush(folder) {
|
|
|
7500
7557
|
clearTimeout(q.timer);
|
|
7501
7558
|
return;
|
|
7502
7559
|
}
|
|
7503
|
-
s
|
|
7504
|
-
s.bcCode = true;
|
|
7505
|
-
engine.cache.set(s.id, s);
|
|
7560
|
+
bcBindOc(s, folder);
|
|
7506
7561
|
const payload = mergedAtts ? { text: merged, attachments: mergedAtts } : merged;
|
|
7507
7562
|
if (engine.send(s.id, payload, { userAction: true })) {
|
|
7508
7563
|
bcQueue.delete(folder);
|
|
@@ -7543,25 +7598,21 @@ ipcMain.handle('beastcode:send', async (_e, payload) => {
|
|
|
7543
7598
|
|
|
7544
7599
|
if (!engine.publicState().hasModel) return { ok: false, error: 'model yok — Ayarlar → Provider sekmesinden ekle' };
|
|
7545
7600
|
/* 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);
|
|
7601
|
+
eşler; boşta/kuyrukta olsa bile id yoksa panel olayları eşleyemez ve ölü kalır */
|
|
7602
|
+
const s = bcBindOc(bcGetSession(ws), ws);
|
|
7551
7603
|
const busy = engine.isBusy(s.id);
|
|
7552
7604
|
if (modeM) {
|
|
7553
|
-
/*
|
|
7554
|
-
|
|
7605
|
+
/* opencode ajan değişimi (agent.ts: plan/build primary ajanlar) — anında
|
|
7606
|
+
uygulanır, meşgulken de (yalnız ajan bayrağı; koşan tur çakışmaz) */
|
|
7607
|
+
const agent = engine.setBcAgent(s.id, modeM[1].toLowerCase() === 'plan' ? 'plan' : 'build');
|
|
7555
7608
|
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 });
|
|
7609
|
+
const body = agent === 'plan'
|
|
7610
|
+
? 'PLAN AJANI (opencode plan) — salt-okur: dosyaları okur/inceler, KOD YAZMAZ; adım adım uygulama planı verir. Uygulamak için /build.'
|
|
7611
|
+
: 'BUILD AJANI (opencode build) — bağlamı inceler, todowrite ile planlar, uygular, doğrular.';
|
|
7612
|
+
win.webContents.send('agent:event', { sessionId: s.id, type: 'bc-agent', agent, body });
|
|
7562
7613
|
}
|
|
7563
|
-
return { ok: true, sessionId: s.id, mode:
|
|
7564
|
-
}
|
|
7614
|
+
return { ok: true, sessionId: s.id, agent, mode: agent };
|
|
7615
|
+
}
|
|
7565
7616
|
if (busy) {
|
|
7566
7617
|
/* OPENCODE STEER: koşan tur varken mesaj kuyrukta BEKLEMEZ — engine.send
|
|
7567
7618
|
konuşmaya ekler, koşan tur sonraki istekte görür (ana chat ile aynı) */
|
|
@@ -7655,8 +7706,7 @@ ipcMain.handle('bc:open', async (_e, payload) => {
|
|
|
7655
7706
|
if (s.bgTitle && s.bgTitle !== 'Beast Code') return { ok: false, error: 'bu oturum Beast Code oturumu değil' };
|
|
7656
7707
|
/* mevcut klasöre bağlan: sonraki mesajlar BU oturumda sürer */
|
|
7657
7708
|
const ws = ideRoot();
|
|
7658
|
-
s
|
|
7659
|
-
s.bcCode = true;
|
|
7709
|
+
bcBindOc(s, ws);
|
|
7660
7710
|
bcMarkWs(s, ws);
|
|
7661
7711
|
engine.cache.set(s.id, s);
|
|
7662
7712
|
bcSessions.set(ws, s.id);
|
|
@@ -7671,7 +7721,8 @@ ipcMain.handle('bc:open', async (_e, payload) => {
|
|
|
7671
7721
|
ok: true,
|
|
7672
7722
|
sessionId: s.id,
|
|
7673
7723
|
busy: !!engine.isBusy(s.id),
|
|
7674
|
-
|
|
7724
|
+
agent: s.bcAgent || 'build',
|
|
7725
|
+
mode: s.bcAgent || 'build',
|
|
7675
7726
|
messages: msgs.slice(-200),
|
|
7676
7727
|
};
|
|
7677
7728
|
});
|
|
@@ -8773,8 +8824,9 @@ function sandboxGetSession(folder) {
|
|
|
8773
8824
|
const s = engine._load(engine.createSession().id);
|
|
8774
8825
|
s.messages = s.messages || [];
|
|
8775
8826
|
s.bgTitle = 'Beast Sandbox'; /* _view.isBg → sohbet geçmişinde gizli */
|
|
8776
|
-
s.bcCode = true; /*
|
|
8777
|
-
s.sbSandbox = true; /* engine:
|
|
8827
|
+
s.bcCode = true; /* opencode ajan sistemi: sandbox ajanı engine'de koşar */
|
|
8828
|
+
s.sbSandbox = true; /* engine: 'sandbox' ajanı çözümlemesi */
|
|
8829
|
+
s.bcAgent = 'sandbox'; /* opencode custom-agent: repo disiplini + panel_run */
|
|
8778
8830
|
try {
|
|
8779
8831
|
fs.appendFileSync(
|
|
8780
8832
|
engine._file(s.id),
|
|
@@ -8817,10 +8869,10 @@ function sbFlush(folder) {
|
|
|
8817
8869
|
clearTimeout(q.timer);
|
|
8818
8870
|
return;
|
|
8819
8871
|
}
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
s.sbSandbox = true;
|
|
8823
|
-
|
|
8872
|
+
/* opencode mantığı: Sandbox da ajan sistemiyle koşar — 'sandbox' ajanı
|
|
8873
|
+
(repo disiplini + panel_run izni, opencode/agents.js'te tanımlı) */
|
|
8874
|
+
s.sbSandbox = true; /* engine: sandbox ajanı çözümlemesi + ÇALIŞTIR paneli köprüsü */
|
|
8875
|
+
bcBindOc(s, folder, 'sandbox');
|
|
8824
8876
|
const payload = mergedAtts ? { text: merged, attachments: mergedAtts } : merged;
|
|
8825
8877
|
engine.send(s.id, payload, { userAction: true });
|
|
8826
8878
|
sbQueue.delete(folder);
|
package/src/preload.js
CHANGED
|
@@ -87,6 +87,8 @@ 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 }),
|
|
90
92
|
studioSend: (msg, attachments) => ipcRenderer.invoke('studio:send', { msg, attachments }),
|
|
91
93
|
studioStop: () => ipcRenderer.invoke('studio:stop'),
|
|
92
94
|
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':
|