74 Commits
Author SHA1 Message Date
Dmitry Ng b611fbebcf fix: installer stack detection, tests that can fail, proxy and port docs
- installer: decide whether the stack is extracted by the provider examples
  beside the env file, not in the working directory
- tests: assert table cells in the markdown editor pipe tests; pin the
  prompter in provider failover, the permission error on a password change
  and the built-in Bedrock config against its shipped example
- docs: state what PROXY_URL covers and which ports flows publish; name the
  cgr.dev registry of the Langfuse stack
- comments: drop history and restated code, correct those that had drifted
  from the code
2026-10-04 01:18:50 +03:00
Dmitry Ng 3cfe5cba4b refactor: improve document handling and validation in knowledge management
- Updated knowledge document creation and update functions to store content as sent, preserving whitespace and line breaks.
- Enhanced validation for flow template fields to ensure titles are trimmed while text retains its original format.
- Refactored tests to verify that blank content is rejected and that stored content matches the input, including line breaks.
- Updated markdown editor to maintain content integrity during serialization and deserialization processes.
- Improved documentation to clarify how content is stored and processed, ensuring consistency across the application.
2026-10-02 09:51:01 +03:00
Dmitry Ng 01acdda6d3 fix: failover on flow creation, minio image, stable build revisions
- Failover: when the primary provider is down, flow and assistant creation now falls back for the tool call ID template.
- Prompts: a stored custom prompt that no longer validates is ignored in favor of the default, with a warning, instead of rendering "<no value>".
- Security: PUT /users/{hash} refuses a password change without users.edit, so a stolen session cookie can no longer reset the account password.
- Langfuse: minio/minio is gone from Docker Hub, so the stack runs cgr.dev/chainguard/minio:latest as root to keep existing volumes readable.
- Installer: the main menu highlights Maintenance while a worker, stack or installer update is waiting.
- Versions: the build revision is the first 7 characters of the commit SHA instead of git rev-parse --short, which depends on the size of the clone.
- Tests: the docker pids-limit test sets its limit after the probes start, so the setup execs no longer exhaust it on slow CI runners.
- Docs: README covers Azure OpenAI through the custom provider and the Neo4j/APOC files a manual Graphiti install needs.
- Reports: added the Azure OpenAI ctester report and regenerated vllm-mixed for Qwen3.8.
2026-10-01 00:55:56 +03:00
Dmitry Ng 6f3d29c3f1 feat: port major fixes 2026-09-30 01:48:35 +03:00
Dmitry Ng 6f34a010e1 feat(cloud): enhance VXControl Cloud API usage and add PentAGI version checks 2026-09-02 02:31:59 +03:00
Dmitry Ng ccb309a628 fix(docker): upgrade Go and dependencies for improved compatibility and performance
- Updated Go version from 1.24 to 1.26.5 in Dockerfile and CI configuration.
- Upgraded various dependencies in go.mod, including AWS SDK and OpenTelemetry packages, to their latest versions for enhanced features and security.
- Refactored Docker client imports from the Docker library to the Moby library for better compatibility with the updated API.
- Adjusted Docker client usage throughout the codebase to align with the new Moby client structure.
2026-08-04 19:09:09 +03:00
Dmitry Ng 5fa405782b fix(docs): remove maxLength constraint for password fields in API documentation
- Updated the API documentation in `docs.go`, `swagger.json`, and `swagger.yaml` to remove the maxLength constraint for password fields, simplifying the validation requirements.
- Added `github.com/docker/go-units` as a direct dependency in `go.mod` to support updated functionality.
2026-08-03 14:49:51 +03:00
Dmitry Ng 9b588bd211 Merge pull request #382 from N1neSun/fix/allow-null-flow-trace-id
fix(flows): allow pending trace IDs in flow responses
2026-08-03 15:44:28 +04:00
Dmitry Ng 21baa20a0b refactor(logging): standardize error logging across controllers and providers
- Replaced direct error logging calls with a centralized `obs.LogErrorOrCancel` function to ensure consistent logging behavior for errors, particularly in cases of context cancellation.
- Updated various controllers and providers to utilize the new logging method, enhancing maintainability and clarity in error handling.
- Introduced new methods for invalidating subtasks and tasks in the flow and subtask controllers to improve resource management and prevent stale references.
- Enhanced the handling of database errors in task and subtask status updates to treat missing records as completed, ensuring idempotent task shutdowns.
2026-07-30 16:33:52 +03:00
N1neSun 3068b626d0 fix(flows): allow pending trace IDs 2026-07-30 16:36:36 +08:00
Dmitry Ng 34a9cd2ee8 feat(config): enhance multi-instance support and Docker configurations
- Introduced `TENANT_ID` to namespace resources for multi-instance deployments, preventing collisions in shared services.
- Added new environment variables in `.env.example` and `docker-compose.yml` for Docker daemon configurations (`DOCKER_INSIDE_HOST`, `DOCKER_INSIDE_TLS_VERIFY`, `DOCKER_INSIDE_CERT_PATH`).
- Updated backend logic to handle tenant-specific configurations, ensuring proper isolation of resources across instances.
- Enhanced documentation to clarify the usage and implications of `TENANT_ID` and related Docker settings.
2026-07-29 16:01:24 +03:00
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