Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src-frontend/src/api/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export {
useGetWorkspaceSuspense,
useGetWorkspacesSuspenseInfinite,
useUpdateWorkspace,
useUpdateWorkspaceNotes,
openWorkspace,
} from "./generated/endpoints/workspace/workspace";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { TABS_WORKSPACE_NAMESPACE } from "@/i18n/resources";
import type { WorkspaceRead } from "@/api/generated/schemas";
import { invalidateWorkspaceQueries, useUpdateWorkspace } from "@/api/workspace";
import { invalidateWorkspaceQueries, useUpdateWorkspaceNotes } from "@/api/workspace";
import { FormShell, FormShellFooter } from "@/components/custom/form/FormShell";
import { Button } from "@/components/ui/button";
import { useWorkspaceStore } from "@/stores/workspace-store";
Expand All @@ -29,7 +29,7 @@ export function WorkspaceNotesEditForm({ workspace, onConfirm }: WorkspaceNotesE
[workspace.notes]
);

const updateMutation = useUpdateWorkspace({
const updateNotesMutation = useUpdateWorkspaceNotes({
mutation: {
async onSuccess(updatedWorkspace: { id: number; name: string }) {
await invalidateWorkspaceQueries(updatedWorkspace.id);
Expand All @@ -47,7 +47,7 @@ export function WorkspaceNotesEditForm({ workspace, onConfirm }: WorkspaceNotesE

const handleSubmit = (data: WorkspaceNotesEditFormValues) => {
const payload = notesEditFormValuesToPayload(data);
updateMutation.mutate({ workspaceId: workspace.id, data: payload });
updateNotesMutation.mutate({ workspaceId: workspace.id, data: payload });
};

return (
Expand All @@ -59,8 +59,8 @@ export function WorkspaceNotesEditForm({ workspace, onConfirm }: WorkspaceNotesE
<WorkspaceNoteField labelClassName="hidden" />

<FormShellFooter>
<Button type="submit" disabled={updateMutation.isPending}>
{updateMutation.isPending ? t("form.submit.saving") : t("form.submit.save")}
<Button type="submit" disabled={updateNotesMutation.isPending}>
{updateNotesMutation.isPending ? t("form.submit.saving") : t("form.submit.save")}
</Button>
</FormShellFooter>
</FormShell>
Expand Down
15 changes: 3 additions & 12 deletions src-frontend/src/features/Tabs/WorkspacePanel/form-types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {
WorkspaceCreate,
WorkspaceNotesUpdate,
WorkspaceRead,
WorkspaceUpdate,
} from "@/api/generated/schemas";
Expand Down Expand Up @@ -52,23 +53,13 @@ export function createFormValuesToPayload(
export function editFormValuesToPayload(
values: WorkspaceEditFormValues,
): WorkspaceUpdate {
return {
...values,
notes: null, // explicitly exclude `notes`
};
return values;
}

export function notesEditFormValuesToPayload(
values: WorkspaceNotesEditFormValues,
): WorkspaceUpdate {
): WorkspaceNotesUpdate {
return {
name: null,
directory: null,
instruction: null,
usable_agent_ids: null,
usable_tool_ids: null,
usable_skill_ids: null,
notes: arboristDataToResources(values.notes),
};
}

3 changes: 2 additions & 1 deletion src-frontend/src/i18n/locales/en/error.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
"TOOLSET_INTERNAL_KEY_ALREADY_EXISTS": "This toolset already exists.",
"TOOLSET_NOT_FOUND": "The toolset was not found.",
"UNEXPECTED_ERROR": "Something went wrong. Please try again.",
"WORKSPACE_NOT_FOUND": "The workspace was not found."
"WORKSPACE_NOT_FOUND": "The workspace was not found.",
"WORKSPACE_NOTES_LOCKED_BY_RUNNING_TASK": "Workspace notes cannot be updated while a task in this workspace is running. Please try again after the task finishes."
}
3 changes: 2 additions & 1 deletion src-frontend/src/i18n/locales/zh_CN/error.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
"TOOLSET_INTERNAL_KEY_ALREADY_EXISTS": "该工具集已存在。",
"TOOLSET_NOT_FOUND": "未找到该工具集。",
"UNEXPECTED_ERROR": "发生错误,请稍后重试。",
"WORKSPACE_NOT_FOUND": "未找到该工作区。"
"WORKSPACE_NOT_FOUND": "未找到该工作区。",
"WORKSPACE_NOTES_LOCKED_BY_RUNNING_TASK": "当前工作区下有任务正在运行,暂时无法更新工作区笔记,请在任务结束后重试。"
}
39 changes: 11 additions & 28 deletions src-server/src/agent/context/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
from .aliases import BuiltInToolAliases
from .models import ToolRuntimeContext, AgentContextResource, AgentContextPersistence

__all__ = [
"AgentContext",
"ToolRuntimeContext",
]

import platform
import xml.etree.ElementTree as ET
from collections import namedtuple
Expand All @@ -14,7 +6,6 @@
from loguru import logger
from dais_sdk.tool import Toolset
from dais_sdk.types import Message, ToolDef
from src.agent.notes import NoteManager
from src.db import db_context
from src.schemas import (
agent as agent_schemas,
Expand All @@ -29,7 +20,10 @@
from src.services.provider import ProviderService
from src.settings import use_app_setting_manager
from .persistence import create_agent_context_persistence
from ..tool import use_mcp_toolset_manager, BuiltinToolsetManager, McpToolsetManager, BuiltInToolset
from .aliases import BuiltInToolAliases
from .models import AgentContextResource, AgentContextPersistence
from ..notes import NoteMaterializer
from ..tool import use_mcp_toolset_manager, BuiltinToolsetManager, McpToolsetManager
from ..prompts import (
BASE_INSTRUCTION,
FAILED_TO_LOAD_NOTES_INDEX,
Expand All @@ -49,7 +43,7 @@ def __init__(self,
*,
messages: list[Message],
resource: AgentContextResource,
tool_context: ToolRuntimeContext,
usage: ContextUsage,
persistence: AgentContextPersistence,
builtin_toolset_manager: BuiltinToolsetManager,
mcp_toolset_manager: McpToolsetManager):
Expand All @@ -58,7 +52,7 @@ def __init__(self,
self._resource = resource
self._messages = messages

self._tool_context = tool_context
self._usage = usage
self._persistence = persistence
self._builtin_toolset_manager = builtin_toolset_manager
self._mcp_toolset_manager = mcp_toolset_manager
Expand All @@ -82,12 +76,7 @@ async def create(cls, task: task_runtime_schemas.TaskRuntimeContext) -> Self:
usage = ContextUsage(**asdict(usage))
messages = task.messages

note_manager = NoteManager(task.workspace_id)
await note_manager.materialize()
await note_manager.start_watching()

tool_context = ToolRuntimeContext(usage=usage, note_manager=note_manager)
builtin_toolset_manager = await BuiltinToolsetManager.create(workspace.id, workspace.directory, tool_context)
builtin_toolset_manager = await BuiltinToolsetManager.create(workspace.id, workspace.directory)
mcp_toolset_manager = use_mcp_toolset_manager()

persistence = create_agent_context_persistence(task)
Expand All @@ -101,7 +90,7 @@ async def create(cls, task: task_runtime_schemas.TaskRuntimeContext) -> Self:
model=provider_schemas.LlmModelRead.model_validate(model),
skills=[skill_schemas.SkillBrief.model_validate(skill) for skill in skills],
),
tool_context=tool_context,
usage=usage,
persistence=persistence,
builtin_toolset_manager=builtin_toolset_manager,
mcp_toolset_manager=mcp_toolset_manager)
Expand Down Expand Up @@ -131,7 +120,7 @@ def _resolve_instructions(self) -> ResolvedInstructions:

@property
def usage(self) -> ContextUsage:
return self._tool_context.usage
return self._usage

@property
def toolsets(self) -> list[Toolset]:
Expand Down Expand Up @@ -171,7 +160,7 @@ async def compose_system_instruction(self) -> str:
available_skills = AgentContext._format_skills([
skill for skill in self._resource.skills if skill.is_enabled])
resolved_instructions = self._resolve_instructions()
notes_index = await self._tool_context.note_manager.get_notes_index()
notes_index = await NoteMaterializer.get_notes_index(self._resource.workspace.id)
resolved_notes_index = notes_index if notes_index is not None else FAILED_TO_LOAD_NOTES_INDEX

return resolved_instructions.base.format(
Expand All @@ -194,14 +183,8 @@ def find_tool(self, tool_name: str) -> ToolDef | None:
return None

async def persist(self) -> task_runtime_schemas.TaskRuntimeContext:
try:
await self._tool_context.note_manager.stop_watching()
await self._tool_context.note_manager.clear_materialized()
except:
self._logger.exception("Failed to execute NoteManager cleanup.")

return await self._persistence.persist(
self.task_id,
self._messages,
self._tool_context.usage,
self._usage,
)
7 changes: 0 additions & 7 deletions src-server/src/agent/context/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from dataclasses import dataclass
from typing import Protocol
from dais_sdk.types import Message
from src.agent.notes import NoteManager
from src.db.models import tasks as task_models
from src.schemas import (
agent as agent_schemas,
Expand All @@ -10,14 +9,8 @@
workspace as workspace_schemas,
)
from src.schemas.tasks import runtime as task_runtime_schemas
from src.agent.types import ContextUsage


@dataclass(frozen=True)
class ToolRuntimeContext:
usage: ContextUsage
note_manager: NoteManager

@dataclass(frozen=True)
class AgentContextResource:
workspace: workspace_schemas.WorkspaceRead
Expand Down
4 changes: 3 additions & 1 deletion src-server/src/agent/notes/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
from .manager import NoteManager
from .materializer import NoteMaterializer
from .watcher import NoteWatcher
from .workspace_ref_manager import WorkspaceRefManager
Loading
Loading