omni-cortex 1.17.3__py3-none-any.whl → 1.17.4__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.
- omni_cortex/_bundled/dashboard/backend/main.py +2 -2
- omni_cortex/_bundled/dashboard/backend/test_database.py +301 -0
- omni_cortex/_bundled/dashboard/backend/tmpclaude-2dfa-cwd +1 -0
- omni_cortex/_bundled/dashboard/backend/tmpclaude-c460-cwd +1 -0
- omni_cortex/_bundled/dashboard/frontend/dist/assets/index-CQlQK3nE.js +551 -0
- omni_cortex/_bundled/dashboard/frontend/dist/assets/index-CmUNNfe4.css +1 -0
- omni_cortex/_bundled/dashboard/frontend/dist/index.html +14 -0
- omni_cortex/_bundled/hooks/user_prompt.py +113 -2
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/main.py +2 -2
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/user_prompt.py +113 -2
- {omni_cortex-1.17.3.dist-info → omni_cortex-1.17.4.dist-info}/METADATA +6 -1
- omni_cortex-1.17.4.dist-info/RECORD +53 -0
- omni_cortex/__init__.py +0 -3
- omni_cortex/categorization/__init__.py +0 -9
- omni_cortex/categorization/auto_tags.py +0 -166
- omni_cortex/categorization/auto_type.py +0 -165
- omni_cortex/config.py +0 -141
- omni_cortex/dashboard.py +0 -238
- omni_cortex/database/__init__.py +0 -24
- omni_cortex/database/connection.py +0 -137
- omni_cortex/database/migrations.py +0 -210
- omni_cortex/database/schema.py +0 -212
- omni_cortex/database/sync.py +0 -421
- omni_cortex/decay/__init__.py +0 -7
- omni_cortex/decay/importance.py +0 -147
- omni_cortex/embeddings/__init__.py +0 -35
- omni_cortex/embeddings/local.py +0 -442
- omni_cortex/models/__init__.py +0 -20
- omni_cortex/models/activity.py +0 -265
- omni_cortex/models/agent.py +0 -144
- omni_cortex/models/memory.py +0 -395
- omni_cortex/models/relationship.py +0 -206
- omni_cortex/models/session.py +0 -290
- omni_cortex/resources/__init__.py +0 -1
- omni_cortex/search/__init__.py +0 -22
- omni_cortex/search/hybrid.py +0 -197
- omni_cortex/search/keyword.py +0 -204
- omni_cortex/search/ranking.py +0 -127
- omni_cortex/search/semantic.py +0 -232
- omni_cortex/server.py +0 -360
- omni_cortex/setup.py +0 -284
- omni_cortex/tools/__init__.py +0 -13
- omni_cortex/tools/activities.py +0 -453
- omni_cortex/tools/memories.py +0 -536
- omni_cortex/tools/sessions.py +0 -311
- omni_cortex/tools/utilities.py +0 -477
- omni_cortex/utils/__init__.py +0 -13
- omni_cortex/utils/formatting.py +0 -282
- omni_cortex/utils/ids.py +0 -72
- omni_cortex/utils/timestamps.py +0 -129
- omni_cortex/utils/truncation.py +0 -111
- omni_cortex-1.17.3.dist-info/RECORD +0 -86
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/.env.example +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/backfill_summaries.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/chat_service.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/database.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/image_service.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/logging_config.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/models.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/project_config.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/project_scanner.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/prompt_security.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/pyproject.toml +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/security.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/uv.lock +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/dashboard/backend/websocket_manager.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/post_tool_use.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/pre_tool_use.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/session_utils.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/stop.py +0 -0
- {omni_cortex-1.17.3.data → omni_cortex-1.17.4.data}/data/share/omni-cortex/hooks/subagent_stop.py +0 -0
- {omni_cortex-1.17.3.dist-info → omni_cortex-1.17.4.dist-info}/WHEEL +0 -0
- {omni_cortex-1.17.3.dist-info → omni_cortex-1.17.4.dist-info}/entry_points.txt +0 -0
- {omni_cortex-1.17.3.dist-info → omni_cortex-1.17.4.dist-info}/licenses/LICENSE +0 -0
omni_cortex/tools/activities.py
DELETED
|
@@ -1,453 +0,0 @@
|
|
|
1
|
-
"""Activity logging tools for Omni Cortex MCP."""
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
from datetime import datetime, timezone, timedelta
|
|
5
|
-
from typing import Optional
|
|
6
|
-
from pydantic import BaseModel, Field, ConfigDict
|
|
7
|
-
|
|
8
|
-
from mcp.server.fastmcp import FastMCP
|
|
9
|
-
|
|
10
|
-
from ..database.connection import init_database
|
|
11
|
-
from ..config import get_project_path, get_session_id
|
|
12
|
-
from ..models.activity import Activity, ActivityCreate, create_activity, get_activities
|
|
13
|
-
from ..models.memory import list_memories
|
|
14
|
-
from ..utils.formatting import format_activity_markdown, format_timeline_markdown
|
|
15
|
-
from ..utils.timestamps import now_iso, parse_iso
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# === Input Models ===
|
|
20
|
-
|
|
21
|
-
class LogActivityInput(BaseModel):
|
|
22
|
-
"""Input for logging an activity."""
|
|
23
|
-
|
|
24
|
-
model_config = ConfigDict(str_strip_whitespace=True, validate_assignment=True)
|
|
25
|
-
|
|
26
|
-
event_type: str = Field(
|
|
27
|
-
..., description="Event type: pre_tool_use, post_tool_use, decision, observation"
|
|
28
|
-
)
|
|
29
|
-
tool_name: Optional[str] = Field(None, description="Tool name if applicable")
|
|
30
|
-
tool_input: Optional[str] = Field(None, description="Tool input (JSON string)")
|
|
31
|
-
tool_output: Optional[str] = Field(None, description="Tool output (JSON string)")
|
|
32
|
-
duration_ms: Optional[int] = Field(None, description="Duration in milliseconds", ge=0)
|
|
33
|
-
success: bool = Field(True, description="Whether the operation succeeded")
|
|
34
|
-
error_message: Optional[str] = Field(None, description="Error message if failed")
|
|
35
|
-
file_path: Optional[str] = Field(None, description="Relevant file path")
|
|
36
|
-
agent_id: Optional[str] = Field(None, description="Agent ID")
|
|
37
|
-
# Command analytics fields
|
|
38
|
-
command_name: Optional[str] = Field(None, description="Slash command name")
|
|
39
|
-
command_scope: Optional[str] = Field(None, description="'universal' or 'project'")
|
|
40
|
-
mcp_server: Optional[str] = Field(None, description="MCP server name")
|
|
41
|
-
skill_name: Optional[str] = Field(None, description="Skill name")
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class GetActivitiesInput(BaseModel):
|
|
45
|
-
"""Input for getting activities."""
|
|
46
|
-
|
|
47
|
-
model_config = ConfigDict(str_strip_whitespace=True, validate_assignment=True)
|
|
48
|
-
|
|
49
|
-
session_id: Optional[str] = Field(None, description="Filter by session ID")
|
|
50
|
-
agent_id: Optional[str] = Field(None, description="Filter by agent ID")
|
|
51
|
-
event_type: Optional[str] = Field(None, description="Filter by event type")
|
|
52
|
-
tool_name: Optional[str] = Field(None, description="Filter by tool name")
|
|
53
|
-
since: Optional[str] = Field(None, description="Start time (ISO 8601)")
|
|
54
|
-
until: Optional[str] = Field(None, description="End time (ISO 8601)")
|
|
55
|
-
limit: int = Field(50, description="Maximum results", ge=1, le=200)
|
|
56
|
-
offset: int = Field(0, description="Pagination offset", ge=0)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class TimelineInput(BaseModel):
|
|
60
|
-
"""Input for getting timeline."""
|
|
61
|
-
|
|
62
|
-
model_config = ConfigDict(str_strip_whitespace=True, validate_assignment=True)
|
|
63
|
-
|
|
64
|
-
hours: int = Field(24, description="Hours to look back", ge=1, le=168)
|
|
65
|
-
include_activities: bool = Field(True, description="Include activities")
|
|
66
|
-
include_memories: bool = Field(True, description="Include memories")
|
|
67
|
-
group_by: str = Field("hour", description="Group by: hour, day, or session")
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def register_activity_tools(mcp: FastMCP) -> None:
|
|
71
|
-
"""Register all activity tools with the MCP server."""
|
|
72
|
-
|
|
73
|
-
@mcp.tool(
|
|
74
|
-
name="cortex_log_activity",
|
|
75
|
-
annotations={
|
|
76
|
-
"title": "Log Activity",
|
|
77
|
-
"readOnlyHint": False,
|
|
78
|
-
"destructiveHint": False,
|
|
79
|
-
"idempotentHint": False,
|
|
80
|
-
"openWorldHint": False,
|
|
81
|
-
},
|
|
82
|
-
)
|
|
83
|
-
async def cortex_log_activity(params: LogActivityInput) -> str:
|
|
84
|
-
"""Log a tool call, decision, or observation.
|
|
85
|
-
|
|
86
|
-
This tool records activities in the audit trail. Most activity logging
|
|
87
|
-
is done automatically by hooks, but this tool allows manual logging.
|
|
88
|
-
|
|
89
|
-
Args:
|
|
90
|
-
params: LogActivityInput with event details
|
|
91
|
-
|
|
92
|
-
Returns:
|
|
93
|
-
Confirmation with activity ID
|
|
94
|
-
"""
|
|
95
|
-
try:
|
|
96
|
-
conn = init_database()
|
|
97
|
-
project_path = str(get_project_path())
|
|
98
|
-
session_id = get_session_id()
|
|
99
|
-
|
|
100
|
-
# Auto-detect command analytics if not provided
|
|
101
|
-
command_name = params.command_name
|
|
102
|
-
command_scope = params.command_scope
|
|
103
|
-
mcp_server = params.mcp_server
|
|
104
|
-
skill_name = params.skill_name
|
|
105
|
-
|
|
106
|
-
# Extract skill info from Skill tool calls
|
|
107
|
-
if params.tool_name == "Skill" and params.tool_input:
|
|
108
|
-
extracted_skill, extracted_scope = _extract_skill_info(
|
|
109
|
-
params.tool_input, project_path
|
|
110
|
-
)
|
|
111
|
-
if extracted_skill:
|
|
112
|
-
skill_name = skill_name or extracted_skill
|
|
113
|
-
command_scope = command_scope or extracted_scope
|
|
114
|
-
|
|
115
|
-
# Extract MCP server from tool name (mcp__servername__toolname pattern)
|
|
116
|
-
if params.tool_name and params.tool_name.startswith("mcp__"):
|
|
117
|
-
extracted_mcp = _extract_mcp_server(params.tool_name)
|
|
118
|
-
mcp_server = mcp_server or extracted_mcp
|
|
119
|
-
|
|
120
|
-
activity_data = ActivityCreate(
|
|
121
|
-
event_type=params.event_type,
|
|
122
|
-
tool_name=params.tool_name,
|
|
123
|
-
tool_input=params.tool_input,
|
|
124
|
-
tool_output=params.tool_output,
|
|
125
|
-
duration_ms=params.duration_ms,
|
|
126
|
-
success=params.success,
|
|
127
|
-
error_message=params.error_message,
|
|
128
|
-
file_path=params.file_path,
|
|
129
|
-
agent_id=params.agent_id,
|
|
130
|
-
command_name=command_name,
|
|
131
|
-
command_scope=command_scope,
|
|
132
|
-
mcp_server=mcp_server,
|
|
133
|
-
skill_name=skill_name,
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
activity = create_activity(
|
|
137
|
-
conn,
|
|
138
|
-
activity_data,
|
|
139
|
-
session_id=session_id,
|
|
140
|
-
project_path=project_path,
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
return (
|
|
144
|
-
f"Logged: {activity.id}\n"
|
|
145
|
-
f"Type: {activity.event_type}\n"
|
|
146
|
-
f"Tool: {activity.tool_name or 'N/A'}\n"
|
|
147
|
-
f"Success: {'Yes' if activity.success else 'No'}"
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
except Exception as e:
|
|
151
|
-
return f"Error logging activity: {e}"
|
|
152
|
-
|
|
153
|
-
@mcp.tool(
|
|
154
|
-
name="cortex_get_activities",
|
|
155
|
-
annotations={
|
|
156
|
-
"title": "Get Activities",
|
|
157
|
-
"readOnlyHint": True,
|
|
158
|
-
"destructiveHint": False,
|
|
159
|
-
"idempotentHint": True,
|
|
160
|
-
"openWorldHint": False,
|
|
161
|
-
},
|
|
162
|
-
)
|
|
163
|
-
async def cortex_get_activities(params: GetActivitiesInput) -> str:
|
|
164
|
-
"""Query the activity log with filters.
|
|
165
|
-
|
|
166
|
-
Args:
|
|
167
|
-
params: GetActivitiesInput with filters and pagination
|
|
168
|
-
|
|
169
|
-
Returns:
|
|
170
|
-
Activities formatted as markdown
|
|
171
|
-
"""
|
|
172
|
-
try:
|
|
173
|
-
conn = init_database()
|
|
174
|
-
|
|
175
|
-
activities, total = get_activities(
|
|
176
|
-
conn,
|
|
177
|
-
session_id=params.session_id,
|
|
178
|
-
agent_id=params.agent_id,
|
|
179
|
-
event_type=params.event_type,
|
|
180
|
-
tool_name=params.tool_name,
|
|
181
|
-
since=params.since,
|
|
182
|
-
until=params.until,
|
|
183
|
-
limit=params.limit,
|
|
184
|
-
offset=params.offset,
|
|
185
|
-
)
|
|
186
|
-
|
|
187
|
-
if not activities:
|
|
188
|
-
return "No activities found."
|
|
189
|
-
|
|
190
|
-
lines = [f"# Activities ({len(activities)} of {total})", ""]
|
|
191
|
-
|
|
192
|
-
for activity in activities:
|
|
193
|
-
lines.append(format_activity_markdown(activity.model_dump()))
|
|
194
|
-
lines.append("")
|
|
195
|
-
|
|
196
|
-
return "\n".join(lines)
|
|
197
|
-
|
|
198
|
-
except Exception as e:
|
|
199
|
-
return f"Error getting activities: {e}"
|
|
200
|
-
|
|
201
|
-
@mcp.tool(
|
|
202
|
-
name="cortex_get_timeline",
|
|
203
|
-
annotations={
|
|
204
|
-
"title": "Get Timeline",
|
|
205
|
-
"readOnlyHint": True,
|
|
206
|
-
"destructiveHint": False,
|
|
207
|
-
"idempotentHint": True,
|
|
208
|
-
"openWorldHint": False,
|
|
209
|
-
},
|
|
210
|
-
)
|
|
211
|
-
async def cortex_get_timeline(params: TimelineInput) -> str:
|
|
212
|
-
"""Get a timeline of activities and memories.
|
|
213
|
-
|
|
214
|
-
This provides a chronological view of what happened in the project
|
|
215
|
-
over the specified time period.
|
|
216
|
-
|
|
217
|
-
Args:
|
|
218
|
-
params: TimelineInput with time range and inclusion options
|
|
219
|
-
|
|
220
|
-
Returns:
|
|
221
|
-
Timeline formatted as markdown
|
|
222
|
-
"""
|
|
223
|
-
try:
|
|
224
|
-
conn = init_database()
|
|
225
|
-
|
|
226
|
-
# Calculate time range
|
|
227
|
-
now = datetime.now(timezone.utc)
|
|
228
|
-
since = (now - timedelta(hours=params.hours)).isoformat()
|
|
229
|
-
|
|
230
|
-
activities_list = []
|
|
231
|
-
memories_list = []
|
|
232
|
-
|
|
233
|
-
if params.include_activities:
|
|
234
|
-
activities_result, _ = get_activities(
|
|
235
|
-
conn,
|
|
236
|
-
since=since,
|
|
237
|
-
limit=100,
|
|
238
|
-
)
|
|
239
|
-
activities_list = [a.model_dump() for a in activities_result]
|
|
240
|
-
|
|
241
|
-
if params.include_memories:
|
|
242
|
-
memories_result, _ = list_memories(
|
|
243
|
-
conn,
|
|
244
|
-
sort_by="created_at",
|
|
245
|
-
sort_order="desc",
|
|
246
|
-
limit=50,
|
|
247
|
-
)
|
|
248
|
-
# Filter to time range
|
|
249
|
-
memories_list = [
|
|
250
|
-
m.model_dump()
|
|
251
|
-
for m in memories_result
|
|
252
|
-
if parse_iso(m.created_at) >= parse_iso(since)
|
|
253
|
-
]
|
|
254
|
-
|
|
255
|
-
return format_timeline_markdown(
|
|
256
|
-
activities_list,
|
|
257
|
-
memories_list,
|
|
258
|
-
group_by=params.group_by,
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
except Exception as e:
|
|
262
|
-
return f"Error getting timeline: {e}"
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
# === Helper Functions for Command Analytics ===
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
def _extract_skill_info(tool_input: str, project_path: str) -> tuple[Optional[str], Optional[str]]:
|
|
269
|
-
"""Extract skill name and scope from Skill tool input.
|
|
270
|
-
|
|
271
|
-
Args:
|
|
272
|
-
tool_input: JSON string of tool input
|
|
273
|
-
project_path: Current project path for scope detection
|
|
274
|
-
|
|
275
|
-
Returns:
|
|
276
|
-
Tuple of (skill_name, scope) where scope is 'universal' or 'project'
|
|
277
|
-
"""
|
|
278
|
-
try:
|
|
279
|
-
input_data = json.loads(tool_input)
|
|
280
|
-
skill_name = input_data.get("skill", "")
|
|
281
|
-
if not skill_name:
|
|
282
|
-
return None, None
|
|
283
|
-
|
|
284
|
-
# Determine scope by checking file locations
|
|
285
|
-
from pathlib import Path
|
|
286
|
-
|
|
287
|
-
# Check project-specific commands first
|
|
288
|
-
project_cmd = Path(project_path) / ".claude" / "commands" / f"{skill_name}.md"
|
|
289
|
-
if project_cmd.exists():
|
|
290
|
-
return skill_name, "project"
|
|
291
|
-
|
|
292
|
-
# Check universal commands
|
|
293
|
-
universal_cmd = Path.home() / ".claude" / "commands" / f"{skill_name}.md"
|
|
294
|
-
if universal_cmd.exists():
|
|
295
|
-
return skill_name, "universal"
|
|
296
|
-
|
|
297
|
-
# Default to unknown scope if skill exists but location is unclear
|
|
298
|
-
return skill_name, "unknown"
|
|
299
|
-
|
|
300
|
-
except (json.JSONDecodeError, TypeError, KeyError):
|
|
301
|
-
return None, None
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
def _extract_mcp_server(tool_name: str) -> Optional[str]:
|
|
305
|
-
"""Extract MCP server name from tool name.
|
|
306
|
-
|
|
307
|
-
Tool names follow the pattern: mcp__servername__toolname
|
|
308
|
-
|
|
309
|
-
Args:
|
|
310
|
-
tool_name: Full tool name
|
|
311
|
-
|
|
312
|
-
Returns:
|
|
313
|
-
MCP server name or None
|
|
314
|
-
"""
|
|
315
|
-
if not tool_name or not tool_name.startswith("mcp__"):
|
|
316
|
-
return None
|
|
317
|
-
|
|
318
|
-
parts = tool_name.split("__")
|
|
319
|
-
if len(parts) >= 3:
|
|
320
|
-
return parts[1] # Server name is the second part
|
|
321
|
-
|
|
322
|
-
return None
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
# === Natural Language Summary Generation ===
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
def generate_activity_summary(
|
|
329
|
-
tool_name: Optional[str],
|
|
330
|
-
tool_input: Optional[str],
|
|
331
|
-
success: bool,
|
|
332
|
-
file_path: Optional[str],
|
|
333
|
-
event_type: str,
|
|
334
|
-
) -> tuple[str, str]:
|
|
335
|
-
"""Generate natural language summary for an activity.
|
|
336
|
-
|
|
337
|
-
Returns:
|
|
338
|
-
tuple of (short_summary, detailed_summary)
|
|
339
|
-
- short_summary: 12-20 words, shown in collapsed view
|
|
340
|
-
- detailed_summary: Expanded description with more context
|
|
341
|
-
"""
|
|
342
|
-
short = ""
|
|
343
|
-
detail = ""
|
|
344
|
-
|
|
345
|
-
# Parse tool input if available
|
|
346
|
-
input_data = {}
|
|
347
|
-
if tool_input:
|
|
348
|
-
try:
|
|
349
|
-
input_data = json.loads(tool_input)
|
|
350
|
-
except (json.JSONDecodeError, TypeError):
|
|
351
|
-
pass
|
|
352
|
-
|
|
353
|
-
# Generate summaries based on tool type
|
|
354
|
-
if tool_name == "Read":
|
|
355
|
-
path = input_data.get("file_path", file_path or "unknown file")
|
|
356
|
-
filename = Path(path).name if path else "file"
|
|
357
|
-
short = f"Read file: {filename}"
|
|
358
|
-
detail = f"Reading contents of {path}"
|
|
359
|
-
|
|
360
|
-
elif tool_name == "Write":
|
|
361
|
-
path = input_data.get("file_path", file_path or "unknown file")
|
|
362
|
-
filename = Path(path).name if path else "file"
|
|
363
|
-
short = f"Write file: {filename}"
|
|
364
|
-
detail = f"Writing/creating file at {path}"
|
|
365
|
-
|
|
366
|
-
elif tool_name == "Edit":
|
|
367
|
-
path = input_data.get("file_path", file_path or "unknown file")
|
|
368
|
-
filename = Path(path).name if path else "file"
|
|
369
|
-
short = f"Edit file: {filename}"
|
|
370
|
-
detail = f"Editing {path} - replacing text content"
|
|
371
|
-
|
|
372
|
-
elif tool_name == "Bash":
|
|
373
|
-
cmd = input_data.get("command", "")[:50]
|
|
374
|
-
short = f"Run command: {cmd}..."
|
|
375
|
-
detail = f"Executing bash command: {input_data.get('command', 'unknown')}"
|
|
376
|
-
|
|
377
|
-
elif tool_name == "Grep":
|
|
378
|
-
pattern = input_data.get("pattern", "")
|
|
379
|
-
short = f"Search for: {pattern[:30]}"
|
|
380
|
-
detail = f"Searching codebase for pattern: {pattern}"
|
|
381
|
-
|
|
382
|
-
elif tool_name == "Glob":
|
|
383
|
-
pattern = input_data.get("pattern", "")
|
|
384
|
-
short = f"Find files: {pattern[:30]}"
|
|
385
|
-
detail = f"Finding files matching pattern: {pattern}"
|
|
386
|
-
|
|
387
|
-
elif tool_name == "Skill":
|
|
388
|
-
skill = input_data.get("skill", "unknown")
|
|
389
|
-
short = f"Run skill: /{skill}"
|
|
390
|
-
detail = f"Executing slash command /{skill}"
|
|
391
|
-
|
|
392
|
-
elif tool_name == "Task":
|
|
393
|
-
desc = input_data.get("description", "task")
|
|
394
|
-
short = f"Spawn agent: {desc[:30]}"
|
|
395
|
-
detail = f"Launching sub-agent for: {input_data.get('prompt', desc)[:100]}"
|
|
396
|
-
|
|
397
|
-
elif tool_name == "WebSearch":
|
|
398
|
-
query = input_data.get("query", "")
|
|
399
|
-
short = f"Web search: {query[:30]}"
|
|
400
|
-
detail = f"Searching the web for: {query}"
|
|
401
|
-
|
|
402
|
-
elif tool_name == "WebFetch":
|
|
403
|
-
url = input_data.get("url", "")
|
|
404
|
-
short = f"Fetch URL: {url[:40]}"
|
|
405
|
-
detail = f"Fetching content from: {url}"
|
|
406
|
-
|
|
407
|
-
elif tool_name == "TodoWrite":
|
|
408
|
-
todos = input_data.get("todos", [])
|
|
409
|
-
count = len(todos) if isinstance(todos, list) else 0
|
|
410
|
-
short = f"Update todo list: {count} items"
|
|
411
|
-
detail = f"Managing task list with {count} items"
|
|
412
|
-
|
|
413
|
-
elif tool_name == "AskUserQuestion":
|
|
414
|
-
questions = input_data.get("questions", [])
|
|
415
|
-
count = len(questions) if isinstance(questions, list) else 1
|
|
416
|
-
short = f"Ask user: {count} question(s)"
|
|
417
|
-
detail = f"Prompting user for input with {count} question(s)"
|
|
418
|
-
|
|
419
|
-
elif tool_name and tool_name.startswith("mcp__"):
|
|
420
|
-
parts = tool_name.split("__")
|
|
421
|
-
server = parts[1] if len(parts) > 1 else "unknown"
|
|
422
|
-
tool = parts[2] if len(parts) > 2 else tool_name
|
|
423
|
-
short = f"MCP call: {server}/{tool}"
|
|
424
|
-
detail = f"Calling {tool} tool from MCP server {server}"
|
|
425
|
-
|
|
426
|
-
elif tool_name == "cortex_remember" or (tool_name and "remember" in tool_name.lower()):
|
|
427
|
-
params = input_data.get("params", {})
|
|
428
|
-
content = params.get("content", "") if isinstance(params, dict) else ""
|
|
429
|
-
short = f"Store memory: {content[:30]}..." if content else "Store memory"
|
|
430
|
-
detail = f"Saving to memory system: {content[:100]}" if content else "Saving to memory system"
|
|
431
|
-
|
|
432
|
-
elif tool_name == "cortex_recall" or (tool_name and "recall" in tool_name.lower()):
|
|
433
|
-
params = input_data.get("params", {})
|
|
434
|
-
query = params.get("query", "") if isinstance(params, dict) else ""
|
|
435
|
-
short = f"Recall: {query[:30]}" if query else "Recall memories"
|
|
436
|
-
detail = f"Searching memories for: {query}" if query else "Retrieving memories"
|
|
437
|
-
|
|
438
|
-
elif tool_name == "NotebookEdit":
|
|
439
|
-
path = input_data.get("notebook_path", "")
|
|
440
|
-
filename = Path(path).name if path else "notebook"
|
|
441
|
-
short = f"Edit notebook: {filename}"
|
|
442
|
-
detail = f"Editing Jupyter notebook {path}"
|
|
443
|
-
|
|
444
|
-
else:
|
|
445
|
-
short = f"{event_type}: {tool_name or 'unknown'}"
|
|
446
|
-
detail = f"Activity type {event_type} with tool {tool_name}"
|
|
447
|
-
|
|
448
|
-
# Add status suffix for failures
|
|
449
|
-
if not success:
|
|
450
|
-
short = f"[FAILED] {short}"
|
|
451
|
-
detail = f"[FAILED] {detail}"
|
|
452
|
-
|
|
453
|
-
return short, detail
|