agent-orcha 0.0.1 → 0.0.3
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/README.md +792 -125
- package/dist/lib/agents/agent-executor.d.ts +6 -1
- package/dist/lib/agents/agent-executor.d.ts.map +1 -1
- package/dist/lib/agents/agent-executor.js +241 -45
- package/dist/lib/agents/agent-executor.js.map +1 -1
- package/dist/lib/agents/agent-loader.d.ts.map +1 -1
- package/dist/lib/agents/agent-loader.js +3 -1
- package/dist/lib/agents/agent-loader.js.map +1 -1
- package/dist/lib/agents/index.d.ts +2 -1
- package/dist/lib/agents/index.d.ts.map +1 -1
- package/dist/lib/agents/index.js +1 -0
- package/dist/lib/agents/index.js.map +1 -1
- package/dist/lib/agents/structured-output-wrapper.d.ts +19 -0
- package/dist/lib/agents/structured-output-wrapper.d.ts.map +1 -0
- package/dist/lib/agents/structured-output-wrapper.js +104 -0
- package/dist/lib/agents/structured-output-wrapper.js.map +1 -0
- package/dist/lib/agents/types.d.ts +17 -10
- package/dist/lib/agents/types.d.ts.map +1 -1
- package/dist/lib/agents/types.js +1 -1
- package/dist/lib/agents/types.js.map +1 -1
- package/dist/lib/index.d.ts +9 -7
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +7 -5
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/knowledge/graph-rag/community-detector.d.ts +16 -0
- package/dist/lib/knowledge/graph-rag/community-detector.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/community-detector.js +81 -0
- package/dist/lib/knowledge/graph-rag/community-detector.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/community-summarizer.d.ts +17 -0
- package/dist/lib/knowledge/graph-rag/community-summarizer.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/community-summarizer.js +87 -0
- package/dist/lib/knowledge/graph-rag/community-summarizer.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/entity-extractor.d.ts +36 -0
- package/dist/lib/knowledge/graph-rag/entity-extractor.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/entity-extractor.js +192 -0
- package/dist/lib/knowledge/graph-rag/entity-extractor.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/extraction-cache.d.ts +30 -0
- package/dist/lib/knowledge/graph-rag/extraction-cache.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/extraction-cache.js +88 -0
- package/dist/lib/knowledge/graph-rag/extraction-cache.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/global-search.d.ts +19 -0
- package/dist/lib/knowledge/graph-rag/global-search.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/global-search.js +96 -0
- package/dist/lib/knowledge/graph-rag/global-search.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/graph-rag-factory.d.ts +24 -0
- package/dist/lib/knowledge/graph-rag/graph-rag-factory.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/graph-rag-factory.js +239 -0
- package/dist/lib/knowledge/graph-rag/graph-rag-factory.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/index.d.ts +14 -0
- package/dist/lib/knowledge/graph-rag/index.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/index.js +12 -0
- package/dist/lib/knowledge/graph-rag/index.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/local-search.d.ts +20 -0
- package/dist/lib/knowledge/graph-rag/local-search.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/local-search.js +110 -0
- package/dist/lib/knowledge/graph-rag/local-search.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/memory-graph-store.d.ts +31 -0
- package/dist/lib/knowledge/graph-rag/memory-graph-store.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/memory-graph-store.js +165 -0
- package/dist/lib/knowledge/graph-rag/memory-graph-store.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/neo4j-graph-store.d.ts +38 -0
- package/dist/lib/knowledge/graph-rag/neo4j-graph-store.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/neo4j-graph-store.js +190 -0
- package/dist/lib/knowledge/graph-rag/neo4j-graph-store.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/search-mode-detector.d.ts +11 -0
- package/dist/lib/knowledge/graph-rag/search-mode-detector.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/search-mode-detector.js +50 -0
- package/dist/lib/knowledge/graph-rag/search-mode-detector.js.map +1 -0
- package/dist/lib/knowledge/graph-rag/types.d.ts +368 -0
- package/dist/lib/knowledge/graph-rag/types.d.ts.map +1 -0
- package/dist/lib/knowledge/graph-rag/types.js +48 -0
- package/dist/lib/knowledge/graph-rag/types.js.map +1 -0
- package/dist/lib/knowledge/index.d.ts +9 -0
- package/dist/lib/knowledge/index.d.ts.map +1 -0
- package/dist/lib/knowledge/index.js +8 -0
- package/dist/lib/knowledge/index.js.map +1 -0
- package/dist/lib/knowledge/knowledge-store-factory.d.ts +16 -0
- package/dist/lib/knowledge/knowledge-store-factory.d.ts.map +1 -0
- package/dist/lib/{vectors/vector-store-factory.js → knowledge/knowledge-store-factory.js} +36 -10
- package/dist/lib/knowledge/knowledge-store-factory.js.map +1 -0
- package/dist/lib/knowledge/knowledge-store-manager.d.ts +18 -0
- package/dist/lib/knowledge/knowledge-store-manager.d.ts.map +1 -0
- package/dist/lib/knowledge/knowledge-store-manager.js +98 -0
- package/dist/lib/knowledge/knowledge-store-manager.js.map +1 -0
- package/dist/lib/knowledge/loaders/database-loader.d.ts +18 -0
- package/dist/lib/knowledge/loaders/database-loader.d.ts.map +1 -0
- package/dist/lib/knowledge/loaders/database-loader.js +115 -0
- package/dist/lib/knowledge/loaders/database-loader.js.map +1 -0
- package/dist/lib/knowledge/loaders/index.d.ts +4 -0
- package/dist/lib/knowledge/loaders/index.d.ts.map +1 -0
- package/dist/lib/knowledge/loaders/index.js +4 -0
- package/dist/lib/knowledge/loaders/index.js.map +1 -0
- package/dist/lib/knowledge/loaders/s3-loader.d.ts +17 -0
- package/dist/lib/knowledge/loaders/s3-loader.d.ts.map +1 -0
- package/dist/lib/knowledge/loaders/s3-loader.js +185 -0
- package/dist/lib/knowledge/loaders/s3-loader.js.map +1 -0
- package/dist/lib/knowledge/loaders/web-loader.d.ts +12 -0
- package/dist/lib/knowledge/loaders/web-loader.d.ts.map +1 -0
- package/dist/lib/knowledge/loaders/web-loader.js +56 -0
- package/dist/lib/knowledge/loaders/web-loader.js.map +1 -0
- package/dist/lib/knowledge/types.d.ts +1839 -0
- package/dist/lib/knowledge/types.d.ts.map +1 -0
- package/dist/lib/knowledge/types.js +111 -0
- package/dist/lib/knowledge/types.js.map +1 -0
- package/dist/lib/knowledge/utils/connection-pool.d.ts +18 -0
- package/dist/lib/knowledge/utils/connection-pool.d.ts.map +1 -0
- package/dist/lib/knowledge/utils/connection-pool.js +77 -0
- package/dist/lib/knowledge/utils/connection-pool.js.map +1 -0
- package/dist/lib/knowledge/utils/file-type-detector.d.ts +10 -0
- package/dist/lib/knowledge/utils/file-type-detector.d.ts.map +1 -0
- package/dist/lib/knowledge/utils/file-type-detector.js +32 -0
- package/dist/lib/knowledge/utils/file-type-detector.js.map +1 -0
- package/dist/lib/knowledge/utils/index.d.ts +3 -0
- package/dist/lib/knowledge/utils/index.d.ts.map +1 -0
- package/dist/lib/knowledge/utils/index.js +3 -0
- package/dist/lib/knowledge/utils/index.js.map +1 -0
- package/dist/lib/mcp/mcp-client.d.ts +9 -1
- package/dist/lib/mcp/mcp-client.d.ts.map +1 -1
- package/dist/lib/mcp/mcp-client.js +33 -0
- package/dist/lib/mcp/mcp-client.js.map +1 -1
- package/dist/lib/memory/conversation-store.d.ts +43 -0
- package/dist/lib/memory/conversation-store.d.ts.map +1 -0
- package/dist/lib/memory/conversation-store.js +109 -0
- package/dist/lib/memory/conversation-store.js.map +1 -0
- package/dist/lib/memory/index.d.ts +3 -0
- package/dist/lib/memory/index.d.ts.map +1 -0
- package/dist/lib/memory/index.js +3 -0
- package/dist/lib/memory/index.js.map +1 -0
- package/dist/lib/memory/types.d.ts +19 -0
- package/dist/lib/memory/types.d.ts.map +1 -0
- package/dist/lib/memory/types.js +6 -0
- package/dist/lib/memory/types.js.map +1 -0
- package/dist/lib/orchestrator.d.ts +56 -14
- package/dist/lib/orchestrator.d.ts.map +1 -1
- package/dist/lib/orchestrator.js +182 -25
- package/dist/lib/orchestrator.js.map +1 -1
- package/dist/lib/tools/agent-tool-wrapper.d.ts +22 -0
- package/dist/lib/tools/agent-tool-wrapper.d.ts.map +1 -0
- package/dist/lib/tools/agent-tool-wrapper.js +56 -0
- package/dist/lib/tools/agent-tool-wrapper.js.map +1 -0
- package/dist/lib/tools/built-in/ask-user.tool.d.ts +7 -0
- package/dist/lib/tools/built-in/ask-user.tool.d.ts.map +1 -0
- package/dist/lib/tools/built-in/ask-user.tool.js +23 -0
- package/dist/lib/tools/built-in/ask-user.tool.js.map +1 -0
- package/dist/lib/tools/built-in/index.d.ts +2 -1
- package/dist/lib/tools/built-in/index.d.ts.map +1 -1
- package/dist/lib/tools/built-in/index.js +2 -1
- package/dist/lib/tools/built-in/index.js.map +1 -1
- package/dist/lib/tools/built-in/knowledge-search.tool.d.ts +4 -0
- package/dist/lib/tools/built-in/knowledge-search.tool.d.ts.map +1 -0
- package/dist/lib/tools/built-in/{vector-search.tool.js → knowledge-search.tool.js} +4 -4
- package/dist/lib/tools/built-in/knowledge-search.tool.js.map +1 -0
- package/dist/lib/tools/index.d.ts +3 -1
- package/dist/lib/tools/index.d.ts.map +1 -1
- package/dist/lib/tools/index.js +3 -1
- package/dist/lib/tools/index.js.map +1 -1
- package/dist/lib/tools/tool-discovery.d.ts +50 -0
- package/dist/lib/tools/tool-discovery.d.ts.map +1 -0
- package/dist/lib/tools/tool-discovery.js +178 -0
- package/dist/lib/tools/tool-discovery.js.map +1 -0
- package/dist/lib/tools/tool-registry.d.ts +19 -3
- package/dist/lib/tools/tool-registry.d.ts.map +1 -1
- package/dist/lib/tools/tool-registry.js +63 -10
- package/dist/lib/tools/tool-registry.js.map +1 -1
- package/dist/lib/workflows/index.d.ts +4 -2
- package/dist/lib/workflows/index.d.ts.map +1 -1
- package/dist/lib/workflows/index.js +3 -1
- package/dist/lib/workflows/index.js.map +1 -1
- package/dist/lib/workflows/interrupt-manager.d.ts +42 -0
- package/dist/lib/workflows/interrupt-manager.d.ts.map +1 -0
- package/dist/lib/workflows/interrupt-manager.js +102 -0
- package/dist/lib/workflows/interrupt-manager.js.map +1 -0
- package/dist/lib/workflows/langgraph-executor.d.ts +51 -0
- package/dist/lib/workflows/langgraph-executor.d.ts.map +1 -0
- package/dist/lib/workflows/langgraph-executor.js +297 -0
- package/dist/lib/workflows/langgraph-executor.js.map +1 -0
- package/dist/lib/workflows/types.d.ts +911 -34
- package/dist/lib/workflows/types.d.ts.map +1 -1
- package/dist/lib/workflows/types.js +51 -2
- package/dist/lib/workflows/types.js.map +1 -1
- package/dist/lib/workflows/workflow-executor.d.ts.map +1 -1
- package/dist/lib/workflows/workflow-executor.js +4 -0
- package/dist/lib/workflows/workflow-executor.js.map +1 -1
- package/dist/lib/workflows/workflow-loader.d.ts.map +1 -1
- package/dist/lib/workflows/workflow-loader.js +3 -1
- package/dist/lib/workflows/workflow-loader.js.map +1 -1
- package/dist/public/index.html +133 -700
- package/dist/public/src/components/AgentsView.js +763 -0
- package/dist/public/src/components/AppRoot.js +76 -0
- package/dist/public/src/components/IdeView.js +330 -0
- package/dist/public/src/components/KnowledgeView.js +133 -0
- package/dist/public/src/components/LlmView.js +127 -0
- package/dist/public/src/components/McpView.js +387 -0
- package/dist/public/src/components/NavBar.js +71 -0
- package/dist/public/src/components/WorkflowsView.js +243 -0
- package/dist/public/src/main.js +9 -0
- package/dist/public/src/services/ApiService.js +142 -0
- package/dist/public/src/store.js +41 -0
- package/dist/public/src/utils/Component.js +23 -0
- package/dist/public/src/utils/markdown.js +82 -0
- package/dist/src/cli/commands/start.d.ts.map +1 -1
- package/dist/src/cli/commands/start.js +3 -2
- package/dist/src/cli/commands/start.js.map +1 -1
- package/dist/src/index.js +46 -12
- package/dist/src/index.js.map +1 -1
- package/dist/src/routes/agents.route.d.ts.map +1 -1
- package/dist/src/routes/agents.route.js +38 -5
- package/dist/src/routes/agents.route.js.map +1 -1
- package/dist/src/routes/files.route.d.ts +3 -0
- package/dist/src/routes/files.route.d.ts.map +1 -0
- package/dist/src/routes/files.route.js +160 -0
- package/dist/src/routes/files.route.js.map +1 -0
- package/dist/src/routes/functions.route.d.ts +3 -0
- package/dist/src/routes/functions.route.d.ts.map +1 -0
- package/dist/src/routes/functions.route.js +83 -0
- package/dist/src/routes/functions.route.js.map +1 -0
- package/dist/src/routes/knowledge.route.d.ts +3 -0
- package/dist/src/routes/knowledge.route.d.ts.map +1 -0
- package/dist/src/routes/knowledge.route.js +153 -0
- package/dist/src/routes/knowledge.route.js.map +1 -0
- package/dist/src/routes/mcp.route.d.ts +3 -0
- package/dist/src/routes/mcp.route.d.ts.map +1 -0
- package/dist/src/routes/mcp.route.js +79 -0
- package/dist/src/routes/mcp.route.js.map +1 -0
- package/dist/src/routes/workflows.route.d.ts.map +1 -1
- package/dist/src/routes/workflows.route.js +2 -1
- package/dist/src/routes/workflows.route.js.map +1 -1
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/server.js +8 -2
- package/dist/src/server.js.map +1 -1
- package/dist/templates/.env.example +21 -0
- package/dist/templates/README.md +43 -152
- package/dist/templates/agents/call-center-analyst-simple.agent.yaml +36 -0
- package/dist/templates/agents/math.agent.yaml +4 -14
- package/dist/templates/agents/sentiment-structured.agent.yaml +42 -0
- package/dist/templates/functions/calculator.function.js +69 -0
- package/dist/templates/functions/text-formatter.function.js +66 -0
- package/dist/templates/{vectors/example.vector.yaml → knowledge/example.knowledge.yaml} +1 -1
- package/dist/templates/knowledge/transcripts/call-001.txt +40 -0
- package/dist/templates/knowledge/transcripts/call-002.txt +36 -0
- package/dist/templates/knowledge/transcripts/call-003.txt +42 -0
- package/dist/templates/llm.md +1195 -0
- package/dist/templates/workflows/example.workflow.yaml +8 -19
- package/dist/templates/workflows/langgraph-example.workflow.yaml +84 -0
- package/package.json +19 -10
- package/dist/lib/tools/built-in/vector-search.tool.d.ts +0 -4
- package/dist/lib/tools/built-in/vector-search.tool.d.ts.map +0 -1
- package/dist/lib/tools/built-in/vector-search.tool.js.map +0 -1
- package/dist/lib/vectors/index.d.ts +0 -5
- package/dist/lib/vectors/index.d.ts.map +0 -1
- package/dist/lib/vectors/index.js +0 -4
- package/dist/lib/vectors/index.js.map +0 -1
- package/dist/lib/vectors/types.d.ts +0 -212
- package/dist/lib/vectors/types.d.ts.map +0 -1
- package/dist/lib/vectors/types.js +0 -39
- package/dist/lib/vectors/types.js.map +0 -1
- package/dist/lib/vectors/vector-store-factory.d.ts +0 -14
- package/dist/lib/vectors/vector-store-factory.d.ts.map +0 -1
- package/dist/lib/vectors/vector-store-factory.js.map +0 -1
- package/dist/lib/vectors/vector-store-manager.d.ts +0 -18
- package/dist/lib/vectors/vector-store-manager.d.ts.map +0 -1
- package/dist/lib/vectors/vector-store-manager.js +0 -79
- package/dist/lib/vectors/vector-store-manager.js.map +0 -1
- package/dist/src/routes/vectors.route.d.ts +0 -3
- package/dist/src/routes/vectors.route.d.ts.map +0 -1
- package/dist/src/routes/vectors.route.js +0 -74
- package/dist/src/routes/vectors.route.js.map +0 -1
- package/dist/templates/agents/example.agent.yaml +0 -32
- package/dist/templates/agents/knowledge.agent.yaml +0 -36
- package/dist/templates/agents/time.agent.yaml +0 -42
- package/dist/templates/functions/README.md +0 -195
- package/dist/templates/functions/fibonacci.function.js +0 -55
- package/dist/templates/vectors/example-chroma.vector.yaml +0 -43
- package/dist/templates/vectors/sample-data/example-document.txt +0 -15
|
@@ -0,0 +1,763 @@
|
|
|
1
|
+
|
|
2
|
+
import { Component } from '../utils/Component.js';
|
|
3
|
+
import { api } from '../services/ApiService.js';
|
|
4
|
+
import { store } from '../store.js';
|
|
5
|
+
import { markdownRenderer } from '../utils/markdown.js';
|
|
6
|
+
|
|
7
|
+
export class AgentsView extends Component {
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
this.isLoading = false;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async connectedCallback() {
|
|
14
|
+
super.connectedCallback();
|
|
15
|
+
await Promise.all([this.loadAgents(), this.loadLLMs()]);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async loadAgents() {
|
|
19
|
+
try {
|
|
20
|
+
const agents = await api.getAgents();
|
|
21
|
+
store.set('agents', agents);
|
|
22
|
+
|
|
23
|
+
if (agents.length > 0 && !store.get('selectedAgent') && !store.get('selectedLlm')) {
|
|
24
|
+
store.set('selectedAgent', agents[agents.length - 1]);
|
|
25
|
+
store.set('selectionType', 'agent');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
this.renderAgentDropdown();
|
|
29
|
+
this.updateSelectedAgentUI();
|
|
30
|
+
} catch (e) {
|
|
31
|
+
console.error('Failed to load agents', e);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async loadLLMs() {
|
|
36
|
+
try {
|
|
37
|
+
const llms = await api.getLLMs();
|
|
38
|
+
store.set('llms', llms);
|
|
39
|
+
this.renderAgentDropdown();
|
|
40
|
+
} catch (e) {
|
|
41
|
+
console.error('Failed to load LLMs', e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
renderAgentDropdown() {
|
|
46
|
+
const list = this.querySelector('#agentDropdownList');
|
|
47
|
+
const agents = store.get('agents') || [];
|
|
48
|
+
const llms = store.get('llms') || [];
|
|
49
|
+
const selectionType = store.get('selectionType');
|
|
50
|
+
const selectedAgent = store.get('selectedAgent');
|
|
51
|
+
const selectedLlm = store.get('selectedLlm');
|
|
52
|
+
|
|
53
|
+
if (!list) return;
|
|
54
|
+
|
|
55
|
+
if (agents.length === 0 && llms.length === 0) {
|
|
56
|
+
list.innerHTML = '<div class="text-gray-500 text-sm text-center py-4">No agents or LLMs available</div>';
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let html = '';
|
|
61
|
+
|
|
62
|
+
// Agents section
|
|
63
|
+
if (agents.length > 0) {
|
|
64
|
+
html += '<div class="px-4 py-2 text-xs font-semibold text-gray-400 uppercase tracking-wider bg-dark-bg/50">Agents</div>';
|
|
65
|
+
html += agents.map(agent => {
|
|
66
|
+
const isSelected = selectionType === 'agent' && selectedAgent?.name === agent.name;
|
|
67
|
+
return `
|
|
68
|
+
<div data-type="agent" data-name="${agent.name}" class="selection-item px-4 py-3 hover:bg-dark-hover cursor-pointer transition-colors border-b border-dark-border ${isSelected ? 'bg-dark-hover' : ''}">
|
|
69
|
+
<div class="flex items-start justify-between">
|
|
70
|
+
<div class="flex-1">
|
|
71
|
+
<div class="font-medium text-gray-200 mb-0.5">${agent.name}</div>
|
|
72
|
+
<div class="text-xs text-gray-500 line-clamp-2">${agent.description}</div>
|
|
73
|
+
</div>
|
|
74
|
+
${isSelected ? '<i class="fas fa-check text-blue-400 ml-2 mt-1"></i>' : ''}
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
`;
|
|
78
|
+
}).join('');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// LLMs section
|
|
82
|
+
if (llms.length > 0) {
|
|
83
|
+
html += '<div class="px-4 py-2 text-xs font-semibold text-gray-400 uppercase tracking-wider bg-dark-bg/50">LLMs</div>';
|
|
84
|
+
html += llms.map(llm => {
|
|
85
|
+
const isSelected = selectionType === 'llm' && selectedLlm?.name === llm.name;
|
|
86
|
+
return `
|
|
87
|
+
<div data-type="llm" data-name="${llm.name}" class="selection-item px-4 py-3 hover:bg-dark-hover cursor-pointer transition-colors border-b border-dark-border last:border-b-0 ${isSelected ? 'bg-dark-hover' : ''}">
|
|
88
|
+
<div class="flex items-start justify-between">
|
|
89
|
+
<div class="flex-1">
|
|
90
|
+
<div class="font-medium text-gray-200 mb-0.5">${llm.name}</div>
|
|
91
|
+
<div class="text-xs text-gray-500 line-clamp-2">${llm.model}</div>
|
|
92
|
+
</div>
|
|
93
|
+
${isSelected ? '<i class="fas fa-check text-blue-400 ml-2 mt-1"></i>' : ''}
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
`;
|
|
97
|
+
}).join('');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
list.innerHTML = html;
|
|
101
|
+
|
|
102
|
+
list.querySelectorAll('.selection-item').forEach(item => {
|
|
103
|
+
item.addEventListener('click', () => {
|
|
104
|
+
const type = item.dataset.type;
|
|
105
|
+
const name = item.dataset.name;
|
|
106
|
+
|
|
107
|
+
// Check if we're actually switching to a different agent/llm
|
|
108
|
+
const currentType = store.get('selectionType');
|
|
109
|
+
const currentAgent = store.get('selectedAgent');
|
|
110
|
+
const currentLlm = store.get('selectedLlm');
|
|
111
|
+
const currentName = currentType === 'agent' ? currentAgent?.name : currentLlm?.name;
|
|
112
|
+
|
|
113
|
+
const isSwitching = !(type === currentType && name === currentName);
|
|
114
|
+
|
|
115
|
+
if (type === 'agent') {
|
|
116
|
+
const agent = agents.find(a => a.name === name);
|
|
117
|
+
store.set('selectedAgent', agent);
|
|
118
|
+
store.set('selectedLlm', null);
|
|
119
|
+
store.set('selectionType', 'agent');
|
|
120
|
+
} else if (type === 'llm') {
|
|
121
|
+
const llm = llms.find(l => l.name === name);
|
|
122
|
+
store.set('selectedLlm', llm);
|
|
123
|
+
store.set('selectedAgent', null);
|
|
124
|
+
store.set('selectionType', 'llm');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Clear chat history when switching
|
|
128
|
+
if (isSwitching) {
|
|
129
|
+
this.clearChatHistory();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this.updateSelectedAgentUI();
|
|
133
|
+
this.toggleDropdown(false);
|
|
134
|
+
this.renderAgentDropdown(); // Re-render to update selection checkmark
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
updateSelectedAgentUI() {
|
|
140
|
+
const selectionType = store.get('selectionType');
|
|
141
|
+
const agent = store.get('selectedAgent');
|
|
142
|
+
const llm = store.get('selectedLlm');
|
|
143
|
+
const nameEl = this.querySelector('#selectedAgentName');
|
|
144
|
+
const btn = this.querySelector('#sendMessageBtn');
|
|
145
|
+
|
|
146
|
+
const selected = selectionType === 'agent' ? agent : llm;
|
|
147
|
+
|
|
148
|
+
if (nameEl && selected) {
|
|
149
|
+
nameEl.textContent = selected.name;
|
|
150
|
+
} else if (nameEl) {
|
|
151
|
+
nameEl.textContent = 'Select Agent/LLM';
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (btn) btn.disabled = !selected || this.isLoading;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
toggleDropdown(show) {
|
|
158
|
+
const dropdown = this.querySelector('#agentDropdown');
|
|
159
|
+
if (dropdown) {
|
|
160
|
+
if (show === undefined) {
|
|
161
|
+
dropdown.classList.toggle('hidden');
|
|
162
|
+
} else if (show) {
|
|
163
|
+
dropdown.classList.remove('hidden');
|
|
164
|
+
} else {
|
|
165
|
+
dropdown.classList.add('hidden');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async sendMessage() {
|
|
171
|
+
const input = this.querySelector('#chatInput');
|
|
172
|
+
const message = input.value.trim();
|
|
173
|
+
const selectionType = store.get('selectionType');
|
|
174
|
+
const agent = store.get('selectedAgent');
|
|
175
|
+
const llm = store.get('selectedLlm');
|
|
176
|
+
|
|
177
|
+
const selected = selectionType === 'agent' ? agent : llm;
|
|
178
|
+
|
|
179
|
+
if (!message || !selected || this.isLoading) return;
|
|
180
|
+
|
|
181
|
+
// Add user message
|
|
182
|
+
this.appendMessage('user', message);
|
|
183
|
+
input.value = '';
|
|
184
|
+
input.style.height = 'auto';
|
|
185
|
+
|
|
186
|
+
this.isLoading = true;
|
|
187
|
+
this.updateUiState();
|
|
188
|
+
|
|
189
|
+
const responseId = 'response-' + Date.now();
|
|
190
|
+
this.createResponseBubble(responseId);
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
if (selectionType === 'agent') {
|
|
194
|
+
await this.sendAgentMessage(agent, message, responseId);
|
|
195
|
+
} else if (selectionType === 'llm') {
|
|
196
|
+
await this.sendLlmMessage(llm, message, responseId);
|
|
197
|
+
}
|
|
198
|
+
} catch (e) {
|
|
199
|
+
this.updateResponseError(responseId, `Error: ${e.message}`);
|
|
200
|
+
} finally {
|
|
201
|
+
this.isLoading = false;
|
|
202
|
+
this.updateUiState();
|
|
203
|
+
input.focus();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async sendAgentMessage(agent, message, responseId) {
|
|
208
|
+
const inputVars = agent.inputVariables || ['message'];
|
|
209
|
+
const inputObj = {};
|
|
210
|
+
inputObj[inputVars[0] || 'message'] = message;
|
|
211
|
+
|
|
212
|
+
const res = await api.streamAgent(agent.name, inputObj, store.get('sessionId'));
|
|
213
|
+
const reader = res.body.getReader();
|
|
214
|
+
const decoder = new TextDecoder();
|
|
215
|
+
|
|
216
|
+
const bubble = this.querySelector(`#${responseId}`);
|
|
217
|
+
const contentDiv = bubble.querySelector('.response-content');
|
|
218
|
+
const container = this.querySelector('#chatMessages');
|
|
219
|
+
const thinkingState = {
|
|
220
|
+
inThinking: false,
|
|
221
|
+
thinkingSections: [],
|
|
222
|
+
currentSection: null
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
let currentContent = '';
|
|
226
|
+
let buffer = '';
|
|
227
|
+
|
|
228
|
+
while (true) {
|
|
229
|
+
const { done, value } = await reader.read();
|
|
230
|
+
if (done) break;
|
|
231
|
+
|
|
232
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
233
|
+
buffer += chunk;
|
|
234
|
+
|
|
235
|
+
const lines = buffer.split('\n');
|
|
236
|
+
// Keep the last partial line in the buffer
|
|
237
|
+
buffer = lines.pop() || '';
|
|
238
|
+
|
|
239
|
+
for (const line of lines) {
|
|
240
|
+
if (line.trim() === '') continue;
|
|
241
|
+
|
|
242
|
+
if (line.startsWith('data: ')) {
|
|
243
|
+
const data = line.slice(6);
|
|
244
|
+
if (data === '[DONE]') continue;
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
const event = JSON.parse(data);
|
|
248
|
+
if (event.type === 'content') {
|
|
249
|
+
currentContent += event.content;
|
|
250
|
+
}
|
|
251
|
+
this.handleStreamEvent(event, responseId, currentContent, thinkingState);
|
|
252
|
+
} catch (e) {
|
|
253
|
+
console.error('Error parsing stream event', e, data);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async sendLlmMessage(llm, message, responseId) {
|
|
261
|
+
const res = await api.streamLLM(llm.name, message);
|
|
262
|
+
const reader = res.body.getReader();
|
|
263
|
+
const decoder = new TextDecoder();
|
|
264
|
+
|
|
265
|
+
const bubble = this.querySelector(`#${responseId}`);
|
|
266
|
+
const contentDiv = bubble.querySelector('.response-content');
|
|
267
|
+
const loadingDots = contentDiv.querySelector('.loading-dots');
|
|
268
|
+
const container = this.querySelector('#chatMessages');
|
|
269
|
+
|
|
270
|
+
if (loadingDots) {
|
|
271
|
+
loadingDots.remove();
|
|
272
|
+
bubble.querySelector('.max-w-4xl').classList.remove('py-4');
|
|
273
|
+
bubble.querySelector('.max-w-4xl').classList.add('py-3');
|
|
274
|
+
contentDiv.classList.remove('flex', 'items-center', 'whitespace-pre-wrap');
|
|
275
|
+
contentDiv.innerHTML = '';
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
let buffer = '';
|
|
279
|
+
let fullContent = '';
|
|
280
|
+
const thinkingState = {
|
|
281
|
+
inThinking: false,
|
|
282
|
+
thinkingSections: [],
|
|
283
|
+
currentSection: null
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
while (true) {
|
|
287
|
+
const { done, value } = await reader.read();
|
|
288
|
+
if (done) break;
|
|
289
|
+
|
|
290
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
291
|
+
buffer += chunk;
|
|
292
|
+
|
|
293
|
+
const lines = buffer.split('\n');
|
|
294
|
+
buffer = lines.pop() || '';
|
|
295
|
+
|
|
296
|
+
for (const line of lines) {
|
|
297
|
+
if (line.trim() === '') continue;
|
|
298
|
+
|
|
299
|
+
if (line.startsWith('data: ')) {
|
|
300
|
+
const data = line.slice(6);
|
|
301
|
+
|
|
302
|
+
if (data === '[DONE]') continue;
|
|
303
|
+
|
|
304
|
+
try {
|
|
305
|
+
const parsed = JSON.parse(data);
|
|
306
|
+
|
|
307
|
+
if (parsed.error) {
|
|
308
|
+
throw new Error(parsed.error);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const text = parsed.content || '';
|
|
312
|
+
|
|
313
|
+
if (text) {
|
|
314
|
+
fullContent += text;
|
|
315
|
+
this.renderLlmContentStreaming(contentDiv, fullContent, responseId, thinkingState);
|
|
316
|
+
container.scrollTop = container.scrollHeight;
|
|
317
|
+
}
|
|
318
|
+
} catch (e) {
|
|
319
|
+
console.error('Error parsing stream chunk:', e, data);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
renderLlmContentStreaming(contentDiv, fullContent, responseId, state) {
|
|
327
|
+
// Parse content to find think sections and regular text
|
|
328
|
+
const parts = [];
|
|
329
|
+
let pos = 0;
|
|
330
|
+
let thinkIndex = 0;
|
|
331
|
+
|
|
332
|
+
while (pos < fullContent.length) {
|
|
333
|
+
const thinkStart = fullContent.indexOf('[THINK]', pos);
|
|
334
|
+
|
|
335
|
+
if (thinkStart === -1) {
|
|
336
|
+
// No more think sections, add remaining text
|
|
337
|
+
const text = fullContent.slice(pos).trim();
|
|
338
|
+
if (text) {
|
|
339
|
+
parts.push({ type: 'text', content: text });
|
|
340
|
+
}
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Add text before [THINK]
|
|
345
|
+
if (thinkStart > pos) {
|
|
346
|
+
const text = fullContent.slice(pos, thinkStart).trim();
|
|
347
|
+
if (text) {
|
|
348
|
+
parts.push({ type: 'text', content: text });
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Find the end of this think section
|
|
353
|
+
const thinkContentStart = thinkStart + 7; // After [THINK]
|
|
354
|
+
const thinkEnd = fullContent.indexOf('[/THINK]', thinkContentStart);
|
|
355
|
+
|
|
356
|
+
if (thinkEnd === -1) {
|
|
357
|
+
// Think section is still streaming
|
|
358
|
+
const thinkContent = fullContent.slice(thinkContentStart).trim();
|
|
359
|
+
parts.push({ type: 'think', content: thinkContent, complete: false, index: thinkIndex });
|
|
360
|
+
thinkIndex++;
|
|
361
|
+
break;
|
|
362
|
+
} else {
|
|
363
|
+
// Complete think section
|
|
364
|
+
const thinkContent = fullContent.slice(thinkContentStart, thinkEnd).trim();
|
|
365
|
+
parts.push({ type: 'think', content: thinkContent, complete: true, index: thinkIndex });
|
|
366
|
+
thinkIndex++;
|
|
367
|
+
pos = thinkEnd + 8; // After [/THINK]
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Update DOM incrementally instead of rebuilding
|
|
372
|
+
let currentChildIndex = 0;
|
|
373
|
+
|
|
374
|
+
for (let i = 0; i < parts.length; i++) {
|
|
375
|
+
const part = parts[i];
|
|
376
|
+
const existingChild = contentDiv.children[currentChildIndex];
|
|
377
|
+
|
|
378
|
+
if (part.type === 'text') {
|
|
379
|
+
if (existingChild && existingChild.classList.contains('content-text')) {
|
|
380
|
+
// Update existing text element with markdown
|
|
381
|
+
const renderedHtml = markdownRenderer.render(part.content);
|
|
382
|
+
existingChild.innerHTML = renderedHtml;
|
|
383
|
+
markdownRenderer.highlightCode(existingChild);
|
|
384
|
+
} else {
|
|
385
|
+
// Create new text element
|
|
386
|
+
const div = document.createElement('div');
|
|
387
|
+
div.className = 'content-text markdown-content';
|
|
388
|
+
const renderedHtml = markdownRenderer.render(part.content);
|
|
389
|
+
div.innerHTML = renderedHtml;
|
|
390
|
+
markdownRenderer.highlightCode(div);
|
|
391
|
+
if (existingChild) {
|
|
392
|
+
contentDiv.insertBefore(div, existingChild);
|
|
393
|
+
} else {
|
|
394
|
+
contentDiv.appendChild(div);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
currentChildIndex++;
|
|
398
|
+
} else if (part.type === 'think') {
|
|
399
|
+
const thinkId = `think-${responseId}-${part.index}`;
|
|
400
|
+
|
|
401
|
+
if (existingChild && existingChild.classList.contains('think-section')) {
|
|
402
|
+
// Update existing think section
|
|
403
|
+
const label = existingChild.querySelector('.think-label');
|
|
404
|
+
const content = existingChild.querySelector('.think-content');
|
|
405
|
+
if (label) {
|
|
406
|
+
label.textContent = part.complete ? 'Thinking' : 'Thinking...';
|
|
407
|
+
}
|
|
408
|
+
if (content) {
|
|
409
|
+
const renderedHtml = markdownRenderer.render(part.content);
|
|
410
|
+
content.innerHTML = renderedHtml;
|
|
411
|
+
content.classList.add('markdown-content');
|
|
412
|
+
markdownRenderer.highlightCode(content);
|
|
413
|
+
}
|
|
414
|
+
} else {
|
|
415
|
+
// Create new think section with event listener
|
|
416
|
+
const section = document.createElement('div');
|
|
417
|
+
section.className = 'think-section mb-3 border-l-2 border-blue-500/40 pl-3 py-1';
|
|
418
|
+
section.dataset.thinkIndex = part.index;
|
|
419
|
+
|
|
420
|
+
const toggle = document.createElement('button');
|
|
421
|
+
toggle.className = 'think-toggle flex items-center gap-1.5 text-xs text-blue-400 hover:text-blue-300 py-1 cursor-pointer';
|
|
422
|
+
toggle.dataset.thinkId = thinkId;
|
|
423
|
+
|
|
424
|
+
toggle.innerHTML = `
|
|
425
|
+
<i class="fas fa-brain text-xs"></i>
|
|
426
|
+
<span class="font-medium think-label">${part.complete ? 'Thinking' : 'Thinking...'}</span>
|
|
427
|
+
<i class="fas fa-chevron-right text-[10px] transition-transform think-chevron"></i>
|
|
428
|
+
`;
|
|
429
|
+
|
|
430
|
+
const thinkContent = document.createElement('div');
|
|
431
|
+
thinkContent.id = thinkId;
|
|
432
|
+
thinkContent.className = 'think-content hidden text-sm text-gray-400 markdown-content mt-1 leading-relaxed';
|
|
433
|
+
const renderedHtml = markdownRenderer.render(part.content);
|
|
434
|
+
thinkContent.innerHTML = renderedHtml;
|
|
435
|
+
markdownRenderer.highlightCode(thinkContent);
|
|
436
|
+
|
|
437
|
+
// Add click handler ONCE when creating
|
|
438
|
+
toggle.addEventListener('click', (e) => {
|
|
439
|
+
e.preventDefault();
|
|
440
|
+
e.stopPropagation();
|
|
441
|
+
const content = section.querySelector('.think-content');
|
|
442
|
+
const chevron = section.querySelector('.think-chevron');
|
|
443
|
+
|
|
444
|
+
if (content && chevron) {
|
|
445
|
+
if (content.classList.contains('hidden')) {
|
|
446
|
+
content.classList.remove('hidden');
|
|
447
|
+
chevron.classList.remove('fa-chevron-right');
|
|
448
|
+
chevron.classList.add('fa-chevron-down');
|
|
449
|
+
} else {
|
|
450
|
+
content.classList.add('hidden');
|
|
451
|
+
chevron.classList.remove('fa-chevron-down');
|
|
452
|
+
chevron.classList.add('fa-chevron-right');
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
section.appendChild(toggle);
|
|
458
|
+
section.appendChild(thinkContent);
|
|
459
|
+
|
|
460
|
+
if (existingChild) {
|
|
461
|
+
contentDiv.insertBefore(section, existingChild);
|
|
462
|
+
} else {
|
|
463
|
+
contentDiv.appendChild(section);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
currentChildIndex++;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Remove any extra children
|
|
471
|
+
while (contentDiv.children.length > currentChildIndex) {
|
|
472
|
+
contentDiv.removeChild(contentDiv.lastChild);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
createResponseBubble(id) {
|
|
477
|
+
const container = this.querySelector('#chatMessages');
|
|
478
|
+
const div = document.createElement('div');
|
|
479
|
+
div.id = id;
|
|
480
|
+
div.className = 'flex justify-start';
|
|
481
|
+
div.innerHTML = `
|
|
482
|
+
<div class="max-w-4xl bg-dark-surface border border-dark-border rounded-3xl px-5 py-4 text-gray-100 text-[15px] leading-relaxed relative group">
|
|
483
|
+
<div class="response-content whitespace-pre-wrap flex items-center">
|
|
484
|
+
<div class="loading-dots flex gap-1">
|
|
485
|
+
<div class="w-2 h-2 bg-blue-500 rounded-full animate-bounce"></div>
|
|
486
|
+
<div class="w-2 h-2 bg-blue-500 rounded-full animate-bounce" style="animation-delay: 0.2s"></div>
|
|
487
|
+
<div class="w-2 h-2 bg-blue-500 rounded-full animate-bounce" style="animation-delay: 0.4s"></div>
|
|
488
|
+
</div>
|
|
489
|
+
</div>
|
|
490
|
+
<div class="tool-invocations space-y-2 mt-2"></div>
|
|
491
|
+
</div>
|
|
492
|
+
`;
|
|
493
|
+
container.appendChild(div);
|
|
494
|
+
container.scrollTop = container.scrollHeight;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
handleStreamEvent(event, responseId, currentContent, thinkingState) {
|
|
498
|
+
const bubble = this.querySelector(`#${responseId}`);
|
|
499
|
+
if (!bubble) return;
|
|
500
|
+
|
|
501
|
+
const contentDiv = bubble.querySelector('.response-content');
|
|
502
|
+
const toolsDiv = bubble.querySelector('.tool-invocations');
|
|
503
|
+
const loadingDots = contentDiv.querySelector('.loading-dots');
|
|
504
|
+
const container = this.querySelector('#chatMessages');
|
|
505
|
+
|
|
506
|
+
if (event.type === 'content') {
|
|
507
|
+
if (loadingDots) {
|
|
508
|
+
loadingDots.remove();
|
|
509
|
+
// Reset padding and remove flex classes
|
|
510
|
+
bubble.querySelector('.max-w-4xl').classList.remove('py-4');
|
|
511
|
+
bubble.querySelector('.max-w-4xl').classList.add('py-3');
|
|
512
|
+
contentDiv.classList.remove('flex', 'items-center', 'whitespace-pre-wrap');
|
|
513
|
+
// Clear any whitespace
|
|
514
|
+
contentDiv.innerHTML = '';
|
|
515
|
+
}
|
|
516
|
+
// Use the same rendering method as LLMs to handle [THINK] tags
|
|
517
|
+
this.renderLlmContentStreaming(contentDiv, currentContent, responseId, thinkingState);
|
|
518
|
+
// Scroll to bottom as content streams in
|
|
519
|
+
container.scrollTop = container.scrollHeight;
|
|
520
|
+
} else if (event.type === 'tool_start') {
|
|
521
|
+
const toolId = `tool-${event.runId}`;
|
|
522
|
+
const toolEl = document.createElement('div');
|
|
523
|
+
toolEl.id = toolId;
|
|
524
|
+
toolEl.className = 'bg-dark-bg/50 border border-dark-border rounded-lg p-2 text-sm text-gray-400 font-mono flex items-center gap-2';
|
|
525
|
+
toolEl.innerHTML = `
|
|
526
|
+
<i class="fas fa-cog animate-spin text-blue-400"></i>
|
|
527
|
+
<span>Using ${event.tool}...</span>
|
|
528
|
+
`;
|
|
529
|
+
toolsDiv.appendChild(toolEl);
|
|
530
|
+
// Scroll to bottom when tool starts
|
|
531
|
+
container.scrollTop = container.scrollHeight;
|
|
532
|
+
|
|
533
|
+
// If we have loading dots, keep them until text arrives
|
|
534
|
+
} else if (event.type === 'tool_end') {
|
|
535
|
+
const toolId = `tool-${event.runId}`;
|
|
536
|
+
const toolEl = toolsDiv.querySelector(`#${toolId}`);
|
|
537
|
+
if (toolEl) {
|
|
538
|
+
toolEl.className = 'bg-dark-bg/30 border border-dark-border/50 rounded-lg p-2 text-sm text-gray-500 font-mono flex flex-col gap-1';
|
|
539
|
+
// Success state
|
|
540
|
+
toolEl.innerHTML = `
|
|
541
|
+
<div class="flex items-center gap-2">
|
|
542
|
+
<i class="fas fa-check text-green-500"></i>
|
|
543
|
+
<span>Used ${event.tool}</span>
|
|
544
|
+
</div>
|
|
545
|
+
`;
|
|
546
|
+
|
|
547
|
+
// Add output preview
|
|
548
|
+
const preview = document.createElement('div');
|
|
549
|
+
preview.className = 'text-xs text-gray-600 pl-6 truncate';
|
|
550
|
+
preview.textContent = typeof event.output === 'string' ? event.output : JSON.stringify(event.output);
|
|
551
|
+
toolEl.appendChild(preview);
|
|
552
|
+
// Scroll to bottom when tool ends (output preview added)
|
|
553
|
+
container.scrollTop = container.scrollHeight;
|
|
554
|
+
}
|
|
555
|
+
} else if (event.type === 'result') {
|
|
556
|
+
if (loadingDots) {
|
|
557
|
+
loadingDots.remove();
|
|
558
|
+
bubble.querySelector('.max-w-4xl').classList.remove('py-4');
|
|
559
|
+
bubble.querySelector('.max-w-4xl').classList.add('py-3');
|
|
560
|
+
contentDiv.classList.remove('flex', 'items-center', 'whitespace-pre-wrap');
|
|
561
|
+
contentDiv.innerHTML = '';
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Display structured output as formatted JSON
|
|
565
|
+
const resultContainer = document.createElement('div');
|
|
566
|
+
resultContainer.className = 'bg-dark-bg/50 border border-dark-border rounded-lg p-4';
|
|
567
|
+
|
|
568
|
+
const resultPre = document.createElement('pre');
|
|
569
|
+
resultPre.className = 'text-sm text-gray-300 font-mono whitespace-pre-wrap overflow-x-auto';
|
|
570
|
+
resultPre.textContent = JSON.stringify(event.output, null, 2);
|
|
571
|
+
|
|
572
|
+
resultContainer.appendChild(resultPre);
|
|
573
|
+
contentDiv.appendChild(resultContainer);
|
|
574
|
+
|
|
575
|
+
// Scroll to bottom
|
|
576
|
+
container.scrollTop = container.scrollHeight;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
updateResponseError(id, errorMsg) {
|
|
581
|
+
const bubble = this.querySelector(`#${id}`);
|
|
582
|
+
if (bubble) {
|
|
583
|
+
const content = bubble.querySelector('.response-content');
|
|
584
|
+
content.innerHTML = `<span class="text-red-400">${errorMsg}</span>`;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
updateUiState() {
|
|
589
|
+
const btn = this.querySelector('#sendMessageBtn');
|
|
590
|
+
const input = this.querySelector('#chatInput');
|
|
591
|
+
if (btn) btn.disabled = this.isLoading;
|
|
592
|
+
if (input) input.disabled = this.isLoading;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
appendMessage(role, content, metadata = {}) {
|
|
596
|
+
const container = this.querySelector('#chatMessages');
|
|
597
|
+
const isUser = role === 'user';
|
|
598
|
+
const hasError = metadata.error;
|
|
599
|
+
|
|
600
|
+
const div = document.createElement('div');
|
|
601
|
+
div.className = isUser ? 'flex justify-end' : 'flex justify-start';
|
|
602
|
+
|
|
603
|
+
const bubbleColor = isUser ? 'bg-dark-surface' : (hasError ? 'bg-red-900/20 border-red-900/30' : 'bg-dark-surface');
|
|
604
|
+
const textColor = hasError ? 'text-red-300' : 'text-gray-100';
|
|
605
|
+
|
|
606
|
+
div.innerHTML = `
|
|
607
|
+
<div class="max-w-4xl ${bubbleColor} border ${isUser ? 'border-transparent' : 'border-dark-border'} rounded-3xl px-5 py-3 ${textColor} text-[15px] leading-relaxed relative group">
|
|
608
|
+
<div class="whitespace-pre-wrap">${this.escapeHtml(content)}</div>
|
|
609
|
+
${!isUser && !hasError ? `
|
|
610
|
+
<button class="copy-btn absolute -bottom-6 left-0 text-gray-500 hover:text-gray-300 opacity-0 group-hover:opacity-100 transition-opacity p-1" title="Copy">
|
|
611
|
+
<i class="far fa-copy"></i>
|
|
612
|
+
</button>
|
|
613
|
+
` : ''}
|
|
614
|
+
</div>
|
|
615
|
+
`;
|
|
616
|
+
|
|
617
|
+
if (!isUser && !hasError) {
|
|
618
|
+
const btn = div.querySelector('.copy-btn');
|
|
619
|
+
btn.addEventListener('click', () => {
|
|
620
|
+
navigator.clipboard.writeText(content);
|
|
621
|
+
btn.innerHTML = '<i class="fas fa-check"></i>';
|
|
622
|
+
setTimeout(() => btn.innerHTML = '<i class="far fa-copy"></i>', 2000);
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
container.appendChild(div);
|
|
627
|
+
container.scrollTop = container.scrollHeight;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
appendLoading() {
|
|
631
|
+
const id = 'loading-' + Date.now();
|
|
632
|
+
const container = this.querySelector('#chatMessages');
|
|
633
|
+
const div = document.createElement('div');
|
|
634
|
+
div.id = id;
|
|
635
|
+
div.className = 'flex justify-start';
|
|
636
|
+
div.innerHTML = `
|
|
637
|
+
<div class="max-w-4xl bg-dark-surface border border-dark-border rounded-3xl px-5 py-4">
|
|
638
|
+
<div class="flex gap-1">
|
|
639
|
+
<div class="w-2 h-2 bg-blue-500 rounded-full animate-bounce"></div>
|
|
640
|
+
<div class="w-2 h-2 bg-blue-500 rounded-full animate-bounce" style="animation-delay: 0.2s"></div>
|
|
641
|
+
<div class="w-2 h-2 bg-blue-500 rounded-full animate-bounce" style="animation-delay: 0.4s"></div>
|
|
642
|
+
</div>
|
|
643
|
+
</div>
|
|
644
|
+
`;
|
|
645
|
+
container.appendChild(div);
|
|
646
|
+
container.scrollTop = container.scrollHeight;
|
|
647
|
+
return id;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
removeLoading(id) {
|
|
651
|
+
const el = this.querySelector(`#${id}`);
|
|
652
|
+
if (el) el.remove();
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
escapeHtml(text) {
|
|
656
|
+
const div = document.createElement('div');
|
|
657
|
+
div.textContent = text;
|
|
658
|
+
return div.innerHTML;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
clearChatHistory() {
|
|
662
|
+
const container = this.querySelector('#chatMessages');
|
|
663
|
+
if (!container) return;
|
|
664
|
+
|
|
665
|
+
// Clear all messages
|
|
666
|
+
container.innerHTML = '';
|
|
667
|
+
|
|
668
|
+
// Add welcome message
|
|
669
|
+
const div = document.createElement('div');
|
|
670
|
+
div.className = 'flex justify-start';
|
|
671
|
+
div.innerHTML = `
|
|
672
|
+
<div class="max-w-4xl bg-dark-surface border border-dark-border rounded-3xl px-5 py-3 text-gray-100 text-[15px] leading-relaxed">
|
|
673
|
+
Welcome to Agent Orcha. Start chatting with your AI agents and LLMs.
|
|
674
|
+
</div>
|
|
675
|
+
`;
|
|
676
|
+
container.appendChild(div);
|
|
677
|
+
|
|
678
|
+
// Clear session ID to start fresh
|
|
679
|
+
store.set('sessionId', null);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
postRender() {
|
|
683
|
+
const input = this.querySelector('#chatInput');
|
|
684
|
+
|
|
685
|
+
// Auto-resize
|
|
686
|
+
input.addEventListener('input', () => {
|
|
687
|
+
input.style.height = 'auto';
|
|
688
|
+
input.style.height = Math.min(input.scrollHeight, 200) + 'px';
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
// Send on enter
|
|
692
|
+
input.addEventListener('keydown', (e) => {
|
|
693
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
694
|
+
e.preventDefault();
|
|
695
|
+
this.sendMessage();
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
this.querySelector('#sendMessageBtn').addEventListener('click', () => this.sendMessage());
|
|
700
|
+
|
|
701
|
+
// Dropdown toggle
|
|
702
|
+
const selectorBtn = this.querySelector('#agentSelectorBtn');
|
|
703
|
+
const dropdown = this.querySelector('#agentDropdown');
|
|
704
|
+
|
|
705
|
+
selectorBtn.addEventListener('click', (e) => {
|
|
706
|
+
e.stopPropagation();
|
|
707
|
+
this.toggleDropdown();
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
document.addEventListener('click', (e) => {
|
|
711
|
+
if (!selectorBtn.contains(e.target) && !dropdown.contains(e.target)) {
|
|
712
|
+
this.toggleDropdown(false);
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
template() {
|
|
718
|
+
return `
|
|
719
|
+
<div class="flex flex-col h-[calc(100vh-220px)]">
|
|
720
|
+
<!-- Chat Messages -->
|
|
721
|
+
<div id="chatMessages" class="flex-1 overflow-y-auto mb-6 space-y-4 pr-2 custom-scrollbar">
|
|
722
|
+
<div class="flex justify-start">
|
|
723
|
+
<div class="max-w-4xl bg-dark-surface border border-dark-border rounded-3xl px-5 py-3 text-gray-100 text-[15px] leading-relaxed">
|
|
724
|
+
Welcome to Agent Orcha. Start chatting with your AI agents and LLMs.
|
|
725
|
+
</div>
|
|
726
|
+
</div>
|
|
727
|
+
</div>
|
|
728
|
+
|
|
729
|
+
<!-- Input Area -->
|
|
730
|
+
<div class="border-t border-dark-border pt-4">
|
|
731
|
+
<div class="relative bg-dark-surface border border-dark-border rounded-2xl focus-within:border-gray-500 transition-colors">
|
|
732
|
+
<textarea id="chatInput" rows="1"
|
|
733
|
+
class="w-full bg-transparent px-4 py-3 pr-32 text-gray-100 placeholder-gray-500 resize-none focus:outline-none max-h-[200px]"
|
|
734
|
+
placeholder="Reply..."></textarea>
|
|
735
|
+
|
|
736
|
+
<div class="absolute bottom-2 right-2 flex items-center gap-2">
|
|
737
|
+
<!-- Agent Selector -->
|
|
738
|
+
<div class="relative">
|
|
739
|
+
<button id="agentSelectorBtn" class="flex items-center gap-2 px-3 py-1.5 bg-dark-bg hover:bg-dark-hover rounded-lg text-sm font-medium text-gray-300 transition-colors">
|
|
740
|
+
<span id="selectedAgentName">Select Agent/LLM</span>
|
|
741
|
+
<i class="fas fa-chevron-down text-xs text-gray-400"></i>
|
|
742
|
+
</button>
|
|
743
|
+
|
|
744
|
+
<div id="agentDropdown" class="hidden absolute bottom-full mb-2 right-0 w-80 bg-dark-surface border border-dark-border rounded-xl shadow-2xl overflow-hidden z-10 max-h-96 flex flex-col">
|
|
745
|
+
<div id="agentDropdownList" class="overflow-y-auto custom-scrollbar">
|
|
746
|
+
<div class="text-gray-500 text-sm text-center py-4">Loading...</div>
|
|
747
|
+
</div>
|
|
748
|
+
</div>
|
|
749
|
+
</div>
|
|
750
|
+
|
|
751
|
+
<button id="sendMessageBtn" disabled
|
|
752
|
+
class="bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-500 hover:to-blue-600 disabled:opacity-50 disabled:cursor-not-allowed text-white p-2 rounded-lg transition-all shadow-lg shadow-blue-900/20">
|
|
753
|
+
<i class="fas fa-paper-plane text-sm"></i>
|
|
754
|
+
</button>
|
|
755
|
+
</div>
|
|
756
|
+
</div>
|
|
757
|
+
</div>
|
|
758
|
+
</div>
|
|
759
|
+
`;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
customElements.define('agents-view', AgentsView);
|