vibecore 0.5.0__tar.gz → 0.6.0__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.
Potentially problematic release.
This version of vibecore might be problematic. Click here for more details.
- {vibecore-0.5.0 → vibecore-0.6.0}/PKG-INFO +91 -31
- {vibecore-0.5.0 → vibecore-0.6.0}/README.md +90 -30
- {vibecore-0.5.0 → vibecore-0.6.0}/pyproject.toml +2 -2
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/agents/default.py +3 -3
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/agents/task.py +3 -3
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/cli.py +68 -43
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/context.py +41 -15
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/flow.py +144 -122
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/handlers/stream_handler.py +0 -10
- vibecore-0.6.0/src/vibecore/main.py +300 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/session/loader.py +2 -2
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/file/executor.py +13 -5
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/file/tools.py +5 -5
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/python/helpers.py +2 -2
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/python/tools.py +2 -2
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/shell/executor.py +5 -5
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/shell/tools.py +5 -5
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/task/executor.py +2 -2
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/task/tools.py +2 -2
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/todo/tools.py +3 -3
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/webfetch/tools.py +1 -4
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/websearch/tools.py +1 -4
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/core.py +2 -9
- vibecore-0.5.0/src/vibecore/main.py +0 -526
- {vibecore-0.5.0 → vibecore-0.6.0}/.gitignore +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/LICENSE +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/agents/prompts.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/auth/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/auth/config.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/auth/interceptor.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/auth/manager.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/auth/models.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/auth/oauth_flow.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/auth/pkce.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/auth/storage.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/auth/token_manager.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/handlers/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/main.tcss +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/mcp/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/mcp/manager.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/mcp/server_wrapper.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/models/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/models/anthropic.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/models/anthropic_auth.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/prompts/common_system_prompt.txt +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/py.typed +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/session/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/session/file_lock.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/session/jsonl_session.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/session/path_utils.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/settings.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/base.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/file/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/file/utils.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/path_validator.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/python/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/python/backends/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/python/backends/terminal_backend.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/python/manager.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/shell/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/task/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/todo/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/todo/manager.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/todo/models.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/webfetch/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/webfetch/executor.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/webfetch/models.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/websearch/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/websearch/base.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/websearch/ddgs/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/websearch/ddgs/backend.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/websearch/executor.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/tools/websearch/models.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/utils/__init__.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/utils/text.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/core.tcss +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/expandable.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/expandable.tcss +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/feedback.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/feedback.tcss +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/info.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/info.tcss +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/messages.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/messages.tcss +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/tool_message_factory.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/tool_messages.py +0 -0
- {vibecore-0.5.0 → vibecore-0.6.0}/src/vibecore/widgets/tool_messages.tcss +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vibecore
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Build your own AI-powered automation tools in the terminal with this extensible agent framework
|
|
5
5
|
Project-URL: Homepage, https://github.com/serialx/vibecore
|
|
6
6
|
Project-URL: Repository, https://github.com/serialx/vibecore
|
|
@@ -158,7 +158,6 @@ Once vibecore is running, you can:
|
|
|
158
158
|
### Commands
|
|
159
159
|
|
|
160
160
|
- `/help` - Show help and keyboard shortcuts
|
|
161
|
-
- `/clear` - Clear the current session and start a new one
|
|
162
161
|
|
|
163
162
|
## Flow Mode (Experimental)
|
|
164
163
|
|
|
@@ -177,37 +176,56 @@ Flow Mode allows you to:
|
|
|
177
176
|
|
|
178
177
|
```python
|
|
179
178
|
import asyncio
|
|
180
|
-
from agents import Agent
|
|
181
|
-
from vibecore.flow import
|
|
179
|
+
from agents import Agent
|
|
180
|
+
from vibecore.flow import Vibecore, VibecoreRunnerBase
|
|
182
181
|
from vibecore.context import VibecoreContext
|
|
182
|
+
from vibecore.settings import settings
|
|
183
183
|
|
|
184
184
|
# Define your agent with tools
|
|
185
185
|
agent = Agent[VibecoreContext](
|
|
186
186
|
name="Assistant",
|
|
187
187
|
instructions="You are a helpful assistant",
|
|
188
188
|
tools=[...], # Your tools here
|
|
189
|
+
model=settings.model,
|
|
189
190
|
)
|
|
190
191
|
|
|
191
|
-
#
|
|
192
|
-
|
|
192
|
+
# Create Vibecore instance
|
|
193
|
+
vibecore = Vibecore[VibecoreContext, str]()
|
|
194
|
+
|
|
195
|
+
# Define your conversation logic with decorator
|
|
196
|
+
@vibecore.workflow()
|
|
197
|
+
async def logic(
|
|
198
|
+
runner: VibecoreRunnerBase[VibecoreContext, str],
|
|
199
|
+
) -> str:
|
|
193
200
|
# Get user input programmatically
|
|
194
|
-
user_message = await user_input("What would you like to do?")
|
|
195
|
-
|
|
196
|
-
#
|
|
197
|
-
|
|
201
|
+
user_message = await runner.user_input("What would you like to do?")
|
|
202
|
+
|
|
203
|
+
# Print status updates
|
|
204
|
+
await runner.print(f"Processing: {user_message}")
|
|
205
|
+
|
|
206
|
+
# Process with agent (handles streaming automatically)
|
|
207
|
+
result = await runner.run_agent(
|
|
198
208
|
agent,
|
|
199
209
|
input=user_message,
|
|
200
|
-
context=
|
|
201
|
-
session=
|
|
210
|
+
context=runner.context,
|
|
211
|
+
session=runner.session,
|
|
202
212
|
)
|
|
203
|
-
|
|
204
|
-
# Handle the response
|
|
205
|
-
app.current_worker = app.handle_streamed_response(result)
|
|
206
|
-
await app.current_worker.wait()
|
|
207
213
|
|
|
208
|
-
|
|
214
|
+
await runner.print("Done!")
|
|
215
|
+
return result.final_output
|
|
216
|
+
|
|
217
|
+
# Run the flow in different modes
|
|
209
218
|
async def main():
|
|
210
|
-
|
|
219
|
+
# Option 1: TUI mode (full terminal interface)
|
|
220
|
+
result = await vibecore.run_textual(shutdown=False)
|
|
221
|
+
|
|
222
|
+
# Option 2: CLI mode (simple stdin/stdout)
|
|
223
|
+
# result = await vibecore.run_cli()
|
|
224
|
+
|
|
225
|
+
# Option 3: Static mode (programmatic, for testing)
|
|
226
|
+
# result = await vibecore.run("Calculate 2+2")
|
|
227
|
+
|
|
228
|
+
print(f"Final output: {result}")
|
|
211
229
|
|
|
212
230
|
if __name__ == "__main__":
|
|
213
231
|
asyncio.run(main())
|
|
@@ -225,11 +243,53 @@ Flow Mode shines when building complex multi-agent systems. See `examples/custom
|
|
|
225
243
|
|
|
226
244
|
### Key Components
|
|
227
245
|
|
|
228
|
-
- **`
|
|
229
|
-
-
|
|
230
|
-
-
|
|
231
|
-
- **`
|
|
232
|
-
-
|
|
246
|
+
- **`Vibecore` class**: Main entry point that orchestrates your workflow
|
|
247
|
+
- **`@vibecore.workflow()` decorator**: Defines your conversation logic function
|
|
248
|
+
- **Runner argument**: Every workflow receives a runner instance for user input, printing, and agent execution
|
|
249
|
+
- **`runner.user_input()`**: Programmatically collect user input
|
|
250
|
+
- **`runner.print()`**: Display status messages to the user
|
|
251
|
+
- **`runner.run_agent()`**: Execute agent with automatic streaming handling
|
|
252
|
+
- **`runner.context`**: Shared state (VibecoreContext) across tools and agents
|
|
253
|
+
- **`runner.session`**: Conversation history and persistence
|
|
254
|
+
- **Multiple execution modes**:
|
|
255
|
+
- `run_textual()`: Full TUI with streaming (original behavior)
|
|
256
|
+
- `run_cli()`: Simple CLI with stdin/stdout
|
|
257
|
+
- `run()`: Static mode with predefined inputs (perfect for testing)
|
|
258
|
+
- **Agent Handoffs**: Transfer control between specialized agents with context preservation
|
|
259
|
+
|
|
260
|
+
> 🛠️ Upgrading from an older release? Read the [Runner Migration Guide](docs/runner_migration.md) for step-by-step instructions.
|
|
261
|
+
|
|
262
|
+
### Multi-Mode Execution
|
|
263
|
+
|
|
264
|
+
One of vibecore's key strengths is the ability to run the **same workflow code** in different execution modes without modification:
|
|
265
|
+
|
|
266
|
+
#### TUI Mode (Textual User Interface)
|
|
267
|
+
Full-featured terminal interface with streaming responses, tool visualization, and interactive controls:
|
|
268
|
+
```python
|
|
269
|
+
result = await vibecore.run_textual(shutdown=False)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### CLI Mode (Command-Line Interface)
|
|
273
|
+
Simple stdin/stdout interaction for scripting and automation:
|
|
274
|
+
```python
|
|
275
|
+
result = await vibecore.run_cli()
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
#### Static Mode (Programmatic)
|
|
279
|
+
Execute with predefined inputs, perfect for testing and batch processing:
|
|
280
|
+
```python
|
|
281
|
+
# Single input
|
|
282
|
+
result = await vibecore.run("Calculate 2+2")
|
|
283
|
+
|
|
284
|
+
# Multiple inputs (for multi-turn workflows)
|
|
285
|
+
result = await vibecore.run(["First query", "Follow-up", "Final question"])
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
This unified interface means you can:
|
|
289
|
+
- **Develop once, deploy anywhere**: Write your workflow logic once and run it in any mode
|
|
290
|
+
- **Test easily**: Use static mode for automated testing with predefined inputs
|
|
291
|
+
- **Choose the right interface**: TUI for development, CLI for scripts, static for tests
|
|
292
|
+
- **Extend to new modes**: Add custom runners (HTTP API, Discord bot, etc.) by implementing the runner interface
|
|
233
293
|
|
|
234
294
|
### Use Cases
|
|
235
295
|
|
|
@@ -446,11 +506,6 @@ When enabled, the path confinement system:
|
|
|
446
506
|
- Resolves symlinks to prevent escapes
|
|
447
507
|
- Blocks access to files outside allowed directories
|
|
448
508
|
|
|
449
|
-
### Reasoning Effort
|
|
450
|
-
|
|
451
|
-
- Set default via env var: `VIBECORE_REASONING_EFFORT` (minimal | low | medium | high)
|
|
452
|
-
- Keyword triggers: `think` → low, `think hard` → medium, `ultrathink` → high
|
|
453
|
-
|
|
454
509
|
### Environment Variables
|
|
455
510
|
|
|
456
511
|
```bash
|
|
@@ -507,10 +562,15 @@ vibecore is built with a modular, extensible architecture:
|
|
|
507
562
|
|
|
508
563
|
## Recent Updates
|
|
509
564
|
|
|
510
|
-
- **
|
|
511
|
-
-
|
|
565
|
+
- **Flow Mode Refactor (v0.5.0)**: Complete redesign with multi-mode execution support
|
|
566
|
+
- New `Vibecore` class with decorator-based workflow definition
|
|
567
|
+
- Unified interface: `user_input()`, `print()`, `run_agent()`
|
|
568
|
+
- Three execution modes: TUI, CLI, and static (perfect for testing)
|
|
569
|
+
- Cleaner API with less boilerplate and better type safety
|
|
570
|
+
- **Path Confinement**: Security feature to restrict file and shell operations to specified directories
|
|
571
|
+
- **Reasoning View**: ReasoningMessage widget with live reasoning summaries during streaming
|
|
512
572
|
- **Context Usage Bar & CWD**: Footer shows token usage progress and current working directory
|
|
513
|
-
- **Keyboard & Commands**: Ctrl+Shift+D toggles theme, Esc cancels, Ctrl+D double-press to exit, `/help`
|
|
573
|
+
- **Keyboard & Commands**: Ctrl+Shift+D toggles theme, Esc cancels, Ctrl+D double-press to exit, `/help` command
|
|
514
574
|
- **MCP Tool Output**: Improved rendering with Markdown and JSON prettification
|
|
515
575
|
- **MCP Support**: Full integration with Model Context Protocol for external tool connections
|
|
516
576
|
- **Print Mode**: `-p` flag to print response and exit for pipes/automation
|
|
@@ -119,7 +119,6 @@ Once vibecore is running, you can:
|
|
|
119
119
|
### Commands
|
|
120
120
|
|
|
121
121
|
- `/help` - Show help and keyboard shortcuts
|
|
122
|
-
- `/clear` - Clear the current session and start a new one
|
|
123
122
|
|
|
124
123
|
## Flow Mode (Experimental)
|
|
125
124
|
|
|
@@ -138,37 +137,56 @@ Flow Mode allows you to:
|
|
|
138
137
|
|
|
139
138
|
```python
|
|
140
139
|
import asyncio
|
|
141
|
-
from agents import Agent
|
|
142
|
-
from vibecore.flow import
|
|
140
|
+
from agents import Agent
|
|
141
|
+
from vibecore.flow import Vibecore, VibecoreRunnerBase
|
|
143
142
|
from vibecore.context import VibecoreContext
|
|
143
|
+
from vibecore.settings import settings
|
|
144
144
|
|
|
145
145
|
# Define your agent with tools
|
|
146
146
|
agent = Agent[VibecoreContext](
|
|
147
147
|
name="Assistant",
|
|
148
148
|
instructions="You are a helpful assistant",
|
|
149
149
|
tools=[...], # Your tools here
|
|
150
|
+
model=settings.model,
|
|
150
151
|
)
|
|
151
152
|
|
|
152
|
-
#
|
|
153
|
-
|
|
153
|
+
# Create Vibecore instance
|
|
154
|
+
vibecore = Vibecore[VibecoreContext, str]()
|
|
155
|
+
|
|
156
|
+
# Define your conversation logic with decorator
|
|
157
|
+
@vibecore.workflow()
|
|
158
|
+
async def logic(
|
|
159
|
+
runner: VibecoreRunnerBase[VibecoreContext, str],
|
|
160
|
+
) -> str:
|
|
154
161
|
# Get user input programmatically
|
|
155
|
-
user_message = await user_input("What would you like to do?")
|
|
156
|
-
|
|
157
|
-
#
|
|
158
|
-
|
|
162
|
+
user_message = await runner.user_input("What would you like to do?")
|
|
163
|
+
|
|
164
|
+
# Print status updates
|
|
165
|
+
await runner.print(f"Processing: {user_message}")
|
|
166
|
+
|
|
167
|
+
# Process with agent (handles streaming automatically)
|
|
168
|
+
result = await runner.run_agent(
|
|
159
169
|
agent,
|
|
160
170
|
input=user_message,
|
|
161
|
-
context=
|
|
162
|
-
session=
|
|
171
|
+
context=runner.context,
|
|
172
|
+
session=runner.session,
|
|
163
173
|
)
|
|
164
|
-
|
|
165
|
-
# Handle the response
|
|
166
|
-
app.current_worker = app.handle_streamed_response(result)
|
|
167
|
-
await app.current_worker.wait()
|
|
168
174
|
|
|
169
|
-
|
|
175
|
+
await runner.print("Done!")
|
|
176
|
+
return result.final_output
|
|
177
|
+
|
|
178
|
+
# Run the flow in different modes
|
|
170
179
|
async def main():
|
|
171
|
-
|
|
180
|
+
# Option 1: TUI mode (full terminal interface)
|
|
181
|
+
result = await vibecore.run_textual(shutdown=False)
|
|
182
|
+
|
|
183
|
+
# Option 2: CLI mode (simple stdin/stdout)
|
|
184
|
+
# result = await vibecore.run_cli()
|
|
185
|
+
|
|
186
|
+
# Option 3: Static mode (programmatic, for testing)
|
|
187
|
+
# result = await vibecore.run("Calculate 2+2")
|
|
188
|
+
|
|
189
|
+
print(f"Final output: {result}")
|
|
172
190
|
|
|
173
191
|
if __name__ == "__main__":
|
|
174
192
|
asyncio.run(main())
|
|
@@ -186,11 +204,53 @@ Flow Mode shines when building complex multi-agent systems. See `examples/custom
|
|
|
186
204
|
|
|
187
205
|
### Key Components
|
|
188
206
|
|
|
189
|
-
- **`
|
|
190
|
-
-
|
|
191
|
-
-
|
|
192
|
-
- **`
|
|
193
|
-
-
|
|
207
|
+
- **`Vibecore` class**: Main entry point that orchestrates your workflow
|
|
208
|
+
- **`@vibecore.workflow()` decorator**: Defines your conversation logic function
|
|
209
|
+
- **Runner argument**: Every workflow receives a runner instance for user input, printing, and agent execution
|
|
210
|
+
- **`runner.user_input()`**: Programmatically collect user input
|
|
211
|
+
- **`runner.print()`**: Display status messages to the user
|
|
212
|
+
- **`runner.run_agent()`**: Execute agent with automatic streaming handling
|
|
213
|
+
- **`runner.context`**: Shared state (VibecoreContext) across tools and agents
|
|
214
|
+
- **`runner.session`**: Conversation history and persistence
|
|
215
|
+
- **Multiple execution modes**:
|
|
216
|
+
- `run_textual()`: Full TUI with streaming (original behavior)
|
|
217
|
+
- `run_cli()`: Simple CLI with stdin/stdout
|
|
218
|
+
- `run()`: Static mode with predefined inputs (perfect for testing)
|
|
219
|
+
- **Agent Handoffs**: Transfer control between specialized agents with context preservation
|
|
220
|
+
|
|
221
|
+
> 🛠️ Upgrading from an older release? Read the [Runner Migration Guide](docs/runner_migration.md) for step-by-step instructions.
|
|
222
|
+
|
|
223
|
+
### Multi-Mode Execution
|
|
224
|
+
|
|
225
|
+
One of vibecore's key strengths is the ability to run the **same workflow code** in different execution modes without modification:
|
|
226
|
+
|
|
227
|
+
#### TUI Mode (Textual User Interface)
|
|
228
|
+
Full-featured terminal interface with streaming responses, tool visualization, and interactive controls:
|
|
229
|
+
```python
|
|
230
|
+
result = await vibecore.run_textual(shutdown=False)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### CLI Mode (Command-Line Interface)
|
|
234
|
+
Simple stdin/stdout interaction for scripting and automation:
|
|
235
|
+
```python
|
|
236
|
+
result = await vibecore.run_cli()
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### Static Mode (Programmatic)
|
|
240
|
+
Execute with predefined inputs, perfect for testing and batch processing:
|
|
241
|
+
```python
|
|
242
|
+
# Single input
|
|
243
|
+
result = await vibecore.run("Calculate 2+2")
|
|
244
|
+
|
|
245
|
+
# Multiple inputs (for multi-turn workflows)
|
|
246
|
+
result = await vibecore.run(["First query", "Follow-up", "Final question"])
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
This unified interface means you can:
|
|
250
|
+
- **Develop once, deploy anywhere**: Write your workflow logic once and run it in any mode
|
|
251
|
+
- **Test easily**: Use static mode for automated testing with predefined inputs
|
|
252
|
+
- **Choose the right interface**: TUI for development, CLI for scripts, static for tests
|
|
253
|
+
- **Extend to new modes**: Add custom runners (HTTP API, Discord bot, etc.) by implementing the runner interface
|
|
194
254
|
|
|
195
255
|
### Use Cases
|
|
196
256
|
|
|
@@ -407,11 +467,6 @@ When enabled, the path confinement system:
|
|
|
407
467
|
- Resolves symlinks to prevent escapes
|
|
408
468
|
- Blocks access to files outside allowed directories
|
|
409
469
|
|
|
410
|
-
### Reasoning Effort
|
|
411
|
-
|
|
412
|
-
- Set default via env var: `VIBECORE_REASONING_EFFORT` (minimal | low | medium | high)
|
|
413
|
-
- Keyword triggers: `think` → low, `think hard` → medium, `ultrathink` → high
|
|
414
|
-
|
|
415
470
|
### Environment Variables
|
|
416
471
|
|
|
417
472
|
```bash
|
|
@@ -468,10 +523,15 @@ vibecore is built with a modular, extensible architecture:
|
|
|
468
523
|
|
|
469
524
|
## Recent Updates
|
|
470
525
|
|
|
471
|
-
- **
|
|
472
|
-
-
|
|
526
|
+
- **Flow Mode Refactor (v0.5.0)**: Complete redesign with multi-mode execution support
|
|
527
|
+
- New `Vibecore` class with decorator-based workflow definition
|
|
528
|
+
- Unified interface: `user_input()`, `print()`, `run_agent()`
|
|
529
|
+
- Three execution modes: TUI, CLI, and static (perfect for testing)
|
|
530
|
+
- Cleaner API with less boilerplate and better type safety
|
|
531
|
+
- **Path Confinement**: Security feature to restrict file and shell operations to specified directories
|
|
532
|
+
- **Reasoning View**: ReasoningMessage widget with live reasoning summaries during streaming
|
|
473
533
|
- **Context Usage Bar & CWD**: Footer shows token usage progress and current working directory
|
|
474
|
-
- **Keyboard & Commands**: Ctrl+Shift+D toggles theme, Esc cancels, Ctrl+D double-press to exit, `/help`
|
|
534
|
+
- **Keyboard & Commands**: Ctrl+Shift+D toggles theme, Esc cancels, Ctrl+D double-press to exit, `/help` command
|
|
475
535
|
- **MCP Tool Output**: Improved rendering with Markdown and JSON prettification
|
|
476
536
|
- **MCP Support**: Full integration with Model Context Protocol for external tool connections
|
|
477
537
|
- **Print Mode**: `-p` flag to print response and exit for pipes/automation
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vibecore"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.6.0"
|
|
4
4
|
description = "Build your own AI-powered automation tools in the terminal with this extensible agent framework"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -120,7 +120,7 @@ indent-style = "space"
|
|
|
120
120
|
|
|
121
121
|
[tool.pyright]
|
|
122
122
|
include = ["**/*.py"]
|
|
123
|
-
exclude = ["**/__pycache__", ".venv", "venv", "build", "dist"]
|
|
123
|
+
exclude = ["**/__pycache__", ".venv", "venv", "build", "dist", ".git"]
|
|
124
124
|
pythonVersion = "3.11"
|
|
125
125
|
venvPath = "."
|
|
126
126
|
venv = ".venv"
|
|
@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
|
|
|
3
3
|
from agents import Agent
|
|
4
4
|
from agents.extensions.handoff_prompt import prompt_with_handoff_instructions
|
|
5
5
|
|
|
6
|
-
from vibecore.context import
|
|
6
|
+
from vibecore.context import FullVibecoreContext
|
|
7
7
|
from vibecore.settings import settings
|
|
8
8
|
from vibecore.tools.file.tools import edit, multi_edit, read, write
|
|
9
9
|
from vibecore.tools.python.tools import execute_python
|
|
@@ -29,7 +29,7 @@ INSTRUCTIONS = (
|
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def create_default_agent(mcp_servers: list["MCPServer"] | None = None) -> Agent[
|
|
32
|
+
def create_default_agent(mcp_servers: list["MCPServer"] | None = None) -> Agent[FullVibecoreContext]:
|
|
33
33
|
"""Create the general-purpose agent with appropriate tools.
|
|
34
34
|
|
|
35
35
|
Args:
|
|
@@ -58,7 +58,7 @@ def create_default_agent(mcp_servers: list["MCPServer"] | None = None) -> Agent[
|
|
|
58
58
|
|
|
59
59
|
instructions = prompt_with_handoff_instructions(instructions)
|
|
60
60
|
|
|
61
|
-
return Agent[
|
|
61
|
+
return Agent[FullVibecoreContext](
|
|
62
62
|
name="Vibecore Agent",
|
|
63
63
|
handoff_description="A versatile general-purpose assistant",
|
|
64
64
|
instructions=instructions,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from agents import Agent
|
|
4
4
|
from agents.extensions.handoff_prompt import prompt_with_handoff_instructions
|
|
5
5
|
|
|
6
|
-
from vibecore.context import
|
|
6
|
+
from vibecore.context import FullVibecoreContext
|
|
7
7
|
from vibecore.settings import settings
|
|
8
8
|
from vibecore.tools.file.tools import edit, multi_edit, read, write
|
|
9
9
|
from vibecore.tools.python.tools import execute_python
|
|
@@ -13,7 +13,7 @@ from vibecore.tools.todo.tools import todo_read, todo_write
|
|
|
13
13
|
from .prompts import COMMON_PROMPT
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def create_task_agent(prompt: str) -> Agent[
|
|
16
|
+
def create_task_agent(prompt: str) -> Agent[FullVibecoreContext]:
|
|
17
17
|
"""Create a task agent with all tools except the Task tool.
|
|
18
18
|
|
|
19
19
|
This agent is used by the Task tool to execute specific tasks.
|
|
@@ -51,7 +51,7 @@ def create_task_agent(prompt: str) -> Agent[VibecoreContext]:
|
|
|
51
51
|
|
|
52
52
|
instructions = prompt_with_handoff_instructions(instructions)
|
|
53
53
|
|
|
54
|
-
return Agent[
|
|
54
|
+
return Agent[FullVibecoreContext](
|
|
55
55
|
name="Task Agent",
|
|
56
56
|
handoff_description="A task-specific agent",
|
|
57
57
|
instructions=instructions,
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
"""Vibecore CLI interface using typer."""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import contextlib
|
|
5
|
+
import datetime
|
|
4
6
|
import logging
|
|
7
|
+
import sys
|
|
5
8
|
from importlib.metadata import version
|
|
6
9
|
from pathlib import Path
|
|
7
10
|
|
|
8
11
|
import typer
|
|
12
|
+
from agents.result import RunResultBase
|
|
9
13
|
from textual.logging import TextualHandler
|
|
10
14
|
|
|
11
15
|
from vibecore.agents.default import create_default_agent
|
|
12
|
-
from vibecore.
|
|
13
|
-
from vibecore.main import VibecoreApp
|
|
16
|
+
from vibecore.flow import AppIsExiting, Vibecore, VibecoreRunner
|
|
14
17
|
from vibecore.mcp import MCPManager
|
|
18
|
+
from vibecore.session import JSONLSession
|
|
15
19
|
from vibecore.settings import settings
|
|
16
20
|
|
|
17
21
|
app = typer.Typer()
|
|
@@ -110,49 +114,70 @@ def main(
|
|
|
110
114
|
logger = logging.getLogger("openai.agents")
|
|
111
115
|
logger.addHandler(TextualHandler())
|
|
112
116
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
# Initialize MCP manager if configured
|
|
117
|
-
mcp_servers = []
|
|
118
|
-
if settings.mcp_servers:
|
|
119
|
-
# Create MCP manager
|
|
120
|
-
mcp_manager = MCPManager(settings.mcp_servers)
|
|
121
|
-
vibecore_ctx.mcp_manager = mcp_manager
|
|
122
|
-
|
|
123
|
-
# Get the MCP servers from the manager
|
|
124
|
-
mcp_servers = mcp_manager.servers
|
|
117
|
+
asyncio.run(
|
|
118
|
+
async_main(continue_session=continue_session, session_id=session_id, prompt=prompt, print_mode=print_mode)
|
|
119
|
+
)
|
|
125
120
|
|
|
126
|
-
# Create agent with MCP servers
|
|
127
|
-
agent = create_default_agent(mcp_servers=mcp_servers)
|
|
128
121
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
122
|
+
async def async_main(continue_session: bool, session_id: str | None, prompt: str | None, print_mode: bool):
|
|
123
|
+
# Create MCP manager
|
|
124
|
+
async with MCPManager(settings.mcp_servers) as mcp_manager:
|
|
125
|
+
# Create agent with MCP servers
|
|
126
|
+
agent = create_default_agent(mcp_servers=mcp_manager.servers)
|
|
127
|
+
|
|
128
|
+
# Create Vibecore instance
|
|
129
|
+
from vibecore.context import FullVibecoreContext
|
|
130
|
+
|
|
131
|
+
vibecore = Vibecore[FullVibecoreContext, RunResultBase](disable_user_input=False)
|
|
132
|
+
|
|
133
|
+
# Determine session to use
|
|
134
|
+
session_to_load = None
|
|
135
|
+
if continue_session:
|
|
136
|
+
session_to_load = find_latest_session()
|
|
137
|
+
if not session_to_load:
|
|
138
|
+
typer.echo("No existing sessions found for this project.")
|
|
139
|
+
raise typer.Exit(1)
|
|
140
|
+
typer.echo(f"Continuing session: {session_to_load}")
|
|
141
|
+
elif session_id:
|
|
142
|
+
session_to_load = session_id
|
|
143
|
+
typer.echo(f"Loading session: {session_to_load}")
|
|
144
|
+
|
|
145
|
+
if session_to_load is None:
|
|
146
|
+
# Generate a new session ID based on current date/time
|
|
147
|
+
session_to_load = f"chat-{datetime.datetime.now().strftime('%Y%m%d-%H%M%S')}"
|
|
148
|
+
|
|
149
|
+
session = JSONLSession(
|
|
150
|
+
session_id=session_to_load,
|
|
151
|
+
project_path=None, # Will use current working directory
|
|
152
|
+
base_dir=settings.session.base_dir,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Define workflow logic
|
|
156
|
+
@vibecore.workflow()
|
|
157
|
+
async def workflow(
|
|
158
|
+
runner: VibecoreRunner[FullVibecoreContext, RunResultBase],
|
|
159
|
+
user_message: str,
|
|
160
|
+
) -> RunResultBase:
|
|
161
|
+
# Run the agent with the input
|
|
162
|
+
return await runner.run_agent(
|
|
163
|
+
agent,
|
|
164
|
+
input=user_message,
|
|
165
|
+
context=runner.context,
|
|
166
|
+
max_turns=settings.max_turns,
|
|
167
|
+
session=runner.session,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
if print_mode:
|
|
171
|
+
# Use static runner for print mode - pass empty input since we get it in workflow
|
|
172
|
+
input_text = prompt.strip() if prompt else sys.stdin.read().strip()
|
|
173
|
+
result = await vibecore.run(input_text)
|
|
174
|
+
# Print raw output to stdout
|
|
175
|
+
print(result.final_output_as(str))
|
|
176
|
+
else:
|
|
177
|
+
# Run in TUI mode
|
|
178
|
+
with contextlib.suppress(AppIsExiting):
|
|
179
|
+
result = await vibecore.run_textual(prompt, session=session)
|
|
180
|
+
print(result)
|
|
156
181
|
|
|
157
182
|
|
|
158
183
|
@auth_app.command("login")
|
|
@@ -1,29 +1,61 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import TYPE_CHECKING, Optional
|
|
3
|
+
from typing import TYPE_CHECKING, Optional, Protocol, runtime_checkable
|
|
4
4
|
|
|
5
5
|
from vibecore.tools.python.manager import PythonExecutionManager
|
|
6
6
|
from vibecore.tools.todo.manager import TodoManager
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from vibecore.main import VibecoreApp
|
|
10
|
-
from vibecore.mcp import MCPManager
|
|
11
10
|
from vibecore.tools.path_validator import PathValidator
|
|
12
11
|
|
|
13
12
|
|
|
13
|
+
@runtime_checkable
|
|
14
|
+
class TodoToolContext(Protocol):
|
|
15
|
+
"""Context required by todo tools."""
|
|
16
|
+
|
|
17
|
+
todo_manager: TodoManager
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@runtime_checkable
|
|
21
|
+
class PythonToolContext(Protocol):
|
|
22
|
+
"""Context required by Python execution tools."""
|
|
23
|
+
|
|
24
|
+
python_manager: PythonExecutionManager
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@runtime_checkable
|
|
28
|
+
class PathValidatorContext(Protocol):
|
|
29
|
+
"""Context that provides a path validator for file-system tools."""
|
|
30
|
+
|
|
31
|
+
path_validator: "PathValidator"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@runtime_checkable
|
|
35
|
+
class AppAwareContext(Protocol):
|
|
36
|
+
"""Context that exposes the optional Textual app for streaming updates."""
|
|
37
|
+
|
|
38
|
+
app: Optional["VibecoreApp"]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@runtime_checkable
|
|
42
|
+
class FullVibecoreContext(TodoToolContext, PythonToolContext, PathValidatorContext, AppAwareContext, Protocol):
|
|
43
|
+
"""Protocol describing the full context required by Vibecore agents."""
|
|
44
|
+
|
|
45
|
+
...
|
|
46
|
+
|
|
47
|
+
|
|
14
48
|
@dataclass
|
|
15
|
-
class
|
|
49
|
+
class DefaultVibecoreContext:
|
|
16
50
|
todo_manager: TodoManager = field(default_factory=TodoManager)
|
|
17
51
|
python_manager: PythonExecutionManager = field(default_factory=PythonExecutionManager)
|
|
18
52
|
app: Optional["VibecoreApp"] = None
|
|
19
|
-
context_fullness: float = 0.0
|
|
20
|
-
mcp_manager: Optional["MCPManager"] = None
|
|
21
53
|
|
|
22
54
|
# Path confinement configuration
|
|
23
55
|
allowed_directories: list[Path] = field(default_factory=list)
|
|
24
56
|
path_validator: "PathValidator" = field(init=False) # Always initialized, never None
|
|
25
57
|
|
|
26
|
-
def __post_init__(self):
|
|
58
|
+
def __post_init__(self) -> None:
|
|
27
59
|
"""Initialize path validator with allowed directories."""
|
|
28
60
|
from vibecore.tools.path_validator import PathValidator
|
|
29
61
|
|
|
@@ -49,13 +81,7 @@ class VibecoreContext:
|
|
|
49
81
|
|
|
50
82
|
self.path_validator = PathValidator(self.allowed_directories)
|
|
51
83
|
|
|
52
|
-
def reset_state(self) -> None:
|
|
53
|
-
"""Reset all context state for a new session."""
|
|
54
|
-
self.todo_manager = TodoManager()
|
|
55
|
-
self.python_manager = PythonExecutionManager()
|
|
56
|
-
self.context_fullness = 0.0
|
|
57
|
-
# Preserve allowed_directories across resets
|
|
58
|
-
# Re-initialize validator in case directories changed
|
|
59
|
-
from vibecore.tools.path_validator import PathValidator
|
|
60
84
|
|
|
61
|
-
|
|
85
|
+
if TYPE_CHECKING:
|
|
86
|
+
# Ensure DefaultVibecoreContext conforms to the VibecoreContext protocol for static analyzers
|
|
87
|
+
_default_context: FullVibecoreContext = DefaultVibecoreContext()
|