|
29 | 29 | TOOL_CALL_PROMPT_SKILLS_LIKE_MODE, |
30 | 30 | ) |
31 | 31 | from astrbot.core.conversation_mgr import Conversation |
| 32 | +from astrbot.core.db import BaseDatabase |
32 | 33 | from astrbot.core.message.components import File, Image, Record, Reply, Video |
33 | 34 | from astrbot.core.persona_error_reply import ( |
34 | 35 | extract_persona_custom_error_message_from_persona, |
|
73 | 74 | RollbackSkillReleaseTool, |
74 | 75 | RunBrowserSkillTool, |
75 | 76 | SyncSkillReleaseTool, |
76 | | - normalize_umo_for_workspace, |
77 | 77 | ) |
78 | 78 | from astrbot.core.tools.cron_tools import FutureTaskTool |
79 | 79 | from astrbot.core.tools.knowledge_base_tools import ( |
|
115 | 115 | extract_quoted_message_text, |
116 | 116 | ) |
117 | 117 | from astrbot.core.utils.string_utils import normalize_and_dedupe_strings |
| 118 | +from astrbot.core.workspace import ( |
| 119 | + normalize_umo_for_workspace, |
| 120 | + resolve_workspace_root_for_umo, |
| 121 | +) |
118 | 122 |
|
119 | 123 | LLM_ERROR_MESSAGE_EXTRA_KEY = "_llm_error_message" |
120 | 124 | WEEKDAY_NAMES = ( |
@@ -357,41 +361,63 @@ def _apply_prompt_prefix(req: ProviderRequest, cfg: dict) -> None: |
357 | 361 | req.prompt = f"{prefix}{req.prompt}" |
358 | 362 |
|
359 | 363 |
|
360 | | -def _get_workspace_path_for_umo(umo: str) -> Path: |
361 | | - normalized_umo = normalize_umo_for_workspace(umo) |
362 | | - return Path(get_astrbot_workspaces_path()) / normalized_umo |
| 364 | +async def _get_workspace_path_for_umo(umo: str, plugin_context: Context) -> Path: |
| 365 | + """Resolve the workspace path for the current request. |
| 366 | +
|
| 367 | + Args: |
| 368 | + umo: Unified message origin. |
| 369 | + plugin_context: Star context containing the database instance. |
| 370 | +
|
| 371 | + Returns: |
| 372 | + Workspace path used as cwd. |
| 373 | + """ |
| 374 | + fallback_root = ( |
| 375 | + Path(get_astrbot_workspaces_path()) / normalize_umo_for_workspace(umo) |
| 376 | + ).resolve(strict=False) |
| 377 | + db = getattr(plugin_context, "_db", None) |
| 378 | + if not isinstance(db, BaseDatabase): |
| 379 | + return fallback_root |
| 380 | + try: |
| 381 | + return await resolve_workspace_root_for_umo(umo, db) |
| 382 | + except Exception: |
| 383 | + return fallback_root |
363 | 384 |
|
364 | 385 |
|
365 | | -def _apply_workspace_extra_prompt( |
| 386 | +async def _apply_workspace_extra_prompt( |
366 | 387 | event: AstrMessageEvent, |
367 | 388 | req: ProviderRequest, |
| 389 | + plugin_context: Context, |
368 | 390 | ) -> None: |
369 | | - extra_prompt_path = _get_workspace_path_for_umo(event.unified_msg_origin) / ( |
370 | | - "EXTRA_PROMPT.md" |
| 391 | + workspace_root = await _get_workspace_path_for_umo( |
| 392 | + event.unified_msg_origin, |
| 393 | + plugin_context, |
371 | 394 | ) |
372 | | - if not extra_prompt_path.is_file(): |
373 | | - return |
374 | | - |
375 | | - try: |
376 | | - extra_prompt = extra_prompt_path.read_text(encoding="utf-8").strip() |
377 | | - except Exception as exc: # noqa: BLE001 |
378 | | - logger.warning( |
379 | | - "Failed to read workspace extra prompt for umo=%s from %s: %s", |
380 | | - event.unified_msg_origin, |
381 | | - extra_prompt_path, |
382 | | - exc, |
383 | | - ) |
384 | | - return |
| 395 | + extra_prompts: list[str] = [] |
| 396 | + extra_prompt_path = workspace_root / "EXTRA_PROMPT.md" |
| 397 | + if extra_prompt_path.is_file(): |
| 398 | + try: |
| 399 | + extra_prompt = extra_prompt_path.read_text(encoding="utf-8").strip() |
| 400 | + except Exception as exc: # noqa: BLE001 |
| 401 | + logger.warning( |
| 402 | + "Failed to read workspace extra prompt for umo=%s from %s: %s", |
| 403 | + event.unified_msg_origin, |
| 404 | + extra_prompt_path, |
| 405 | + exc, |
| 406 | + ) |
| 407 | + else: |
| 408 | + if extra_prompt: |
| 409 | + extra_prompts.append(f"From `{extra_prompt_path}`:\n{extra_prompt}") |
385 | 410 |
|
386 | | - if not extra_prompt: |
| 411 | + if not extra_prompts: |
387 | 412 | return |
388 | 413 |
|
| 414 | + extra_prompt_text = "\n\n".join(extra_prompts) |
389 | 415 | req.system_prompt = ( |
390 | 416 | f"{req.system_prompt or ''}\n" |
391 | 417 | "[Workspace Extra Prompt]\n" |
392 | 418 | "The following instructions are loaded from the current workspace " |
393 | 419 | "`EXTRA_PROMPT.md` file.\n" |
394 | | - f"{extra_prompt}\n" |
| 420 | + f"{extra_prompt_text}\n" |
395 | 421 | ) |
396 | 422 |
|
397 | 423 |
|
@@ -498,13 +524,13 @@ async def _ensure_persona_and_skills( |
498 | 524 | skill_manager = SkillManager() |
499 | 525 | skills = skill_manager.list_skills(active_only=True, runtime=runtime) |
500 | 526 | skills = _filter_skills_for_current_config(skills, cfg) |
501 | | - workspace_skills = ( |
502 | | - skill_manager.list_workspace_skills( |
503 | | - _get_workspace_path_for_umo(event.unified_msg_origin) |
| 527 | + workspace_skills: list[SkillInfo] = [] |
| 528 | + if runtime == "local": |
| 529 | + workspace_root = await _get_workspace_path_for_umo( |
| 530 | + event.unified_msg_origin, |
| 531 | + plugin_context, |
504 | 532 | ) |
505 | | - if runtime == "local" |
506 | | - else [] |
507 | | - ) |
| 533 | + workspace_skills.extend(skill_manager.list_workspace_skills(workspace_root)) |
508 | 534 |
|
509 | 535 | if skills or workspace_skills: |
510 | 536 | if persona and persona.get("skills") is not None: |
@@ -989,7 +1015,7 @@ async def _decorate_llm_request( |
989 | 1015 | if tz is None: |
990 | 1016 | tz = plugin_context.get_config().get("timezone") |
991 | 1017 | _append_system_reminders(event, req, cfg, tz) |
992 | | - _apply_workspace_extra_prompt(event, req) |
| 1018 | + await _apply_workspace_extra_prompt(event, req, plugin_context) |
993 | 1019 |
|
994 | 1020 |
|
995 | 1021 | def _plugin_tool_fix(event: AstrMessageEvent, req: ProviderRequest) -> None: |
@@ -1590,10 +1616,14 @@ async def build_main_agent( |
1590 | 1616 | ) |
1591 | 1617 |
|
1592 | 1618 | if config.computer_use_runtime == "local": |
| 1619 | + workspace_root = await _get_workspace_path_for_umo( |
| 1620 | + event.unified_msg_origin, |
| 1621 | + plugin_context, |
| 1622 | + ) |
| 1623 | + workspace_prompt = f"\nCurrent workspace you can use: `{workspace_root}`\n" |
1593 | 1624 | tool_prompt += ( |
1594 | | - f"\nCurrent workspace you can use: " |
1595 | | - f"`{_get_workspace_path_for_umo(event.unified_msg_origin)}`\n" |
1596 | | - "Unless the user explicitly specifies a different directory, " |
| 1625 | + workspace_prompt |
| 1626 | + + "Unless the user explicitly specifies a different directory, " |
1597 | 1627 | "perform all file-related operations in this workspace.\n" |
1598 | 1628 | ) |
1599 | 1629 |
|
|
0 commit comments