Commit Graph
4941 Commits
Author SHA1 Message Date
Alex 396eb92ab0 Run-scope artifact tools for workflow agent nodes
Stamp the engine's workflow_run_id into a workflow agent node's tool config, so
artifact_generator, code_executor, and document_extractor address artifacts by
the workflow run. An artifact (and its short ref like A1) created by one agent
node is then visible to a later code node and editable by a later agent node in
the same run - enabling an 'agent generates, a code node transforms, a second
agent edits' flow. Workflow agent nodes carry no conversation id, so only the
run scope applies.
2026-06-24 17:46:33 +01:00
Alex 6c8a72c836 Add an inline-rendering, versionable html artifact kind
Add an html kind to the artifact generator: it renders a styled HTML report from
a stored JSON spec (title + heading/paragraph/list/table/code blocks), producing
text/html bytes the sidebar already previews inline in the sandboxed iframe,
while keeping the spec as the source of truth so edit and rewrite make real
versions. So a single artifact both renders inline and versions conversationally.
The renderer is a fixed program fed the spec as data, and every spec text value
is HTML-escaped into the output.
2026-06-24 16:30:26 +01:00
Alex d573bab4a0 Add the code node to the workflow builder
Expose the workflow code node in the builder UI: a draggable palette entry, a
canvas node, and a config panel for the code, inputs, output variable, timeout,
and an optional JSON schema (validated before save). The panel serializes to the
same config the engine reads, so a code node built in the UI runs and produces an
artifact reference; workflows without code nodes load unchanged.
2026-06-24 15:47:49 +01:00
Alex e7f765b628 Add short artifact handle (A1) so the model can edit by reference
Give each produced artifact a short virtual handle - A1, A2, ... - the n-th
artifact in the conversation or workflow run (case-insensitive, not stored). The
tools return it in their results, and the edit, rewrite, and input parameters
accept either the handle or the full id. A handle resolves only within the
caller's own conversation or run, and the resolved id is still checked against
that parent before any read, so it cannot reach another tenant's artifact. This
fixes the model creating a duplicate instead of a new version when asked to
edit an artifact.
2026-06-24 15:35:06 +01:00
Alex a06b348c34 Preview artifact bytes inline in the sidebar
Render produced-artifact bytes inline when a version has no embedded spec:
HTML and SVG in the existing sandboxed iframe (with the restrictive CSP),
images inline via a blob URL, and Markdown/CSV/JSON/plain text as escaped text;
office documents and PDFs keep the download card. Bytes are fetched through the
existing authenticated download path, version-aware, with object URLs revoked on
change. Untrusted HTML/SVG renders only inside the scriptless sandboxed iframe
and Markdown is rendered without raw HTML, so artifact content cannot script the
app.
2026-06-24 15:23:49 +01:00
Alex afc423a818 Make the sandbox output-cap test deterministic
The output-cap test flooded ~100MB through a 20s wall-clock timeout, so under
heavy parallel load the timeout could fire before enough output accumulated to
trip the cap, intermittently failing. Emit a bounded ~200 KiB (4x the cap)
under a generous timeout so the truncation path triggers deterministically.
2026-06-24 14:04:01 +01:00
Alex 30397a1905 Expose artifacts as MCP resources and add sandbox egress policy
Expose a user's artifacts through the MCP server as readable resources: each is
listed under an artifact:// URI with its mime type and read on demand as inline
text or a base64 blob, bounded by a size cap and scoped strictly to the owning
principal resolved from the request's API key, so no artifact is served across
tenants. Ship the network-level egress controls the sandbox runner needs but
cannot self-apply: a Kubernetes NetworkPolicy that allows public egress while
denying RFC1918, link-local, and cloud-metadata ranges, an optional
docker-compose egress overlay, and runner network-hardening docs.
2026-06-24 13:57:39 +01:00
Alex d26a973189 Harden sandbox sessions and artifact quotas
Add runtime governance for the sandbox and artifact store: a per-process
concurrent-session cap with least-recently-used eviction of idle sessions and a
periodic idle reaper (Celery beat), so sandbox kernels do not accumulate. The
session manager performs all backend start/stop outside its lock and tears down
the captured handle, so eviction never closes a concurrently re-opened session.
Add per-user artifact quotas (count, total bytes, and per-file size) enforced at
persistence time as a soft cap, and best-effort cleanup of per-render scratch
directories in the sandbox workspace.
2026-06-24 13:34:56 +01:00
Alex f8bdf998ac Add document extraction tool using Docling
Add a document extractor tool with an extract_document action that converts an
input artifact (PDF, docx, pptx, ...) into structured JSON by running a fixed
Docling program in the sandbox (the document and parameters travel as data, so
nothing in them can execute). Output is a compact payload bounded by an input
size cap, a head-and-tail markdown window, and per-table caps, can be validated
against a JSON schema, and is persisted as a data artifact by reference. Docling
is heavy, so it stays out of the base image and ships in an opt-in sandbox image
variant.
2026-06-24 12:50:45 +01:00
Alex 381fb3335d Add document generation tool with editable spec-backed artifacts
Add an artifact generator tool with create, edit, and rewrite actions that
render presentations, documents, spreadsheets, and PDFs from a validated JSON
spec by running a fixed program in the sandbox (the spec travels as data, so
its contents can never execute). The spec is stored as the source of truth on
each artifact version; edits apply a JSON merge-patch and re-render, appending
a new version while earlier versions stay intact.
2026-06-24 12:30:18 +01:00
Alex 1ac1f793b7 Add workflow code node and artifacts templating namespace
Add a code workflow node that runs code in the run-scoped sandbox session and
writes produced files as artifact references into workflow state, passing them
by reference (only id and metadata, never bytes) so downstream nodes and CEL
conditions can branch on them. Add an artifacts.* templating namespace that
resolves those references to metadata via a run-scoped lookup, available to
both the workflow engine and the prompt renderer. Extract the sandbox-to-
artifact persistence into a shared helper reused by the code node and the
code_executor tool.
2026-06-24 12:30:18 +01:00
Alex 1fe6236281 Add code_executor tool to run sandboxed code and persist artifacts
Add a code_executor agent tool with a run_code action that runs agent-provided
code in the per-conversation sandbox session and captures produced files as
artifacts. Inputs are materialized only from artifacts the caller can access
(parent-scoped); produced files are stored under the user's namespace with
server-computed size and sha256, and the storage write is ordered last in the
transaction so a failure cannot orphan bytes. Output is a compact payload with
no raw bytes, and the produced artifact lights up the existing tool artifact
rail. Execution honors a wall-clock timeout and an agent-selectable session TTL
clamped by the global cap, and the action can be gated behind approval.
Tool-call argument logging is redacted so code bodies are not written to logs.
2026-06-24 12:00:09 +01:00
Alex 45f72258f4 Add Daytona Cloud sandbox backend
Add a pluggable Daytona backend (SANDBOX_BACKEND=daytona) that runs code on
Daytona Cloud via the Apache-2.0 SDK and DAYTONA_API_KEY, conforming to the
CodeSandbox interface. Sessions reattach to a labelled cloud sandbox by id
(waking a stopped one) and are created crash-safe so a failed setup never
orphans a paid sandbox; a configurable ceiling caps concurrent sandboxes and
auto-delete is clamped on so orphans always self-reap. File transfer is
workspace-contained with a size guard. Includes mocked unit tests and an
opt-in live smoke test.
2026-06-24 11:56:52 +01:00
Alex 182a14d257 Add artifact preview, versions, and download to the sidebar
Extend the artifact sidebar with a document/file view: a version selector,
authenticated download honoring Content-Disposition (following the backend
redirect to a presigned URL when configured), and version restore. Preview is
chosen by kind - html, svg, and mermaid render inside a sandboxed iframe with a
restrictive CSP (mermaid via its own sandboxed render so untrusted diagram text
never reaches the app DOM), office documents and PDFs show a download card, and
code or data render as text. Wires the new artifact endpoints into the API
service and leaves the existing notes/todo path unchanged.
2026-06-24 11:29:33 +01:00
Alex 3b795dbb83 Add semi-persistent code-execution sandbox (Jupyter Kernel Gateway runner)
Introduce a pluggable CodeSandbox abstraction with a SandboxManager and a
Jupyter Kernel Gateway backend: the app is a client of a single always-on
runner that executes code in stateful in-process kernels (no child-container
spawning, no docker socket). Sessions bind to a conversation or workflow run
with an agent-selectable TTL clamped by a global cap; execution enforces a
wall-clock deadline with interrupt-on-timeout and capped output, and file
transfer is workspace-contained with size and integrity checks. Adds a
docsgpt-sandbox docker-compose service (resource-capped, read-only, internal
network) plus settings, with a real local-gateway integration test.
2026-06-24 11:26:23 +01:00
Alex 922ed53a70 Add artifact REST endpoints (list, get, download, restore)
Serve artifact metadata and bytes over HTTP with parent-derived
authorization: conversation-parented artifacts inherit conversation
access (owner, shared_with, or a public share token whose conversation
matches the parent), workflow-run artifacts check run ownership, and
access fails closed when the parent is missing or deleted.

