vibecore 0.3.0__py3-none-any.whl → 0.6.2__py3-none-any.whl
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.
- vibecore/agents/default.py +3 -3
- vibecore/agents/task.py +3 -3
- vibecore/cli.py +67 -43
- vibecore/context.py +74 -11
- vibecore/flow.py +335 -73
- vibecore/handlers/stream_handler.py +35 -56
- vibecore/main.py +70 -272
- vibecore/session/jsonl_session.py +3 -1
- vibecore/session/loader.py +2 -2
- vibecore/settings.py +48 -1
- vibecore/tools/file/executor.py +59 -13
- vibecore/tools/file/tools.py +9 -9
- vibecore/tools/path_validator.py +251 -0
- vibecore/tools/python/helpers.py +2 -2
- vibecore/tools/python/tools.py +2 -2
- vibecore/tools/shell/executor.py +63 -7
- vibecore/tools/shell/tools.py +9 -9
- vibecore/tools/task/executor.py +2 -2
- vibecore/tools/task/tools.py +2 -2
- vibecore/tools/todo/manager.py +2 -10
- vibecore/tools/todo/models.py +5 -14
- vibecore/tools/todo/tools.py +5 -5
- vibecore/tools/webfetch/tools.py +1 -4
- vibecore/tools/websearch/ddgs/backend.py +1 -1
- vibecore/tools/websearch/tools.py +1 -4
- vibecore/widgets/core.py +3 -17
- vibecore/widgets/feedback.py +164 -0
- vibecore/widgets/feedback.tcss +121 -0
- vibecore/widgets/messages.py +22 -2
- vibecore/widgets/messages.tcss +28 -0
- vibecore/widgets/tool_messages.py +19 -4
- vibecore/widgets/tool_messages.tcss +23 -0
- {vibecore-0.3.0.dist-info → vibecore-0.6.2.dist-info}/METADATA +122 -29
- {vibecore-0.3.0.dist-info → vibecore-0.6.2.dist-info}/RECORD +37 -34
- {vibecore-0.3.0.dist-info → vibecore-0.6.2.dist-info}/WHEEL +0 -0
- {vibecore-0.3.0.dist-info → vibecore-0.6.2.dist-info}/entry_points.txt +0 -0
- {vibecore-0.3.0.dist-info → vibecore-0.6.2.dist-info}/licenses/LICENSE +0 -0
vibecore/agents/default.py
CHANGED
|
@@ -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,
|
vibecore/agents/task.py
CHANGED
|
@@ -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,
|
vibecore/cli.py
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
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.context import
|
|
13
|
-
from vibecore.
|
|
16
|
+
from vibecore.context import DefaultVibecoreContext, FullVibecoreContext
|
|
17
|
+
from vibecore.flow import AppIsExiting, Vibecore, VibecoreRunner
|
|
14
18
|
from vibecore.mcp import MCPManager
|
|
19
|
+
from vibecore.session import JSONLSession
|
|
15
20
|
from vibecore.settings import settings
|
|
16
21
|
|
|
17
22
|
app = typer.Typer()
|
|
@@ -110,49 +115,68 @@ def main(
|
|
|
110
115
|
logger = logging.getLogger("openai.agents")
|
|
111
116
|
logger.addHandler(TextualHandler())
|
|
112
117
|
|
|
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
|
|
118
|
+
asyncio.run(
|
|
119
|
+
async_main(continue_session=continue_session, session_id=session_id, prompt=prompt, print_mode=print_mode)
|
|
120
|
+
)
|
|
125
121
|
|
|
126
|
-
# Create agent with MCP servers
|
|
127
|
-
agent = create_default_agent(mcp_servers=mcp_servers)
|
|
128
122
|
|
|
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
|
-
|
|
123
|
+
async def async_main(continue_session: bool, session_id: str | None, prompt: str | None, print_mode: bool):
|
|
124
|
+
# Create MCP manager
|
|
125
|
+
async with MCPManager(settings.mcp_servers) as mcp_manager:
|
|
126
|
+
# Create agent with MCP servers
|
|
127
|
+
agent = create_default_agent(mcp_servers=mcp_manager.servers)
|
|
128
|
+
|
|
129
|
+
vibecore = Vibecore[FullVibecoreContext, RunResultBase](disable_user_input=False)
|
|
130
|
+
context = DefaultVibecoreContext()
|
|
131
|
+
|
|
132
|
+
# Determine session to use
|
|
133
|
+
session_to_load = None
|
|
134
|
+
if continue_session:
|
|
135
|
+
session_to_load = find_latest_session()
|
|
136
|
+
if not session_to_load:
|
|
137
|
+
typer.echo("No existing sessions found for this project.")
|
|
138
|
+
raise typer.Exit(1)
|
|
139
|
+
typer.echo(f"Continuing session: {session_to_load}")
|
|
140
|
+
elif session_id:
|
|
141
|
+
session_to_load = session_id
|
|
142
|
+
typer.echo(f"Loading session: {session_to_load}")
|
|
143
|
+
|
|
144
|
+
if session_to_load is None:
|
|
145
|
+
# Generate a new session ID based on current date/time
|
|
146
|
+
session_to_load = f"chat-{datetime.datetime.now().strftime('%Y%m%d-%H%M%S')}"
|
|
147
|
+
|
|
148
|
+
session = JSONLSession(
|
|
149
|
+
session_id=session_to_load,
|
|
150
|
+
project_path=None, # Will use current working directory
|
|
151
|
+
base_dir=settings.session.base_dir,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Define workflow logic
|
|
155
|
+
@vibecore.workflow()
|
|
156
|
+
async def workflow(
|
|
157
|
+
runner: VibecoreRunner[FullVibecoreContext, RunResultBase],
|
|
158
|
+
user_message: str,
|
|
159
|
+
) -> RunResultBase:
|
|
160
|
+
# Run the agent with the input
|
|
161
|
+
return await runner.run_agent(
|
|
162
|
+
agent,
|
|
163
|
+
input=user_message,
|
|
164
|
+
context=runner.context,
|
|
165
|
+
max_turns=settings.max_turns,
|
|
166
|
+
session=runner.session,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
if print_mode:
|
|
170
|
+
# Use static runner for print mode - pass empty input since we get it in workflow
|
|
171
|
+
input_text = prompt.strip() if prompt else sys.stdin.read().strip()
|
|
172
|
+
result = await vibecore.run(input_text, context=context)
|
|
173
|
+
# Print raw output to stdout
|
|
174
|
+
print(result.final_output_as(str))
|
|
175
|
+
else:
|
|
176
|
+
# Run in TUI mode
|
|
177
|
+
with contextlib.suppress(AppIsExiting):
|
|
178
|
+
result = await vibecore.run_textual(prompt, context=context, session=session)
|
|
179
|
+
print(result)
|
|
156
180
|
|
|
157
181
|
|
|
158
182
|
@auth_app.command("login")
|
vibecore/context.py
CHANGED
|
@@ -1,24 +1,87 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
|
-
from
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import TYPE_CHECKING, Optional, Protocol, runtime_checkable
|
|
3
4
|
|
|
4
5
|
from vibecore.tools.python.manager import PythonExecutionManager
|
|
5
6
|
from vibecore.tools.todo.manager import TodoManager
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from vibecore.main import VibecoreApp
|
|
9
|
-
from vibecore.
|
|
10
|
+
from vibecore.tools.path_validator import PathValidator
|
|
11
|
+
|
|
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
|
+
...
|
|
10
46
|
|
|
11
47
|
|
|
12
48
|
@dataclass
|
|
13
|
-
class
|
|
49
|
+
class DefaultVibecoreContext:
|
|
14
50
|
todo_manager: TodoManager = field(default_factory=TodoManager)
|
|
15
51
|
python_manager: PythonExecutionManager = field(default_factory=PythonExecutionManager)
|
|
16
52
|
app: Optional["VibecoreApp"] = None
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
53
|
+
|
|
54
|
+
# Path confinement configuration
|
|
55
|
+
allowed_directories: list[Path] = field(default_factory=list)
|
|
56
|
+
path_validator: "PathValidator" = field(init=False) # Always initialized, never None
|
|
57
|
+
|
|
58
|
+
def __post_init__(self) -> None:
|
|
59
|
+
"""Initialize path validator with allowed directories."""
|
|
60
|
+
from vibecore.tools.path_validator import PathValidator
|
|
61
|
+
|
|
62
|
+
if not self.allowed_directories:
|
|
63
|
+
# Load from settings if not explicitly provided
|
|
64
|
+
from vibecore.settings import settings
|
|
65
|
+
|
|
66
|
+
if settings.path_confinement.enabled:
|
|
67
|
+
self.allowed_directories = settings.path_confinement.allowed_directories
|
|
68
|
+
# Add home directory if configured
|
|
69
|
+
if settings.path_confinement.allow_home:
|
|
70
|
+
self.allowed_directories.append(Path.home())
|
|
71
|
+
# Add temp directories if configured
|
|
72
|
+
if settings.path_confinement.allow_temp:
|
|
73
|
+
import tempfile
|
|
74
|
+
|
|
75
|
+
temp_dir = Path(tempfile.gettempdir())
|
|
76
|
+
if temp_dir not in self.allowed_directories:
|
|
77
|
+
self.allowed_directories.append(temp_dir)
|
|
78
|
+
else:
|
|
79
|
+
# If path confinement is disabled, allow CWD only (but validator won't be used)
|
|
80
|
+
self.allowed_directories = [Path.cwd()]
|
|
81
|
+
|
|
82
|
+
self.path_validator = PathValidator(self.allowed_directories)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if TYPE_CHECKING:
|
|
86
|
+
# Ensure DefaultVibecoreContext conforms to the VibecoreContext protocol for static analyzers
|
|
87
|
+
_default_context: FullVibecoreContext = DefaultVibecoreContext()
|