Commit Graph
63 Commits
Author SHA1 Message Date
Dmitry NgandSergey Kozyrenko 45c84c500f test(frontend): make the e2e suite falsifiable, and fix what it found (#380)
The e2e suite and CI gates could report green without checking anything: the
lint/codegen gate never ran on fork PRs, the codegen freshness check diffed the
wrong range, the sticky comment claimed passes it never read, and several
visual/palette/contrast/a11y gates were written so they could not fail. Closing
those gates then exposed real defects.

**E2E and CI.** New coverage for the assistant lifecycle, flow interrupt, live
panels, tab deep links, the report route and its exports, session expiry, and
uploads/downloads (59 → 125 spec cases). Gates now fail on real regressions:
absolute pixel budget, per-tab panel sweeps, scoped a11y waivers, page-error
assertions. CI runs on `pull_request`, ranges from the PR base, routes comments
by PR identity, and redacts stand secrets from the public artifact.

**Markdown editor.** ~20 round-trip and toolbar fixes: table pipe escaping
(nested lists, Go template pipelines, headerless tables), fence validity,
setext and line-leading escapes, inline code containing a backtick, block
toggles under select-all, controls disabled where the command is unavailable or
a table cell cannot hold the block, theme-aware code surface. Two perf fixes cut
1 MB document load from 69s to 4s.

**Accessibility and UI.** Focus returns to whatever opened a dialog, sheet or
menu; icon-only buttons named; `aria-sort` on table columns; syntax tokens
retuned to clear AA in both themes; a dedicated link token. Detail and settings
pages now distinguish authz denials and partial errors from missing records,
survive background refetches without blanking or discarding unsaved edits, and
stop naming exported PDFs `*.pdf.pdf`.

**Backend.** Passwords capped at the 72 bytes bcrypt can hash (over-long ones
previously 500'd after passing validation); four agent options the GraphQL round
trip silently dropped are carried through; a flow whose worker fails to start is
no longer left in the listing; the Graphiti health check retries before
permanently disabling the client.

---------

Co-authored-by: Sergey Kozyrenko <sirozha_blr@tut.by>
2026-07-29 16:34:29 +04:00
Dmitry Ng 762c6233ce feat(flow): enhance error handling and documentation for flow retrieval
- Added specific error handling for `ErrFlowNotFound` in `PatchAssistant` and `DeleteAssistant` methods, returning a warning-level response when the flow is not found.
- Updated documentation in templates to clarify requirements for `center_node_uuid` in search types, ensuring users understand the necessity of copying UUIDs from prior results.
- Improved JSON schema descriptions for `GraphitiSearchAction` to emphasize the mandatory nature of the `query` field across all search types.
- Introduced new tests to validate handling of empty timeout values and ensure proper parsing of temporal window timestamps, addressing potential production issues.
2026-07-26 14:40:01 +03:00
Dmitry Ng deaff9eafe chore(config): update launch.json and add new provider configurations
- Added new configuration options in `.vscode/launch.json` for vllm and hcnsec providers.
- Updated `deepinfra.provider.yml` to reflect changes in model configurations and pricing.
- Introduced `hcnsec.provider.yml` with detailed model settings and pricing for HCNSec.
- Adjusted various test reports to reflect updated success rates and latencies for different models.
2026-07-23 17:37:44 +03:00
Dmitry Ng 796c7faf3d fix(agent): stop network and malformed-arg failures from hard-failing tools
Graphiti transport errors, an empty file path, and an omitted 'action' or
double-encoded 'questions' arg from the LLM all hard-failed the tool chain
and burned retries instead of degrading gracefully. Also: stopTaskTimeout
5s->60s (flow kept running after a false 500), and the routine "cookie
claim invalid" case now logs at Warn instead of Error.
2026-07-22 16:25:07 +03:00
Dmitry Ng 74c2663114 Merge branch 'integrate/open-prs-v2' into feature/next-release 2026-07-22 01:25:25 +03:00
Dmitry Ng e772a5cd82 Merge pull request #373 from rakshith48/feat/firecrawl-search
feat(tools): add Firecrawl web search provider
2026-07-18 19:33:57 +04:00
Dmitry Ng af3df846ff Merge pull request #339 from mason5052/codex/issue-338-stream-zip-downloads
fix: stream ZIP downloads without buffering archives
2026-07-17 16:46:19 +04:00
rramprakash 3f68960d98 feat(tools): add Firecrawl web search provider
Add Firecrawl as a network search provider alongside Tavily, Perplexity,
Traversaal, SearXNG and the others. Firecrawl's /v2/search endpoint combines
web search with page scraping, returning full-page markdown content for each
result, which the searcher agent summarizes like the other content-rich
engines.

- New firecrawl tool mirrors the Tavily provider layer-for-layer: registry
  definition, tool-type mapping, factory wiring in both tool builders, and
  ftester executor/args/mocks support.
- Configurable endpoint: FIRECRAWL_API_KEY plus an optional FIRECRAWL_API_URL
  (default https://api.firecrawl.dev) so self-hosted Firecrawl instances work.
- Adds 'firecrawl' to the searchengine_type enum (goose migration + models)
  and the search-log server model so searches are recorded per engine.
- Installer wizard, .env.example, docker-compose, prompts and docs updated.

The tool is only registered when FIRECRAWL_API_KEY is set, so existing
deployments are unaffected.
2026-07-16 12:53:11 +05:30
Sergey KozyrenkoandClaude Opus 4.8 ffbbabb517 fix(docker,flows): surface truncated/systemerr exec streams, bound ftester drain, tidy failure logging
- demuxExecStdout errors on a header cut short mid-frame (was a silent EOF that
  dropped the tail) and surfaces a docker systemerr frame instead of discarding it.
- ftester drains telemetry on exit through the bounded observer.Drain instead of
  two unbounded ForceFlush calls, so an unreachable collector can't hang it at exit.
- container-listing failures are sorted for a deterministic skipped-entries preview,
  logged per-entry at Debug (the detail is already in the response and the endpoint
  is hit on every navigation) with names quoted so control bytes in a hostile
  filename can't inject into a log line; corrected the stat-failure comment
  (a dangling symlink lstats fine, it doesn't fail).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 00:06:21 +07:00
Sergey KozyrenkoandClaude Opus 4.8 7cd22ccbc9 test(docker,flows): cover the listing cap paths, bound the container-list path count
The truncation slice and the demux stdout byte-cap had no docker-layer tests —
only the handler's Truncated wiring was exercised through the fake, so a
mis-slice or a dropped cap would have gone unnoticed. Extract find-output
parsing into a pure parseFindEntries and take the byte cap as a demuxExecStdout
parameter, then unit-test both boundaries (at cap / cap+1 / over-limit stream).

Also bound how many paths one container-files request may list
(maxContainerListPaths), so the per-path entry cap can't be multiplied by an
attacker-chosen path count into a large fan-out or response body.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 23:22:33 +07:00
Sergey KozyrenkoandClaude Opus 4.8 7b67b1c0ea fix(flows): return partial container listings instead of failing; stop the refetch skeleton flash
Container-listing polish on top of the partial-success work:

- A directory whose entries all fail to stat no longer 500s. The find exec
  already proved the container alive, so ListContainerDir returns the readable
  entries (possibly none) plus the per-entry failures, and the handler serves a
  200 partial listing; only a cancelled request or a dir that can't be listed at
  all still errors.

- Over the entry cap, list the first page and set a Truncated flag rather than
  erroring with end-user copy from the docker layer. The flag flows through to
  the Pull dialog, which now warns the user the directory was truncated instead
  of silently showing a subset.

- The Pull dialog no longer flashes a skeleton on an in-place refetch (Refresh,
  or after a Pull): the listing hook clears its rows only when the path actually
  changes, so a same-path reload keeps the current rows under the loading guard.

Tests: an all-entries-failed listing returns 200 with the failures; the
Truncated flag surfaces in the response. Swagger regenerated for the new field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 22:38:17 +07:00
Sergey KozyrenkoandClaude Opus 4.8 2c524faea9 fix(observability,flows): drain telemetry sinks in parallel, stop leaking docker errors, dedup listing failures
Three defects on the shutdown and container-listing paths:

- Telemetry drain ran the langfuse and otel sinks serially under one deadline.
  langfuse's ForceFlush/Shutdown ignore the caller ctx and block on their own
  timeout, so a langfuse outage burned the whole budget and the healthy otel
  sink's final batch was never flushed. Add observer.Drain, which flushes then
  shuts down each sink in its own goroutine bounded by the deadline; main uses
  it, retiring the inline flush-then-shutdown dance.

- The partial-success listing put the raw stat/list error into the 200 body's
  Failures[].Message, exposing docker-layer detail (container ids, the daemon
  address) that response.Error only reveals under develop mode. Send a generic
  message to the client and keep the raw text dev-gated, logged server-side.

- A path read successfully by one query could also appear in Failures when
  another query failed on it, order-dependent. Reconcile at assembly: drop any
  failure whose path was read successfully, so no path is in both arrays.

Also bound the exec stdout buffered before parsing so a compromised sandbox
can't stream unbounded output into memory.

Tests: Drain delivers a healthy otel sink while a langfuse sink blocks and
returns within its deadline; the listing failure message is dev-gated; a path
never lands in both Files and Failures. Live: unreachable collector -> shutdown
stays bounded (~5s) and exits cleanly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 22:24:02 +07:00
Sergey KozyrenkoandClaude Opus 4.8 345b91e4c1 docs(swagger): regenerate for the container-files Failures field
ContainerFiles gained a Failures list when the container listing switched to
partial-success; regenerate the Swagger docs (swag v1.8.7, the pinned version)
so generated clients see the new field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 16:37:18 +07:00
Sergey KozyrenkoandClaude Opus 4.8 93d36c9827 fix(flows): keep serving readable paths when one container path fails
The multi-path container listing still fail-fasted: a single bad top-level
path (nonexistent, not a directory, list failed) returned HTTP 500 and
blanked every path that had already listed. Record each such path as a
failure and keep going so the readable paths are still returned; only a
cancelled request aborts, and if every path fails at the directory level the
request is failed as a whole. Also drop a per-entry failure whose path was
already read successfully by an overlapping query.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 16:12:40 +07:00
Sergey KozyrenkoandClaude Opus 4.8 1300f60a2b feat(docker): partial-success container listing instead of fail-fast
A single unreadable directory entry (dangling symlink, a file removed
between ls and stat, a transient /proc entry) used to fail the whole
listing with HTTP 500, blanking the file browser and discarding every
readable sibling. The frontend already expects /proc/sys to not fail
spuriously, but the backend did the opposite.

ListContainerDir now returns a ContainerDirListing{Files, Failures}: per-
entry stat errors no longer abort the batch. GetFlowContainerFiles serves
the readable entries as HTTP 200, carries the failures back in a new
ContainerFiles.Failures field, and logs each skipped entry (capped) plus a
degradation summary. Directory-level faults (not a dir, ls failed, container
gone) still return 500 — there is no partial to show. statContainerEntries
returns successes + failures instead of the lowest-index error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 13:32:48 +07:00
Sergey KozyrenkoandClaude Opus 4.8 f5f7974826 test(validation): cover REST prompt validation and knowledge length limits
- prompts_test.go: PatchPrompt rejects a syntax error, an undeclared variable,
  and a whitespace-only template over REST (the path a raw client hits when the
  UI is bypassed) and does not persist them; valid templates still create/update.
- validation_test.go: validateKnowledgeFieldLengths accepts each field at its
  max length and rejects one character over.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 16:34:04 +07:00
Sergey KozyrenkoandClaude Opus 4.8 72da224033 feat(prompts): validate template syntax on the REST update endpoint
The GraphQL createPrompt/updatePrompt mutations run validator.ValidatePrompt
(Go text/template parse + declared-variable check + trial render), but the
REST PUT /prompts/:type handler only checked the field was present, so a
prompt with a syntax error or an undeclared variable could be stored over
REST and later break rendering. Mirror the GraphQL check in PatchPrompt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 16:01:36 +07:00
Sergey KozyrenkoandClaude Opus 4.8 e1b7d8e5d9 fix(resources): pre-flight blob stats so a ZIP download can't truncate under 200
The streaming ZIP refactor made `ZipResources` open each blob inline while
`streamZipArchive`'s writer commits HTTP 200 on the first byte. A blob missing
on disk (a DB record whose blob file is gone) failed mid-stream, so the client
received a 200 with a central-directory-valid but incomplete archive — the
missing files silently dropped (regression vs main, which buffered then sent).

Stat every blob up front; a missing one now returns before any byte is written,
so `streamZipArchive` emits a clean structured error instead. Keeps the
streaming memory benefit.

Tests (both proven fail-on-unfixed / pass-on-fixed): a unit test asserts the
writer stays empty when a blob is missing, and a download-handler test asserts
a missing blob in a multi-file ZIP returns a clean 500, not a truncated 200.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 13:51:54 +07:00
Sergey KozyrenkoandClaude Opus 4.8 2d2aea5785 fix(auth): reject OAuth logins with a provider-unverified email
The OAuth callback links/creates an account by the email from ResolveEmail, and
Google/GitHub only ever return a verified address — but that invariant lived
inside each provider and was invisible at the callback. A future OAuth provider
that omitted the verified check would let an attacker register a victim's email
there (unverified), "sign in", and be linked straight into the victim's account:
instant takeover.

Make verification part of the contract: ResolveEmail now returns
(email, verified, err), and the callback refuses to proceed when !verified.
Because Go's bool zero value is false and the compiler forces the new return, a
provider that forgets to report verification fails closed (its own login breaks)
rather than opening a takeover. Google reports claims.EmailVerified; GitHub only
selects verified addresses, so reports true. Added a callback test: a provider
reporting an unverified email is rejected (no link, no session) — red before the
gate, green after.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:43:16 +07:00
Sergey KozyrenkoandClaude Opus 4.8 497cfdd555 fix(users): require a real email on user-initiated email change
EmailChange.Mail validated with `vmail`, which accepts not just a real address
but also the literal "admin" and any UUID — escape hatches that exist so the
seeded admin row (mail "admin") passes User.Mail's Valid(). The account's
change-email form (added this branch) reaches it, so a user could save "admin"
or a UUID as their own email — a non-deliverable value (no privilege gain: roles
come from role_id, and UNIQUE(mail) blocks colliding with the real admin row).

Add a strict `realemail` validator (same address regex as vmail, minus the
hatches) and use it for EmailChange.Mail; User.Mail keeps `vmail` so the seeded
admin still validates. Tests cover the validator (admin/UUID rejected, real
address accepted) and the handler (changing to a UUID or "admin" now 400s).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 13:00:36 +07:00
Sergey KozyrenkoandClaude Opus 4.8 14e0a0ae71 fix(users): preserve email case on change to match login, OAuth and create
ChangeEmailCurrentUser was the only path that lowercased the email
(strings.ToLower), while local login, the OAuth callback and CreateUser all
store/compare it raw against a case-sensitive UNIQUE(mail). That lone
normalization let a changed address (now lowercased) miss a later raw-case
login, and let the uniqueness pre-check (run on the lowercased value) skip an
existing mixed-case row. Drop the ToLower so every path is consistently
case-sensitive again — the pre-branch invariant. The email validator already
rejects surrounding whitespace, so the paired TrimSpace was dead.

Update the test that codified the old lowercasing to assert case preservation.
A fully case-insensitive scheme (normalize everywhere, or citext /
UNIQUE(lower(mail))) is tracked separately as a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 10:15:44 +07:00
Sergey KozyrenkoandClaude Opus 4.8 28036f652c refactor(providers): table-driven provider registry
The provider controller repeated every provider type across five hand-written
blocks (default-config wiring, key-gated instantiation, GetProvider fallback,
NewProvider, buildProviderFromConfig) plus the API-layer Valid() whitelist.

Introduce pkg/providers/registry.go: a providerRegistry table whose entries hold
the per-type constructors and credential gating, with small adapter helpers
(ignoreConfig/fromData) absorbing the signature variance (bedrock/ollama/custom
take *config.Config; the rest don't). The controller now wires and looks up
providers in loops over the table. Valid() validates against the new canonical
provider.AllProviderTypes list (no heavyweight import, no cycle).

Adding a provider's backend wiring drops from ~6 edits across these functions to
one registry entry. providers.go shrinks ~300 lines; behavior is unchanged
(same exported funcs, same gating) and all provider/server/graph tests stay green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 19:07:11 +07:00
Sergey KozyrenkoandClaude Opus 4.8 bfd80b1de9 test(minimax): cover provider whitelist + secret pattern parity (refs #328)
The QA audit found minimax was wired into production everywhere but omitted
from provider-enumeration test data, so a future regression dropping it would
go uncaught. Add minimax to ProviderType.Valid()'s validTypes table, to the
GetSecretPatterns config (expected count 29→30, exercising the "MiniMax Key"
redaction pattern), and to clearConfigEnv's hermetic env list.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 16:25:51 +07:00
Sergey KozyrenkoandClaude Opus 4.8 55335feb17 feat(minimax): add MiniMax provider with full app/UI/installer parity (refs #328)
Reworks external PR #328 (octo-patch). The PR added only the provider core;
this brings MiniMax to full parity with the other providers (qwen) so it is
selectable and configurable in the UI and installer.

Applied from the PR (verified against MiniMax's official API docs — M3/M2.7/
M2.7-highspeed are real current models; corrected the M3 description from the
PR's "512K" to the documented ~1M context):
- minimax provider package (OpenAI-compatible https://api.minimax.io/v1),
  config.yml, models.yml, tests; MINIMAX_API_KEY/SERVER_URL/PROVIDER env vars;
  ProviderMiniMax type + DefaultProviderNameMiniMax; providers.go wiring;
  Valid() whitelist.

Added for completeness:
- goose migration adding 'minimax' to the PROVIDER_TYPE enum + database
  ProviderTypeMinimax const.
- GraphQL: minimax in ProviderType enum, ProvidersModelsList,
  ProvidersReadinessStatus, DefaultProvidersConfig; resolvers wire default
  config/models + enabled status; gqlgen regenerated.
- Frontend: MiniMax icon (lobehub), provider-icon + settings-providers
  registration + provider type list; regenerated GraphQL types.
- Installer wizard: provider form, screen, list, registry, env-var mappings,
  locale strings + help text.
- ctester/ftester: -type/-provider minimax support.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:24:04 +07:00
mason5052 3c6bea3c5d fix: return structured error when zip build fails before streaming
Commit the ZIP response status and headers lazily, on the first byte written, via a small zipStreamWriter. A build failure before any output now returns the normal structured error response instead of a committed 200 with a truncated body; mid-stream failures still abort. Also check the reader Close error in the helper test and cover the pre-stream failure path.
2026-06-19 04:20:28 +07:00
mason5052 f7e2ac6615 fix: stream zip downloads without buffering archive
DownloadResource and DownloadFlowFile built the entire ZIP archive in a bytes.Buffer before sending it, so heap usage scaled with archive size and a few concurrent large-directory downloads could exhaust process memory.

Stream the archive straight to the response writer via a shared streamZipArchive helper; the existing ZipResources/ZipDirectory/ZipRelativePaths helpers already accept an io.Writer. Responses are now chunked (no Content-Length) and memory stays proportional to one file's copy buffer.
2026-06-19 04:20:28 +07:00
Sergey KozyrenkoandClaude Fable 5 9a5a8b53a5 fix(server): return 404 from name change when the user no longer exists
ChangeNameCurrentUser issued a bare UPDATE and ignored RowsAffected, so a stale
session for a deleted user got 200 — inconsistent with the email/password handlers
(which 404) and leaving the frontend's Users.NotFound mapping unreachable.

- check RowsAffected and return ErrUsersNotFound (404) when no row matched
- document the 404 in the swagger annotation
- add TestChangeNameCurrentUser (success, missing user, invalid name)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-14 10:35:52 +07:00
Sergey KozyrenkoandClaude Fable 5 c14ba936fb fix(auth): accept mixed-case and long-TLD emails; normalize on change
The vmail validator rejected addresses the frontend's z.string().email() accepts
(uppercase, TLDs longer than 4 chars like .cloud), so users saw a confusing 400.

- relax the vmail regex to allow uppercase and TLDs of 2+ chars
- lowercase + trim the new address in ChangeEmailCurrentUser and in the form schema
  so storage, the duplicate check, and login lookups stay case-stable
- validator + change-email tests for mixed case and long TLDs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 19:26:44 +07:00
Sergey KozyrenkoandClaude Fable 5 06178bf868 fix(server): link OAuth logins to existing accounts by email; harden email change
- authLoginCallback matches users by email alone so an OAuth login links into an
  existing (incl. local) account instead of 500-ing on users_mail_unique
- relink on a create-branch unique-violation race instead of returning 500
- issue the session with the linked account's actual role privileges
- clear the stale OAuth provider link when a user changes their email
- map the email-change unique-violation race to 409 instead of 500
- isUniqueViolation matches Postgres and SQLite case-insensitively
- tests for link/create/blocked/role-inheritance/race, email 409, provider reset
- update auth form test selectors after the form refactor

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 19:00:26 +07:00
Sergey KozyrenkoandClaude Opus 4.8 7d504914b8 feat(server): persist OAuth provider and add self-service name change
- OAuth login callback now stores the provider (google/github) on the
  user record and backfills it for pre-existing OAuth users on login,
  so the UI can show which provider an account is linked to.
- Add PUT /user/name for any authenticated user (including OAuth): a
  NameChange model + ChangeNameCurrentUser handler that lets users edit
  their display name. Placed in a /user group without localUserRequired.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 02:56:15 +07:00
Sergey Kozyrenko 182642ba6b Merge pull request #340 from Akalanka1337/user-profile-email-update
Replace Change Password with My Profile (email and password update)
2026-06-11 19:35:53 +07:00
Sergey KozyrenkoandClaude Fable 5 99c8b6786c fix: recover from stale-chunk and DOM-desync SPA crashes
Two crashes seen in production, both reproduced on the live app:

- "Failed to fetch dynamically imported module": after a redeploy rotates the
  hashed chunk filenames, an open tab imports a deleted one. The server answered a
  missing /assets/* with 301 -> index.html (HTML for a JS module -> a MIME
  failure); it now returns 404 + no-store. The client listens for Vite's
  vite:preloadError and reloads once (debounced) to pull the current build. Hashed
  assets are served immutable; index.html and SPA routes no-cache.

- "Failed to execute 'removeChild' ... not a child of this node": an external
  agent (a browser extension or auto-translation) mutates the DOM React owns,
  desyncing reconciliation. A root react-router errorElement catches this
  commit-phase crash and self-heals with a debounced reload, instead of React
  Router's dead default error screen. translate="no" opts the English-only UI out
  of the one trigger it can prevent (browser translation); the errorElement covers
  the rest regardless of source.

Verified by reproducing both on the live old build (missing-chunk 301->HTML;
extension/translation DOM mutation -> the exact removeChild crash) and confirming
the fixed build recovers from each. Adds chunk-reload + RouteErrorBoundary unit
tests and a static-serving integration test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 17:32:34 +07:00
Akalanka1337 82bca05ac3 feat(webui): replace Change Password with My Profile (email and password updates) 2026-06-05 23:51:36 +05:30
mason5052 41524bd07e fix: return structured error when zip build fails before streaming
Commit the ZIP response status and headers lazily, on the first byte written, via a small zipStreamWriter. A build failure before any output now returns the normal structured error response instead of a committed 200 with a truncated body; mid-stream failures still abort. Also check the reader Close error in the helper test and cover the pre-stream failure path.
2026-06-05 10:16:52 -04:00
mason5052 556692aeb1 fix: stream zip downloads without buffering archive
DownloadResource and DownloadFlowFile built the entire ZIP archive in a bytes.Buffer before sending it, so heap usage scaled with archive size and a few concurrent large-directory downloads could exhaust process memory.

Stream the archive straight to the response writer via a shared streamZipArchive helper; the existing ZipResources/ZipDirectory/ZipRelativePaths helpers already accept an io.Writer. Responses are now chunked (no Content-Length) and memory stays proportional to one file's copy buffer.
2026-06-05 10:04:03 -04:00
octo-patch 9ca254efa3 feat: upgrade MiniMax default model to M3
- Add MiniMax provider with M3 as the default model (512K context, 128K max output, image input support)
- Keep MiniMax-M2.7 and MiniMax-M2.7-highspeed as alternatives
- Configure agent defaults (simple, primary_agent, assistant, generator, etc.) on M3
- Register MiniMax provider type, env vars (MINIMAX_API_KEY, MINIMAX_SERVER_URL, MINIMAX_PROVIDER)
- Add unit tests covering config loading, models list, prefix behavior, and missing API key
2026-06-03 12:54:50 +08:00
Dmitry Ng 39f122467d feat(config): add new embedding and rename database connection pool settings
- Introduced `EMBEDDING_MAX_TEXT_BYTES` to limit the maximum byte size of text sent to the embedding model.
- Renamed database connection pool settings: `DATABASE_MAX_OPEN_CONNS`, `DATABASE_MAX_IDLE_CONNS`, and `DATABASE_VECTOR_MAX_CONNS` for improved PostgreSQL connection management.
- Updated relevant documentation to reflect these new configuration options and their usage.
- Adjusted various components to utilize the new settings for enhanced performance and resource management.
2026-05-18 18:26:52 +03:00
Dmitry Ng 2ce863ec1a feat(toolcall): implement ToolCall logging functionality
- Added ToolCallLogProvider interface with methods for logging tool calls, updating success and failure statuses.
- Introduced proxyToolCallLogProvider to handle ToolCall logging operations.
- Updated flow execution components to integrate ToolCall logging, including flow workers and controllers.
- Enhanced GraphQL schema to support ToolCall logs, including queries and subscriptions for real-time updates.
- Updated documentation to reflect the new ToolCall logging features and their usage.
2026-05-18 11:21:56 +03:00
Dmitry Ng 077ddce476 feat(database): enhance PostgreSQL connection pooling and configuration
- Introduced shared connection pooling for PostgreSQL using `*sql.DB` for sqlc and GORM, optimizing resource usage.
- Added new environment variables: `DB_MAX_OPEN_CONNS`, `DB_MAX_IDLE_CONNS`, and `DB_VECTOR_MAX_CONNS` for configurable connection limits.
- Updated documentation to reflect new connection pooling strategy and provide operational commands for monitoring.
- Implemented shared `pgxpool` for pgvector stores to reduce connection overhead and improve performance.
- Adjusted various components to utilize the new connection pooling setup, ensuring efficient database interactions.
2026-05-18 11:13:43 +03:00
Dmitry Ng 403a84b0a6 feat(toolcalls): implement toolcall management features via REST API
- Added a new SQL migration to insert toolcall privileges into the privileges table.
- Introduced the `ToolcallService` for managing toolcall data, including retrieval of toolcalls and flow-specific toolcalls.
- Implemented API endpoints for fetching toolcalls and toolcall details, with appropriate permission checks.
- Enhanced Swagger documentation to include new toolcall endpoints and their specifications.
- Created a new model for toolcalls, defining their structure and validation rules.
- Added error handling for invalid toolcall requests and not found scenarios.
2026-05-14 14:12:37 +03:00
Dmitry Ng 2f4da118e0 feat(anonymization): implement anonymizeText mutation and associated service
- Added a new SQL migration to insert the 'anonymize.call' privilege into the privileges table.
- Introduced the `anonymizeText` mutation in the GraphQL schema, allowing users to anonymize sensitive text.
- Implemented the `AnonymizerService` to handle text anonymization requests via a REST API endpoint.
- Updated the GraphQL resolver to integrate the new mutation and ensure proper permission checks.
- Enhanced documentation with Swagger and OpenAPI specifications for the new endpoint.
- Added error handling for invalid requests and unavailable anonymizer configurations.
2026-05-12 21:47:40 +03:00
Dmitry Ng ba0cee43c8 fix(router): add new frontend routes for resources and knowledges to preserve route in the browser
- Introduced "/resources" and "/knowledges" routes to the frontendRoutes array in the router configuration, expanding the application's routing capabilities.
2026-05-08 20:46:47 +03:00
Dmitry Ng a9aeb81e4e refactor(resources): update MoveResourceRequest to allow empty destination
- Removed the requirement for the "destination" field in MoveResourceRequest, allowing it to be an empty string, which signifies moving to the root directory.
- Updated related documentation in swagger.json, swagger.yaml, and docs.go to reflect the new behavior.
- Adjusted the MoveResource function to handle cases where the destination is empty, ensuring proper path sanitization and resource movement semantics.
- Enhanced test cases to cover scenarios involving moving resources to the root directory and handling conflicts appropriately.
2026-05-08 20:24:39 +03:00
Dmitry Ng dc2fd43928 feat(assistants): support flowID=0 in REST API to create assistant with new flow
- Allow POST /flows/0/assistants/ to create a new flow together with the assistant, mirroring the existing GraphQL createAssistant(flowID: 0) behavior
- Require both assistants.create and flows.create permissions when flowID=0
- Add explicit flow ownership check for non-zero flowID using flows.admin scope
- Load flow data in the response by fetching it via assistant.FlowID after creation, ensuring AssistantFlow is fully populated in all cases
2026-05-08 18:54:14 +03:00
Dmitry Ng a348e41a31 feat(settings): add version and isDevelopMode fields to Settings model and GraphQL schema
- Introduced new fields `version` and `isDevelopMode` in the Settings model to provide application versioning and development mode status.
- Updated GraphQL schema and resolvers to support the new fields, ensuring they are accessible via the Settings query.
- Enhanced Swagger documentation to reflect the changes in the Settings API endpoint.
- Added necessary validation and response handling for the new fields in the Settings service.
2026-05-08 13:06:07 +03:00
Dmitry Ng 6890584c64 feat(resources): add multi-source move, copy and flow-file promotion
- Add Sources []string to MoveResourceRequest, CopyResourceRequest and AddResourceFromFlowRequest; merged with Source, deduplicated; multi-source uses destination as base dir and runs in a single atomic DB transaction
- Fix MoveResource response to return Added + Updated (not Updated only) so Apollo cache receives new parent directory entries alongside moved items
- Add missing errResourceNotFound case in CopyResource (was 500 instead of 404)
- Cover all new behaviour with table-driven tests (basename conflict, force overwrite, missing source, empty input, dir-into-itself guard, etc.)
2026-05-06 17:03:13 +03:00
Dmitry Ng 3a52079278 feat(knowledge): add pgvector knowledge base management
- GraphQL/REST CRUD + semantic search for knowledge documents
- KnowledgeStore with admin/user-scoped filtering, re-embedding on update
- Real-time subscriptions (created/updated/deleted) per user and admin
- user_id tracking in all agent-stored documents (guide/answer/code/memory)
- sqlc queries, goose migrations, privilege grants, user_id backfill
- Memory cleanup on flow deletion; stale orphan purge via migration
- Unit tests for all KnowledgeStore operations including security cases
- Frontend GraphQL schema and TypeScript types regenerated
2026-05-05 01:09:20 +03:00
Dmitry Ng ca9f4a0211 feat: add multi-path support and ZIP improvements across file APIs
- Added `paths[]` query/body parameter to DeleteFlowFile, DownloadFlowFile,
  GetFlowContainerFiles, PullFlowFiles, ListResources, DeleteResource, and
  DownloadResource; single `path` parameter retained for backward compatibility.
- Introduced `DeduplicatePaths` in flowfiles package with coverage-based
  deduplication (parent covers children), path normalization, and traversal safety.
- Added `ZipRelativePaths` to create ZIP archives from cache-relative paths,
  sharing `zipWriteFile` helper with refactored `ZipDirectory`.
- Switched all ZIP and single-file responses to buffered `DataFromReader` with
  explicit `Content-Length`, fixing Swagger UI download rendering.
- Expanded response payloads: delete and pull operations now enumerate all
  affected nested files; list responses include ancestor directories for tree
  completeness.
- Extended test coverage across flowfiles, flow_files, and resources packages
  with batch, deduplication, atomicity, Docker exec, and security scenarios.
2026-05-04 14:32:39 +03:00
Dmitry Ng 8830ae7010 fix: update resource handling and API documentation
- Adjusted descriptions in API documentation to clarify paths for uploads, resources, and containers.
- Updated data models to use consistent naming conventions (e.g., `isDir` to `is_dir`, `modifiedAt` to `modified_at`).
- Changed resource ID types from string to uint64 for better consistency across the application.
- Enhanced flow file upload functionality to support batch processing of resource files.
- Removed deprecated code related to resource entry responses in tests.
2026-05-01 16:11:09 +03:00
Dmitry Ng 1d6f842bb9 test: add comprehensive coverage for FlowFileService HTTP handlers
- Added table-driven scenarios for all 8 endpoints (Get/Upload/Delete/Download flow files, Pull from container, GetContainerFiles, AddResourcesToFlow, AddResourceFromFlow) covering success paths, all privilege combinations (view/upload/admin/cross-user), error responses (forbidden/not-found/conflict/invalid request), and security checks (path traversal, symlink rejection).
- Introduced reusable test infrastructure: sqlite-backed flows/user_resources schema, fakeDockerClient implementing the full docker.DockerClient interface, flowFileCaptureSubscriptions recording both FlowPublisher and ResourcePublisher events, and helpers for multipart upload bodies and container TAR fixtures.
- Added direct unit tests for shellQuote, parseFlowIDParam, cleanupPendingUploads, and flowScopeForFiles privilege matrix.
- Lifts handler coverage from 0% to 60-90% across the file and total services package coverage from 10.2% to 28.6%.
2026-04-28 22:48:23 +03:00