Adds list/get/versions/download/restore routes, an authenticated
storage-agnostic download (sanitized Content-Disposition, 302 to a
short-lived private S3 presigned URL when that strategy is configured),
a generate_presigned_url primitive on the storage base and S3 backend,
and generalizes the tools artifact endpoint for documents/files. Shared
authorization helpers live in a dedicated module used by both surfaces.
2026-06-24 10:53:41 +01:00
Alex 31525621e0 Add artifacts data model (tables, migration, repository)
Introduce artifacts and artifact_versions tables: an append-only,
pass-by-reference store with a stable identity row and immutable
versions that atomically bump current_version. Access is parent-derived
(conversation or workflow run); a CHECK enforces at least one parent and
a nullable team_id is reserved for future team scoping.

Adds the 0025_artifacts migration, ArtifactsRepository with a
parent-scoped safe getter alongside the unscoped one, and repo tests.
2026-06-24 10:21:48 +01:00
Alex 1acb836332 feat: guard on remote embedding size 2026-06-24 09:28:39 +01:00
Alex 872152e62a Merge pull request #2559 from arc53/fix-embeds-remote
fix: remote embeds
2026-06-23 21:43:48 +01:00
Alex df5582db37 fix: remote embeds 2026-06-23 21:43:11 +01:00
Alex 9c0803f017 Merge pull request #2557 from ManishMadan2882/main
minor ui, filter users intead of exact match
2026-06-23 21:32:39 +01:00
Alex f45b8df4e5 Merge pull request #2558 from arc53/graph-mini-fixes
fix: GraphRAG follow-ups (rebuild + progress streaming), Brave graph view, compression null guard
2026-06-23 20:53:35 +01:00
Manish Madan 23cd3d2e50 Merge pull request #2446 from arc53/dependabot/npm_and_yarn/extensions/react-widget/globals-17.6.0
chore(deps-dev): bump globals from 17.5.0 to 17.6.0 in /extensions/react-widget
2026-06-24 01:09:37 +05:30
ManishMadan2882 aa10146e25 (fix)ui/settings: prompts dropdown 2026-06-24 01:08:02 +05:30
Alex d7bbfcfe17 fix: minor graph rag improvements 2026-06-23 20:10:41 +01:00
Alex ae3e79bf8f fix: graph view on brave 2026-06-23 19:15:43 +01:00
Alex 6e4480b61b fix: mini compression issues 2026-06-23 19:15:22 +01:00
Alex 8c312ed311 Merge pull request #2556 from arc53/rag-graphrag
feat: GraphRAG retriever: per-source knowledge graph + PPR retrieval
2026-06-23 18:56:40 +01:00
Alex db3af415ac fix: scale content on graph rag 2026-06-23 18:50:27 +01:00
Alex ba5c9a8910 fix: graph rag ui improvements 2026-06-23 17:11:49 +01:00
ManishMadan2882 2965e1d5ac (feat:admin) filter users intead of exact match, minor ui 2026-06-23 14:48:56 +05:30
Alex 92e64cc192 fix(ui): wrap long source-card titles instead of overflowing under the menu
A long underscore-heavy filename (no natural break points) overflowed the card toward the 3-dots menu: the title <h3> was a flex item without min-w-0, so it couldn't shrink below its min-content width, and wrap-break-word doesn't reduce flex min-content. Add min-w-0 flex-1 + wrap-anywhere on the title and shrink-0 on the menu column so the title shrinks, breaks anywhere, and stays left of the menu (still line-clamp-3).
2026-06-23 08:50:51 +01:00
Alex 91d17694b3 fix(graphrag): graph view rendered blank — measure container after load
The ResizeObserver/size effect ran once on mount with [] deps while loading=true, so containerRef was null (the graph container isn't in the DOM yet) and size.width stayed 0, gating out ForceGraph2D (blank canvas) even though the data loaded. Re-run the measure effect on [loading, data.nodes.length] so it attaches + measures once the container actually mounts.
2026-06-23 08:46:03 +01:00
Alex 7e7f34ee9c test(graphrag): address code-quality nits in graph tests
Meaningful self-loop degree assertion (was always-true); single import style per module; explicit returns in the live-store helper. (CI code-quality bot.)
2026-06-23 03:48:21 +01:00
Alex 2594bb0bed feat(graphrag): graph-view endpoints + network visualization
GraphStore.get_graph_overview (top-N by degree, bounded) + get_node_detail (description + linked chunks). GET /api/sources/<id>/graph + /graph/node/<id> (read-access gated, node scoped to source_id; empty graph -> {nodes:[],edges:[]}). Frontend GraphView (react-force-graph-2d) wired to config.kind=graphrag via card-click/'View graph'; node-click -> description + chunks; tooltip renders untrusted names as text (no innerHTML XSS). All read-only GraphStore methods rollback their txn (no idle-in-transaction lock). Unit G7. (Also a pre-existing prettier fix in WorkflowPreview to keep lint green.)
2026-06-23 02:48:18 +01:00
Alex daddbeb062 chore: fix pre-existing prettier formatting in TeamSwitcher (unblock CI lint) 2026-06-23 01:57:00 +01:00
Alex 8ccc291ef5 feat(graphrag): frontend Enable GraphRAG action + status + badge
/api/config exposes graphrag_available. 'Enable GraphRAG' source action (owner/editor + pgvector + not-already-graphrag) -> POST graphrag/enable, confirm + task-poll + 'Building graph...' + summary (EnableGraphRAGModal, unmount-guarded; pure graphragEnableUtils). GraphRAG badge for config.kind==graphrag. Mirrors the wiki convert UX. Unit G6.
2026-06-23 01:57:00 +01:00
Alex 4e0c792a6d feat(graphrag): GraphRAGRetriever (PPR local) + register + ClassicRAG fallback
Query-side: composes ClassicRAG (rephrase/budget/fallback). Per source: pgvector entity-name seed -> bounded subgraph -> networkx personalized PageRank (IDF hub down-weight) -> rank graph_node_chunks -> chunk text -> shared token budget; no LLM at query time. Citations derived from chunk metadata (matches ClassicRAG). Falls back to ClassicRAG per-source when no graph rows / unavailable / error (retrieval never breaks). get_chunk_texts queries the co-located documents table by configured table/column names (parameterized). Registered 'graphrag'. Unit G5.
2026-06-23 01:45:14 +01:00
Alex 4742aec4c6 feat(graphrag): durable extract_graph task + ingest-path enqueue + enable route
graph_enabled() sets kind=graphrag + retriever=graphrag. extract_graph_worker fetches the source's pgvector chunks and runs G3 extraction (graphrag_available guard, empty no-op). extract_graph durable+idempotent task; key varies with source updated_at so re-ingest/re-enable re-run incrementally (G3 checkpoint skips done chunks) while concurrent same-state enqueues dedup. The 4 ingest paths enqueue after embed when kind=graphrag (isolated in try/except so a broker hiccup can't fail the ingest). POST /api/sources/<id>/graphrag/enable: pgvector+GRAPHRAG_ENABLED gated, owner/editor write-authz; PATCH config still can't flip kind->graphrag. Unit G4.
2026-06-23 01:29:51 +01:00
Alex 22582e900c feat(graphrag): ingest-time extraction pipeline (entities/relations -> graph)
Per-chunk schema-constrained LLM extraction (gleanings off, one .gen() per chunk) into the GraphStore: model resolves config.graph.extraction_model -> GRAPHRAG_EXTRACTION_MODEL -> instance LLM_NAME; token_usage logged per call (_token_usage_source=graph_extraction, owner-attributed via decoded_token); chunk text fenced as untrusted; robust JSON parse (malformed/errors skip the chunk, never crash); resumable via graph_ingest_progress; max_chunks cap; entity names embedded + merged by normalized_name; chunk_id = doc_id so links match retrieval. Unit G3.
2026-06-23 01:00:21 +01:00
Alex 6687d85085 feat(graphrag): GraphStore — per-source graph tables in the pgvector DB
On-demand graph_nodes/graph_edges/graph_node_chunks/graph_ingest_progress in the same DB as pgvector documents (no Alembic, no cross-DB FK; Python uuids; parameterized SQL). upsert_node (merge by normalized_name, doc_freq, dedup description), add_edge (+degree), link_node_chunk, search_nodes_by_embedding (cosine), bounded get_subgraph, checkpoint, delete_by_source. Embedding dim derived from the configured model (768 fallback). Unit G2.
2026-06-23 00:51:41 +01:00
Alex b4c465e608 feat(graphrag): config.graph sub-model + settings + pgvector availability gate
GraphConfig (extraction_model?, max_chunks?, gleanings=0; extra=forbid) on SourceConfig; settings GRAPHRAG_EXTRACTION_MODEL (None=instance default) + GRAPHRAG_MAX_CHUNKS_FOR_EXTRACTION; graphrag_available() = GRAPHRAG_ENABLED and VECTOR_STORE==pgvector (D27-D32 foundation). Unit G1.
2026-06-23 00:39:27 +01:00
Alex acb7956fe0 Merge pull request #2554 from arc53/rag-wiki
feat: LLM-editable wiki source (F-Wiki v1)
2026-06-23 00:20:24 +01:00
Alex ef44459984 fix: small wiki fixes 2026-06-23 00:19:56 +01:00
Alex 8b099ef1aa fix(wiki): monochrome icon for the New wiki source option
The add-source grid inverts black icons to white (dark:invert), but the wiki used book.svg (fill #6A4DF4), which inverted to lime. Point the wiki ingestor at a new black book-mono.svg so it renders white like the others; book.svg stays purple for its other use (PromptsModal, no invert there).
2026-06-22 23:39:03 +01:00
Alex f809f660f4 fix(wiki): maintain sources.tokens for wikis (sum of page token_counts)
sources.tokens was only set at ingest, so wikis showed no/stale token count on the card (blank wikis showed nothing; converted ones showed the stale original count). rebuild_wiki_directory_structure (called after every wiki mutation) now also sets sources.tokens to the sum of wiki_pages.token_count; blank wiki create sets tokens=0. So the card reflects live wiki content.
2026-06-22 23:33:47 +01:00
Alex 2616ec5d1b fix(wiki): detect wiki sources by config.kind, not type
A converted source keeps its origin type (e.g. crawler) with the wiki-ness in config.kind=wiki (D5/D20), so the UI's type==='wiki' checks treated converted sources as normal (wrong view, convert action still offered). Sources.tsx now keys isWiki + the view branch on config.kind==='wiki' (with a type fallback for blank-created wikis). The paginated endpoint already returns config.
2026-06-22 23:26:12 +01:00
Alex 54773cdf0f feat(wiki): open source view on card click (wiki viewer or normal view)
Clicking a source card opens its view via the existing setDocumentToView handler (wiki -> WikiViewer, nested -> FileTree/ConnectorTree, else -> Chunks). The 3-dots Button and both DropdownMenuContent menus stopPropagation so clicks on the trigger or menu items don't bubble (through the React tree, even though Radix portals them) to the card's onClick. Adds cursor + keyboard/role a11y matching AgentCard.
2026-06-22 23:21:11 +01:00
Alex 8a0f7024e3 fix(wiki): convert reassembles pages from existing chunks (crawler/remote)
convert_source_to_wiki now builds pages from the source's already-ingested vector-store chunks instead of re-parsing storage files, so it works for crawler/remote/connector sources (which have no stored files; file_path empty). Groups by metadata file_path/file_name (URL- and connector-aware; URLs normalized to virtual paths) rather than the raw source. Passes embeddings_key to create_vectorstore in BOTH convert and reembed_wiki_page (fixes a TypeError crash on faiss/elasticsearch). Conservative overlap-trim (min length). Deletes the original chunks after reassembling so retrieval has no duplicate/stale content.
2026-06-22 23:03:52 +01:00
Alex 0a73381457 Merge pull request #2555 from ManishMadan2882/main
Minor UI polish
2026-06-22 22:38:21 +01:00