vibecore 0.2.0a1__tar.gz → 0.3.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.2.0a1 → vibecore-0.3.0}/PKG-INFO +107 -1
- {vibecore-0.2.0a1 → vibecore-0.3.0}/README.md +103 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/pyproject.toml +5 -2
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/agents/default.py +6 -11
- vibecore-0.2.0a1/src/vibecore/agents/task_agent.py → vibecore-0.3.0/src/vibecore/agents/task.py +2 -6
- vibecore-0.3.0/src/vibecore/auth/__init__.py +15 -0
- vibecore-0.3.0/src/vibecore/auth/config.py +38 -0
- vibecore-0.3.0/src/vibecore/auth/interceptor.py +141 -0
- vibecore-0.3.0/src/vibecore/auth/manager.py +173 -0
- vibecore-0.3.0/src/vibecore/auth/models.py +54 -0
- vibecore-0.3.0/src/vibecore/auth/oauth_flow.py +129 -0
- vibecore-0.3.0/src/vibecore/auth/pkce.py +29 -0
- vibecore-0.3.0/src/vibecore/auth/storage.py +111 -0
- vibecore-0.3.0/src/vibecore/auth/token_manager.py +131 -0
- vibecore-0.3.0/src/vibecore/cli.py +239 -0
- vibecore-0.3.0/src/vibecore/flow.py +105 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/handlers/stream_handler.py +11 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/main.py +28 -6
- vibecore-0.3.0/src/vibecore/models/anthropic_auth.py +226 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/settings.py +61 -5
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/task/executor.py +1 -1
- vibecore-0.3.0/src/vibecore/tools/webfetch/__init__.py +7 -0
- vibecore-0.3.0/src/vibecore/tools/webfetch/executor.py +127 -0
- vibecore-0.3.0/src/vibecore/tools/webfetch/models.py +22 -0
- vibecore-0.3.0/src/vibecore/tools/webfetch/tools.py +46 -0
- vibecore-0.3.0/src/vibecore/tools/websearch/__init__.py +5 -0
- vibecore-0.3.0/src/vibecore/tools/websearch/base.py +27 -0
- vibecore-0.3.0/src/vibecore/tools/websearch/ddgs/__init__.py +5 -0
- vibecore-0.3.0/src/vibecore/tools/websearch/ddgs/backend.py +64 -0
- vibecore-0.3.0/src/vibecore/tools/websearch/executor.py +43 -0
- vibecore-0.3.0/src/vibecore/tools/websearch/models.py +20 -0
- vibecore-0.3.0/src/vibecore/tools/websearch/tools.py +49 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/tool_message_factory.py +24 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/tool_messages.py +219 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/tool_messages.tcss +94 -0
- vibecore-0.2.0a1/src/vibecore/cli.py +0 -131
- {vibecore-0.2.0a1 → vibecore-0.3.0}/.gitignore +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/LICENSE +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/agents/prompts.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/context.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/handlers/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/main.tcss +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/mcp/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/mcp/manager.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/mcp/server_wrapper.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/models/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/models/anthropic.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/prompts/common_system_prompt.txt +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/py.typed +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/session/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/session/file_lock.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/session/jsonl_session.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/session/loader.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/session/path_utils.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/base.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/file/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/file/executor.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/file/tools.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/file/utils.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/python/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/python/backends/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/python/backends/terminal_backend.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/python/helpers.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/python/manager.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/python/tools.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/shell/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/shell/executor.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/shell/tools.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/task/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/task/tools.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/todo/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/todo/manager.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/todo/models.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/tools/todo/tools.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/utils/__init__.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/utils/text.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/core.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/core.tcss +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/expandable.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/expandable.tcss +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/info.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/info.tcss +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/messages.py +0 -0
- {vibecore-0.2.0a1 → vibecore-0.3.0}/src/vibecore/widgets/messages.tcss +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vibecore
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.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
|
|
@@ -27,6 +27,9 @@ Classifier: Topic :: Terminals
|
|
|
27
27
|
Classifier: Topic :: Text Processing :: Linguistic
|
|
28
28
|
Classifier: Typing :: Typed
|
|
29
29
|
Requires-Python: >=3.11
|
|
30
|
+
Requires-Dist: ddgs>=9.5.4
|
|
31
|
+
Requires-Dist: html2text>=2024.2.26
|
|
32
|
+
Requires-Dist: httpx>=0.24.0
|
|
30
33
|
Requires-Dist: litellm>=1.72.4
|
|
31
34
|
Requires-Dist: openai-agents[litellm]>=0.2.2
|
|
32
35
|
Requires-Dist: pydantic-settings>=2.10.1
|
|
@@ -65,6 +68,7 @@ Built on [Textual](https://textual.textualize.io/) and the [OpenAI Agents SDK](h
|
|
|
65
68
|
|
|
66
69
|
### Key Features
|
|
67
70
|
|
|
71
|
+
- **Flow Mode (Experimental)** - Build structured agent-based applications with programmatic conversation control
|
|
68
72
|
- **AI-Powered Chat Interface** - Interact with state-of-the-art language models through an intuitive terminal interface
|
|
69
73
|
- **Rich Tool Integration** - Built-in tools for file operations, shell commands, Python execution, and task management
|
|
70
74
|
- **MCP Support** - Connect to external tools and services via Model Context Protocol servers
|
|
@@ -79,6 +83,26 @@ Built on [Textual](https://textual.textualize.io/) and the [OpenAI Agents SDK](h
|
|
|
79
83
|
### Prerequisites
|
|
80
84
|
|
|
81
85
|
- Python 3.11 or higher
|
|
86
|
+
- (Optional) [uv](https://docs.astral.sh/uv/) for quick testing and better package management
|
|
87
|
+
|
|
88
|
+
### Quick Test (No Installation)
|
|
89
|
+
|
|
90
|
+
Try vibecore instantly without installing it:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Install uv if you don't have it (optional)
|
|
94
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
95
|
+
|
|
96
|
+
# Configure your API key
|
|
97
|
+
export ANTHROPIC_API_KEY="your-api-key-here"
|
|
98
|
+
# or
|
|
99
|
+
export OPENAI_API_KEY="your-api-key-here"
|
|
100
|
+
|
|
101
|
+
# Run vibecore directly with uvx
|
|
102
|
+
uvx vibecore
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
This will download and run vibecore in an isolated environment without affecting your system Python installation.
|
|
82
106
|
|
|
83
107
|
### Install from PyPI
|
|
84
108
|
|
|
@@ -136,6 +160,88 @@ Once vibecore is running, you can:
|
|
|
136
160
|
- `/help` - Show help and keyboard shortcuts
|
|
137
161
|
- `/clear` - Clear the current session and start a new one
|
|
138
162
|
|
|
163
|
+
## Flow Mode (Experimental)
|
|
164
|
+
|
|
165
|
+
Flow Mode is vibecore's **key differentiator** - it transforms the framework from a chat interface into a platform for building structured agent-based applications with programmatic conversation control.
|
|
166
|
+
|
|
167
|
+
### What is Flow Mode?
|
|
168
|
+
|
|
169
|
+
Flow Mode allows you to:
|
|
170
|
+
- **Define custom conversation logic** that controls how agents process user input
|
|
171
|
+
- **Build multi-step workflows** with defined sequences and decision points
|
|
172
|
+
- **Orchestrate multiple agents** with handoffs and shared context
|
|
173
|
+
- **Maintain conversation state** across interactions
|
|
174
|
+
- **Create agent-based applications** rather than just chatbots
|
|
175
|
+
|
|
176
|
+
### Example: Simple Flow
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
import asyncio
|
|
180
|
+
from agents import Agent, Runner
|
|
181
|
+
from vibecore.flow import flow, UserInputFunc
|
|
182
|
+
from vibecore.context import VibecoreContext
|
|
183
|
+
|
|
184
|
+
# Define your agent with tools
|
|
185
|
+
agent = Agent[VibecoreContext](
|
|
186
|
+
name="Assistant",
|
|
187
|
+
instructions="You are a helpful assistant",
|
|
188
|
+
tools=[...], # Your tools here
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Define your conversation logic
|
|
192
|
+
async def logic(app, ctx: VibecoreContext, user_input: UserInputFunc):
|
|
193
|
+
# Get user input programmatically
|
|
194
|
+
user_message = await user_input("What would you like to do?")
|
|
195
|
+
|
|
196
|
+
# Process with agent
|
|
197
|
+
result = Runner.run_streamed(
|
|
198
|
+
agent,
|
|
199
|
+
input=user_message,
|
|
200
|
+
context=ctx,
|
|
201
|
+
session=app.session,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Handle the response
|
|
205
|
+
app.current_worker = app.handle_streamed_response(result)
|
|
206
|
+
await app.current_worker.wait()
|
|
207
|
+
|
|
208
|
+
# Run the flow
|
|
209
|
+
async def main():
|
|
210
|
+
await flow(agent, logic)
|
|
211
|
+
|
|
212
|
+
if __name__ == "__main__":
|
|
213
|
+
asyncio.run(main())
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Example: Multi-Agent Customer Service
|
|
217
|
+
|
|
218
|
+
Flow Mode shines when building complex multi-agent systems. See `examples/customer_service.py` for a complete implementation featuring:
|
|
219
|
+
|
|
220
|
+
- **Triage Agent**: Routes requests to appropriate specialists
|
|
221
|
+
- **FAQ Agent**: Handles frequently asked questions
|
|
222
|
+
- **Booking Agent**: Manages seat reservations
|
|
223
|
+
- **Agent Handoffs**: Seamless transitions between agents with context preservation
|
|
224
|
+
- **Shared State**: Maintains customer information across the conversation
|
|
225
|
+
|
|
226
|
+
### Key Components
|
|
227
|
+
|
|
228
|
+
- **`flow()`**: Entry point that sets up the Vibecore app with your custom logic
|
|
229
|
+
- **`logic()`**: Your async function that controls the conversation flow
|
|
230
|
+
- **`UserInputFunc`**: Provides programmatic user input collection
|
|
231
|
+
- **`VibecoreContext`**: Shared state across tools and agents
|
|
232
|
+
- **Agent Handoffs**: Transfer control between specialized agents
|
|
233
|
+
|
|
234
|
+
### Use Cases
|
|
235
|
+
|
|
236
|
+
Flow Mode enables building:
|
|
237
|
+
- **Customer service systems** with routing and escalation
|
|
238
|
+
- **Guided workflows** for complex tasks
|
|
239
|
+
- **Interactive tutorials** with step-by-step guidance
|
|
240
|
+
- **Task automation** with human-in-the-loop controls
|
|
241
|
+
- **Multi-stage data processing** pipelines
|
|
242
|
+
|
|
243
|
+
The examples in the `examples/` directory are adapted from the official OpenAI Agents SDK with minimal modifications, demonstrating how easily you can build sophisticated agent applications with vibecore.
|
|
244
|
+
|
|
139
245
|
### Available Tools
|
|
140
246
|
|
|
141
247
|
vibecore comes with powerful built-in tools:
|
|
@@ -29,6 +29,7 @@ Built on [Textual](https://textual.textualize.io/) and the [OpenAI Agents SDK](h
|
|
|
29
29
|
|
|
30
30
|
### Key Features
|
|
31
31
|
|
|
32
|
+
- **Flow Mode (Experimental)** - Build structured agent-based applications with programmatic conversation control
|
|
32
33
|
- **AI-Powered Chat Interface** - Interact with state-of-the-art language models through an intuitive terminal interface
|
|
33
34
|
- **Rich Tool Integration** - Built-in tools for file operations, shell commands, Python execution, and task management
|
|
34
35
|
- **MCP Support** - Connect to external tools and services via Model Context Protocol servers
|
|
@@ -43,6 +44,26 @@ Built on [Textual](https://textual.textualize.io/) and the [OpenAI Agents SDK](h
|
|
|
43
44
|
### Prerequisites
|
|
44
45
|
|
|
45
46
|
- Python 3.11 or higher
|
|
47
|
+
- (Optional) [uv](https://docs.astral.sh/uv/) for quick testing and better package management
|
|
48
|
+
|
|
49
|
+
### Quick Test (No Installation)
|
|
50
|
+
|
|
51
|
+
Try vibecore instantly without installing it:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Install uv if you don't have it (optional)
|
|
55
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
56
|
+
|
|
57
|
+
# Configure your API key
|
|
58
|
+
export ANTHROPIC_API_KEY="your-api-key-here"
|
|
59
|
+
# or
|
|
60
|
+
export OPENAI_API_KEY="your-api-key-here"
|
|
61
|
+
|
|
62
|
+
# Run vibecore directly with uvx
|
|
63
|
+
uvx vibecore
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This will download and run vibecore in an isolated environment without affecting your system Python installation.
|
|
46
67
|
|
|
47
68
|
### Install from PyPI
|
|
48
69
|
|
|
@@ -100,6 +121,88 @@ Once vibecore is running, you can:
|
|
|
100
121
|
- `/help` - Show help and keyboard shortcuts
|
|
101
122
|
- `/clear` - Clear the current session and start a new one
|
|
102
123
|
|
|
124
|
+
## Flow Mode (Experimental)
|
|
125
|
+
|
|
126
|
+
Flow Mode is vibecore's **key differentiator** - it transforms the framework from a chat interface into a platform for building structured agent-based applications with programmatic conversation control.
|
|
127
|
+
|
|
128
|
+
### What is Flow Mode?
|
|
129
|
+
|
|
130
|
+
Flow Mode allows you to:
|
|
131
|
+
- **Define custom conversation logic** that controls how agents process user input
|
|
132
|
+
- **Build multi-step workflows** with defined sequences and decision points
|
|
133
|
+
- **Orchestrate multiple agents** with handoffs and shared context
|
|
134
|
+
- **Maintain conversation state** across interactions
|
|
135
|
+
- **Create agent-based applications** rather than just chatbots
|
|
136
|
+
|
|
137
|
+
### Example: Simple Flow
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
import asyncio
|
|
141
|
+
from agents import Agent, Runner
|
|
142
|
+
from vibecore.flow import flow, UserInputFunc
|
|
143
|
+
from vibecore.context import VibecoreContext
|
|
144
|
+
|
|
145
|
+
# Define your agent with tools
|
|
146
|
+
agent = Agent[VibecoreContext](
|
|
147
|
+
name="Assistant",
|
|
148
|
+
instructions="You are a helpful assistant",
|
|
149
|
+
tools=[...], # Your tools here
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Define your conversation logic
|
|
153
|
+
async def logic(app, ctx: VibecoreContext, user_input: UserInputFunc):
|
|
154
|
+
# Get user input programmatically
|
|
155
|
+
user_message = await user_input("What would you like to do?")
|
|
156
|
+
|
|
157
|
+
# Process with agent
|
|
158
|
+
result = Runner.run_streamed(
|
|
159
|
+
agent,
|
|
160
|
+
input=user_message,
|
|
161
|
+
context=ctx,
|
|
162
|
+
session=app.session,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Handle the response
|
|
166
|
+
app.current_worker = app.handle_streamed_response(result)
|
|
167
|
+
await app.current_worker.wait()
|
|
168
|
+
|
|
169
|
+
# Run the flow
|
|
170
|
+
async def main():
|
|
171
|
+
await flow(agent, logic)
|
|
172
|
+
|
|
173
|
+
if __name__ == "__main__":
|
|
174
|
+
asyncio.run(main())
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Example: Multi-Agent Customer Service
|
|
178
|
+
|
|
179
|
+
Flow Mode shines when building complex multi-agent systems. See `examples/customer_service.py` for a complete implementation featuring:
|
|
180
|
+
|
|
181
|
+
- **Triage Agent**: Routes requests to appropriate specialists
|
|
182
|
+
- **FAQ Agent**: Handles frequently asked questions
|
|
183
|
+
- **Booking Agent**: Manages seat reservations
|
|
184
|
+
- **Agent Handoffs**: Seamless transitions between agents with context preservation
|
|
185
|
+
- **Shared State**: Maintains customer information across the conversation
|
|
186
|
+
|
|
187
|
+
### Key Components
|
|
188
|
+
|
|
189
|
+
- **`flow()`**: Entry point that sets up the Vibecore app with your custom logic
|
|
190
|
+
- **`logic()`**: Your async function that controls the conversation flow
|
|
191
|
+
- **`UserInputFunc`**: Provides programmatic user input collection
|
|
192
|
+
- **`VibecoreContext`**: Shared state across tools and agents
|
|
193
|
+
- **Agent Handoffs**: Transfer control between specialized agents
|
|
194
|
+
|
|
195
|
+
### Use Cases
|
|
196
|
+
|
|
197
|
+
Flow Mode enables building:
|
|
198
|
+
- **Customer service systems** with routing and escalation
|
|
199
|
+
- **Guided workflows** for complex tasks
|
|
200
|
+
- **Interactive tutorials** with step-by-step guidance
|
|
201
|
+
- **Task automation** with human-in-the-loop controls
|
|
202
|
+
- **Multi-stage data processing** pipelines
|
|
203
|
+
|
|
204
|
+
The examples in the `examples/` directory are adapted from the official OpenAI Agents SDK with minimal modifications, demonstrating how easily you can build sophisticated agent applications with vibecore.
|
|
205
|
+
|
|
103
206
|
### Available Tools
|
|
104
207
|
|
|
105
208
|
vibecore comes with powerful built-in tools:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "vibecore"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.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 = [
|
|
@@ -44,6 +44,9 @@ classifiers = [
|
|
|
44
44
|
"Typing :: Typed",
|
|
45
45
|
]
|
|
46
46
|
dependencies = [
|
|
47
|
+
"ddgs>=9.5.4",
|
|
48
|
+
"html2text>=2024.2.26",
|
|
49
|
+
"httpx>=0.24.0",
|
|
47
50
|
"litellm>=1.72.4",
|
|
48
51
|
"openai-agents[litellm]>=0.2.2",
|
|
49
52
|
"pydantic-settings>=2.10.1",
|
|
@@ -59,7 +62,7 @@ dependencies = [
|
|
|
59
62
|
"Documentation" = "https://github.com/serialx/vibecore#readme"
|
|
60
63
|
|
|
61
64
|
[project.scripts]
|
|
62
|
-
vibecore = "vibecore.cli:
|
|
65
|
+
vibecore = "vibecore.cli:cli_main"
|
|
63
66
|
|
|
64
67
|
[[tool.uv.index]]
|
|
65
68
|
name = "testpypi"
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
|
-
from agents import Agent
|
|
3
|
+
from agents import Agent
|
|
4
4
|
from agents.extensions.handoff_prompt import prompt_with_handoff_instructions
|
|
5
|
-
from openai.types import Reasoning
|
|
6
5
|
|
|
7
6
|
from vibecore.context import VibecoreContext
|
|
8
7
|
from vibecore.settings import settings
|
|
@@ -11,6 +10,8 @@ from vibecore.tools.python.tools import execute_python
|
|
|
11
10
|
from vibecore.tools.shell.tools import bash, glob, grep, ls
|
|
12
11
|
from vibecore.tools.task.tools import task
|
|
13
12
|
from vibecore.tools.todo.tools import todo_read, todo_write
|
|
13
|
+
from vibecore.tools.webfetch.tools import webfetch
|
|
14
|
+
from vibecore.tools.websearch.tools import websearch
|
|
14
15
|
|
|
15
16
|
from .prompts import COMMON_PROMPT
|
|
16
17
|
|
|
@@ -50,26 +51,20 @@ def create_default_agent(mcp_servers: list["MCPServer"] | None = None) -> Agent[
|
|
|
50
51
|
grep,
|
|
51
52
|
ls,
|
|
52
53
|
task,
|
|
54
|
+
websearch,
|
|
55
|
+
webfetch,
|
|
53
56
|
]
|
|
54
57
|
instructions = INSTRUCTIONS
|
|
55
58
|
|
|
56
59
|
instructions = prompt_with_handoff_instructions(instructions)
|
|
57
60
|
|
|
58
|
-
# Configure reasoning based on settings
|
|
59
|
-
reasoning_config = Reasoning(summary="auto")
|
|
60
|
-
if settings.reasoning_effort is not None:
|
|
61
|
-
reasoning_config = Reasoning(effort=settings.reasoning_effort, summary="auto")
|
|
62
|
-
|
|
63
61
|
return Agent[VibecoreContext](
|
|
64
62
|
name="Vibecore Agent",
|
|
65
63
|
handoff_description="A versatile general-purpose assistant",
|
|
66
64
|
instructions=instructions,
|
|
67
65
|
tools=tools,
|
|
68
66
|
model=settings.model,
|
|
69
|
-
model_settings=
|
|
70
|
-
include_usage=True, # Ensure token usage is tracked in streaming mode
|
|
71
|
-
reasoning=reasoning_config,
|
|
72
|
-
),
|
|
67
|
+
model_settings=settings.default_model_settings,
|
|
73
68
|
handoffs=[],
|
|
74
69
|
mcp_servers=mcp_servers or [],
|
|
75
70
|
)
|
vibecore-0.2.0a1/src/vibecore/agents/task_agent.py → vibecore-0.3.0/src/vibecore/agents/task.py
RENAMED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"""Task-specific agent configuration for executing delegated tasks."""
|
|
2
2
|
|
|
3
|
-
from agents import Agent
|
|
3
|
+
from agents import Agent
|
|
4
4
|
from agents.extensions.handoff_prompt import prompt_with_handoff_instructions
|
|
5
|
-
from openai.types import Reasoning
|
|
6
5
|
|
|
7
6
|
from vibecore.context import VibecoreContext
|
|
8
7
|
from vibecore.settings import settings
|
|
@@ -58,9 +57,6 @@ def create_task_agent(prompt: str) -> Agent[VibecoreContext]:
|
|
|
58
57
|
instructions=instructions,
|
|
59
58
|
tools=tools,
|
|
60
59
|
model=settings.model,
|
|
61
|
-
model_settings=
|
|
62
|
-
include_usage=True, # Ensure token usage is tracked in streaming mode
|
|
63
|
-
reasoning=Reasoning(summary="auto"),
|
|
64
|
-
),
|
|
60
|
+
model_settings=settings.default_model_settings,
|
|
65
61
|
handoffs=[],
|
|
66
62
|
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Anthropic Pro/Max authentication module."""
|
|
2
|
+
|
|
3
|
+
from vibecore.auth.config import ANTHROPIC_CONFIG
|
|
4
|
+
from vibecore.auth.manager import AnthropicAuthManager
|
|
5
|
+
from vibecore.auth.models import AnthropicAuth, ApiKeyCredentials, OAuthCredentials
|
|
6
|
+
from vibecore.auth.storage import SecureAuthStorage
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"ANTHROPIC_CONFIG",
|
|
10
|
+
"AnthropicAuth",
|
|
11
|
+
"AnthropicAuthManager",
|
|
12
|
+
"ApiKeyCredentials",
|
|
13
|
+
"OAuthCredentials",
|
|
14
|
+
"SecureAuthStorage",
|
|
15
|
+
]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Configuration constants for Anthropic authentication."""
|
|
2
|
+
|
|
3
|
+
from typing import Final
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AnthropicConfig:
|
|
7
|
+
"""Configuration for Anthropic OAuth and API."""
|
|
8
|
+
|
|
9
|
+
# OAuth Client Configuration
|
|
10
|
+
OAUTH_CLIENT_ID: Final[str] = "9d1c250a-e61b-44d9-88ed-5944d1962f5e"
|
|
11
|
+
OAUTH_SCOPES: Final[str] = "org:create_api_key user:profile user:inference"
|
|
12
|
+
OAUTH_REDIRECT_URI: Final[str] = "https://console.anthropic.com/oauth/code/callback"
|
|
13
|
+
OAUTH_RESPONSE_TYPE: Final[str] = "code"
|
|
14
|
+
OAUTH_CODE_CHALLENGE_METHOD: Final[str] = "S256"
|
|
15
|
+
|
|
16
|
+
# API Endpoints
|
|
17
|
+
CLAUDE_AI_AUTHORIZE: Final[str] = "https://claude.ai/oauth/authorize"
|
|
18
|
+
CONSOLE_AUTHORIZE: Final[str] = "https://console.anthropic.com/oauth/authorize"
|
|
19
|
+
TOKEN_EXCHANGE: Final[str] = "https://console.anthropic.com/v1/oauth/token"
|
|
20
|
+
API_BASE: Final[str] = "https://api.anthropic.com"
|
|
21
|
+
MESSAGES: Final[str] = "https://api.anthropic.com/v1/messages"
|
|
22
|
+
|
|
23
|
+
# Beta Headers (Critical for Claude Code spoofing)
|
|
24
|
+
BETA_OAUTH: Final[str] = "oauth-2025-04-20"
|
|
25
|
+
BETA_CLAUDE_CODE: Final[str] = "claude-code-20250219" # CRITICAL: Identifies as Claude Code
|
|
26
|
+
BETA_INTERLEAVED_THINKING: Final[str] = "interleaved-thinking-2025-05-14"
|
|
27
|
+
BETA_FINE_GRAINED_STREAMING: Final[str] = "fine-grained-tool-streaming-2025-05-14"
|
|
28
|
+
|
|
29
|
+
# Token Management
|
|
30
|
+
TOKEN_REFRESH_BUFFER_SECONDS: Final[int] = 300 # Refresh 5 minutes before expiry
|
|
31
|
+
TOKEN_MAX_RETRY_ATTEMPTS: Final[int] = 3
|
|
32
|
+
TOKEN_RETRY_DELAY_MS: Final[int] = 1000
|
|
33
|
+
|
|
34
|
+
# Claude Code Identity
|
|
35
|
+
CLAUDE_CODE_IDENTITY: Final[str] = "You are Claude Code, Anthropic's official CLI for Claude."
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
ANTHROPIC_CONFIG = AnthropicConfig()
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""HTTP request interceptor for Claude Code spoofing."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
from httpx import URL
|
|
7
|
+
|
|
8
|
+
from vibecore.auth.config import ANTHROPIC_CONFIG
|
|
9
|
+
from vibecore.auth.storage import SecureAuthStorage
|
|
10
|
+
from vibecore.auth.token_manager import TokenRefreshManager
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AnthropicRequestInterceptor:
|
|
14
|
+
"""Intercepts and modifies Anthropic API requests."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, storage: SecureAuthStorage):
|
|
17
|
+
"""
|
|
18
|
+
Initialize request interceptor.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
storage: Secure storage for credentials.
|
|
22
|
+
"""
|
|
23
|
+
self.storage = storage
|
|
24
|
+
self.token_manager = TokenRefreshManager(storage)
|
|
25
|
+
|
|
26
|
+
async def intercept_request(self, url: str, headers: dict[str, str] | None = None, **kwargs: Any) -> dict[str, Any]:
|
|
27
|
+
"""
|
|
28
|
+
Intercept and modify request for Anthropic API.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
url: Request URL.
|
|
32
|
+
headers: Request headers.
|
|
33
|
+
**kwargs: Additional request parameters.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Modified request parameters.
|
|
37
|
+
"""
|
|
38
|
+
auth = await self.storage.load("anthropic")
|
|
39
|
+
|
|
40
|
+
if not auth:
|
|
41
|
+
raise ValueError("Not authenticated with Anthropic")
|
|
42
|
+
|
|
43
|
+
# Prepare headers
|
|
44
|
+
headers = {} if headers is None else headers.copy()
|
|
45
|
+
|
|
46
|
+
if auth.type == "oauth": # OAuth auth
|
|
47
|
+
await self._configure_oauth_headers(headers)
|
|
48
|
+
else: # API key auth
|
|
49
|
+
self._configure_api_key_headers(headers, auth.key) # type: ignore
|
|
50
|
+
|
|
51
|
+
# Apply Claude Code spoofing headers
|
|
52
|
+
self._apply_claude_code_headers(headers)
|
|
53
|
+
|
|
54
|
+
# Return modified request parameters
|
|
55
|
+
return {**kwargs, "headers": headers}
|
|
56
|
+
|
|
57
|
+
async def _configure_oauth_headers(self, headers: dict[str, str]) -> None:
|
|
58
|
+
"""Configure headers for OAuth authentication."""
|
|
59
|
+
# Get valid access token (handles refresh automatically)
|
|
60
|
+
access_token = await self.token_manager.get_valid_token()
|
|
61
|
+
|
|
62
|
+
# Remove any API key headers (OAuth takes precedence)
|
|
63
|
+
headers.pop("x-api-key", None)
|
|
64
|
+
headers.pop("X-Api-Key", None)
|
|
65
|
+
headers.pop("anthropic-api-key", None)
|
|
66
|
+
|
|
67
|
+
# Set OAuth bearer token
|
|
68
|
+
headers["Authorization"] = f"Bearer {access_token}"
|
|
69
|
+
|
|
70
|
+
def _configure_api_key_headers(self, headers: dict[str, str], api_key: str) -> None:
|
|
71
|
+
"""Configure headers for API key authentication."""
|
|
72
|
+
# Remove OAuth headers if present
|
|
73
|
+
headers.pop("Authorization", None)
|
|
74
|
+
|
|
75
|
+
# Set API key
|
|
76
|
+
headers["x-api-key"] = api_key
|
|
77
|
+
|
|
78
|
+
def _apply_claude_code_headers(self, headers: dict[str, str]) -> None:
|
|
79
|
+
"""Apply Claude Code spoofing headers."""
|
|
80
|
+
# Build beta features header
|
|
81
|
+
beta_features = [
|
|
82
|
+
ANTHROPIC_CONFIG.BETA_OAUTH,
|
|
83
|
+
ANTHROPIC_CONFIG.BETA_CLAUDE_CODE, # Critical for spoofing
|
|
84
|
+
ANTHROPIC_CONFIG.BETA_INTERLEAVED_THINKING,
|
|
85
|
+
# ANTHROPIC_CONFIG.BETA_FINE_GRAINED_STREAMING,
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
# Set the beta header (this is what makes Anthropic think we're Claude Code)
|
|
89
|
+
headers["anthropic-beta"] = ",".join(beta_features)
|
|
90
|
+
|
|
91
|
+
# Set additional headers that Claude Code uses
|
|
92
|
+
headers["anthropic-version"] = "2023-06-01"
|
|
93
|
+
headers.setdefault("accept", "application/json")
|
|
94
|
+
|
|
95
|
+
# Add Claude Code specific headers
|
|
96
|
+
headers["user-agent"] = "Claude-Code/1.0"
|
|
97
|
+
headers["x-client-id"] = ANTHROPIC_CONFIG.OAUTH_CLIENT_ID
|
|
98
|
+
|
|
99
|
+
# Ensure content-type is set for POST requests
|
|
100
|
+
headers.setdefault("content-type", "application/json")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class GlobalAnthropicInterceptor:
|
|
104
|
+
"""Global interceptor for automatic Anthropic request modification."""
|
|
105
|
+
|
|
106
|
+
def __init__(self, storage: SecureAuthStorage):
|
|
107
|
+
"""
|
|
108
|
+
Initialize global interceptor.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
storage: Secure storage for credentials.
|
|
112
|
+
"""
|
|
113
|
+
self.interceptor = AnthropicRequestInterceptor(storage)
|
|
114
|
+
self.original_client_class = httpx.AsyncClient
|
|
115
|
+
|
|
116
|
+
def install(self) -> None:
|
|
117
|
+
"""Install global request interception."""
|
|
118
|
+
interceptor = self.interceptor
|
|
119
|
+
|
|
120
|
+
class InterceptedAsyncClient(httpx.AsyncClient):
|
|
121
|
+
"""Custom AsyncClient that intercepts Anthropic requests."""
|
|
122
|
+
|
|
123
|
+
async def request(self, method: str, url: URL | str, **kwargs: Any) -> httpx.Response:
|
|
124
|
+
"""Override request method to intercept Anthropic API calls."""
|
|
125
|
+
# Convert URL to string if needed
|
|
126
|
+
url_str = str(url)
|
|
127
|
+
|
|
128
|
+
# Check if this is an Anthropic API request
|
|
129
|
+
if "anthropic.com" in url_str or "claude.ai" in url_str:
|
|
130
|
+
# Intercept and modify request
|
|
131
|
+
kwargs = await interceptor.intercept_request(url_str, **kwargs)
|
|
132
|
+
|
|
133
|
+
# Call original request method
|
|
134
|
+
return await super().request(method, url, **kwargs)
|
|
135
|
+
|
|
136
|
+
# Replace httpx.AsyncClient globally
|
|
137
|
+
httpx.AsyncClient = InterceptedAsyncClient # type: ignore
|
|
138
|
+
|
|
139
|
+
def uninstall(self) -> None:
|
|
140
|
+
"""Uninstall global request interception."""
|
|
141
|
+
httpx.AsyncClient = self.original_client_class # type: ignore
|