opc-agent 4.1.24 → 4.2.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/CHANGELOG.md +59 -119
- package/COMPETITIVE-GAP.md +92 -92
- package/CONTRIBUTING.md +36 -36
- package/README.md +290 -290
- package/README.zh-CN.md +269 -269
- package/dist/channels/telegram.d.ts +0 -5
- package/dist/channels/telegram.d.ts.map +1 -1
- package/dist/channels/telegram.js +0 -108
- package/dist/channels/telegram.js.map +1 -1
- package/dist/channels/voice.d.ts +97 -71
- package/dist/channels/voice.d.ts.map +1 -1
- package/dist/channels/voice.js +347 -369
- package/dist/channels/voice.js.map +1 -1
- package/dist/channels/web.d.ts.map +1 -1
- package/dist/channels/web.js +2 -8
- package/dist/channels/web.js.map +1 -1
- package/dist/channels/wechat.js +6 -6
- package/dist/cli/chat.d.ts +1 -4
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +73 -680
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/setup.js +1 -1
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli.js +280 -373
- package/dist/cli.js.map +1 -1
- package/dist/core/agent.d.ts +0 -1
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +0 -3
- package/dist/core/agent.js.map +1 -1
- package/dist/core/runtime.d.ts.map +1 -1
- package/dist/core/runtime.js +22 -192
- package/dist/core/runtime.js.map +1 -1
- package/dist/deploy/index.js +56 -56
- package/dist/doctor.d.ts +0 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +10 -155
- package/dist/doctor.js.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -9
- package/dist/index.js.map +1 -1
- package/dist/memory/deepbrain.d.ts +1 -1
- package/dist/memory/deepbrain.d.ts.map +1 -1
- package/dist/memory/deepbrain.js +4 -95
- package/dist/memory/deepbrain.js.map +1 -1
- package/dist/memory/index.d.ts +0 -2
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +1 -3
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/user-profiler.d.ts +0 -8
- package/dist/memory/user-profiler.d.ts.map +1 -1
- package/dist/memory/user-profiler.js +0 -89
- package/dist/memory/user-profiler.js.map +1 -1
- package/dist/scheduler/cron-engine.d.ts.map +1 -1
- package/dist/scheduler/cron-engine.js +36 -3
- package/dist/scheduler/cron-engine.js.map +1 -1
- package/dist/skills/auto-learn.d.ts.map +1 -1
- package/dist/skills/auto-learn.js +11 -65
- package/dist/skills/auto-learn.js.map +1 -1
- package/dist/skills/builtin/index.d.ts.map +1 -1
- package/dist/skills/builtin/index.js +30 -163
- package/dist/skills/builtin/index.js.map +1 -1
- package/dist/skills/types.d.ts +1 -1
- package/dist/skills/types.d.ts.map +1 -1
- package/dist/skills/types.js +0 -1
- package/dist/skills/types.js.map +1 -1
- package/dist/studio/server.d.ts +0 -1
- package/dist/studio/server.d.ts.map +1 -1
- package/dist/studio/server.js +12 -142
- package/dist/studio/server.js.map +1 -1
- package/dist/studio-ui/index.html +40 -359
- package/dist/ui/components.js +105 -105
- package/examples/README.md +22 -22
- package/examples/basic-agent.ts +90 -90
- package/examples/brain-integration.ts +71 -71
- package/examples/multi-channel.ts +74 -74
- package/install.ps1 +127 -127
- package/install.sh +154 -154
- package/models.json +164 -164
- package/package.json +63 -66
- package/scripts/install.ps1 +31 -31
- package/scripts/install.sh +40 -40
- package/templates/ecommerce-assistant/README.md +45 -45
- package/templates/ecommerce-assistant/oad.yaml +47 -47
- package/templates/tech-support/README.md +43 -43
- package/templates/tech-support/oad.yaml +45 -45
- package/.opc/memory.db +0 -0
- package/dist/core/model-recommender.d.ts +0 -40
- package/dist/core/model-recommender.d.ts.map +0 -1
- package/dist/core/model-recommender.js +0 -186
- package/dist/core/model-recommender.js.map +0 -1
- package/dist/memory/evolve-engine.d.ts +0 -113
- package/dist/memory/evolve-engine.d.ts.map +0 -1
- package/dist/memory/evolve-engine.js +0 -549
- package/dist/memory/evolve-engine.js.map +0 -1
- package/dist/memory/sqlite-store.d.ts +0 -40
- package/dist/memory/sqlite-store.d.ts.map +0 -1
- package/dist/memory/sqlite-store.js +0 -269
- package/dist/memory/sqlite-store.js.map +0 -1
- package/dist/scheduler/proactive.d.ts +0 -62
- package/dist/scheduler/proactive.d.ts.map +0 -1
- package/dist/scheduler/proactive.js +0 -185
- package/dist/scheduler/proactive.js.map +0 -1
|
@@ -388,9 +388,6 @@
|
|
|
388
388
|
<div class="nav-item" data-page="global-models" onclick="navigate('global-models')">
|
|
389
389
|
<span class="icon">🧠</span> Models
|
|
390
390
|
</div>
|
|
391
|
-
<div class="nav-item" data-page="global-channels" onclick="navigate('global-channels')">
|
|
392
|
-
<span class="icon">📡</span> Channels
|
|
393
|
-
</div>
|
|
394
391
|
<div class="nav-item" data-page="global-memory" onclick="navigate('global-memory')">
|
|
395
392
|
<span class="icon">💾</span> Memory
|
|
396
393
|
</div>
|
|
@@ -422,14 +419,6 @@
|
|
|
422
419
|
</div>
|
|
423
420
|
<button class="btn btn-primary" onclick="navigate('create')">✨ Create New Agent</button>
|
|
424
421
|
</div>
|
|
425
|
-
<!-- Dashboard Stats -->
|
|
426
|
-
<div class="card-grid" style="margin-bottom:24px;" id="dashboard-stats"></div>
|
|
427
|
-
<!-- Quick Actions -->
|
|
428
|
-
<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:24px;" id="dashboard-actions">
|
|
429
|
-
<button class="btn btn-secondary" onclick="navigate('create')">✨ Create Agent</button>
|
|
430
|
-
<button class="btn btn-secondary" onclick="navigate('global-models')">🧠 Configure Model</button>
|
|
431
|
-
<button class="btn btn-secondary" onclick="navigate('templates')">📋 Browse Templates</button>
|
|
432
|
-
</div>
|
|
433
422
|
<!-- Health Status Section -->
|
|
434
423
|
<div id="health-section" style="margin-bottom:24px;"></div>
|
|
435
424
|
<div id="agents-list" class="card-grid"></div>
|
|
@@ -481,46 +470,31 @@
|
|
|
481
470
|
<div class="agent-settings-content" id="agent-settings-content">
|
|
482
471
|
<div class="agent-tab-panel active" id="atab-role">
|
|
483
472
|
<h3>角色配置</h3>
|
|
484
|
-
<
|
|
485
|
-
<div class="form-group"><label class="label">描述</label><textarea class="input" id="atab-role-desc" rows="2" placeholder="Brief description..."></textarea></div>
|
|
486
|
-
<div class="form-group"><label class="label">System Prompt</label><textarea class="input" id="atab-role-prompt" rows="6" placeholder="You are a helpful assistant..."></textarea></div>
|
|
487
|
-
<button class="btn btn-primary" onclick="saveAgentRole()">💾 保存</button>
|
|
488
|
-
<span id="atab-role-status" style="margin-left:12px;font-size:18px;"></span>
|
|
473
|
+
<p style="color:var(--text-muted)">Agent 角色和人设配置(即将上线)</p>
|
|
489
474
|
</div>
|
|
490
475
|
<div class="agent-tab-panel" id="atab-models">
|
|
491
476
|
<h3>模型配置</h3>
|
|
492
|
-
<
|
|
493
|
-
<label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-size:18px;"><input type="checkbox" id="atab-model-override"> 覆盖全局模型设置</label>
|
|
494
|
-
</div>
|
|
495
|
-
<div id="atab-model-fields" style="display:none;">
|
|
496
|
-
<div class="form-group"><label class="label">Provider</label><select class="input" id="atab-model-provider"><option value="ollama">Ollama (Local)</option><option value="openai">OpenAI</option><option value="anthropic">Anthropic</option><option value="deepseek">DeepSeek</option></select></div>
|
|
497
|
-
<div class="form-group"><label class="label">Model</label><input class="input" id="atab-model-name" placeholder="e.g. gpt-4o-mini"></div>
|
|
498
|
-
<div class="form-group"><label class="label">Temperature</label><input class="input" id="atab-model-temp" type="number" min="0" max="2" step="0.1" value="0.7"></div>
|
|
499
|
-
</div>
|
|
500
|
-
<button class="btn btn-primary" onclick="saveAgentModel()">💾 保存</button>
|
|
501
|
-
<span id="atab-model-status" style="margin-left:12px;font-size:18px;"></span>
|
|
477
|
+
<p style="color:var(--text-muted)">Agent 使用的模型配置(即将上线)</p>
|
|
502
478
|
</div>
|
|
503
479
|
<div class="agent-tab-panel" id="atab-channels">
|
|
504
480
|
<h3>渠道配置</h3>
|
|
505
|
-
<
|
|
506
|
-
<button class="btn btn-primary" style="margin-top:16px;" onclick="saveAgentChannels()">💾 保存</button>
|
|
507
|
-
<span id="atab-channels-status" style="margin-left:12px;font-size:18px;"></span>
|
|
481
|
+
<p style="color:var(--text-muted)">Agent 接入的渠道配置(即将上线)</p>
|
|
508
482
|
</div>
|
|
509
483
|
<div class="agent-tab-panel" id="atab-memory">
|
|
510
484
|
<h3>记忆管理</h3>
|
|
511
|
-
<
|
|
485
|
+
<p style="color:var(--text-muted)">Agent 记忆和知识库(即将上线)</p>
|
|
512
486
|
</div>
|
|
513
487
|
<div class="agent-tab-panel" id="atab-skills">
|
|
514
488
|
<h3>技能配置</h3>
|
|
515
|
-
<
|
|
489
|
+
<p style="color:var(--text-muted)">Agent 已安装的技能(即将上线)</p>
|
|
516
490
|
</div>
|
|
517
491
|
<div class="agent-tab-panel" id="atab-schedules">
|
|
518
492
|
<h3>定时任务</h3>
|
|
519
|
-
<
|
|
493
|
+
<p style="color:var(--text-muted)">Agent 定时任务配置(即将上线)</p>
|
|
520
494
|
</div>
|
|
521
495
|
<div class="agent-tab-panel" id="atab-usage">
|
|
522
496
|
<h3>用量统计</h3>
|
|
523
|
-
<
|
|
497
|
+
<p style="color:var(--text-muted)">Agent 使用量和成本(即将上线)</p>
|
|
524
498
|
</div>
|
|
525
499
|
</div>
|
|
526
500
|
</div>
|
|
@@ -633,42 +607,22 @@
|
|
|
633
607
|
<label class="label">Company / Business Description</label>
|
|
634
608
|
<textarea class="input" id="agent-desc" rows="3" placeholder="Brief description of your business so the agent can better help you..."></textarea>
|
|
635
609
|
</div>
|
|
636
|
-
|
|
637
|
-
<!-- AI Prompt Generator -->
|
|
638
|
-
<div class="form-group">
|
|
639
|
-
<label class="label">What should this agent do? <span style="color:var(--text-dim);font-size:13px;">(Describe in plain words, AI generates the prompt)</span></label>
|
|
640
|
-
<textarea class="input" id="agent-task-desc" rows="2" placeholder="e.g. Help me answer customer questions about our products, be friendly and professional..."></textarea>
|
|
641
|
-
<button class="btn btn-sm" style="margin-top:8px;background:var(--accent-light);color:var(--accent);border:1px solid var(--border);" onclick="generatePrompt()">✨ AI Generate Prompt</button>
|
|
642
|
-
<textarea class="input" id="agent-prompt" rows="4" placeholder="System prompt will appear here (or write your own)..." style="margin-top:8px;display:none;"></textarea>
|
|
643
|
-
</div>
|
|
644
|
-
|
|
645
610
|
<div class="form-group">
|
|
646
611
|
<label class="label">AI Model</label>
|
|
647
612
|
<select class="input" id="agent-model">
|
|
648
|
-
<option value="
|
|
649
|
-
<option value="
|
|
650
|
-
<option value="
|
|
651
|
-
<option value="
|
|
652
|
-
<option value="
|
|
653
|
-
<option value="
|
|
654
|
-
<option value="claude-sonnet-4">☁️ Claude Sonnet (Balanced)</option>
|
|
655
|
-
<option value="deepseek-v3">☁️ DeepSeek V3 (Affordable)</option>
|
|
656
|
-
<option value="gemini-2.0-flash">☁️ Gemini Flash (Google)</option>
|
|
613
|
+
<option value="gpt-4o-mini">GPT-4o Mini (Fast & Affordable) ⭐ Recommended</option>
|
|
614
|
+
<option value="gpt-4o">GPT-4o (Most Capable)</option>
|
|
615
|
+
<option value="claude-sonnet-4">Claude Sonnet (Balanced)</option>
|
|
616
|
+
<option value="claude-haiku">Claude Haiku (Fast)</option>
|
|
617
|
+
<option value="gemini-2.0-flash">Gemini 2.0 Flash (Google)</option>
|
|
618
|
+
<option value="deepseek-v3">DeepSeek V3 (Open Source)</option>
|
|
657
619
|
</select>
|
|
658
|
-
<p style="color:var(--text-dim);font-size:12px;margin-top:4px;">🏠 = runs locally, free forever. ☁️ = needs API key.</p>
|
|
659
620
|
</div>
|
|
660
|
-
|
|
661
|
-
<!-- Skill Toggles -->
|
|
662
|
-
<div class="form-group">
|
|
663
|
-
<label class="label">Enable Skills <span style="color:var(--text-dim);font-size:13px;">(What can your agent do?)</span></label>
|
|
664
|
-
<div id="skill-toggles" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:8px;max-height:200px;overflow-y:auto;padding:4px;"></div>
|
|
665
|
-
</div>
|
|
666
|
-
|
|
667
621
|
<div class="form-group">
|
|
668
622
|
<label class="label">Language Preference</label>
|
|
669
623
|
<select class="input" id="agent-lang">
|
|
670
|
-
<option value="zh">中文</option>
|
|
671
624
|
<option value="en">English</option>
|
|
625
|
+
<option value="zh">中文</option>
|
|
672
626
|
<option value="auto">Auto-detect</option>
|
|
673
627
|
</select>
|
|
674
628
|
</div>
|
|
@@ -781,10 +735,6 @@
|
|
|
781
735
|
<label class="label">Description</label>
|
|
782
736
|
<textarea class="input" id="sched-desc" rows="2" placeholder="e.g. Send a news summary every morning at 8am"></textarea>
|
|
783
737
|
</div>
|
|
784
|
-
<div class="form-group">
|
|
785
|
-
<label class="label">Agent</label>
|
|
786
|
-
<select class="input" id="sched-agent"></select>
|
|
787
|
-
</div>
|
|
788
738
|
<div class="form-group">
|
|
789
739
|
<label class="label">Output Channel</label>
|
|
790
740
|
<select class="input" id="sched-channel">
|
|
@@ -811,8 +761,17 @@
|
|
|
811
761
|
</div>
|
|
812
762
|
</div>
|
|
813
763
|
|
|
814
|
-
<!--
|
|
815
|
-
<div class="
|
|
764
|
+
<!-- Channel Config Dialog -->
|
|
765
|
+
<div class="dialog-overlay" id="channel-dialog">
|
|
766
|
+
<div class="dialog" style="max-width:480px;width:92%;">
|
|
767
|
+
<div class="dialog-title" id="channel-dialog-title">配置渠道</div>
|
|
768
|
+
<div id="channel-dialog-body" style="margin-bottom:4px;"></div>
|
|
769
|
+
<div class="dialog-actions">
|
|
770
|
+
<button class="btn btn-secondary btn-sm" onclick="closeChannelDialog()">取消</button>
|
|
771
|
+
<button class="btn btn-primary btn-sm" onclick="saveCurrentChannel()">💾 保存</button>
|
|
772
|
+
</div>
|
|
773
|
+
<!-- Settings Page -->
|
|
774
|
+
<div class="page" id="page-settings">
|
|
816
775
|
<div class="settings-layout">
|
|
817
776
|
<div class="settings-nav">
|
|
818
777
|
<div class="settings-nav-item active" data-settings="models" onclick="showSettings('models')">🤖 模型配置</div>
|
|
@@ -1030,6 +989,9 @@
|
|
|
1030
989
|
</div>
|
|
1031
990
|
</div>
|
|
1032
991
|
|
|
992
|
+
</div>
|
|
993
|
+
</div>
|
|
994
|
+
|
|
1033
995
|
<!-- Delete Confirm Dialog -->
|
|
1034
996
|
<div class="dialog-overlay" id="delete-dialog">
|
|
1035
997
|
<div class="dialog">
|
|
@@ -1165,7 +1127,6 @@
|
|
|
1165
1127
|
async function init() {
|
|
1166
1128
|
await Promise.all([loadTemplates(), loadAgents(), loadSidebarAgents()]);
|
|
1167
1129
|
loadSidebarGroups();
|
|
1168
|
-
loadDashboardStats();
|
|
1169
1130
|
handleRoute();
|
|
1170
1131
|
window.addEventListener('popstate', handleRoute);
|
|
1171
1132
|
checkFirstRun();
|
|
@@ -1306,7 +1267,7 @@
|
|
|
1306
1267
|
document.getElementById('agent-chat-view').style.display = '';
|
|
1307
1268
|
document.getElementById('agent-settings-view').style.display = 'none';
|
|
1308
1269
|
document.getElementById('agent-detail-toggle').classList.remove('active');
|
|
1309
|
-
|
|
1270
|
+
document.getElementById('agent-chat-messages').innerHTML = document.querySelector('.agent-chat-welcome').outerHTML || '<div class="agent-chat-welcome"><div style="font-size:48px;margin-bottom:16px">💬</div><div style="font-size:18px;font-weight:600;margin-bottom:8px">开始对话</div><div style="color:var(--text-muted);font-size:14px">向你的 Agent 发送第一条消息</div></div>';
|
|
1310
1271
|
document.getElementById('agent-chat-input').value = '';
|
|
1311
1272
|
|
|
1312
1273
|
// Show agent detail page
|
|
@@ -1331,7 +1292,6 @@
|
|
|
1331
1292
|
document.querySelector(`.agent-tab[data-atab="${tab}"]`)?.classList.add('active');
|
|
1332
1293
|
document.querySelectorAll('.agent-tab-panel').forEach(p => p.classList.remove('active'));
|
|
1333
1294
|
document.getElementById(`atab-${tab}`)?.classList.add('active');
|
|
1334
|
-
if (typeof loadAgentTabData === 'function') loadAgentTabData(tab);
|
|
1335
1295
|
}
|
|
1336
1296
|
|
|
1337
1297
|
let agentChatHistory = [];
|
|
@@ -1430,12 +1390,11 @@
|
|
|
1430
1390
|
const navItem = document.querySelector(`.nav-item[data-page="${page}"]`);
|
|
1431
1391
|
if (navItem) navItem.classList.add('active');
|
|
1432
1392
|
|
|
1433
|
-
if (page === 'dashboard') { loadAgents(); loadHealthDashboard(); loadSidebarAgents();
|
|
1393
|
+
if (page === 'dashboard') { loadAgents(); loadHealthDashboard(); loadSidebarAgents(); }
|
|
1434
1394
|
if (page === 'create') { renderWizard(); renderWizardTemplates(); }
|
|
1435
1395
|
if (page === 'settings') { showSettings(currentSettingsTab || 'models'); }
|
|
1436
1396
|
if (page === 'global-runtime') { currentSettingsTab='status'; showSettings('status'); showPage('settings'); return; }
|
|
1437
1397
|
if (page === 'global-models') { currentSettingsTab='models'; showSettings('models'); showPage('settings'); return; }
|
|
1438
|
-
if (page === 'global-channels') { currentSettingsTab='channels'; showSettings('channels'); showPage('settings'); return; }
|
|
1439
1398
|
if (page === 'global-memory') { currentSettingsTab='memory'; showSettings('memory'); showPage('settings'); return; }
|
|
1440
1399
|
if (page === 'global-templates') { navigate('templates'); return; }
|
|
1441
1400
|
if (page === 'create-group') { loadGroupAgentSelect(); }
|
|
@@ -1646,112 +1605,13 @@
|
|
|
1646
1605
|
}
|
|
1647
1606
|
if (wizardStep === 2 && selectedTemplate) {
|
|
1648
1607
|
document.getElementById('agent-name').placeholder = selectedTemplate.name;
|
|
1649
|
-
document.getElementById('agent-model').value = selectedTemplate.suggestedModel
|
|
1650
|
-
renderSkillToggles();
|
|
1608
|
+
document.getElementById('agent-model').value = selectedTemplate.suggestedModel;
|
|
1651
1609
|
}
|
|
1652
1610
|
if (wizardStep === 3) {
|
|
1653
1611
|
renderConfirmCard();
|
|
1654
1612
|
}
|
|
1655
1613
|
}
|
|
1656
1614
|
|
|
1657
|
-
// --- Skill toggle rendering ---
|
|
1658
|
-
const WIZARD_SKILL_CATEGORIES = {
|
|
1659
|
-
productivity: { icon: '📋', label: 'Productivity' },
|
|
1660
|
-
knowledge: { icon: '📚', label: 'Knowledge' },
|
|
1661
|
-
creative: { icon: '✍️', label: 'Creative' },
|
|
1662
|
-
developer: { icon: '💻', label: 'Developer' },
|
|
1663
|
-
lifestyle: { icon: '🏠', label: 'Lifestyle' },
|
|
1664
|
-
business: { icon: '💼', label: 'Business' },
|
|
1665
|
-
education: { icon: '🎓', label: 'Education' },
|
|
1666
|
-
};
|
|
1667
|
-
const PRESET_SKILLS = [
|
|
1668
|
-
{ id: 'note-assistant', name: '📝 Notes', cat: 'productivity', default: true },
|
|
1669
|
-
{ id: 'todo-manager', name: '✅ Todo', cat: 'productivity', default: true },
|
|
1670
|
-
{ id: 'reminder', name: '🔔 Reminder', cat: 'productivity', default: true },
|
|
1671
|
-
{ id: 'reading-summary', name: '📚 Summarize', cat: 'knowledge', default: true },
|
|
1672
|
-
{ id: 'knowledge-search', name: '🔍 Search', cat: 'knowledge', default: true },
|
|
1673
|
-
{ id: 'dictionary-translator', name: '📖 Translate', cat: 'knowledge', default: false },
|
|
1674
|
-
{ id: 'calculator', name: '🧮 Calculate', cat: 'knowledge', default: false },
|
|
1675
|
-
{ id: 'writing-assistant', name: '✍️ Writing', cat: 'creative', default: true },
|
|
1676
|
-
{ id: 'social-media', name: '📱 Social', cat: 'creative', default: false },
|
|
1677
|
-
{ id: 'code-assistant', name: '💻 Code', cat: 'developer', default: false },
|
|
1678
|
-
{ id: 'data-analysis', name: '📊 Data', cat: 'knowledge', default: false },
|
|
1679
|
-
{ id: 'customer-followup', name: '🤝 CRM', cat: 'business', default: false },
|
|
1680
|
-
{ id: 'weather-query', name: '🌤 Weather', cat: 'lifestyle', default: false },
|
|
1681
|
-
{ id: 'language-tutor', name: '🗣 Language', cat: 'education', default: false },
|
|
1682
|
-
{ id: 'meeting-summarizer', name: '📋 Meeting', cat: 'productivity', default: false },
|
|
1683
|
-
{ id: 'brainstorm', name: '💡 Brainstorm', cat: 'creative', default: false },
|
|
1684
|
-
];
|
|
1685
|
-
let selectedSkills = new Set(PRESET_SKILLS.filter(s => s.default).map(s => s.id));
|
|
1686
|
-
|
|
1687
|
-
function renderSkillToggles() {
|
|
1688
|
-
const grid = document.getElementById('skill-toggles');
|
|
1689
|
-
if (!grid) return;
|
|
1690
|
-
grid.innerHTML = PRESET_SKILLS.map(s => `
|
|
1691
|
-
<label style="display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:10px;border:1px solid ${selectedSkills.has(s.id) ? 'var(--accent)' : 'var(--border)'};background:${selectedSkills.has(s.id) ? 'var(--accent-light)' : 'transparent'};cursor:pointer;font-size:14px;transition:all 0.2s;" onclick="toggleSkill('${s.id}',this)">
|
|
1692
|
-
<input type="checkbox" ${selectedSkills.has(s.id) ? 'checked' : ''} style="display:none;">
|
|
1693
|
-
<span>${s.name}</span>
|
|
1694
|
-
</label>
|
|
1695
|
-
`).join('');
|
|
1696
|
-
}
|
|
1697
|
-
|
|
1698
|
-
function toggleSkill(id, el) {
|
|
1699
|
-
if (selectedSkills.has(id)) { selectedSkills.delete(id); } else { selectedSkills.add(id); }
|
|
1700
|
-
renderSkillToggles();
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
|
-
// --- AI Prompt Generator ---
|
|
1704
|
-
async function generatePrompt() {
|
|
1705
|
-
const taskDesc = document.getElementById('agent-task-desc').value.trim();
|
|
1706
|
-
const tplName = selectedTemplate?.name || '';
|
|
1707
|
-
const agentName = document.getElementById('agent-name').value.trim();
|
|
1708
|
-
const bizDesc = document.getElementById('agent-desc').value.trim();
|
|
1709
|
-
|
|
1710
|
-
if (!taskDesc && !tplName) { alert('Please describe what your agent should do'); return; }
|
|
1711
|
-
|
|
1712
|
-
const promptArea = document.getElementById('agent-prompt');
|
|
1713
|
-
promptArea.style.display = 'block';
|
|
1714
|
-
promptArea.value = '✨ Generating prompt...';
|
|
1715
|
-
|
|
1716
|
-
// Build the meta-prompt
|
|
1717
|
-
const context = [
|
|
1718
|
-
tplName ? `Role template: ${tplName}` : '',
|
|
1719
|
-
agentName ? `Agent name: ${agentName}` : '',
|
|
1720
|
-
bizDesc ? `Business: ${bizDesc}` : '',
|
|
1721
|
-
taskDesc ? `User request: ${taskDesc}` : '',
|
|
1722
|
-
`Enabled skills: ${[...selectedSkills].join(', ')}`,
|
|
1723
|
-
].filter(Boolean).join('\n');
|
|
1724
|
-
|
|
1725
|
-
const metaPrompt = `Generate a system prompt for an AI agent with these requirements:\n${context}\n\nRules:\n- Be specific and actionable\n- Include personality traits\n- Mention the skills it can use\n- Keep it under 300 words\n- Write in the same language as the user's request\n\nOutput ONLY the system prompt, no explanation.`;
|
|
1726
|
-
|
|
1727
|
-
try {
|
|
1728
|
-
const res = await fetch(`${API}/api/agents/generate-prompt`, {
|
|
1729
|
-
method: 'POST',
|
|
1730
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1731
|
-
body: JSON.stringify({ prompt: metaPrompt }),
|
|
1732
|
-
});
|
|
1733
|
-
if (res.ok) {
|
|
1734
|
-
const data = await res.json();
|
|
1735
|
-
promptArea.value = data.prompt || data.text || 'Failed to generate. Try writing manually.';
|
|
1736
|
-
} else {
|
|
1737
|
-
// Fallback: generate a simple prompt locally
|
|
1738
|
-
promptArea.value = generateLocalPrompt(tplName, taskDesc, bizDesc);
|
|
1739
|
-
}
|
|
1740
|
-
} catch {
|
|
1741
|
-
// Offline fallback
|
|
1742
|
-
promptArea.value = generateLocalPrompt(tplName, taskDesc, bizDesc);
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
|
|
1746
|
-
function generateLocalPrompt(role, task, biz) {
|
|
1747
|
-
const parts = [`You are ${role || 'an AI assistant'}.`];
|
|
1748
|
-
if (biz) parts.push(`You work for: ${biz}.`);
|
|
1749
|
-
if (task) parts.push(`Your main job: ${task}.`);
|
|
1750
|
-
parts.push('Be helpful, professional, and friendly. Ask clarifying questions when needed.');
|
|
1751
|
-
if (selectedSkills.size > 0) parts.push(`You have access to these skills: ${[...selectedSkills].join(', ')}.`);
|
|
1752
|
-
return parts.join('\n');
|
|
1753
|
-
}
|
|
1754
|
-
|
|
1755
1615
|
function wizardNext() {
|
|
1756
1616
|
if (wizardStep === 1 && !selectedTemplate) { alert('Please select a template first'); return; }
|
|
1757
1617
|
if (wizardStep < 3) { wizardStep++; renderWizard(); }
|
|
@@ -2604,31 +2464,8 @@
|
|
|
2604
2464
|
let frCreatedAgentId = null;
|
|
2605
2465
|
|
|
2606
2466
|
async function checkFirstRun() {
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
const data = await res.json();
|
|
2610
|
-
if (data.completed) return; // already configured
|
|
2611
|
-
// Check if models are configured — if so, skip
|
|
2612
|
-
const modelRes = await fetch(`${API}/api/settings/models`);
|
|
2613
|
-
const modelData = await modelRes.json();
|
|
2614
|
-
const hasCloudKey = modelData.providers && Object.values(modelData.providers).some(p => p && p.apiKey);
|
|
2615
|
-
if (hasCloudKey) return; // user already has API keys
|
|
2616
|
-
// Check if Ollama is running with models
|
|
2617
|
-
const ollamaRes = await fetch(`${API}/api/settings/models/local`);
|
|
2618
|
-
const ollamaData = await ollamaRes.json();
|
|
2619
|
-
if (ollamaData.running && ollamaData.models?.length > 0) {
|
|
2620
|
-
// Ollama ready — auto-set local mode and skip wizard
|
|
2621
|
-
await fetch(`${API}/api/settings/models`, {
|
|
2622
|
-
method: 'PUT', headers: {'Content-Type':'application/json'},
|
|
2623
|
-
body: JSON.stringify({ mode: 'local', provider: 'ollama', chatModel: ollamaData.models[0]?.name || 'qwen2.5:7b' })
|
|
2624
|
-
});
|
|
2625
|
-
return;
|
|
2626
|
-
}
|
|
2627
|
-
// Nothing configured — show wizard
|
|
2628
|
-
showFirstRunWizard({ ollamaDetected: ollamaData.running, ollamaModels: ollamaData.models });
|
|
2629
|
-
} catch {
|
|
2630
|
-
// API not ready, skip
|
|
2631
|
-
}
|
|
2467
|
+
// Skip first-run wizard — agents are configured via init
|
|
2468
|
+
return;
|
|
2632
2469
|
}
|
|
2633
2470
|
|
|
2634
2471
|
function showFirstRunWizard(data) {
|
|
@@ -2759,158 +2596,6 @@
|
|
|
2759
2596
|
});
|
|
2760
2597
|
}
|
|
2761
2598
|
|
|
2762
|
-
// === Dashboard Stats ===
|
|
2763
|
-
async function loadDashboardStats() {
|
|
2764
|
-
const el = document.getElementById('dashboard-stats');
|
|
2765
|
-
if (!el) return;
|
|
2766
|
-
try {
|
|
2767
|
-
const [agentsRes, modelsRes] = await Promise.all([
|
|
2768
|
-
fetch('/api/agents').then(r=>r.json()).catch(()=>({})),
|
|
2769
|
-
fetch('/api/settings/models').then(r=>r.json()).catch(()=>({})),
|
|
2770
|
-
]);
|
|
2771
|
-
const agentList = agentsRes.agents || [];
|
|
2772
|
-
const currentModel = modelsRes.chatModel || 'Not configured';
|
|
2773
|
-
el.innerHTML = `
|
|
2774
|
-
<div class="card stat-card"><div class="stat-value">${agentList.length}</div><div class="stat-label">Agents</div></div>
|
|
2775
|
-
<div class="card stat-card"><div class="stat-value" style="font-size:18px;">${currentModel}</div><div class="stat-label">Current Model</div></div>
|
|
2776
|
-
<div class="card stat-card"><div class="stat-value">${agentList.filter(a=>(a.status||'').toLowerCase()==='online').length}</div><div class="stat-label">Online</div></div>
|
|
2777
|
-
`;
|
|
2778
|
-
} catch { el.innerHTML = ''; }
|
|
2779
|
-
}
|
|
2780
|
-
|
|
2781
|
-
// === Agent Detail Settings Tab Logic ===
|
|
2782
|
-
|
|
2783
|
-
async function loadAgentTabData(tab) {
|
|
2784
|
-
if (!selectedAgentId) return;
|
|
2785
|
-
const id = selectedAgentId;
|
|
2786
|
-
try {
|
|
2787
|
-
if (tab === 'role') {
|
|
2788
|
-
const res = await fetch(`/api/agents/${id}`);
|
|
2789
|
-
const a = await res.json();
|
|
2790
|
-
document.getElementById('atab-role-name').value = a.name || '';
|
|
2791
|
-
document.getElementById('atab-role-desc').value = a.description || '';
|
|
2792
|
-
document.getElementById('atab-role-prompt').value = a.systemPrompt || a.prompt || '';
|
|
2793
|
-
} else if (tab === 'models') {
|
|
2794
|
-
const res = await fetch(`/api/agents/${id}`);
|
|
2795
|
-
const a = await res.json();
|
|
2796
|
-
const ov = document.getElementById('atab-model-override');
|
|
2797
|
-
const fields = document.getElementById('atab-model-fields');
|
|
2798
|
-
ov.checked = !!a.modelOverride;
|
|
2799
|
-
fields.style.display = ov.checked ? '' : 'none';
|
|
2800
|
-
ov.onchange = () => { fields.style.display = ov.checked ? '' : 'none'; };
|
|
2801
|
-
if (a.modelOverride) {
|
|
2802
|
-
document.getElementById('atab-model-provider').value = a.provider || 'ollama';
|
|
2803
|
-
document.getElementById('atab-model-name').value = a.model || '';
|
|
2804
|
-
document.getElementById('atab-model-temp').value = a.temperature ?? 0.7;
|
|
2805
|
-
}
|
|
2806
|
-
} else if (tab === 'channels') {
|
|
2807
|
-
const chList = ['web','telegram','discord','slack','feishu','email','whatsapp'];
|
|
2808
|
-
const res = await fetch(`/api/agents/${id}`);
|
|
2809
|
-
const a = await res.json();
|
|
2810
|
-
const enabled = a.channels || ['web'];
|
|
2811
|
-
document.getElementById('atab-channels-list').innerHTML = chList.map(ch =>
|
|
2812
|
-
`<label style="display:flex;align-items:center;gap:10px;padding:8px 0;font-size:18px;cursor:pointer;">
|
|
2813
|
-
<input type="checkbox" class="atab-ch-cb" value="${ch}" ${enabled.includes(ch)?'checked':''}>
|
|
2814
|
-
${ch.charAt(0).toUpperCase()+ch.slice(1)}
|
|
2815
|
-
</label>`
|
|
2816
|
-
).join('');
|
|
2817
|
-
} else if (tab === 'memory') {
|
|
2818
|
-
const el = document.getElementById('atab-memory-list');
|
|
2819
|
-
el.innerHTML = '<span style="color:var(--text-muted);">⏳ Loading...</span>';
|
|
2820
|
-
try {
|
|
2821
|
-
const res = await fetch(`/api/agents/${id}/memory`);
|
|
2822
|
-
const data = await res.json();
|
|
2823
|
-
const entries = data.entries || [];
|
|
2824
|
-
if (!entries.length) { el.innerHTML = '<p style="color:var(--text-muted);">No memories yet.</p>'; return; }
|
|
2825
|
-
el.innerHTML = '<div class="timeline">' + entries.map(e =>
|
|
2826
|
-
`<div class="timeline-item"><div class="timeline-date">${new Date(e.timestamp).toLocaleString()}</div><div class="timeline-content">${esc(e.summary||e.content||'')}</div></div>`
|
|
2827
|
-
).join('') + '</div>';
|
|
2828
|
-
} catch { el.innerHTML = '<p style="color:var(--text-muted);">Failed to load memories.</p>'; }
|
|
2829
|
-
} else if (tab === 'skills') {
|
|
2830
|
-
const el = document.getElementById('atab-skills-list');
|
|
2831
|
-
el.innerHTML = '<span style="color:var(--text-muted);">⏳ Loading...</span>';
|
|
2832
|
-
try {
|
|
2833
|
-
const res = await fetch(`/api/agents/${id}`);
|
|
2834
|
-
const a = await res.json();
|
|
2835
|
-
const skills = a.skills || [];
|
|
2836
|
-
if (!skills.length) { el.innerHTML = '<p style="color:var(--text-muted);">No skills installed.</p>'; return; }
|
|
2837
|
-
el.innerHTML = skills.map(s => `<div class="card" style="margin-bottom:8px;padding:12px;"><span style="font-size:18px;font-weight:600;">${s.name||s}</span></div>`).join('');
|
|
2838
|
-
} catch { el.innerHTML = '<p style="color:var(--text-muted);">Failed to load skills.</p>'; }
|
|
2839
|
-
} else if (tab === 'schedules') {
|
|
2840
|
-
const el = document.getElementById('atab-schedules-list');
|
|
2841
|
-
el.innerHTML = '<span style="color:var(--text-muted);">⏳ Loading...</span>';
|
|
2842
|
-
try {
|
|
2843
|
-
const res = await fetch('/api/schedules');
|
|
2844
|
-
const all = await res.json();
|
|
2845
|
-
const tasks = (Array.isArray(all)?all:[]).filter(t => t.agentId === id);
|
|
2846
|
-
if (!tasks.length) { el.innerHTML = '<p style="color:var(--text-muted);">No schedules for this agent.</p>'; return; }
|
|
2847
|
-
el.innerHTML = tasks.map(t => `<div class="card" style="margin-bottom:8px;padding:12px;display:flex;align-items:center;gap:12px;">
|
|
2848
|
-
<span>⏰</span><div style="flex:1;"><div style="font-weight:600;font-size:18px;">${esc(t.name)}</div><div style="font-size:18px;color:var(--text-dim);">${esc(t.schedule||t.frequency||'')}</div></div>
|
|
2849
|
-
<span style="font-size:18px;color:${t.enabled?'var(--green)':'var(--text-dim)'};">${t.enabled?'Active':'Paused'}</span>
|
|
2850
|
-
</div>`).join('');
|
|
2851
|
-
} catch { el.innerHTML = '<p style="color:var(--text-muted);">Failed to load schedules.</p>'; }
|
|
2852
|
-
} else if (tab === 'usage') {
|
|
2853
|
-
const el = document.getElementById('atab-usage-content');
|
|
2854
|
-
el.innerHTML = '<span style="color:var(--text-muted);">⏳ Loading...</span>';
|
|
2855
|
-
try {
|
|
2856
|
-
const res = await fetch('/api/settings/usage');
|
|
2857
|
-
const data = await res.json();
|
|
2858
|
-
const tokens = data.totalTokens || 0;
|
|
2859
|
-
const cost = data.totalCost || 0;
|
|
2860
|
-
el.innerHTML = `<div class="card-grid"><div class="card stat-card"><div class="stat-value">${tokens>1000?(tokens/1000).toFixed(1)+'K':tokens}</div><div class="stat-label">Total Tokens</div></div><div class="card stat-card"><div class="stat-value">$${cost.toFixed(4)}</div><div class="stat-label">Est. Cost</div></div></div>`;
|
|
2861
|
-
} catch { el.innerHTML = '<p style="color:var(--text-muted);">Failed to load usage data.</p>'; }
|
|
2862
|
-
}
|
|
2863
|
-
} catch(e) { console.error('loadAgentTabData error:', e); }
|
|
2864
|
-
}
|
|
2865
|
-
|
|
2866
|
-
async function saveAgentRole() {
|
|
2867
|
-
if (!selectedAgentId) return;
|
|
2868
|
-
const st = document.getElementById('atab-role-status');
|
|
2869
|
-
try {
|
|
2870
|
-
await fetch(`/api/agents/${selectedAgentId}`, { method:'PUT', headers:{'Content-Type':'application/json'}, body:JSON.stringify({
|
|
2871
|
-
name: document.getElementById('atab-role-name').value.trim(),
|
|
2872
|
-
description: document.getElementById('atab-role-desc').value.trim(),
|
|
2873
|
-
systemPrompt: document.getElementById('atab-role-prompt').value.trim(),
|
|
2874
|
-
})});
|
|
2875
|
-
st.textContent = '✅ Saved'; st.style.color = 'var(--green)';
|
|
2876
|
-
loadSidebarAgents();
|
|
2877
|
-
} catch { st.textContent = '❌ Failed'; st.style.color = 'var(--red)'; }
|
|
2878
|
-
}
|
|
2879
|
-
|
|
2880
|
-
async function saveAgentModel() {
|
|
2881
|
-
if (!selectedAgentId) return;
|
|
2882
|
-
const st = document.getElementById('atab-model-status');
|
|
2883
|
-
const ov = document.getElementById('atab-model-override').checked;
|
|
2884
|
-
const body = { modelOverride: ov };
|
|
2885
|
-
if (ov) { body.provider = document.getElementById('atab-model-provider').value; body.model = document.getElementById('atab-model-name').value; body.temperature = parseFloat(document.getElementById('atab-model-temp').value); }
|
|
2886
|
-
try {
|
|
2887
|
-
await fetch(`/api/agents/${selectedAgentId}`, { method:'PUT', headers:{'Content-Type':'application/json'}, body:JSON.stringify(body) });
|
|
2888
|
-
st.textContent = '✅ Saved'; st.style.color = 'var(--green)';
|
|
2889
|
-
} catch { st.textContent = '❌ Failed'; st.style.color = 'var(--red)'; }
|
|
2890
|
-
}
|
|
2891
|
-
|
|
2892
|
-
async function saveAgentChannels() {
|
|
2893
|
-
if (!selectedAgentId) return;
|
|
2894
|
-
const st = document.getElementById('atab-channels-status');
|
|
2895
|
-
const channels = [...document.querySelectorAll('.atab-ch-cb:checked')].map(cb => cb.value);
|
|
2896
|
-
try {
|
|
2897
|
-
await fetch(`/api/agents/${selectedAgentId}`, { method:'PUT', headers:{'Content-Type':'application/json'}, body:JSON.stringify({ channels }) });
|
|
2898
|
-
st.textContent = '✅ Saved'; st.style.color = 'var(--green)';
|
|
2899
|
-
} catch { st.textContent = '❌ Failed'; st.style.color = 'var(--red)'; }
|
|
2900
|
-
}
|
|
2901
|
-
|
|
2902
|
-
// === Populate schedule form agent select ===
|
|
2903
|
-
async function populateSchedAgentSelect() {
|
|
2904
|
-
const sel = document.getElementById('sched-agent');
|
|
2905
|
-
if (!sel) return;
|
|
2906
|
-
try {
|
|
2907
|
-
const res = await fetch('/api/agents');
|
|
2908
|
-
const data = await res.json();
|
|
2909
|
-
const list = data.agents || [];
|
|
2910
|
-
sel.innerHTML = list.map(a => `<option value="${a.id}">${a.name||a.id}</option>`).join('');
|
|
2911
|
-
} catch { sel.innerHTML = '<option value="">No agents</option>'; }
|
|
2912
|
-
}
|
|
2913
|
-
|
|
2914
2599
|
// === Start ===
|
|
2915
2600
|
init();
|
|
2916
2601
|
|
|
@@ -2977,9 +2662,6 @@
|
|
|
2977
2662
|
document.getElementById('sched-desc').value = task ? task.description : '';
|
|
2978
2663
|
document.getElementById('sched-channel').value = task ? task.outputChannel : 'web';
|
|
2979
2664
|
onSchedFreqChange();
|
|
2980
|
-
populateSchedAgentSelect().then(() => {
|
|
2981
|
-
if (task?.agentId) document.getElementById('sched-agent').value = task.agentId;
|
|
2982
|
-
});
|
|
2983
2665
|
}
|
|
2984
2666
|
|
|
2985
2667
|
function hideScheduleForm() {
|
|
@@ -3000,7 +2682,6 @@
|
|
|
3000
2682
|
time: document.getElementById('sched-time').value,
|
|
3001
2683
|
schedule: document.getElementById('sched-frequency').value === 'custom' ? document.getElementById('sched-cron').value.trim() : '',
|
|
3002
2684
|
description: document.getElementById('sched-desc').value.trim(),
|
|
3003
|
-
agentId: document.getElementById('sched-agent').value,
|
|
3004
2685
|
outputChannel: document.getElementById('sched-channel').value,
|
|
3005
2686
|
enabled: true,
|
|
3006
2687
|
};
|
|
@@ -3156,17 +2837,17 @@
|
|
|
3156
2837
|
// =============================================
|
|
3157
2838
|
async function saveImageGenConfig() {
|
|
3158
2839
|
const data = {
|
|
3159
|
-
openaiApiKey: document.getElementById('ig-openai-key')
|
|
3160
|
-
sdApiUrl: document.getElementById('ig-sd-url')
|
|
3161
|
-
replicateApiKey: document.getElementById('ig-replicate-key')
|
|
2840
|
+
openaiApiKey: document.getElementById('ig-openai-key').value.trim(),
|
|
2841
|
+
sdApiUrl: document.getElementById('ig-sd-url').value.trim(),
|
|
2842
|
+
replicateApiKey: document.getElementById('ig-replicate-key').value.trim(),
|
|
3162
2843
|
};
|
|
3163
2844
|
try {
|
|
3164
2845
|
await fetch('/api/image-gen/config', { method: 'PUT', headers: {'Content-Type':'application/json'}, body: JSON.stringify(data) });
|
|
3165
|
-
|
|
3166
|
-
|
|
2846
|
+
document.getElementById('ig-status').textContent = '✅ Configuration saved!';
|
|
2847
|
+
document.getElementById('ig-status').style.color = 'var(--green)';
|
|
3167
2848
|
} catch(e) {
|
|
3168
|
-
|
|
3169
|
-
|
|
2849
|
+
document.getElementById('ig-status').textContent = '❌ Failed: ' + e.message;
|
|
2850
|
+
document.getElementById('ig-status').style.color = 'var(--red)';
|
|
3170
2851
|
}
|
|
3171
2852
|
}
|
|
3172
2853
|
|