elidia-agent-cli 0.4.0__tar.gz → 0.4.2__tar.gz
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.
- {elidia_agent_cli-0.4.0/elidia_agent_cli.egg-info → elidia_agent_cli-0.4.2}/PKG-INFO +72 -6
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/README.md +71 -5
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/agent/loop.py +403 -4
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/api/client.py +46 -3
- elidia_agent_cli-0.4.2/elidia/attachments.py +186 -0
- elidia_agent_cli-0.4.2/elidia/cli/banner.py +398 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/cli/repl.py +213 -31
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/config/defaults.py +1 -1
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/daemon/ipc.py +16 -3
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/daemon/worker.py +189 -1
- elidia_agent_cli-0.4.2/elidia/memory/knowledge_graph.py +286 -0
- elidia_agent_cli-0.4.2/elidia/memory/output_evaluator.py +155 -0
- elidia_agent_cli-0.4.2/elidia/memory/pattern_learner.py +205 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/models/router.py +38 -6
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/modes/classifier.py +8 -1
- elidia_agent_cli-0.4.2/elidia/orchestration/__init__.py +7 -0
- elidia_agent_cli-0.4.2/elidia/orchestration/deep_evaluator.py +223 -0
- elidia_agent_cli-0.4.2/elidia/orchestration/project_planner.py +323 -0
- elidia_agent_cli-0.4.2/elidia/orchestration/sprint_executor.py +204 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/research/orchestrator.py +24 -9
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2/elidia_agent_cli.egg-info}/PKG-INFO +72 -6
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia_agent_cli.egg-info/SOURCES.txt +9 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/pyproject.toml +1 -1
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/CHANGELOG.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/LICENSE +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/MANIFEST.in +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/ARCHITECTURE_FLOWCHARTS.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/AUDIT_REPORT_v0.1.0.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/api/commands.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/architecture/modules.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/architecture/overview.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/getting-started/configuration.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/getting-started/installation.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/getting-started/quickstart.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/guide/chat-modes.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/guide/creative.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/guide/models.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/guide/research.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/guide/themes.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/guide/tools-mcp.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/guide/workflows.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/docs/index.md +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/__main__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/agent/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/agent/personas.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/agent/portal.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/api/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/api/streaming.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/auth/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/auth/keychain.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/cache/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/cache/lru.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/cli/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/cli/commands.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/cli/main.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/cli/pager.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/cli/progress.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/cli/renderer.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/cli/themes.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/config/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/config/rules.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/config/settings.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/creative/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/creative/audio.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/creative/display.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/creative/image.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/creative/local.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/creative/video.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/daemon/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/daemon/config.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/daemon/manager.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/daemon/process.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/db/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/db/database.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/mcp/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/mcp/client.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/mcp/config.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/mcp/registry.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/mcp/types.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/memory/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/memory/auto.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/memory/compaction.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/memory/embeddings.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/memory/outcomes.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/memory/patterns.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/memory/store.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/models/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/models/adaptive.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/models/local.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/modes/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/modes/autonomous.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/modes/budget.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/modes/consensus.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/modes/deep_think.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/modes/swarm.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/modes/thinking.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/permissions/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/permissions/audit.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/permissions/manager.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/permissions/trust.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/rag/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/rag/chunker.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/rag/engine.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/rag/ingest.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/rag/portal_bridge.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/rag/watcher.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/research/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/research/export.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/research/sources.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/session/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/session/history.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/session/manager.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/base.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/browser.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/calendar.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/database.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/email.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/fetch.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/filesystem.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/git.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/office.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/rag.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/search.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/terminal.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/tools/tool_router.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/widgets/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/widgets/protocol.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/widgets/renderer.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/workflow/__init__.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia/workflow/engine.py +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia_agent_cli.egg-info/dependency_links.txt +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia_agent_cli.egg-info/entry_points.txt +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia_agent_cli.egg-info/requires.txt +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/elidia_agent_cli.egg-info/top_level.txt +0 -0
- {elidia_agent_cli-0.4.0 → elidia_agent_cli-0.4.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: elidia-agent-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Elidia Agent CLI — Universal AI Agent for your terminal
|
|
5
5
|
Author-email: Elidia Technology Pvt Ltd <support@aiutils.io>
|
|
6
6
|
License-Expression: LicenseRef-Proprietary
|
|
@@ -171,18 +171,84 @@ pip install elidia_agent_cli-0.3.0-py3-none-any.whl
|
|
|
171
171
|
## Quick Start
|
|
172
172
|
|
|
173
173
|
### 1. Authenticate
|
|
174
|
-
|
|
175
174
|
```bash
|
|
176
175
|
elidia auth login
|
|
177
176
|
```
|
|
178
|
-
|
|
179
|
-
You'll be prompted for your AiUtils Developer API key (`ak-dev-...`).
|
|
177
|
+
Enter your AiUtils Developer API key (`ak-dev-...`). Get one at [developer.aiutils.io](https://developer.aiutils.io).
|
|
180
178
|
|
|
181
179
|
### 2. Start chatting
|
|
180
|
+
```bash
|
|
181
|
+
elidia ask "Write a Python function to reverse a string"
|
|
182
|
+
elidia # Interactive REPL
|
|
183
|
+
```
|
|
182
184
|
|
|
185
|
+
## All Commands
|
|
186
|
+
|
|
187
|
+
| Command | Description |
|
|
188
|
+
|---|---|
|
|
189
|
+
| `elidia ask <msg>` | One-shot message (supports `--model`, `--mode`, `--file`, `--image`) |
|
|
190
|
+
| `elidia` | Interactive REPL with 27 slash commands |
|
|
191
|
+
| `elidia auth login/logout/status` | Manage API key |
|
|
192
|
+
| `elidia auth email-login/email-logout/email-status` | Email credentials |
|
|
193
|
+
| `elidia config show` | View current configuration |
|
|
194
|
+
| `elidia config set <section.field> <value>` | Persist preferences (e.g., `models.default gpt-4o`) |
|
|
195
|
+
| `elidia daemon start/stop/restart/status/init` | Background daemon (24/7 agent) |
|
|
196
|
+
| `elidia mcp list/health` | MCP server management |
|
|
197
|
+
| `elidia models` | List all 30+ available LLMs |
|
|
198
|
+
| `elidia models --local` | List local Ollama models |
|
|
199
|
+
| `elidia rag ingest/search/list/clear` | Local RAG document store |
|
|
200
|
+
| `elidia session list/new/delete` | Session management |
|
|
201
|
+
| `elidia version` | Show version |
|
|
202
|
+
| `elidia workflow run <file>` | Execute YAML workflow |
|
|
203
|
+
|
|
204
|
+
## Available Models
|
|
205
|
+
|
|
206
|
+
### Language Models (LLMs) — `elidia models`
|
|
207
|
+
30+ models via AiUtils API: Claude (Opus 4.8, Sonnet 4-6), GPT (4o, 5.5), Gemini (2.5 Pro/Flash), DeepSeek (V4, Reasoner), Llama (4, 3.3), Qwen (3, 2.5), Mistral, and more.
|
|
208
|
+
|
|
209
|
+
### Creative Models — available through chat
|
|
210
|
+
| Category | Count | Example |
|
|
211
|
+
|---|---|---|
|
|
212
|
+
| Image Generation | 500+ | Flux, SDXL, DALL-E, Midjourney |
|
|
213
|
+
| Video Generation | 500+ | Runway, Pika, Kling, Sora |
|
|
214
|
+
| Audio/Music | 100+ | ElevenLabs, MusicGen, Whisper |
|
|
215
|
+
| 3D Generation | 20+ | TripoSR, Zero123++, Stable3D |
|
|
216
|
+
|
|
217
|
+
### Local Models — `elidia models --local`
|
|
218
|
+
Ollama models running on your machine. Zero API cost, works offline.
|
|
183
219
|
```bash
|
|
184
|
-
|
|
185
|
-
elidia
|
|
220
|
+
ollama pull qwen3:1.7b
|
|
221
|
+
elidia models --local
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Working Modes
|
|
225
|
+
|
|
226
|
+
| Mode | Use for |
|
|
227
|
+
|---|---|
|
|
228
|
+
| `chat` | General conversation, creative work |
|
|
229
|
+
| `code` | Software development, debugging |
|
|
230
|
+
| `research` | Deep research with web search + RAG |
|
|
231
|
+
| `think` | Extended chain-of-thought reasoning |
|
|
232
|
+
| `create` | Content generation (books, scripts, ads) |
|
|
233
|
+
|
|
234
|
+
Set via `--mode` flag, `/mode` in REPL, or mode selector in Desktop.
|
|
235
|
+
|
|
236
|
+
**Advanced execution strategies (REPL):**
|
|
237
|
+
| Command | Description |
|
|
238
|
+
|---|---|
|
|
239
|
+
| `/research <topic>` | 3-agent research pipeline (plan → search → synthesize) |
|
|
240
|
+
| `/think <problem>` | Deep reasoning with chain-of-thought |
|
|
241
|
+
| `/budget` | Show session cost |
|
|
242
|
+
| `/persona <slug>` | Switch domain persona (coder, doctor, lawyer, marketer, etc.) |
|
|
243
|
+
|
|
244
|
+
## MCP Servers — `elidia mcp`
|
|
245
|
+
|
|
246
|
+
Connect to any MCP server to extend capabilities:
|
|
247
|
+
```bash
|
|
248
|
+
elidia mcp list # Show connected servers
|
|
249
|
+
elidia mcp health # Check server status
|
|
250
|
+
```
|
|
251
|
+
Configure in `~/.elidia/mcp.json`. Connect databases, APIs, GitHub, Slack, Jira, and more.
|
|
186
252
|
|
|
187
253
|
# One-shot query
|
|
188
254
|
elidia chat "Explain async/await in Python"
|
|
@@ -111,18 +111,84 @@ pip install elidia_agent_cli-0.3.0-py3-none-any.whl
|
|
|
111
111
|
## Quick Start
|
|
112
112
|
|
|
113
113
|
### 1. Authenticate
|
|
114
|
-
|
|
115
114
|
```bash
|
|
116
115
|
elidia auth login
|
|
117
116
|
```
|
|
118
|
-
|
|
119
|
-
You'll be prompted for your AiUtils Developer API key (`ak-dev-...`).
|
|
117
|
+
Enter your AiUtils Developer API key (`ak-dev-...`). Get one at [developer.aiutils.io](https://developer.aiutils.io).
|
|
120
118
|
|
|
121
119
|
### 2. Start chatting
|
|
120
|
+
```bash
|
|
121
|
+
elidia ask "Write a Python function to reverse a string"
|
|
122
|
+
elidia # Interactive REPL
|
|
123
|
+
```
|
|
122
124
|
|
|
125
|
+
## All Commands
|
|
126
|
+
|
|
127
|
+
| Command | Description |
|
|
128
|
+
|---|---|
|
|
129
|
+
| `elidia ask <msg>` | One-shot message (supports `--model`, `--mode`, `--file`, `--image`) |
|
|
130
|
+
| `elidia` | Interactive REPL with 27 slash commands |
|
|
131
|
+
| `elidia auth login/logout/status` | Manage API key |
|
|
132
|
+
| `elidia auth email-login/email-logout/email-status` | Email credentials |
|
|
133
|
+
| `elidia config show` | View current configuration |
|
|
134
|
+
| `elidia config set <section.field> <value>` | Persist preferences (e.g., `models.default gpt-4o`) |
|
|
135
|
+
| `elidia daemon start/stop/restart/status/init` | Background daemon (24/7 agent) |
|
|
136
|
+
| `elidia mcp list/health` | MCP server management |
|
|
137
|
+
| `elidia models` | List all 30+ available LLMs |
|
|
138
|
+
| `elidia models --local` | List local Ollama models |
|
|
139
|
+
| `elidia rag ingest/search/list/clear` | Local RAG document store |
|
|
140
|
+
| `elidia session list/new/delete` | Session management |
|
|
141
|
+
| `elidia version` | Show version |
|
|
142
|
+
| `elidia workflow run <file>` | Execute YAML workflow |
|
|
143
|
+
|
|
144
|
+
## Available Models
|
|
145
|
+
|
|
146
|
+
### Language Models (LLMs) — `elidia models`
|
|
147
|
+
30+ models via AiUtils API: Claude (Opus 4.8, Sonnet 4-6), GPT (4o, 5.5), Gemini (2.5 Pro/Flash), DeepSeek (V4, Reasoner), Llama (4, 3.3), Qwen (3, 2.5), Mistral, and more.
|
|
148
|
+
|
|
149
|
+
### Creative Models — available through chat
|
|
150
|
+
| Category | Count | Example |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| Image Generation | 500+ | Flux, SDXL, DALL-E, Midjourney |
|
|
153
|
+
| Video Generation | 500+ | Runway, Pika, Kling, Sora |
|
|
154
|
+
| Audio/Music | 100+ | ElevenLabs, MusicGen, Whisper |
|
|
155
|
+
| 3D Generation | 20+ | TripoSR, Zero123++, Stable3D |
|
|
156
|
+
|
|
157
|
+
### Local Models — `elidia models --local`
|
|
158
|
+
Ollama models running on your machine. Zero API cost, works offline.
|
|
123
159
|
```bash
|
|
124
|
-
|
|
125
|
-
elidia
|
|
160
|
+
ollama pull qwen3:1.7b
|
|
161
|
+
elidia models --local
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Working Modes
|
|
165
|
+
|
|
166
|
+
| Mode | Use for |
|
|
167
|
+
|---|---|
|
|
168
|
+
| `chat` | General conversation, creative work |
|
|
169
|
+
| `code` | Software development, debugging |
|
|
170
|
+
| `research` | Deep research with web search + RAG |
|
|
171
|
+
| `think` | Extended chain-of-thought reasoning |
|
|
172
|
+
| `create` | Content generation (books, scripts, ads) |
|
|
173
|
+
|
|
174
|
+
Set via `--mode` flag, `/mode` in REPL, or mode selector in Desktop.
|
|
175
|
+
|
|
176
|
+
**Advanced execution strategies (REPL):**
|
|
177
|
+
| Command | Description |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `/research <topic>` | 3-agent research pipeline (plan → search → synthesize) |
|
|
180
|
+
| `/think <problem>` | Deep reasoning with chain-of-thought |
|
|
181
|
+
| `/budget` | Show session cost |
|
|
182
|
+
| `/persona <slug>` | Switch domain persona (coder, doctor, lawyer, marketer, etc.) |
|
|
183
|
+
|
|
184
|
+
## MCP Servers — `elidia mcp`
|
|
185
|
+
|
|
186
|
+
Connect to any MCP server to extend capabilities:
|
|
187
|
+
```bash
|
|
188
|
+
elidia mcp list # Show connected servers
|
|
189
|
+
elidia mcp health # Check server status
|
|
190
|
+
```
|
|
191
|
+
Configure in `~/.elidia/mcp.json`. Connect databases, APIs, GitHub, Slack, Jira, and more.
|
|
126
192
|
|
|
127
193
|
# One-shot query
|
|
128
194
|
elidia chat "Explain async/await in Python"
|
|
@@ -112,7 +112,17 @@ class AgentLoop:
|
|
|
112
112
|
state.model = self._router.get_model_for_type("vision")
|
|
113
113
|
decision_reason = "Vision content attached"
|
|
114
114
|
else:
|
|
115
|
-
|
|
115
|
+
# Load routing hints from PatternLearner (self-learning)
|
|
116
|
+
routing_hints = None
|
|
117
|
+
if self._memory_store:
|
|
118
|
+
try:
|
|
119
|
+
from elidia.memory.pattern_learner import PatternLearner
|
|
120
|
+
learner = PatternLearner(self._memory_store)
|
|
121
|
+
routing_hints = learner.generate_routing_hints(min_samples=2)
|
|
122
|
+
except Exception as e:
|
|
123
|
+
logger.debug(f"Routing hints skipped: {e}")
|
|
124
|
+
|
|
125
|
+
decision = self._router.route(user_text, mode=mode, routing_hints=routing_hints)
|
|
116
126
|
state.model = forced_model or decision.model
|
|
117
127
|
decision_reason = decision.reason
|
|
118
128
|
yield AgentEvent(kind="thinking", data={"model": state.model, "reason": decision_reason})
|
|
@@ -128,10 +138,20 @@ class AgentLoop:
|
|
|
128
138
|
return
|
|
129
139
|
|
|
130
140
|
if state.exec_mode == ExecMode.HARNESS:
|
|
141
|
+
# For complex multi-step tasks, use ProjectOrchestrator
|
|
142
|
+
if self._memory_store and len(user_text) > 50:
|
|
143
|
+
async for event in self._run_project_orchestrator(state, user_text, session_id):
|
|
144
|
+
yield event
|
|
145
|
+
return
|
|
131
146
|
async for event in self._run_harness(state, user_text, session_id):
|
|
132
147
|
yield event
|
|
133
148
|
return
|
|
134
149
|
|
|
150
|
+
if state.exec_mode == ExecMode.SWARM:
|
|
151
|
+
async for event in self._run_swarm(state, user_text, session_id):
|
|
152
|
+
yield event
|
|
153
|
+
return
|
|
154
|
+
|
|
135
155
|
effective_max_loops = min(self._max_loops, caps.max_loops)
|
|
136
156
|
all_tool_schemas = self._build_tool_schemas() if caps.allow_tools else []
|
|
137
157
|
|
|
@@ -244,6 +264,132 @@ class AgentLoop:
|
|
|
244
264
|
else:
|
|
245
265
|
yield AgentEvent(kind="error", data=f"Agent exceeded maximum tool loop count ({self._max_loops})")
|
|
246
266
|
|
|
267
|
+
# Evaluate output quality + record outcome (AIUT-2170 + AIUT-2177)
|
|
268
|
+
if self._memory_store:
|
|
269
|
+
try:
|
|
270
|
+
from elidia.memory.outcomes import Outcome, OutcomeTracker
|
|
271
|
+
from elidia.memory.output_evaluator import OutputEvaluator
|
|
272
|
+
|
|
273
|
+
tracker = OutcomeTracker(self._memory_store)
|
|
274
|
+
task_type = state.exec_mode.value if state.exec_mode else "direct"
|
|
275
|
+
|
|
276
|
+
# Get the agent's final output text for evaluation
|
|
277
|
+
output_text = ""
|
|
278
|
+
for msg in reversed(state.messages):
|
|
279
|
+
if msg.role == "assistant" and msg.content:
|
|
280
|
+
output_text = extract_text(msg.content)[:6000]
|
|
281
|
+
break
|
|
282
|
+
|
|
283
|
+
# Deep quality evaluation with self-reasoning (AIUT-2179)
|
|
284
|
+
from elidia.orchestration.deep_evaluator import DeepEvaluator
|
|
285
|
+
deep_eval = DeepEvaluator(self._client)
|
|
286
|
+
assessment = await deep_eval.evaluate(
|
|
287
|
+
objective=user_text,
|
|
288
|
+
output=output_text or "(no output produced)",
|
|
289
|
+
task_type=mode,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# Use 8-dimension quality score as success metric
|
|
293
|
+
quality_score = assessment.score_8dim.overall
|
|
294
|
+
success = assessment.should_accept
|
|
295
|
+
tracker.record(Outcome(
|
|
296
|
+
model=state.model,
|
|
297
|
+
task_type=task_type,
|
|
298
|
+
approach=mode,
|
|
299
|
+
success=success,
|
|
300
|
+
tokens_used=state.tokens_in + state.tokens_out,
|
|
301
|
+
elapsed_ms=0,
|
|
302
|
+
cost_dt=state.total_cost_dt,
|
|
303
|
+
domain=task_type,
|
|
304
|
+
notes=(
|
|
305
|
+
f"score={quality_score:.1f}/10 verdict={assessment.verdict} "
|
|
306
|
+
f"quality={assessment.quality_level} style={assessment.approach_style} "
|
|
307
|
+
f"match={assessment.matches_objective}"
|
|
308
|
+
),
|
|
309
|
+
))
|
|
310
|
+
|
|
311
|
+
# Emit detailed quality event
|
|
312
|
+
yield AgentEvent(kind="quality", data={
|
|
313
|
+
"score": quality_score,
|
|
314
|
+
"verdict": assessment.verdict,
|
|
315
|
+
"quality_level": assessment.quality_level,
|
|
316
|
+
"approach_style": assessment.approach_style,
|
|
317
|
+
"matches_objective": assessment.matches_objective,
|
|
318
|
+
"self_questions": [{"q": sq.question, "a": sq.answer[:100]} for sq in assessment.self_questions[:3]],
|
|
319
|
+
"summary": assessment.summary_verdict[:300],
|
|
320
|
+
"score_8dim": {
|
|
321
|
+
"correctness": assessment.score_8dim.correctness,
|
|
322
|
+
"completeness": assessment.score_8dim.completeness,
|
|
323
|
+
"modernity": assessment.score_8dim.modernity,
|
|
324
|
+
"elegance": assessment.score_8dim.elegance,
|
|
325
|
+
"efficiency": assessment.score_8dim.efficiency,
|
|
326
|
+
"clarity": assessment.score_8dim.clarity,
|
|
327
|
+
"innovation": assessment.score_8dim.innovation,
|
|
328
|
+
"reliability": assessment.score_8dim.reliability,
|
|
329
|
+
},
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
logger.debug(
|
|
333
|
+
f"Deep evaluation: score={quality_score:.1f}/10, verdict={assessment.verdict}, "
|
|
334
|
+
f"quality={assessment.quality_level}, style={assessment.approach_style}"
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
# Iterative refinement (1-3 iterations for small, up to 5 for long tasks)
|
|
338
|
+
max_refinements = 3 if mode in ("chat", "code") else 5
|
|
339
|
+
for ref_iter in range(1, max_refinements + 1):
|
|
340
|
+
if assessment.should_accept:
|
|
341
|
+
break
|
|
342
|
+
if not assessment.improvement_prompt:
|
|
343
|
+
break
|
|
344
|
+
|
|
345
|
+
yield AgentEvent(kind="thinking", data={
|
|
346
|
+
"model": state.model,
|
|
347
|
+
"reason": f"[Refine {ref_iter}/{max_refinements}] {assessment.verdict} — {assessment.summary_verdict[:100]}",
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
try:
|
|
351
|
+
refine_msg = deep_eval.build_refinement_message(
|
|
352
|
+
objective=user_text,
|
|
353
|
+
previous_output=output_text,
|
|
354
|
+
assessment=assessment,
|
|
355
|
+
iteration=ref_iter,
|
|
356
|
+
max_iterations=max_refinements,
|
|
357
|
+
)
|
|
358
|
+
state.messages.append(ChatMessage(role="user", content=refine_msg[:4000]))
|
|
359
|
+
response = await self._client.chat_completion(
|
|
360
|
+
messages=self._build_api_messages(state, user_message=refine_msg[:1000]),
|
|
361
|
+
model=state.model,
|
|
362
|
+
temperature=0.3,
|
|
363
|
+
)
|
|
364
|
+
if response.content:
|
|
365
|
+
state.messages.append(ChatMessage(role="assistant", content=response.content))
|
|
366
|
+
output_text = response.content
|
|
367
|
+
yield AgentEvent(kind="content", data=f"[Refined v{ref_iter+1} — {assessment.verdict} → improving]\n\n{response.content}")
|
|
368
|
+
|
|
369
|
+
# Re-evaluate after refinement
|
|
370
|
+
assessment = await deep_eval.evaluate(
|
|
371
|
+
objective=user_text, output=output_text, task_type=mode,
|
|
372
|
+
)
|
|
373
|
+
except Exception as e:
|
|
374
|
+
logger.debug(f"Refinement iteration {ref_iter} failed: {e}")
|
|
375
|
+
break
|
|
376
|
+
|
|
377
|
+
except Exception as e:
|
|
378
|
+
logger.debug(f"Outcome recording/evaluation skipped: {e}")
|
|
379
|
+
|
|
380
|
+
# Extract entities into knowledge graph (async, non-blocking)
|
|
381
|
+
try:
|
|
382
|
+
from elidia.memory.knowledge_graph import KnowledgeGraph
|
|
383
|
+
kg = KnowledgeGraph(self._memory_store, self._client)
|
|
384
|
+
messages_for_extraction = [
|
|
385
|
+
{"role": m.role, "content": extract_text(m.content)}
|
|
386
|
+
for m in state.messages[-20:]
|
|
387
|
+
]
|
|
388
|
+
import asyncio
|
|
389
|
+
asyncio.create_task(self._extract_and_save_kg(kg, messages_for_extraction))
|
|
390
|
+
except Exception as e:
|
|
391
|
+
logger.debug(f"KG extraction skipped: {e}")
|
|
392
|
+
|
|
247
393
|
yield AgentEvent(kind="done", data={
|
|
248
394
|
"loops": state.loop_count,
|
|
249
395
|
"tools_called": state.tools_called,
|
|
@@ -325,8 +471,53 @@ class AgentLoop:
|
|
|
325
471
|
tool_list = self._format_tools_for_prompt()
|
|
326
472
|
|
|
327
473
|
base = (
|
|
328
|
-
"You are Elidia
|
|
329
|
-
"
|
|
474
|
+
"You are Elidia Agent — a next-generation AI agent platform developed by "
|
|
475
|
+
"Elidia Technology Pvt. Ltd. It brings together specialized AI agents to help "
|
|
476
|
+
"users generate images, videos, audio, music, voiceovers, 3D models, books, "
|
|
477
|
+
"audiobooks, scripts, advertisements, marketing campaigns, code, research, "
|
|
478
|
+
"reports, presentations, and high-quality written content.\n\n"
|
|
479
|
+
"Built for creators, developers, businesses, doctors, lawyers, pharmaceutical "
|
|
480
|
+
"professionals, educators, and enterprises, Elidia Agent streamlines complex "
|
|
481
|
+
"workflows with powerful, domain-specific AI capabilities.\n\n"
|
|
482
|
+
"You are available on Terminal CLI, Native Desktop (macOS/Linux/Windows), "
|
|
483
|
+
"VS Code Extension, and Mobile (iOS/Android). You have access to 147+ built-in "
|
|
484
|
+
"tools plus the full AiUtils model catalog — thousands of models across all "
|
|
485
|
+
"categories (LLMs, image generation, video, audio/music, voiceovers, 3D, "
|
|
486
|
+
"embeddings, and more). When you need to know exactly which models are "
|
|
487
|
+
"available for a specific task, use the model listing tools or call the "
|
|
488
|
+
"AiUtils API to get the live catalog — never hardcode model names or counts "
|
|
489
|
+
"because the catalog is dynamic and grows continuously.\n\n"
|
|
490
|
+
"Advanced capabilities:\n"
|
|
491
|
+
"- Autonomous Mode: The system can decompose complex tasks into subtasks, "
|
|
492
|
+
"execute them sequentially with tool access, verify results, and replan on "
|
|
493
|
+
"failure. For parallel work, the system's SWARM mode runs multiple specialized "
|
|
494
|
+
"sub-agents concurrently (each with tool access) and synthesizes their findings.\n"
|
|
495
|
+
"- Consensus Mode: The system queries 2-3 different models on the same question, "
|
|
496
|
+
"compares their answers, assesses agreement, and produces a synthesized response "
|
|
497
|
+
"with confidence scoring.\n"
|
|
498
|
+
"- Research Pipeline: A 5-stage pipeline (Decompose → Search → Analyze → "
|
|
499
|
+
"Synthesize → Verify) conducts deep research with web search, source citations, "
|
|
500
|
+
"and a verification stage that cross-references claims against search results.\n"
|
|
501
|
+
"- MCP Integration: Connect to MCP (Model Context Protocol) servers to extend "
|
|
502
|
+
"capabilities — databases, APIs, file systems, GitHub, Slack, and more.\n"
|
|
503
|
+
"- RAG / Local Search: Index local files and documents for semantic search across "
|
|
504
|
+
"your projects.\n\n"
|
|
505
|
+
"Core principles:\n"
|
|
506
|
+
"- Be truthful and honest — never fabricate, hallucinate, or make false claims.\n"
|
|
507
|
+
"- When uncertain, state your confidence level and cite sources.\n"
|
|
508
|
+
"- Verify with real tools — use filesystem, web search, and database tools to "
|
|
509
|
+
"confirm facts before stating them.\n"
|
|
510
|
+
"- No placeholders or stubs — produce real, working code and content.\n\n"
|
|
511
|
+
"Key capabilities:\n"
|
|
512
|
+
"- Creative Generation: images, videos, audio, music, voiceovers, 3D models\n"
|
|
513
|
+
"- Content Creation: books, audiobooks, scripts, ads, marketing campaigns\n"
|
|
514
|
+
"- Code & Development: write, edit, review, debug any language, full projects\n"
|
|
515
|
+
"- Research & Analysis: deep research, web search, document analysis, reports\n"
|
|
516
|
+
"- Business & Enterprise: presentations, data analysis, workflow automation\n"
|
|
517
|
+
"- Domain Expertise: medical/healthcare, legal/compliance, pharma, finance/trading,\n"
|
|
518
|
+
" marketing/SEO, advertising, education, career, creative design, and more\n"
|
|
519
|
+
"- Office & Communication: Word, Excel, PowerPoint, email, calendar\n"
|
|
520
|
+
"- Knowledge: RAG search over documents, persistent memory across sessions\n\n"
|
|
330
521
|
f"Available tools:\n{tool_list}\n\n"
|
|
331
522
|
"To use a tool, respond with a JSON block using the exact argument names listed above:\n"
|
|
332
523
|
"```tool\n"
|
|
@@ -365,7 +556,18 @@ class AgentLoop:
|
|
|
365
556
|
except Exception as e:
|
|
366
557
|
logger.debug(f"Memory recall skipped: {e}")
|
|
367
558
|
|
|
368
|
-
# 3.
|
|
559
|
+
# 3. Knowledge Graph — entity-aware context from past conversations
|
|
560
|
+
if self._memory_store and user_message:
|
|
561
|
+
try:
|
|
562
|
+
from elidia.memory.knowledge_graph import KnowledgeGraph
|
|
563
|
+
kg = KnowledgeGraph(self._memory_store, self._client)
|
|
564
|
+
kg_context = kg.get_context_for_prompt(user_message, limit=5)
|
|
565
|
+
if kg_context:
|
|
566
|
+
context_parts.append(kg_context)
|
|
567
|
+
except Exception as e:
|
|
568
|
+
logger.debug(f"Knowledge graph context skipped: {e}")
|
|
569
|
+
|
|
570
|
+
# 4. RAG — search local documents for relevant context
|
|
369
571
|
if self._rag_engine and user_message:
|
|
370
572
|
try:
|
|
371
573
|
rag_results = self._rag_engine.search(
|
|
@@ -487,6 +689,70 @@ class AgentLoop:
|
|
|
487
689
|
}
|
|
488
690
|
return action_map.get(tool_name, "mcp_call_session")
|
|
489
691
|
|
|
692
|
+
async def _run_project_orchestrator(
|
|
693
|
+
self, state: AgentState, user_text: str, session_id: str,
|
|
694
|
+
) -> AsyncIterator[AgentEvent]:
|
|
695
|
+
"""Execute complex task via ProjectOrchestrator — SCRUM-style planning + multi-agent execution."""
|
|
696
|
+
logger.debug("Entered into _run_project_orchestrator")
|
|
697
|
+
from elidia.orchestration.project_planner import ProjectPlanner
|
|
698
|
+
from elidia.orchestration.sprint_executor import SprintExecutor, SprintEvent
|
|
699
|
+
|
|
700
|
+
yield AgentEvent(kind="thinking", data={
|
|
701
|
+
"model": "orchestrator",
|
|
702
|
+
"reason": "Planning project with SCRUM-style EPIC/Story/Ticket decomposition",
|
|
703
|
+
})
|
|
704
|
+
|
|
705
|
+
# Phase 1: Plan
|
|
706
|
+
planner = ProjectPlanner(self._client)
|
|
707
|
+
plan = await planner.plan(user_text)
|
|
708
|
+
yield AgentEvent(kind="thinking", data={
|
|
709
|
+
"model": "orchestrator",
|
|
710
|
+
"reason": f"Plan created: {len(plan.epics)} epics, {plan.total_tickets} tickets → {plan.plan_path}",
|
|
711
|
+
})
|
|
712
|
+
yield AgentEvent(kind="content", data=f"📋 **Project Plan** ({plan.plan_path})\n{plan.total_tickets} tickets across {len(plan.epics)} epics. Executing...")
|
|
713
|
+
|
|
714
|
+
# Phase 2: Execute
|
|
715
|
+
async def worker_fn(task: str, role: str) -> str:
|
|
716
|
+
resp = await self._client.chat_completion(
|
|
717
|
+
messages=[ChatMessage(role="user", content=task)],
|
|
718
|
+
model=state.model,
|
|
719
|
+
temperature=0.3,
|
|
720
|
+
)
|
|
721
|
+
return resp.content or ""
|
|
722
|
+
|
|
723
|
+
executor = SprintExecutor(self._client, execute_fn=worker_fn, agent_model=state.model)
|
|
724
|
+
async for event in executor.execute(plan):
|
|
725
|
+
if event.kind == "ticket_start":
|
|
726
|
+
yield AgentEvent(kind="tool_call", data={
|
|
727
|
+
"name": f"sprint:wave{event.data.get('wave','?')}",
|
|
728
|
+
"arguments": {"count": event.data.get("count", 0), "mode": event.data.get("mode", "")},
|
|
729
|
+
})
|
|
730
|
+
elif event.kind == "ticket_done":
|
|
731
|
+
yield AgentEvent(kind="tool_result", data={
|
|
732
|
+
"name": event.data.get("ticket", "?"),
|
|
733
|
+
"content": f"✅ score={event.data.get('score',0)}/10",
|
|
734
|
+
})
|
|
735
|
+
elif event.kind == "assembly":
|
|
736
|
+
yield AgentEvent(kind="thinking", data={
|
|
737
|
+
"model": "orchestrator",
|
|
738
|
+
"reason": f"Assembling {event.data.get('parts',0)} completed parts into final deliverable",
|
|
739
|
+
})
|
|
740
|
+
elif event.kind == "done":
|
|
741
|
+
result = event.data
|
|
742
|
+
yield AgentEvent(kind="content", data=result.final_output if hasattr(result, 'final_output') else str(result))
|
|
743
|
+
yield AgentEvent(kind="done", data={
|
|
744
|
+
"loops": 1,
|
|
745
|
+
"tools_called": [f"ticket_{i}" for i in range(result.tickets_completed if hasattr(result, 'tickets_completed') else 0)],
|
|
746
|
+
"total_tokens_in": state.tokens_in,
|
|
747
|
+
"total_tokens_out": state.tokens_out,
|
|
748
|
+
"total_cost_dt": state.total_cost_dt,
|
|
749
|
+
"exec_mode": "orchestrator",
|
|
750
|
+
"plan_path": result.plan_path if hasattr(result, 'plan_path') else "",
|
|
751
|
+
"quality_score": f"{result.overall_score:.1f}/10" if hasattr(result, 'overall_score') and result.overall_score else "N/A",
|
|
752
|
+
})
|
|
753
|
+
elif event.kind == "error":
|
|
754
|
+
yield AgentEvent(kind="error", data=str(event.data))
|
|
755
|
+
|
|
490
756
|
async def _run_deep_think(
|
|
491
757
|
self, state: AgentState, user_text: str, session_id: str,
|
|
492
758
|
) -> AsyncIterator[AgentEvent]:
|
|
@@ -733,3 +999,136 @@ class AgentLoop:
|
|
|
733
999
|
|
|
734
1000
|
except Exception as e:
|
|
735
1001
|
yield AgentEvent(kind="error", data=f"Harness execution failed: {e}")
|
|
1002
|
+
|
|
1003
|
+
async def _run_swarm(
|
|
1004
|
+
self,
|
|
1005
|
+
state: AgentState,
|
|
1006
|
+
user_text: str,
|
|
1007
|
+
session_id: str,
|
|
1008
|
+
) -> AsyncIterator[AgentEvent]:
|
|
1009
|
+
"""Execute a complex task via parallel sub-agents using AgentSwarm."""
|
|
1010
|
+
logger.debug("Entered into _run_swarm")
|
|
1011
|
+
from elidia.modes.swarm import AgentSwarm, SwarmEvent
|
|
1012
|
+
|
|
1013
|
+
yield AgentEvent(kind="thinking", data={
|
|
1014
|
+
"model": "swarm",
|
|
1015
|
+
"reason": "Decomposing into parallel sub-agents via AgentSwarm",
|
|
1016
|
+
})
|
|
1017
|
+
|
|
1018
|
+
# execute_fn: called by AgentSwarm for each sub-agent (task, role) -> result string
|
|
1019
|
+
all_tool_schemas = self._build_tool_schemas() if self._caps.allow_tools else []
|
|
1020
|
+
|
|
1021
|
+
async def execute_subtask(task: str, role: str) -> str:
|
|
1022
|
+
worker = _SwarmWorker(
|
|
1023
|
+
client=self._client, task=task, role=role, model=state.model,
|
|
1024
|
+
all_tool_schemas=all_tool_schemas,
|
|
1025
|
+
extract_tool_calls=self._extract_tool_calls,
|
|
1026
|
+
execute_tool=self._execute_tool,
|
|
1027
|
+
)
|
|
1028
|
+
return await worker.execute()
|
|
1029
|
+
|
|
1030
|
+
swarm = AgentSwarm(
|
|
1031
|
+
client=self._client,
|
|
1032
|
+
execute_fn=execute_subtask,
|
|
1033
|
+
max_agents=5,
|
|
1034
|
+
agent_model=state.model,
|
|
1035
|
+
)
|
|
1036
|
+
|
|
1037
|
+
try:
|
|
1038
|
+
async for event in swarm.run(user_text):
|
|
1039
|
+
if event.kind == "plan":
|
|
1040
|
+
yield AgentEvent(kind="thinking", data={
|
|
1041
|
+
"model": "swarm",
|
|
1042
|
+
"reason": f"Planned {event.data.get('agent_count', 0)} parallel sub-agents",
|
|
1043
|
+
})
|
|
1044
|
+
elif event.kind == "agent_start":
|
|
1045
|
+
yield AgentEvent(kind="tool_call", data={
|
|
1046
|
+
"name": f"sub_agent:{event.data.get('role','worker')}",
|
|
1047
|
+
"arguments": {"task": event.data.get("task", "")[:200]},
|
|
1048
|
+
})
|
|
1049
|
+
elif event.kind == "agent_done":
|
|
1050
|
+
yield AgentEvent(kind="tool_result", data={
|
|
1051
|
+
"name": f"sub_agent:{event.data.get('role','worker')}",
|
|
1052
|
+
"content": str(event.data.get("result_preview", ""))[:500],
|
|
1053
|
+
})
|
|
1054
|
+
elif event.kind == "aggregate":
|
|
1055
|
+
yield AgentEvent(kind="content", data=event.data.get("content", ""))
|
|
1056
|
+
elif event.kind == "done":
|
|
1057
|
+
yield AgentEvent(kind="done", data={
|
|
1058
|
+
"loops": event.data.get("completed", 0),
|
|
1059
|
+
"tools_called": [f"sub_agent_{i}" for i in range(1, event.data.get('completed', 0) + 1)],
|
|
1060
|
+
"total_tokens_in": event.data.get("total_tokens", 0),
|
|
1061
|
+
"total_tokens_out": 0,
|
|
1062
|
+
"total_cost_dt": 0.0,
|
|
1063
|
+
"exec_mode": "swarm",
|
|
1064
|
+
})
|
|
1065
|
+
elif event.kind == "error":
|
|
1066
|
+
yield AgentEvent(kind="error", data=event.data.get("message", str(event.data)))
|
|
1067
|
+
except Exception as e:
|
|
1068
|
+
yield AgentEvent(kind="error", data=f"Swarm execution failed: {e}")
|
|
1069
|
+
|
|
1070
|
+
|
|
1071
|
+
async def _extract_and_save_kg(self, kg: Any, messages: list[dict[str, str]]) -> None:
|
|
1072
|
+
"""Background task: extract entities from conversation and save to knowledge graph."""
|
|
1073
|
+
try:
|
|
1074
|
+
extraction = await kg.extract_from_conversation(messages)
|
|
1075
|
+
if extraction.entities or extraction.relations:
|
|
1076
|
+
saved = kg.save_extraction(extraction)
|
|
1077
|
+
logger.debug(f"KG extraction: {len(extraction.entities)} entities, {len(extraction.relations)} relations saved ({saved} total)")
|
|
1078
|
+
except Exception as e:
|
|
1079
|
+
logger.debug(f"KG background extraction failed: {e}")
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
class _SwarmWorker:
|
|
1083
|
+
"""Lightweight single-task agent used by AgentSwarm sub-agents with tool access."""
|
|
1084
|
+
|
|
1085
|
+
def __init__(self, client, task: str, role: str, model: str,
|
|
1086
|
+
all_tool_schemas: list, extract_tool_calls, execute_tool):
|
|
1087
|
+
self._client = client
|
|
1088
|
+
self._task = task
|
|
1089
|
+
self._role = role
|
|
1090
|
+
self._model = model
|
|
1091
|
+
self._all_tool_schemas = all_tool_schemas
|
|
1092
|
+
self._extract_tool_calls = extract_tool_calls
|
|
1093
|
+
self._execute_tool = execute_tool
|
|
1094
|
+
|
|
1095
|
+
async def execute(self) -> str:
|
|
1096
|
+
"""Execute a single subtask with tool access."""
|
|
1097
|
+
from elidia.api.client import ChatMessage
|
|
1098
|
+
system = (
|
|
1099
|
+
f"You are a specialized AI {self._role}. Complete the following task "
|
|
1100
|
+
f"thoroughly and accurately. You may use tools if needed.\n\n"
|
|
1101
|
+
f"Task: {self._task}"
|
|
1102
|
+
)
|
|
1103
|
+
messages = [ChatMessage(role="system", content=system)]
|
|
1104
|
+
max_iterations = 5
|
|
1105
|
+
|
|
1106
|
+
for _ in range(max_iterations):
|
|
1107
|
+
try:
|
|
1108
|
+
response = await self._client.chat_completion(
|
|
1109
|
+
messages=messages,
|
|
1110
|
+
model=self._model,
|
|
1111
|
+
temperature=0.3,
|
|
1112
|
+
)
|
|
1113
|
+
except Exception as e:
|
|
1114
|
+
return f"Error: {e}"
|
|
1115
|
+
|
|
1116
|
+
tool_calls = self._extract_tool_calls(response.content) if self._all_tool_schemas else []
|
|
1117
|
+
if not tool_calls:
|
|
1118
|
+
return response.content or ""
|
|
1119
|
+
|
|
1120
|
+
messages.append(ChatMessage(role="assistant", content=response.content))
|
|
1121
|
+
for tc in tool_calls:
|
|
1122
|
+
try:
|
|
1123
|
+
result, _ = await self._execute_tool(tc["name"], tc.get("arguments", {}))
|
|
1124
|
+
messages.append(ChatMessage(
|
|
1125
|
+
role="user",
|
|
1126
|
+
content=f"Tool result for {tc['name']}: {result[:2000]}"
|
|
1127
|
+
))
|
|
1128
|
+
except Exception as e:
|
|
1129
|
+
messages.append(ChatMessage(
|
|
1130
|
+
role="user",
|
|
1131
|
+
content=f"Tool {tc['name']} failed: {e}"
|
|
1132
|
+
))
|
|
1133
|
+
|
|
1134
|
+
return "Max iterations reached without completion."
|