mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-13 09:42:40 +02:00
feat: improved document, folder mentions rendering
Some checks are pending
Build and Push Docker Images / tag_release (push) Waiting to run
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (backend, surfsense-backend) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (web, surfsense-web) (push) Blocked by required conditions
Some checks are pending
Build and Push Docker Images / tag_release (push) Waiting to run
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_backend, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_web, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (backend, surfsense-backend) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (web, surfsense-web) (push) Blocked by required conditions
This commit is contained in:
parent
28a02a9143
commit
c8374e6c5b
59 changed files with 1725 additions and 361 deletions
|
|
@ -26,9 +26,7 @@ def handle_report_progress(
|
|||
return None, last_active_step_items
|
||||
|
||||
phase = data.get("phase", "")
|
||||
topic_items = [
|
||||
item for item in last_active_step_items if item.startswith("Topic:")
|
||||
]
|
||||
topic_items = [item for item in last_active_step_items if item.startswith("Topic:")]
|
||||
|
||||
if phase in ("revising_section", "adding_section"):
|
||||
plan_items = [
|
||||
|
|
@ -56,7 +54,9 @@ def handle_report_progress(
|
|||
return frame, new_items
|
||||
|
||||
|
||||
def handle_document_created(data: dict[str, Any], *, streaming_service: Any) -> str | None:
|
||||
def handle_document_created(
|
||||
data: dict[str, Any], *, streaming_service: Any
|
||||
) -> str | None:
|
||||
if not data.get("id"):
|
||||
return None
|
||||
return streaming_service.format_data(
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ from app.tasks.chat.streaming.handlers.tools import (
|
|||
)
|
||||
from app.tasks.chat.streaming.helpers.tool_output import tool_output_has_error
|
||||
from app.tasks.chat.streaming.relay.state import AgentEventRelayState
|
||||
from app.tasks.chat.streaming.relay.task_span import clear_task_span_if_delegating_task_ended
|
||||
from app.tasks.chat.streaming.relay.task_span import (
|
||||
clear_task_span_if_delegating_task_ended,
|
||||
)
|
||||
from app.tasks.chat.streaming.relay.thinking_step_sse import emit_thinking_step_frame
|
||||
|
||||
|
||||
|
|
@ -32,9 +34,7 @@ def iter_tool_end_frames(
|
|||
run_id = event.get("run_id", "")
|
||||
tool_name = event.get("name", "unknown_tool")
|
||||
raw_output = event.get("data", {}).get("output", "")
|
||||
staged_file_path = (
|
||||
state.file_path_by_run.pop(run_id, None) if run_id else None
|
||||
)
|
||||
staged_file_path = state.file_path_by_run.pop(run_id, None) if run_id else None
|
||||
|
||||
if tool_name == "update_memory":
|
||||
state.called_update_memory = True
|
||||
|
|
@ -116,6 +116,4 @@ def iter_tool_end_frames(
|
|||
)
|
||||
yield from iter_tool_completion_emission_frames(emission_ctx)
|
||||
|
||||
clear_task_span_if_delegating_task_ended(
|
||||
state, tool_name=tool_name, run_id=run_id
|
||||
)
|
||||
clear_task_span_if_delegating_task_ended(state, tool_name=tool_name, run_id=run_id)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
return default_thinking.resolve_completed_thinking(
|
||||
tool_name, tool_output, last_items
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_name
|
||||
items = last_items
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_name
|
||||
items = last_items
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_name
|
||||
items = last_items
|
||||
|
|
@ -44,9 +46,7 @@ def resolve_completed_thinking(
|
|||
else "Report"
|
||||
)
|
||||
word_count = (
|
||||
tool_output.get("word_count", 0)
|
||||
if isinstance(tool_output, dict)
|
||||
else 0
|
||||
tool_output.get("word_count", 0) if isinstance(tool_output, dict) else 0
|
||||
)
|
||||
is_revision = (
|
||||
tool_output.get("is_revision", False)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
return default_thinking.resolve_completed_thinking(
|
||||
tool_name, tool_output, last_items
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_name
|
||||
items = last_items
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_name
|
||||
items = last_items
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_output, tool_name
|
||||
return ("Editing file", last_items)
|
||||
|
|
|
|||
|
|
@ -24,9 +24,7 @@ def iter_completion_emission_frames(
|
|||
output_text = om.group(1) if om else ""
|
||||
thread_id_str = ctx.langgraph_config.get("configurable", {}).get("thread_id", "")
|
||||
|
||||
for sf_match in re.finditer(
|
||||
r"^SANDBOX_FILE:\s*(.+)$", output_text, re.MULTILINE
|
||||
):
|
||||
for sf_match in re.finditer(r"^SANDBOX_FILE:\s*(.+)$", output_text, re.MULTILINE):
|
||||
fpath = sf_match.group(1).strip()
|
||||
if fpath and fpath not in ctx.stream_result.sandbox_files:
|
||||
ctx.stream_result.sandbox_files.append(fpath)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_name
|
||||
items = last_items
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_output, tool_name
|
||||
return ("Searching files", last_items)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_output, tool_name
|
||||
return ("Searching content", last_items)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_name
|
||||
if isinstance(tool_output, dict):
|
||||
|
|
@ -38,9 +40,7 @@ def resolve_completed_thinking(
|
|||
paths = [str(p) for p in parsed]
|
||||
except (ValueError, SyntaxError):
|
||||
paths = [
|
||||
line.strip()
|
||||
for line in ls_output.strip().split("\n")
|
||||
if line.strip()
|
||||
line.strip() for line in ls_output.strip().split("\n") if line.strip()
|
||||
]
|
||||
for p in paths:
|
||||
name = p.rstrip("/").split("/")[-1]
|
||||
|
|
|
|||
|
|
@ -17,11 +17,15 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
d = as_tool_input_dict(tool_input)
|
||||
p = d.get("path", "") if isinstance(tool_input, dict) else str(tool_input)
|
||||
display = p if len(p) <= 80 else "…" + p[-77:]
|
||||
return ToolStartThinking(title="Creating folder", items=[display] if display else [])
|
||||
return ToolStartThinking(
|
||||
title="Creating folder", items=[display] if display else []
|
||||
)
|
||||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_output, tool_name
|
||||
return ("Creating folder", last_items)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_output, tool_name
|
||||
return ("Moving file", last_items)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_output, tool_name
|
||||
return ("Reading file", last_items)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_output, tool_name
|
||||
return ("Deleting file", last_items)
|
||||
|
|
|
|||
|
|
@ -17,11 +17,15 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
d = as_tool_input_dict(tool_input)
|
||||
p = d.get("path", "") if isinstance(tool_input, dict) else str(tool_input)
|
||||
display = p if len(p) <= 80 else "…" + p[-77:]
|
||||
return ToolStartThinking(title="Deleting folder", items=[display] if display else [])
|
||||
return ToolStartThinking(
|
||||
title="Deleting folder", items=[display] if display else []
|
||||
)
|
||||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_output, tool_name
|
||||
return ("Deleting folder", last_items)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_output, tool_name
|
||||
return ("Writing file", last_items)
|
||||
|
|
|
|||
|
|
@ -20,15 +20,15 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
return ToolStartThinking(
|
||||
title="Planning tasks",
|
||||
items=(
|
||||
[f"{todo_count} task{'s' if todo_count != 1 else ''}"]
|
||||
if todo_count
|
||||
else []
|
||||
[f"{todo_count} task{'s' if todo_count != 1 else ''}"] if todo_count else []
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_output, tool_name
|
||||
return ("Planning tasks", last_items)
|
||||
|
|
|
|||
|
|
@ -58,14 +58,18 @@ def _emission_module(tool_name: str) -> str:
|
|||
|
||||
def _import_thinking(tool_name: str):
|
||||
try:
|
||||
return importlib.import_module(f"{_BASE}.{_thinking_module(tool_name)}.thinking")
|
||||
return importlib.import_module(
|
||||
f"{_BASE}.{_thinking_module(tool_name)}.thinking"
|
||||
)
|
||||
except ModuleNotFoundError:
|
||||
return importlib.import_module(f"{_BASE}.default.thinking")
|
||||
|
||||
|
||||
def _import_emission(tool_name: str):
|
||||
try:
|
||||
return importlib.import_module(f"{_BASE}.{_emission_module(tool_name)}.emission")
|
||||
return importlib.import_module(
|
||||
f"{_BASE}.{_emission_module(tool_name)}.emission"
|
||||
)
|
||||
except ModuleNotFoundError:
|
||||
return importlib.import_module(f"{_BASE}.default.emission")
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ def resolve_start_thinking(tool_name: str, tool_input: Any) -> ToolStartThinking
|
|||
|
||||
|
||||
def resolve_completed_thinking(
|
||||
tool_name: str, tool_output: Any, last_items: list[str],
|
||||
tool_name: str,
|
||||
tool_output: Any,
|
||||
last_items: list[str],
|
||||
) -> tuple[str, list[str]]:
|
||||
del tool_name
|
||||
items = last_items
|
||||
|
|
|
|||
|
|
@ -28,11 +28,7 @@ def iter_completion_emission_frames(
|
|||
xml,
|
||||
):
|
||||
chunk_url, content = m.group(1).strip(), m.group(2).strip()
|
||||
if (
|
||||
chunk_url.startswith("http")
|
||||
and chunk_url in citations
|
||||
and content
|
||||
):
|
||||
if chunk_url.startswith("http") and chunk_url in citations and content:
|
||||
citations[chunk_url]["snippet"] = (
|
||||
content[:200] + "…" if len(content) > 200 else content
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue