agent-orcha 0.0.2 → 0.0.4
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 +777 -100
- 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/init.js +3 -3
- package/dist/src/cli/commands/init.js.map +1 -1
- 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 +21 -12
- 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/sample-data/example-document.txt +0 -15
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
|
|
2
|
+
import { Component } from '../utils/Component.js';
|
|
3
|
+
import { store } from '../store.js';
|
|
4
|
+
import './NavBar.js';
|
|
5
|
+
import './AgentsView.js';
|
|
6
|
+
import './WorkflowsView.js';
|
|
7
|
+
import './KnowledgeView.js';
|
|
8
|
+
import './McpView.js';
|
|
9
|
+
import './IdeView.js';
|
|
10
|
+
|
|
11
|
+
export class AppRoot extends Component {
|
|
12
|
+
postRender() {
|
|
13
|
+
store.addEventListener('state-change', (e) => {
|
|
14
|
+
if (e.detail.key === 'activeTab') {
|
|
15
|
+
this.switchTab(e.detail.value);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Handle browser back/forward
|
|
20
|
+
window.addEventListener('hashchange', () => {
|
|
21
|
+
const hash = window.location.hash.replace('#', '');
|
|
22
|
+
if (hash && hash !== store.get('activeTab')) {
|
|
23
|
+
store.set('activeTab', hash);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Initial tab from hash or default
|
|
28
|
+
const initialTab = store.get('activeTab');
|
|
29
|
+
if (!window.location.hash) {
|
|
30
|
+
window.location.hash = initialTab;
|
|
31
|
+
}
|
|
32
|
+
this.switchTab(initialTab);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
switchTab(tabId) {
|
|
36
|
+
const container = this.querySelector('#tabContent');
|
|
37
|
+
if (!container) return;
|
|
38
|
+
|
|
39
|
+
container.innerHTML = '';
|
|
40
|
+
let el;
|
|
41
|
+
switch (tabId) {
|
|
42
|
+
case 'agents': el = document.createElement('agents-view'); break;
|
|
43
|
+
case 'workflows': el = document.createElement('workflows-view'); break;
|
|
44
|
+
case 'knowledge': el = document.createElement('knowledge-view'); break;
|
|
45
|
+
case 'mcp': el = document.createElement('mcp-view'); break;
|
|
46
|
+
case 'ide': el = document.createElement('ide-view'); break;
|
|
47
|
+
default: el = document.createElement('agents-view'); break;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Preserve state or re-render? Web Components are cheap to re-create usually,
|
|
51
|
+
// but for chat history we might want to keep it in store (which we do).
|
|
52
|
+
// If we wanted to keep DOM alive we'd hide/show, but replacing is cleaner for now.
|
|
53
|
+
container.appendChild(el);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
template() {
|
|
57
|
+
return `
|
|
58
|
+
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 h-screen flex flex-col">
|
|
59
|
+
<div class="mb-4 flex-shrink-0">
|
|
60
|
+
<h1 class="text-4xl font-bold bg-gradient-to-r from-blue-400 to-purple-500 bg-clip-text text-transparent">
|
|
61
|
+
Agent Orcha
|
|
62
|
+
</h1>
|
|
63
|
+
<p class="text-gray-400 mt-2">Declare the system. Orcha handles the REST.</p>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<nav-bar class="flex-shrink-0"></nav-bar>
|
|
67
|
+
|
|
68
|
+
<div id="tabContent" class="flex-1 min-h-0 relative">
|
|
69
|
+
<!-- Dynamic Content -->
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
customElements.define('app-root', AppRoot);
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
|
|
2
|
+
import { Component } from '../utils/Component.js';
|
|
3
|
+
import { api } from '../services/ApiService.js';
|
|
4
|
+
|
|
5
|
+
const FILE_ICONS = {
|
|
6
|
+
yaml: { icon: 'fa-file-code', color: 'text-orange-400' },
|
|
7
|
+
yml: { icon: 'fa-file-code', color: 'text-orange-400' },
|
|
8
|
+
json: { icon: 'fa-file-code', color: 'text-yellow-400' },
|
|
9
|
+
js: { icon: 'fa-file-code', color: 'text-yellow-300' },
|
|
10
|
+
ts: { icon: 'fa-file-code', color: 'text-yellow-300' },
|
|
11
|
+
txt: { icon: 'fa-file-lines', color: 'text-gray-400' },
|
|
12
|
+
md: { icon: 'fa-file-lines', color: 'text-blue-400' },
|
|
13
|
+
default: { icon: 'fa-file', color: 'text-gray-500' },
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const ACE_MODES = {
|
|
17
|
+
yaml: 'ace/mode/yaml',
|
|
18
|
+
yml: 'ace/mode/yaml',
|
|
19
|
+
json: 'ace/mode/json',
|
|
20
|
+
js: 'ace/mode/javascript',
|
|
21
|
+
ts: 'ace/mode/typescript',
|
|
22
|
+
md: 'ace/mode/markdown',
|
|
23
|
+
default: 'ace/mode/text',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function getExtension(filename) {
|
|
27
|
+
const parts = filename.split('.');
|
|
28
|
+
return parts.length > 1 ? parts.pop().toLowerCase() : '';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class IdeView extends Component {
|
|
32
|
+
constructor() {
|
|
33
|
+
super();
|
|
34
|
+
this.editor = null;
|
|
35
|
+
this.currentFile = null;
|
|
36
|
+
this.isDirty = false;
|
|
37
|
+
this.treeData = [];
|
|
38
|
+
this.expandedDirs = new Set();
|
|
39
|
+
this._handleKeyDown = this._handleKeyDown.bind(this);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
disconnectedCallback() {
|
|
43
|
+
document.removeEventListener('keydown', this._handleKeyDown);
|
|
44
|
+
if (this.editor) {
|
|
45
|
+
this.editor.destroy();
|
|
46
|
+
this.editor = null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async postRender() {
|
|
51
|
+
document.addEventListener('keydown', this._handleKeyDown);
|
|
52
|
+
|
|
53
|
+
const saveBtn = this.querySelector('#saveBtn');
|
|
54
|
+
if (saveBtn) {
|
|
55
|
+
saveBtn.addEventListener('click', () => this._saveFile());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await this._loadTree();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
_handleKeyDown(e) {
|
|
62
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
this._saveFile();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async _loadTree() {
|
|
69
|
+
try {
|
|
70
|
+
const data = await api.getFileTree();
|
|
71
|
+
this.treeData = data.tree || [];
|
|
72
|
+
this._renderTree();
|
|
73
|
+
} catch (err) {
|
|
74
|
+
console.error('Failed to load file tree:', err);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_renderTree() {
|
|
79
|
+
const container = this.querySelector('#fileTree');
|
|
80
|
+
if (!container) return;
|
|
81
|
+
container.innerHTML = this._buildTreeHTML(this.treeData, 0);
|
|
82
|
+
this._attachTreeListeners();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
_buildTreeHTML(nodes, depth) {
|
|
86
|
+
return nodes.map(node => {
|
|
87
|
+
if (node.type === 'directory') {
|
|
88
|
+
const isExpanded = this.expandedDirs.has(node.path);
|
|
89
|
+
const chevron = isExpanded ? 'fa-chevron-down' : 'fa-chevron-right';
|
|
90
|
+
const childrenHTML = isExpanded
|
|
91
|
+
? this._buildTreeHTML(node.children || [], depth + 1)
|
|
92
|
+
: '';
|
|
93
|
+
|
|
94
|
+
return `
|
|
95
|
+
<div class="tree-item tree-depth-${Math.min(depth, 5)} flex items-center gap-2 cursor-pointer hover:bg-dark-hover rounded text-sm text-gray-300"
|
|
96
|
+
data-path="${node.path}" data-type="directory">
|
|
97
|
+
<i class="fas ${chevron} text-xs text-gray-500 w-3"></i>
|
|
98
|
+
<i class="fas fa-folder${isExpanded ? '-open' : ''} text-yellow-500 text-sm"></i>
|
|
99
|
+
<span>${node.name}</span>
|
|
100
|
+
</div>
|
|
101
|
+
${childrenHTML}
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const ext = getExtension(node.name);
|
|
106
|
+
const iconInfo = FILE_ICONS[ext] || FILE_ICONS.default;
|
|
107
|
+
const isActive = this.currentFile && this.currentFile.path === node.path;
|
|
108
|
+
const activeClass = isActive ? 'bg-dark-hover text-white' : '';
|
|
109
|
+
|
|
110
|
+
return `
|
|
111
|
+
<div class="tree-item tree-depth-${Math.min(depth, 5)} flex items-center gap-2 cursor-pointer hover:bg-dark-hover rounded text-sm text-gray-300 ${activeClass}"
|
|
112
|
+
data-path="${node.path}" data-type="file">
|
|
113
|
+
<span class="w-3"></span>
|
|
114
|
+
<i class="fas ${iconInfo.icon} ${iconInfo.color} text-sm"></i>
|
|
115
|
+
<span class="truncate max-w-[160px]">${node.name}</span>
|
|
116
|
+
</div>
|
|
117
|
+
`;
|
|
118
|
+
}).join('');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
_attachTreeListeners() {
|
|
122
|
+
this.querySelectorAll('.tree-item').forEach(item => {
|
|
123
|
+
item.addEventListener('click', () => {
|
|
124
|
+
const filePath = item.dataset.path;
|
|
125
|
+
const type = item.dataset.type;
|
|
126
|
+
|
|
127
|
+
if (type === 'directory') {
|
|
128
|
+
this._toggleDir(filePath);
|
|
129
|
+
} else {
|
|
130
|
+
this._openFile(filePath);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
_toggleDir(dirPath) {
|
|
137
|
+
if (this.expandedDirs.has(dirPath)) {
|
|
138
|
+
this.expandedDirs.delete(dirPath);
|
|
139
|
+
} else {
|
|
140
|
+
this.expandedDirs.add(dirPath);
|
|
141
|
+
}
|
|
142
|
+
this._renderTree();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async _openFile(filePath) {
|
|
146
|
+
if (this.isDirty) {
|
|
147
|
+
const confirmed = confirm('You have unsaved changes. Discard and open another file?');
|
|
148
|
+
if (!confirmed) return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
const data = await api.readFile(filePath);
|
|
153
|
+
this.currentFile = { path: data.path, content: data.content };
|
|
154
|
+
this.isDirty = false;
|
|
155
|
+
this._renderEditor();
|
|
156
|
+
this._renderTree();
|
|
157
|
+
} catch (err) {
|
|
158
|
+
console.error('Failed to read file:', err);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
_renderEditor() {
|
|
163
|
+
const editorContainer = this.querySelector('#editorContainer');
|
|
164
|
+
const welcomePanel = this.querySelector('#welcomePanel');
|
|
165
|
+
const breadcrumb = this.querySelector('#breadcrumb');
|
|
166
|
+
const saveBtn = this.querySelector('#saveBtn');
|
|
167
|
+
const dirtyIndicator = this.querySelector('#dirtyIndicator');
|
|
168
|
+
|
|
169
|
+
if (!this.currentFile) {
|
|
170
|
+
if (welcomePanel) welcomePanel.classList.remove('hidden');
|
|
171
|
+
if (editorContainer) editorContainer.classList.add('hidden');
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (welcomePanel) welcomePanel.classList.add('hidden');
|
|
176
|
+
if (editorContainer) editorContainer.classList.remove('hidden');
|
|
177
|
+
|
|
178
|
+
// Update breadcrumb
|
|
179
|
+
if (breadcrumb) {
|
|
180
|
+
const parts = this.currentFile.path.split('/');
|
|
181
|
+
breadcrumb.textContent = parts.join(' / ');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Update dirty state
|
|
185
|
+
this._updateDirtyState();
|
|
186
|
+
|
|
187
|
+
// Initialize or update Ace
|
|
188
|
+
const aceEl = this.querySelector('#aceEditor');
|
|
189
|
+
if (!aceEl) return;
|
|
190
|
+
|
|
191
|
+
if (!this.editor) {
|
|
192
|
+
this.editor = ace.edit(aceEl);
|
|
193
|
+
this.editor.setTheme('ace/theme/one_dark');
|
|
194
|
+
this.editor.setOptions({
|
|
195
|
+
fontSize: '14px',
|
|
196
|
+
showPrintMargin: false,
|
|
197
|
+
wrap: true,
|
|
198
|
+
tabSize: 2,
|
|
199
|
+
useSoftTabs: true,
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
this.editor.session.on('change', () => {
|
|
203
|
+
if (!this.isDirty) {
|
|
204
|
+
this.isDirty = true;
|
|
205
|
+
this._updateDirtyState();
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Set mode based on file extension
|
|
211
|
+
const ext = getExtension(this.currentFile.path);
|
|
212
|
+
const mode = ACE_MODES[ext] || ACE_MODES.default;
|
|
213
|
+
this.editor.session.setMode(mode);
|
|
214
|
+
|
|
215
|
+
// Set content without triggering change event
|
|
216
|
+
this.editor.setValue(this.currentFile.content, -1);
|
|
217
|
+
this.isDirty = false;
|
|
218
|
+
this._updateDirtyState();
|
|
219
|
+
this.editor.focus();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
_updateDirtyState() {
|
|
223
|
+
const dirtyIndicator = this.querySelector('#dirtyIndicator');
|
|
224
|
+
const saveBtn = this.querySelector('#saveBtn');
|
|
225
|
+
const savedMsg = this.querySelector('#savedMsg');
|
|
226
|
+
|
|
227
|
+
if (dirtyIndicator) {
|
|
228
|
+
dirtyIndicator.classList.toggle('hidden', !this.isDirty);
|
|
229
|
+
}
|
|
230
|
+
if (saveBtn) {
|
|
231
|
+
saveBtn.disabled = !this.isDirty;
|
|
232
|
+
saveBtn.classList.toggle('opacity-50', !this.isDirty);
|
|
233
|
+
saveBtn.classList.toggle('cursor-not-allowed', !this.isDirty);
|
|
234
|
+
}
|
|
235
|
+
if (savedMsg) {
|
|
236
|
+
savedMsg.classList.add('hidden');
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async _saveFile() {
|
|
241
|
+
if (!this.currentFile || !this.isDirty || !this.editor) return;
|
|
242
|
+
|
|
243
|
+
const content = this.editor.getValue();
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
const result = await api.writeFile(this.currentFile.path, content);
|
|
247
|
+
this.currentFile.content = content;
|
|
248
|
+
this.isDirty = false;
|
|
249
|
+
this._updateDirtyState();
|
|
250
|
+
|
|
251
|
+
// Show saved confirmation with reload info
|
|
252
|
+
const savedMsg = this.querySelector('#savedMsg');
|
|
253
|
+
if (savedMsg) {
|
|
254
|
+
const reloaded = result.reloaded && result.reloaded !== 'none';
|
|
255
|
+
const failed = result.reloaded === 'error';
|
|
256
|
+
if (failed) {
|
|
257
|
+
savedMsg.textContent = 'Saved (reload failed)';
|
|
258
|
+
savedMsg.classList.remove('hidden', 'text-green-400');
|
|
259
|
+
savedMsg.classList.add('text-yellow-400');
|
|
260
|
+
} else if (reloaded) {
|
|
261
|
+
savedMsg.textContent = `Saved & reloaded ${result.reloaded}`;
|
|
262
|
+
savedMsg.classList.remove('hidden', 'text-yellow-400');
|
|
263
|
+
savedMsg.classList.add('text-green-400');
|
|
264
|
+
} else {
|
|
265
|
+
savedMsg.textContent = 'Saved!';
|
|
266
|
+
savedMsg.classList.remove('hidden', 'text-yellow-400');
|
|
267
|
+
savedMsg.classList.add('text-green-400');
|
|
268
|
+
}
|
|
269
|
+
setTimeout(() => savedMsg.classList.add('hidden'), 2500);
|
|
270
|
+
}
|
|
271
|
+
} catch (err) {
|
|
272
|
+
console.error('Failed to save file:', err);
|
|
273
|
+
alert('Failed to save file.');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
template() {
|
|
278
|
+
return `
|
|
279
|
+
<div class="flex flex-col h-full">
|
|
280
|
+
<!-- Toolbar -->
|
|
281
|
+
<div class="flex items-center justify-between bg-dark-surface border border-dark-border rounded-t-lg px-4 py-2 flex-shrink-0">
|
|
282
|
+
<div class="flex items-center gap-2 text-sm text-gray-400">
|
|
283
|
+
<i class="fas fa-code text-green-400"></i>
|
|
284
|
+
<span id="breadcrumb">Select a file to edit</span>
|
|
285
|
+
</div>
|
|
286
|
+
<div class="flex items-center gap-3">
|
|
287
|
+
<span id="dirtyIndicator" class="hidden text-yellow-400 text-xs flex items-center gap-1">
|
|
288
|
+
<i class="fas fa-circle text-[6px]"></i> Unsaved
|
|
289
|
+
</span>
|
|
290
|
+
<span id="savedMsg" class="hidden text-green-400 text-xs">Saved!</span>
|
|
291
|
+
<button id="saveBtn" class="px-3 py-1 bg-green-600 hover:bg-green-700 text-white text-sm rounded transition-colors opacity-50 cursor-not-allowed" disabled>
|
|
292
|
+
<i class="fas fa-save mr-1"></i> Save
|
|
293
|
+
</button>
|
|
294
|
+
</div>
|
|
295
|
+
</div>
|
|
296
|
+
|
|
297
|
+
<!-- Main content -->
|
|
298
|
+
<div class="flex flex-1 min-h-0 border border-t-0 border-dark-border rounded-b-lg overflow-hidden">
|
|
299
|
+
<!-- File tree sidebar -->
|
|
300
|
+
<div class="w-60 flex-shrink-0 bg-dark-surface border-r border-dark-border overflow-y-auto">
|
|
301
|
+
<div class="px-3 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wider border-b border-dark-border">
|
|
302
|
+
Explorer
|
|
303
|
+
</div>
|
|
304
|
+
<div id="fileTree" class="py-1">
|
|
305
|
+
<div class="px-4 py-8 text-center text-gray-500 text-sm">
|
|
306
|
+
<i class="fas fa-spinner fa-spin mr-2"></i> Loading...
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
|
|
311
|
+
<!-- Editor / Welcome -->
|
|
312
|
+
<div class="flex-1 min-w-0 relative">
|
|
313
|
+
<div id="welcomePanel" class="flex items-center justify-center h-full text-gray-500">
|
|
314
|
+
<div class="text-center">
|
|
315
|
+
<i class="fas fa-code text-4xl mb-4 text-gray-600"></i>
|
|
316
|
+
<p class="text-lg">Select a file from the tree to begin editing</p>
|
|
317
|
+
<p class="text-sm mt-2 text-gray-600">Supports YAML, JSON, JavaScript, TypeScript, and more</p>
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
<div id="editorContainer" class="hidden h-full">
|
|
321
|
+
<div id="aceEditor" class="h-full w-full"></div>
|
|
322
|
+
</div>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
`;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
customElements.define('ide-view', IdeView);
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
|
|
2
|
+
import { Component } from '../utils/Component.js';
|
|
3
|
+
import { api } from '../services/ApiService.js';
|
|
4
|
+
|
|
5
|
+
export class KnowledgeView extends Component {
|
|
6
|
+
async connectedCallback() {
|
|
7
|
+
super.connectedCallback();
|
|
8
|
+
this.loadKnowledge();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async loadKnowledge() {
|
|
12
|
+
try {
|
|
13
|
+
const knowledgeStores = await api.getKnowledgeStores();
|
|
14
|
+
const select = this.querySelector('#knowledgeSelect');
|
|
15
|
+
select.innerHTML = '<option value="">-- Select Knowledge Store --</option>' +
|
|
16
|
+
knowledgeStores.map(k => `<option value="${k.name}">${k.name}</option>`).join('');
|
|
17
|
+
} catch (e) {
|
|
18
|
+
console.error(e);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async onKnowledgeSelected(name) {
|
|
23
|
+
if (!name) {
|
|
24
|
+
this.querySelector('#knowledgeInfo').classList.add('hidden');
|
|
25
|
+
this.querySelector('#searchKnowledge').disabled = true;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const info = await api.getKnowledgeStore(name);
|
|
31
|
+
this.renderInfo(info);
|
|
32
|
+
this.querySelector('#searchKnowledge').disabled = false;
|
|
33
|
+
} catch (e) {
|
|
34
|
+
console.error(e);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
renderInfo(info) {
|
|
39
|
+
const el = this.querySelector('#knowledgeInfo');
|
|
40
|
+
el.classList.remove('hidden');
|
|
41
|
+
el.innerHTML = `
|
|
42
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
|
|
43
|
+
<div><span class="text-gray-400">Description:</span> <span class="text-gray-200 ml-2">${info.description || 'N/A'}</span></div>
|
|
44
|
+
<div><span class="text-gray-400">Source:</span> <span class="text-gray-200 ml-2">${info.source?.type || 'N/A'}</span></div>
|
|
45
|
+
<div><span class="text-gray-400">Store:</span> <span class="text-gray-200 ml-2">${info.store?.type || 'memory'}</span></div>
|
|
46
|
+
</div>
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async search() {
|
|
51
|
+
const storeName = this.querySelector('#knowledgeSelect').value;
|
|
52
|
+
const query = this.querySelector('#knowledgeQuery').value;
|
|
53
|
+
const k = this.querySelector('#knowledgeK').value;
|
|
54
|
+
|
|
55
|
+
if (!storeName || !query) return;
|
|
56
|
+
|
|
57
|
+
const resultsEl = this.querySelector('#knowledgeResults');
|
|
58
|
+
resultsEl.innerHTML = '<div class="text-gray-400 italic text-center py-8">Searching...</div>';
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
const res = await api.searchKnowledgeStore(storeName, query, k);
|
|
62
|
+
const results = Array.isArray(res) ? res : res.results || [];
|
|
63
|
+
|
|
64
|
+
if (results.length === 0) {
|
|
65
|
+
resultsEl.innerHTML = '<div class="text-gray-500 italic text-center py-8">No results found</div>';
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
resultsEl.innerHTML = results.map((r, i) => `
|
|
70
|
+
<div class="mb-4 last:mb-0 bg-dark-bg border border-dark-border rounded-lg p-4">
|
|
71
|
+
<div class="flex items-center justify-between mb-2 pb-2 border-b border-dark-border">
|
|
72
|
+
<span class="font-semibold text-gray-200">Result ${i + 1}</span>
|
|
73
|
+
<span class="text-sm font-mono text-gray-400">Score: ${r.score?.toFixed(3)}</span>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="text-sm text-gray-300 mb-3 whitespace-pre-wrap">${this.escapeHtml(r.content)}</div>
|
|
76
|
+
<div class="text-xs text-gray-500">
|
|
77
|
+
${r.metadata ? Object.entries(r.metadata).map(([k, v]) => `<span class="mr-3"><span class="text-gray-600">${k}:</span> ${v}</span>`).join('') : ''}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
`).join('');
|
|
81
|
+
|
|
82
|
+
} catch (e) {
|
|
83
|
+
resultsEl.innerHTML = `<div class="text-red-400 text-center">Error: ${e.message}</div>`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
escapeHtml(text) {
|
|
88
|
+
if (!text) return '';
|
|
89
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
postRender() {
|
|
93
|
+
this.querySelector('#knowledgeSelect').addEventListener('change', (e) => this.onKnowledgeSelected(e.target.value));
|
|
94
|
+
this.querySelector('#searchKnowledge').addEventListener('click', () => this.search());
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
template() {
|
|
98
|
+
return `
|
|
99
|
+
<div class="space-y-6 h-full overflow-y-auto pb-8 custom-scrollbar">
|
|
100
|
+
<div>
|
|
101
|
+
<label class="block text-sm font-medium text-gray-300 mb-2">Select Knowledge Store</label>
|
|
102
|
+
<select id="knowledgeSelect" class="w-full bg-dark-surface border border-dark-border rounded-lg px-4 py-2.5 text-gray-100 focus:outline-none focus:ring-2 focus:ring-orange-500"></select>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<div id="knowledgeInfo" class="bg-dark-surface/50 border border-dark-border rounded-lg p-4 hidden"></div>
|
|
106
|
+
|
|
107
|
+
<div>
|
|
108
|
+
<label class="block text-sm font-medium text-gray-300 mb-2">Search Query</label>
|
|
109
|
+
<textarea id="knowledgeQuery" rows="3" class="w-full bg-dark-surface border border-dark-border rounded-lg px-4 py-3 text-gray-100 focus:outline-none focus:ring-2 focus:ring-orange-500"></textarea>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div class="flex items-center gap-4">
|
|
113
|
+
<button id="searchKnowledge" disabled class="bg-orange-600 hover:bg-orange-700 disabled:bg-gray-700 disabled:cursor-not-allowed text-white font-medium px-6 py-2.5 rounded-lg transition-colors">
|
|
114
|
+
Search
|
|
115
|
+
</button>
|
|
116
|
+
<div class="flex items-center gap-2">
|
|
117
|
+
<label class="text-sm text-gray-400">Results:</label>
|
|
118
|
+
<input type="number" id="knowledgeK" value="4" min="1" max="20" class="w-20 bg-dark-surface border border-dark-border rounded-lg px-3 py-2 text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-orange-500">
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div>
|
|
123
|
+
<label class="block text-sm font-medium text-gray-300 mb-2">Results</label>
|
|
124
|
+
<div id="knowledgeResults" class="bg-dark-surface border border-dark-border rounded-lg p-4 min-h-[200px]">
|
|
125
|
+
<div class="text-gray-500 italic text-center py-8">Select a knowledge store to search</div>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
customElements.define('knowledge-view', KnowledgeView);
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
|
|
2
|
+
import { Component } from '../utils/Component.js';
|
|
3
|
+
import { api } from '../services/ApiService.js';
|
|
4
|
+
|
|
5
|
+
export class LlmView extends Component {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.isLoading = false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async connectedCallback() {
|
|
12
|
+
super.connectedCallback();
|
|
13
|
+
this.loadLLMs();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async loadLLMs() {
|
|
17
|
+
try {
|
|
18
|
+
const llms = await api.getLLMs();
|
|
19
|
+
const select = this.querySelector('#llmSelect');
|
|
20
|
+
select.innerHTML = '<option value="">-- Select LLM --</option>' +
|
|
21
|
+
llms.map(l => `<option value="${l.name}">${l.name} (${l.model})</option>`).join('');
|
|
22
|
+
|
|
23
|
+
select.addEventListener('change', () => {
|
|
24
|
+
const info = this.querySelector('#llmInfo');
|
|
25
|
+
const selected = llms.find(l => l.name === select.value);
|
|
26
|
+
|
|
27
|
+
if (selected) {
|
|
28
|
+
info.classList.remove('hidden');
|
|
29
|
+
info.innerHTML = `
|
|
30
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
|
|
31
|
+
<div><span class="text-gray-400">Model:</span> <span class="text-gray-200 ml-2">${selected.model}</span></div>
|
|
32
|
+
<div><span class="text-gray-400">Base URL:</span> <span class="text-gray-200 ml-2">${selected.baseUrl || 'Default'}</span></div>
|
|
33
|
+
</div>
|
|
34
|
+
`;
|
|
35
|
+
this.updateButtons(false);
|
|
36
|
+
} else {
|
|
37
|
+
info.classList.add('hidden');
|
|
38
|
+
this.updateButtons(true);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
} catch (e) {
|
|
42
|
+
console.error(e);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
updateButtons(disabled) {
|
|
47
|
+
this.querySelector('#runLlm').disabled = disabled;
|
|
48
|
+
this.querySelector('#streamLlm').disabled = disabled;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async run(stream) {
|
|
52
|
+
const name = this.querySelector('#llmSelect').value;
|
|
53
|
+
const msg = this.querySelector('#llmInput').value;
|
|
54
|
+
const outputEl = this.querySelector('#llmOutput');
|
|
55
|
+
|
|
56
|
+
if (!name || !msg) return;
|
|
57
|
+
|
|
58
|
+
this.isLoading = true;
|
|
59
|
+
this.updateButtons(true);
|
|
60
|
+
outputEl.textContent = 'Processing...';
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
if (stream) {
|
|
64
|
+
const res = await api.streamLLM(name, msg);
|
|
65
|
+
const reader = res.body.getReader();
|
|
66
|
+
const decoder = new TextDecoder();
|
|
67
|
+
outputEl.textContent = '';
|
|
68
|
+
|
|
69
|
+
while (true) {
|
|
70
|
+
const { done, value } = await reader.read();
|
|
71
|
+
if (done) break;
|
|
72
|
+
outputEl.textContent += decoder.decode(value);
|
|
73
|
+
outputEl.scrollTop = outputEl.scrollHeight;
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
const res = await api.chatLLM(name, msg);
|
|
77
|
+
outputEl.textContent = res.output || JSON.stringify(res, null, 2);
|
|
78
|
+
}
|
|
79
|
+
} catch (e) {
|
|
80
|
+
outputEl.textContent = 'Error: ' + e.message;
|
|
81
|
+
outputEl.classList.add('text-red-400');
|
|
82
|
+
} finally {
|
|
83
|
+
this.isLoading = false;
|
|
84
|
+
this.updateButtons(false);
|
|
85
|
+
outputEl.classList.remove('text-red-400');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
postRender() {
|
|
90
|
+
this.querySelector('#runLlm').addEventListener('click', () => this.run(false));
|
|
91
|
+
this.querySelector('#streamLlm').addEventListener('click', () => this.run(true));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
template() {
|
|
95
|
+
return `
|
|
96
|
+
<div class="space-y-6 h-full overflow-y-auto pb-8 custom-scrollbar">
|
|
97
|
+
<div>
|
|
98
|
+
<label class="block text-sm font-medium text-gray-300 mb-2">Select LLM</label>
|
|
99
|
+
<select id="llmSelect" class="w-full bg-dark-surface border border-dark-border rounded-lg px-4 py-2.5 text-gray-100 focus:outline-none focus:ring-2 focus:ring-green-500"></select>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div id="llmInfo" class="bg-dark-surface/50 border border-dark-border rounded-lg p-4 hidden"></div>
|
|
103
|
+
|
|
104
|
+
<div>
|
|
105
|
+
<label class="block text-sm font-medium text-gray-300 mb-2">Message</label>
|
|
106
|
+
<textarea id="llmInput" rows="5" class="w-full bg-dark-surface border border-dark-border rounded-lg px-4 py-3 text-gray-100 focus:outline-none focus:ring-2 focus:ring-green-500"></textarea>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<div class="flex gap-3">
|
|
110
|
+
<button id="runLlm" disabled class="bg-green-600 hover:bg-green-700 disabled:bg-gray-700 disabled:cursor-not-allowed text-white font-medium px-6 py-2.5 rounded-lg transition-colors">
|
|
111
|
+
Send Message
|
|
112
|
+
</button>
|
|
113
|
+
<button id="streamLlm" disabled class="bg-emerald-600 hover:bg-emerald-700 disabled:bg-gray-700 disabled:cursor-not-allowed text-white font-medium px-6 py-2.5 rounded-lg transition-colors">
|
|
114
|
+
Stream
|
|
115
|
+
</button>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div>
|
|
119
|
+
<label class="block text-sm font-medium text-gray-300 mb-2">Output</label>
|
|
120
|
+
<div id="llmOutput" class="bg-dark-surface border border-dark-border rounded-lg p-4 min-h-[200px] font-mono text-sm text-gray-300 whitespace-pre-wrap overflow-x-auto"></div>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
customElements.define('llm-view', LlmView);
|