vibecore 0.2.0__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.
Potentially problematic release.
This version of vibecore might be problematic. Click here for more details.
- vibecore/__init__.py +0 -0
- vibecore/agents/default.py +79 -0
- vibecore/agents/prompts.py +12 -0
- vibecore/agents/task_agent.py +66 -0
- vibecore/cli.py +150 -0
- vibecore/context.py +24 -0
- vibecore/handlers/__init__.py +5 -0
- vibecore/handlers/stream_handler.py +231 -0
- vibecore/main.py +506 -0
- vibecore/main.tcss +0 -0
- vibecore/mcp/__init__.py +6 -0
- vibecore/mcp/manager.py +167 -0
- vibecore/mcp/server_wrapper.py +109 -0
- vibecore/models/__init__.py +5 -0
- vibecore/models/anthropic.py +239 -0
- vibecore/prompts/common_system_prompt.txt +64 -0
- vibecore/py.typed +0 -0
- vibecore/session/__init__.py +5 -0
- vibecore/session/file_lock.py +127 -0
- vibecore/session/jsonl_session.py +236 -0
- vibecore/session/loader.py +193 -0
- vibecore/session/path_utils.py +81 -0
- vibecore/settings.py +161 -0
- vibecore/tools/__init__.py +1 -0
- vibecore/tools/base.py +27 -0
- vibecore/tools/file/__init__.py +5 -0
- vibecore/tools/file/executor.py +282 -0
- vibecore/tools/file/tools.py +184 -0
- vibecore/tools/file/utils.py +78 -0
- vibecore/tools/python/__init__.py +1 -0
- vibecore/tools/python/backends/__init__.py +1 -0
- vibecore/tools/python/backends/terminal_backend.py +58 -0
- vibecore/tools/python/helpers.py +80 -0
- vibecore/tools/python/manager.py +208 -0
- vibecore/tools/python/tools.py +27 -0
- vibecore/tools/shell/__init__.py +5 -0
- vibecore/tools/shell/executor.py +223 -0
- vibecore/tools/shell/tools.py +156 -0
- vibecore/tools/task/__init__.py +5 -0
- vibecore/tools/task/executor.py +51 -0
- vibecore/tools/task/tools.py +51 -0
- vibecore/tools/todo/__init__.py +1 -0
- vibecore/tools/todo/manager.py +31 -0
- vibecore/tools/todo/models.py +36 -0
- vibecore/tools/todo/tools.py +111 -0
- vibecore/utils/__init__.py +5 -0
- vibecore/utils/text.py +28 -0
- vibecore/widgets/core.py +332 -0
- vibecore/widgets/core.tcss +63 -0
- vibecore/widgets/expandable.py +121 -0
- vibecore/widgets/expandable.tcss +69 -0
- vibecore/widgets/info.py +25 -0
- vibecore/widgets/info.tcss +17 -0
- vibecore/widgets/messages.py +232 -0
- vibecore/widgets/messages.tcss +85 -0
- vibecore/widgets/tool_message_factory.py +121 -0
- vibecore/widgets/tool_messages.py +483 -0
- vibecore/widgets/tool_messages.tcss +289 -0
- vibecore-0.2.0.dist-info/METADATA +407 -0
- vibecore-0.2.0.dist-info/RECORD +63 -0
- vibecore-0.2.0.dist-info/WHEEL +4 -0
- vibecore-0.2.0.dist-info/entry_points.txt +2 -0
- vibecore-0.2.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""Shell and system tools for Vibecore agents."""
|
|
2
|
+
|
|
3
|
+
from agents import RunContextWrapper, function_tool
|
|
4
|
+
|
|
5
|
+
from vibecore.context import VibecoreContext
|
|
6
|
+
|
|
7
|
+
from .executor import bash_executor, glob_files, grep_files, list_directory
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@function_tool
|
|
11
|
+
async def bash(
|
|
12
|
+
ctx: RunContextWrapper[VibecoreContext],
|
|
13
|
+
command: str,
|
|
14
|
+
timeout: int | None = None,
|
|
15
|
+
description: str | None = None,
|
|
16
|
+
) -> str:
|
|
17
|
+
"""Executes a given bash command in a persistent shell session with optional timeout, ensuring proper handling
|
|
18
|
+
and security measures.
|
|
19
|
+
|
|
20
|
+
Before executing the command, please follow these steps:
|
|
21
|
+
|
|
22
|
+
1. Directory Verification:
|
|
23
|
+
- If the command will create new directories or files, first use the LS tool to verify the parent directory
|
|
24
|
+
exists and is the correct location
|
|
25
|
+
- For example, before running "mkdir foo/bar", first use LS to check that "foo" exists and is the intended
|
|
26
|
+
parent directory
|
|
27
|
+
|
|
28
|
+
2. Command Execution:
|
|
29
|
+
- Always quote file paths that contain spaces with double quotes (e.g., cd "path with spaces/file.txt")
|
|
30
|
+
- Examples of proper quoting:
|
|
31
|
+
- cd "/Users/name/My Documents" (correct)
|
|
32
|
+
- cd /Users/name/My Documents (incorrect - will fail)
|
|
33
|
+
- python "/path/with spaces/script.py" (correct)
|
|
34
|
+
- python /path/with spaces/script.py (incorrect - will fail)
|
|
35
|
+
- After ensuring proper quoting, execute the command.
|
|
36
|
+
- Capture the output of the command.
|
|
37
|
+
|
|
38
|
+
Usage notes:
|
|
39
|
+
- The command argument is required.
|
|
40
|
+
- You can specify an optional timeout in milliseconds (up to 600000ms / 10 minutes). If not specified, commands
|
|
41
|
+
will timeout after 120000ms (2 minutes).
|
|
42
|
+
- It is very helpful if you write a clear, concise description of what this command does in 5-10 words.
|
|
43
|
+
- If the output exceeds 30000 characters, output will be truncated before being returned to you.
|
|
44
|
+
- VERY IMPORTANT: You MUST avoid using search commands like `find` and `grep`. Instead use Grep, Glob, or Task
|
|
45
|
+
to search. You MUST avoid read tools like `cat`, `head`, `tail`, and `ls`, and use Read and LS to read files.
|
|
46
|
+
- If you _still_ need to run `grep`, STOP. ALWAYS USE ripgrep at `rg` first, which all users have pre-installed.
|
|
47
|
+
- When issuing multiple commands, use the ';' or '&&' operator to separate them. DO NOT use newlines (newlines
|
|
48
|
+
are ok in quoted strings).
|
|
49
|
+
- Try to maintain your current working directory throughout the session by using absolute paths and avoiding
|
|
50
|
+
usage of `cd`. You may use `cd` if the User explicitly requests it.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
ctx: The run context wrapper
|
|
54
|
+
command: The command to execute
|
|
55
|
+
timeout: Optional timeout in milliseconds (max 600000)
|
|
56
|
+
description: Clear, concise description of what this command does in 5-10 words
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
The command output or error message
|
|
60
|
+
"""
|
|
61
|
+
output, exit_code = await bash_executor(command, timeout)
|
|
62
|
+
if exit_code != 0:
|
|
63
|
+
return f"{output}\nExit code: {exit_code}"
|
|
64
|
+
return output
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@function_tool
|
|
68
|
+
async def glob(
|
|
69
|
+
ctx: RunContextWrapper[VibecoreContext],
|
|
70
|
+
pattern: str,
|
|
71
|
+
path: str | None = None,
|
|
72
|
+
) -> str:
|
|
73
|
+
"""Fast file pattern matching tool that works with any codebase size.
|
|
74
|
+
|
|
75
|
+
- Supports glob patterns like "**/*.js" or "src/**/*.ts"
|
|
76
|
+
- Returns matching file paths sorted by modification time
|
|
77
|
+
- Use this tool when you need to find files by name patterns
|
|
78
|
+
- When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the
|
|
79
|
+
Agent tool instead
|
|
80
|
+
- You have the capability to call multiple tools in a single response. It is always better to speculatively
|
|
81
|
+
perform multiple searches as a batch that are potentially useful.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
ctx: The run context wrapper
|
|
85
|
+
pattern: The glob pattern to match files against
|
|
86
|
+
path: The directory to search in. If not specified, the current working directory will be used.
|
|
87
|
+
IMPORTANT: Omit this field to use the default directory. DO NOT enter "undefined" or "null" -
|
|
88
|
+
simply omit it for the default behavior. Must be a valid directory path if provided.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
List of matching file paths, one per line
|
|
92
|
+
"""
|
|
93
|
+
files = await glob_files(pattern, path)
|
|
94
|
+
if files and files[0].startswith("Error:"):
|
|
95
|
+
return files[0]
|
|
96
|
+
return "\n".join(files) if files else "No files found matching pattern"
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@function_tool
|
|
100
|
+
async def grep(
|
|
101
|
+
ctx: RunContextWrapper[VibecoreContext],
|
|
102
|
+
pattern: str,
|
|
103
|
+
path: str | None = None,
|
|
104
|
+
include: str | None = None,
|
|
105
|
+
) -> str:
|
|
106
|
+
"""Fast content search tool that works with any codebase size.
|
|
107
|
+
|
|
108
|
+
- Searches file contents using regular expressions
|
|
109
|
+
- Supports full regex syntax (eg. "log.*Error", "function\\s+\\w+", etc.)
|
|
110
|
+
- Filter files by pattern with the include parameter (eg. "*.js", "*.{ts,tsx}")
|
|
111
|
+
- Returns file paths with at least one match sorted by modification time
|
|
112
|
+
- Use this tool when you need to find files containing specific patterns
|
|
113
|
+
- If you need to identify/count the number of matches within files, use the Bash tool with `rg` (ripgrep)
|
|
114
|
+
directly. Do NOT use `grep`.
|
|
115
|
+
- When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the
|
|
116
|
+
Agent tool instead
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
ctx: The run context wrapper
|
|
120
|
+
pattern: The regular expression pattern to search for in file contents
|
|
121
|
+
path: The directory to search in. Defaults to the current working directory.
|
|
122
|
+
include: File pattern to include in the search (e.g. "*.js", "*.{ts,tsx}")
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
List of file paths containing matches, one per line
|
|
126
|
+
"""
|
|
127
|
+
files = await grep_files(pattern, path, include)
|
|
128
|
+
if files and files[0].startswith("Error:"):
|
|
129
|
+
return files[0]
|
|
130
|
+
return "\n".join(files) if files else "No files found containing pattern"
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@function_tool
|
|
134
|
+
async def ls(
|
|
135
|
+
ctx: RunContextWrapper[VibecoreContext],
|
|
136
|
+
path: str,
|
|
137
|
+
ignore: list[str] | None = None,
|
|
138
|
+
) -> str:
|
|
139
|
+
"""Lists files and directories in a given path.
|
|
140
|
+
|
|
141
|
+
The path parameter must be an absolute path, not a relative path. You can optionally provide an array of glob
|
|
142
|
+
patterns to ignore with the ignore parameter. You should generally prefer the Glob and Grep tools, if you know
|
|
143
|
+
which directories to search.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
ctx: The run context wrapper
|
|
147
|
+
path: The absolute path to the directory to list (must be absolute, not relative)
|
|
148
|
+
ignore: List of glob patterns to ignore
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
List of entries in the directory, one per line
|
|
152
|
+
"""
|
|
153
|
+
entries = await list_directory(path, ignore)
|
|
154
|
+
if entries and entries[0].startswith("Error:"):
|
|
155
|
+
return entries[0]
|
|
156
|
+
return "\n".join(entries) if entries else "Empty directory"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Task execution logic for spawning sub-agents."""
|
|
2
|
+
|
|
3
|
+
import traceback
|
|
4
|
+
|
|
5
|
+
from agents import (
|
|
6
|
+
Runner,
|
|
7
|
+
)
|
|
8
|
+
from textual import log
|
|
9
|
+
|
|
10
|
+
from vibecore.agents.task_agent import create_task_agent
|
|
11
|
+
from vibecore.context import VibecoreContext
|
|
12
|
+
from vibecore.settings import settings
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def execute_task(
|
|
16
|
+
context: VibecoreContext,
|
|
17
|
+
description: str,
|
|
18
|
+
prompt: str,
|
|
19
|
+
tool_name: str,
|
|
20
|
+
tool_call_id: str,
|
|
21
|
+
) -> str:
|
|
22
|
+
"""Execute a task using a sub-agent with streaming support.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
context: The vibecore context to pass to the task agent
|
|
26
|
+
description: Short task description (for logging/display)
|
|
27
|
+
prompt: Full task instructions
|
|
28
|
+
tool_name: Name of the tool being invoked (e.g., "task")
|
|
29
|
+
tool_call_id: Unique identifier for this tool call
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Task execution results as a string with formatted sub-agent activity
|
|
33
|
+
"""
|
|
34
|
+
try:
|
|
35
|
+
# Create the task agent
|
|
36
|
+
task_agent = create_task_agent(prompt)
|
|
37
|
+
|
|
38
|
+
# Run the task agent with streaming
|
|
39
|
+
result = Runner.run_streamed(task_agent, prompt, context=context, max_turns=settings.max_turns)
|
|
40
|
+
|
|
41
|
+
# Check if app is available for streaming
|
|
42
|
+
if context.app:
|
|
43
|
+
# Stream events to app handler
|
|
44
|
+
async for event in result.stream_events():
|
|
45
|
+
await context.app.handle_task_tool_event(tool_name, tool_call_id, event)
|
|
46
|
+
|
|
47
|
+
return result.final_output
|
|
48
|
+
|
|
49
|
+
except Exception as e:
|
|
50
|
+
log.error(f"Task execution error: {type(e).__name__}: {e!s}\n%s", traceback.format_exc())
|
|
51
|
+
return f"Task '{description}' failed with error: {e!s}"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Task tool for spawning sub-agents to execute specific tasks."""
|
|
2
|
+
|
|
3
|
+
from agents import function_tool
|
|
4
|
+
from agents.tool_context import ToolContext
|
|
5
|
+
|
|
6
|
+
from vibecore.context import VibecoreContext
|
|
7
|
+
|
|
8
|
+
from .executor import execute_task
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@function_tool
|
|
12
|
+
async def task(
|
|
13
|
+
ctx: ToolContext[VibecoreContext],
|
|
14
|
+
description: str,
|
|
15
|
+
prompt: str,
|
|
16
|
+
) -> str:
|
|
17
|
+
"""Launch a new agent to execute a specific task with access to all tools except the Task tool itself.
|
|
18
|
+
|
|
19
|
+
The task agent has access to: bash, glob, grep, ls, read, edit, multi_edit, write, execute_python,
|
|
20
|
+
todo_read, and todo_write. Use this tool when you need to delegate complex, multi-step operations
|
|
21
|
+
or searches to a sub-agent.
|
|
22
|
+
|
|
23
|
+
When to use the Task tool:
|
|
24
|
+
- When searching for a keyword like "config" or "logger" across many files
|
|
25
|
+
- For questions like "which file does X?" where you're not sure of the location
|
|
26
|
+
- When you need to perform complex multi-step operations autonomously
|
|
27
|
+
- When the task requires extensive file exploration or analysis
|
|
28
|
+
|
|
29
|
+
When NOT to use the Task tool:
|
|
30
|
+
- If you want to read a specific file path (use Read instead)
|
|
31
|
+
- If searching for a specific class definition like "class Foo" (use Grep instead)
|
|
32
|
+
- If searching within a specific file or set of 2-3 files (use Read instead)
|
|
33
|
+
- For simple, single-step operations (use the appropriate tool directly)
|
|
34
|
+
|
|
35
|
+
Usage notes:
|
|
36
|
+
1. Launch multiple tasks concurrently when possible by using multiple tool calls
|
|
37
|
+
2. The task agent returns a single final message - you should summarize results for the user
|
|
38
|
+
3. Each task invocation is stateless - provide complete instructions in the prompt
|
|
39
|
+
4. Clearly specify whether the agent should write code or just research/analyze
|
|
40
|
+
5. The agent is not aware of the user's original request - be explicit in instructions
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
ctx: The run context wrapper
|
|
44
|
+
description: A short task description (3-5 words)
|
|
45
|
+
prompt: Full task instructions for the agent - be highly detailed and specify
|
|
46
|
+
exactly what information should be returned
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
The task execution results as a string
|
|
50
|
+
"""
|
|
51
|
+
return await execute_task(ctx.context, description, prompt, ctx.tool_name, ctx.tool_call_id)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Todo management tools."""
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Todo list manager."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from .models import TodoItem, TodoPriority, TodoStatus
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TodoManager:
|
|
9
|
+
"""Manages a session-scoped todo list."""
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
self.todos: list[TodoItem] = []
|
|
13
|
+
|
|
14
|
+
def read(self) -> list[dict[str, Any]]:
|
|
15
|
+
"""Read all todos."""
|
|
16
|
+
return [
|
|
17
|
+
{"id": todo.id, "content": todo.content, "status": todo.status.value, "priority": todo.priority.value}
|
|
18
|
+
for todo in self.todos
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
def write(self, todos: list[dict[str, Any]]) -> None:
|
|
22
|
+
"""Replace the entire todo list."""
|
|
23
|
+
self.todos = [
|
|
24
|
+
TodoItem(
|
|
25
|
+
id=todo["id"],
|
|
26
|
+
content=todo["content"],
|
|
27
|
+
status=TodoStatus(todo["status"]),
|
|
28
|
+
priority=TodoPriority(todo["priority"]),
|
|
29
|
+
)
|
|
30
|
+
for todo in todos
|
|
31
|
+
]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Todo data models."""
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from enum import Enum
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TodoStatus(str, Enum):
|
|
11
|
+
PENDING = "pending"
|
|
12
|
+
IN_PROGRESS = "in_progress"
|
|
13
|
+
COMPLETED = "completed"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TodoPriority(str, Enum):
|
|
17
|
+
HIGH = "high"
|
|
18
|
+
MEDIUM = "medium"
|
|
19
|
+
LOW = "low"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class TodoItem:
|
|
24
|
+
content: str
|
|
25
|
+
status: TodoStatus
|
|
26
|
+
priority: TodoPriority
|
|
27
|
+
id: str = field(default_factory=lambda: str(uuid.uuid4()))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TodoItemModel(BaseModel):
|
|
31
|
+
"""Pydantic model for todo items."""
|
|
32
|
+
|
|
33
|
+
id: str
|
|
34
|
+
content: str
|
|
35
|
+
status: str
|
|
36
|
+
priority: str
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""Todo management tools."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from agents import RunContextWrapper, function_tool
|
|
6
|
+
|
|
7
|
+
from vibecore.context import VibecoreContext
|
|
8
|
+
|
|
9
|
+
from .models import TodoItemModel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@function_tool
|
|
13
|
+
async def todo_read(ctx: RunContextWrapper[VibecoreContext]) -> list[dict[str, Any]]:
|
|
14
|
+
"""Use this tool to read the current to-do list for the session. This tool should be used proactively and
|
|
15
|
+
frequently to ensure that you are aware of the status of the current task list. You should make use of this
|
|
16
|
+
tool as often as possible, especially in the following situations:
|
|
17
|
+
- At the beginning of conversations to see what's pending
|
|
18
|
+
- Before starting new tasks to prioritize work
|
|
19
|
+
- When the user asks about previous tasks or plans
|
|
20
|
+
- Whenever you're uncertain about what to do next
|
|
21
|
+
- After completing tasks to update your understanding of remaining work
|
|
22
|
+
- After every few messages to ensure you're on track
|
|
23
|
+
|
|
24
|
+
Usage:
|
|
25
|
+
- This tool takes in no parameters. So leave the input blank or empty. DO NOT include a dummy object,
|
|
26
|
+
placeholder string or a key like "input" or "empty". LEAVE IT BLANK.
|
|
27
|
+
- Returns a list of todo items with their status, priority, and content
|
|
28
|
+
- Use this information to track progress and plan next steps
|
|
29
|
+
- If no todos exist yet, an empty list will be returned
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
ctx: The run context wrapper containing the todo manager.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
A list of todo items with their status, priority, and content.
|
|
36
|
+
"""
|
|
37
|
+
return ctx.context.todo_manager.read()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@function_tool
|
|
41
|
+
async def todo_write(ctx: RunContextWrapper[VibecoreContext], todos: list[TodoItemModel]) -> str:
|
|
42
|
+
"""Use this tool to create and manage a structured task list for your current coding session. This helps you
|
|
43
|
+
track progress, organize complex tasks, and demonstrate thoroughness to the user. It also helps the user
|
|
44
|
+
understand the progress of the task and overall progress of their requests.
|
|
45
|
+
|
|
46
|
+
## When to Use This Tool
|
|
47
|
+
Use this tool proactively in these scenarios:
|
|
48
|
+
|
|
49
|
+
1. Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
|
|
50
|
+
2. Non-trivial and complex tasks - Tasks that require careful planning or multiple operations
|
|
51
|
+
3. User explicitly requests todo list - When the user directly asks you to use the todo list
|
|
52
|
+
4. User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
|
|
53
|
+
5. After receiving new instructions - Immediately capture user requirements as todos
|
|
54
|
+
6. When you start working on a task - Mark it as in_progress BEFORE beginning work. Ideally you should only
|
|
55
|
+
have one todo as in_progress at a time
|
|
56
|
+
7. After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation
|
|
57
|
+
|
|
58
|
+
## When NOT to Use This Tool
|
|
59
|
+
|
|
60
|
+
Skip using this tool when:
|
|
61
|
+
1. There is only a single, straightforward task
|
|
62
|
+
2. The task is trivial and tracking it provides no organizational benefit
|
|
63
|
+
3. The task can be completed in less than 3 trivial steps
|
|
64
|
+
4. The task is purely conversational or informational
|
|
65
|
+
|
|
66
|
+
NOTE that you should not use this tool if there is only one trivial task to do. In this case you are
|
|
67
|
+
better off just doing the task directly.
|
|
68
|
+
|
|
69
|
+
## Task States and Management
|
|
70
|
+
|
|
71
|
+
1. **Task States**: Use these states to track progress:
|
|
72
|
+
- pending: Task not yet started
|
|
73
|
+
- in_progress: Currently working on (limit to ONE task at a time)
|
|
74
|
+
- completed: Task finished successfully
|
|
75
|
+
|
|
76
|
+
2. **Task Management**:
|
|
77
|
+
- Update task status in real-time as you work
|
|
78
|
+
- Mark tasks complete IMMEDIATELY after finishing (don't batch completions)
|
|
79
|
+
- Only have ONE task in_progress at any time
|
|
80
|
+
- Complete current tasks before starting new ones
|
|
81
|
+
- Remove tasks that are no longer relevant from the list entirely
|
|
82
|
+
|
|
83
|
+
3. **Task Completion Requirements**:
|
|
84
|
+
- ONLY mark a task as completed when you have FULLY accomplished it
|
|
85
|
+
- If you encounter errors, blockers, or cannot finish, keep the task as in_progress
|
|
86
|
+
- When blocked, create a new task describing what needs to be resolved
|
|
87
|
+
- Never mark a task as completed if:
|
|
88
|
+
- Tests are failing
|
|
89
|
+
- Implementation is partial
|
|
90
|
+
- You encountered unresolved errors
|
|
91
|
+
- You couldn't find necessary files or dependencies
|
|
92
|
+
|
|
93
|
+
4. **Task Breakdown**:
|
|
94
|
+
- Create specific, actionable items
|
|
95
|
+
- Break complex tasks into smaller, manageable steps
|
|
96
|
+
- Use clear, descriptive task names
|
|
97
|
+
|
|
98
|
+
When in doubt, use this tool. Being proactive with task management demonstrates attentiveness and ensures
|
|
99
|
+
you complete all requirements successfully.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
ctx: The run context wrapper containing the todo manager.
|
|
103
|
+
todos: The updated todo list.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
Success message.
|
|
107
|
+
"""
|
|
108
|
+
# Convert Pydantic models to dicts for the implementation
|
|
109
|
+
todos_dict = [todo.model_dump() for todo in todos]
|
|
110
|
+
ctx.context.todo_manager.write(todos_dict)
|
|
111
|
+
return "Todo list updated successfully."
|
vibecore/utils/text.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Text extraction utilities for vibecore."""
|
|
2
|
+
|
|
3
|
+
from openai.types.responses.response_output_message import Content
|
|
4
|
+
from openai.types.responses.response_output_refusal import ResponseOutputRefusal
|
|
5
|
+
from openai.types.responses.response_output_text import ResponseOutputText
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TextExtractor:
|
|
9
|
+
"""Utility class for extracting text from various content formats."""
|
|
10
|
+
|
|
11
|
+
@staticmethod
|
|
12
|
+
def extract_from_content(content: list[Content]) -> str:
|
|
13
|
+
"""Extract text from various content formats.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
content: List of content items from OpenAI response
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
Concatenated text from all text content items
|
|
20
|
+
"""
|
|
21
|
+
text_parts = []
|
|
22
|
+
for item in content:
|
|
23
|
+
match item:
|
|
24
|
+
case ResponseOutputText(text=text):
|
|
25
|
+
text_parts.append(text)
|
|
26
|
+
case ResponseOutputRefusal(refusal=text):
|
|
27
|
+
text_parts.append(text)
|
|
28
|
+
return "".join(text_parts)
|